source: Klonkt/test/feed-alt-view.test.js@ e46ebaa

main
Last change on this file since e46ebaa was e46ebaa, checked in by Robin <roboburr@…>, 3 weeks ago

Lezen: snappen dat je laat lezen, en geen lege schermen meer

Barts meldingen van 20 augustus, in een stuk of zes rondes bijgesteld. De
uitkomst is korter dan de weg ernaartoe, en die weg is het waard om vast te
leggen omdat ik er twee keer overheen ben geschoten.

SNAPPEN. De regel is nu in drie zinnen te zeggen:

omhoog scrollen nooit snappen -- je zoekt iets terug en bepaalt zelf

waar je stopt

omlaag, ver weg vrij scrollen
omlaag, laatste
150px van een
bericht vangt, en je landt op de bovenkant van het volgende

Er is geen top-zone: de bovenkant van het bericht waar je IN zit is geen
doelwit meer. Dat was de oorspronkelijke klacht -- je las een paar regels
verder en proximity trok je terug naar de bovenrand, waardoor het leek of
het scrollen vastliep. De grens die wel vangt is de onderkant van je huidige
bericht, en dat is hetzelfde punt als de bovenkant van het volgende.

Onderweg twee doodlopende wegen, allebei door Robin gecorrigeerd:

  • Eerst zette ik de snap UIT voor berichten langer dan het scherm. Op een telefoon is bijna elk bericht net iets langer dan de viewport, dus daar verdween het snappen overal: op 812px hoog kregen berichten van 1009 en zelfs 839 al geen snap meer.
  • Toen probeerde ik de vangzone aan de VOET van het bericht te hangen ("ben je de reacties voorbij"). Bij een kort bericht staat die voet middenin de lege ruimte die min-height maakte, dus de zone begon op een willekeurige plek. Gelukkig ving Robin dat voordat het uitgerold stond.

Het moest dus een getal in pixels zijn, en 150 is dat getal.

GEEN LEGE SCHERMEN MEER. min-height:100svh rekte elk bericht op tot een vol
scherm. Bij een kort bericht gaf dat een halve pagina leegte onder "Replies
and reactions" -- je keek naar niets en moest doorscrollen om te ontdekken
dat er nog iets kwam. Weg dus: berichten hebben hun eigen hoogte (gemeten:
360/1009/839/250 waar het eerst 888/888/888/888 was) en de stroom is gewoon
bericht na bericht. Het snappen hangt aan scroll-snap-align en niet aan die
hoogte, dus dat werkt onveranderd.

VLOEIEND: scroll-behavior:smooth, want zonder dat springt een snap er in een
frame naartoe en voelt het als een hik. Uit bij prefers-reduced-motion.

TERUG NAAR BOVEN, rechtsonder, in twee stappen: eerst naar het begin van DIT
bericht, daarna pas naar de kop van de pagina. Die knop is de enige die naar
een bovenkant mag springen, en hij heeft het snappen daar niet voor nodig --
scrollIntoView stuurt zelf. Nagemeten, juist omdat omhoog-snappen uit staat:
1706 -> 1206, exact de bovenkant.

COVERS nemen de volle kolombreedte met de verhouding intact. De ronde ervoor
haalde het opblazen eruit maar liet kleine afbeeldingen op ware grootte
staan, en dat was als postzegel in een brede kolom te klein.

DE CIRKEL. Lezen blijft daar dood (berichten van anderen), maar een tijdlijn
werkt er juist bij uitstek. Die dwong ik eerst af zodra de site geen
Lezen-site was, en dan kon je in de cirkel geen Grid meer kiezen. Nu is Grid
de landing en staat Tijdlijn ernaast: bij feed_alt_view=timeline altijd, bij
auto op desktop. De cirkel krijgt zijn eigen geheugen terug, met een eigen
sleutel zodat een keuze daar je thuisweergave niet aanraakt.

style.css naar v77 en MOD_V naar 13.

Suite 1165/1165.

Co-Authored-By: Claude Opus 5 <noreply@…>

  • Property mode set to 100644
File size: 5.1 KB
Line 
1// De tweede weergave van een site: Lezen, Tijdlijn, of allebei (mobiel/desktop).
2//
3// Tijdlijn was geen KEUZE meer sinds Lezen hem verving, maar de renderkant is
4// nooit weggehaald: home.ejs stuurt alle drie de secties mee en de CSS kiest op
5// body[data-feed-view]. Dit maakt er weer een instelling van.
6//
7// Deze tests gaan door de ECHTE routes heen, en niet langs de SQL met een
8// handgemaakte rij. Reden: bij het bouwen zette ik een waarde in de INSERT
9// zonder de kolom (te weinig vraagtekens) en een kolom in de UPDATE zonder de
10// waarde -- waarbij alles erna een plek opschuift en show_search de waarde van
11// feed_alt_view kreeg. Geen van beide had een test langs de zijkant gevangen.
12import { test } from 'node:test';
13import assert from 'node:assert/strict';
14
15process.env.DATABASE_PATH = ':memory:';
16process.env.PUBLIC_BASE_URL = 'https://test.example';
17const dbMod = await import('../src/config/database.js');
18const db = dbMod.default;
19dbMod.initializeDatabase();
20
21db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)')
22 .run('u1', 'baas', 'b@t.nl', 'x', 'god');
23
24const express = (await import('express')).default;
25const router = (await import('../src/routes/admin-sites.js')).default;
26const app = express();
27app.use(express.urlencoded({ extended: true }));
28app.use((req, _res, next) => { req.session = { user: { id: 'u1', role: 'god' } }; next(); });
29app.use('/admin/sites', router);
30
31const server = app.listen(0);
32server.unref(); // houdt de suite niet in leven als een test halverwege stopt
33const poort = server.address().port;
34// MET EEN TIJDSLIMIET, en dat is geen voorzorg maar een gemeten noodzaak: gaat er
35// in de route iets mis (een SQL-fout door een scheve parameterlijst), dan vangt
36// express dat in een async-handler niet af en komt er NOOIT een antwoord. Zonder
37// limiet hangt de hele suite dan op 124 in plaats van te falen -- precies wat er
38// gebeurde toen ik de controleproef deed. Een test die op de fout die hij moet
39// vangen blijft hangen, meldt niets.
40const post = async (pad, velden) => {
41 try {
42 return await fetch(`http://127.0.0.1:${poort}${pad}`, {
43 method: 'POST', redirect: 'manual',
44 headers: { 'content-type': 'application/x-www-form-urlencoded' },
45 body: new URLSearchParams(velden).toString(),
46 signal: AbortSignal.timeout(5000),
47 });
48 } catch (e) {
49 assert.fail(`de route antwoordde niet op ${pad} (${e.name}) -- vrijwel altijd een `
50 + 'worp in de handler, en bij dit formulier meestal een kolommenlijst die niet '
51 + 'meer bij de waarden past');
52 }
53};
54const siteVan = (slug) => db.prepare('SELECT * FROM sites WHERE slug = ?').get(slug);
55
56test('de kolom bestaat en staat standaard op Lezen', async () => {
57 const r = await post('/admin/sites/create', { slug: 'proef', title: 'Proef' });
58 assert.ok(r.status === 302 || r.status === 200, 'aanmaken mag niet stranden, kreeg ' + r.status);
59 const s = siteVan('proef');
60 assert.ok(s, 'de site hoort aangemaakt te zijn');
61 assert.equal(s.feed_alt_view, 'reader', 'een verse site biedt Lezen aan');
62});
63
64test('opslaan zet de tweede weergave, en raakt zijn buren niet', async () => {
65 // show_search is de kolom die in de UPDATE direct NA feed_alt_view komt. Zette
66 // je de kolom er wel bij en de waarde niet, dan kwam de checkbox-waarde in
67 // feed_alt_view terecht en schoof al het andere op. Daarom staat hij hier.
68 await post('/admin/sites/proef/save', {
69 title: 'Proef', feed_alt_view: 'timeline', feed_view_default: 'reader',
70 feed_view_switch: '1', show_search: '1', show_archive_link: '1',
71 });
72 const s = siteVan('proef');
73 assert.equal(s.feed_alt_view, 'timeline');
74 assert.equal(s.show_search, 1, 'de buurkolom mag niet meeschuiven');
75 assert.equal(s.show_archive_link, 1, 'en die erachter ook niet');
76 assert.equal(s.feed_view_switch, 1);
77});
78
79test('de standaardweergave volgt de tweede weergave, niet een vaste naam', () => {
80 // Hier hing het scheef: het aanmaakpad schreef 'reader' en het opslaanpad
81 // 'timeline', voor precies dezelfde keuze. De waarde betekende dus niet wat
82 // er stond, en de client vertaalde dat stil terug.
83 const s = siteVan('proef');
84 assert.equal(s.feed_view_default, 'timeline',
85 'kiest de site Tijdlijn, dan opent hij daar ook in');
86});
87
88test('Grid als standaard blijft Grid, wat de tweede weergave ook is', async () => {
89 await post('/admin/sites/proef/save', { title: 'Proef', feed_alt_view: 'auto', feed_view_default: 'grid' });
90 const s = siteVan('proef');
91 assert.equal(s.feed_alt_view, 'auto');
92 assert.equal(s.feed_view_default, 'grid');
93});
94
95test('onzin in het formulier valt terug op Lezen', async () => {
96 await post('/admin/sites/proef/save', { title: 'Proef', feed_alt_view: 'iets-anders', feed_view_default: 'reader' });
97 assert.equal(siteVan('proef').feed_alt_view, 'reader');
98});
99
100// closeAllConnections EERST: fetch houdt de verbinding open (keep-alive), en dan
101// wacht server.close() tot in de eeuwigheid. Bij een geslaagde run valt dat niet
102// op; valt er een test om, dan hangt de hele suite. Zo overkwam het me bij de
103// controleproef -- de test die de fout moest aantonen, hing erop.
104test.after(() => { server.closeAllConnections?.(); server.close(); });
Note: See TracBrowser for help on using the repository browser.