diff --git a/web/e2e/smoke.spec.js b/web/e2e/smoke.spec.js index 0e1facc..63ca5de 100644 --- a/web/e2e/smoke.spec.js +++ b/web/e2e/smoke.spec.js @@ -4657,16 +4657,23 @@ test('en søgning i ⌘K efterlader de træffere, den fandt', async ({ page }) = // Gemt ved at forlade feltet, som resten af fladen gør det — der er ingen // Gem-knap at huske. // - // Der ventes på "Gemt", før den næste note laves. Uden det klikkes "Ny note", - // mens den forrige stadig er undervejs, og listen når ikke at få den med — det - // fejlede i CI én gang ud af tre kørsler, og bestod hver gang her på maskinen. - // En prøve, der er hurtigere end programmet, måler maskinen den kører på. + // Der ventes på et TOMT tekstfelt, før der skrives. Uden det kan udfyldningen + // ramme den forrige notes felt, mens den nye er undervejs, og så bliver teksten + // enten skrevet på den forkerte note eller tabt undervejs. + // + // Og der ventes IKKE på "Gemt": den tekst er hvilestanden, ikke et signal. + // Feltet siger "Gemmer" mens en gemning kører og "Gemt" ellers — altså også før + // den første gemning overhovedet er begyndt. En prøve, der venter på den, får + // grønt med det samme og måler ingenting. Det var den fejl, der gjorde den her + // prøve ustabil: rettelsen var en ventetid, der ikke kunne vente på noget. + // Rækken i listen er det rigtige tegn — den kommer først, når serveren har + // svaret. for (const title of ['Fyrreskov nord', 'Fyrreskov syd', 'Egeskov']) { await page.getByRole('button', { name: 'Ny note' }).click(); const body = page.getByLabel('Notens tekst'); + await expect(body).toHaveText(''); await body.fill(`${title}\n\nnoget om den`); await body.blur(); - await expect(page.getByText('Gemt', { exact: true })).toBeVisible(); await expect(page.locator('.list').getByText(title, { exact: true })).toBeVisible(); } @@ -4696,6 +4703,51 @@ test('en søgning i ⌘K efterlader de træffere, den fandt', async ({ page }) = expect(trouble).toEqual([]); }); + +/** + * En ny note åbnes med det samme, uden at editoren forsvinder undervejs. + * + * Serveren tømmer `body` på listerækker med vilje, og siden brugte den tomme krop + * som tegn på "det her er en række, hent noten hel". En nyoprettet note er også + * tom — og hel — så den blev sendt samme vej: editoren blev pillet af skærmen, + * noten hentet igen, og editoren sat op på ny. + * + * Det hul var ikke kun et blink. Mens det stod åbent, var der ingen valgt note, og + * gemningen går tavst tilbage uden en. Skrev man i det sekund, var teksten væk — + * ingen fejl, ingen toast, bare en tom note. Det er også det, der gjorde + * søgeprøven ovenfor ustabil: i CI var maskinen langsom nok til at ramme hullet. + * + * Prøven tæller opslagene frem for at måle et blink. Et blink er en tidsting og + * ville kræve, at prøven var hurtigere end programmet — præcis den fejl, den er + * skrevet for at lukke. Et opslag, der ikke sker, er et tal. + */ +test('en ny note hentes ikke igen, når den lige er lavet', async ({ page }) => { + const trouble = watchForTrouble(page); + + const fetched = []; + page.on('request', (r) => { + // Selve noten, ikke dens delinger: /notes/ og ikke /notes//shares. + const m = new URL(r.url()).pathname.match(/^\/api\/v1\/notes\/([0-9a-f-]+)$/); + if (r.method() === 'GET' && m) fetched.push(m[1]); + }); + + await page.goto('/noter'); + await page.getByRole('button', { name: 'Ny note' }).click(); + + // Editoren er der, og den er tom — ikke væk og på vej tilbage. + const body = page.getByLabel('Notens tekst'); + await expect(body).toHaveText(''); + + await body.fill('Grantræ\n\nnoget om det'); + await body.blur(); + await expect(page.locator('.list').getByText('Grantræ', { exact: true })).toBeVisible(); + + // Noten blev aldrig hentet igen: svaret på oprettelsen var den hele. + expect(fetched).toEqual([]); + + expect(trouble).toEqual([]); +}); + /** * Et indsat billede kan ses i fuld størrelse og kopieres videre. * diff --git a/web/src/routes/noter/+page.svelte b/web/src/routes/noter/+page.svelte index 38a4204..369d108 100644 --- a/web/src/routes/noter/+page.svelte +++ b/web/src/routes/noter/+page.svelte @@ -561,7 +561,17 @@ * Derfor hentes den hele her. Rækken vises med det samme, så det ikke føles som * at vente; teksten kommer, når den er der. */ - async function open(note) { + /** + * `whole` siger, at noten allerede er hel, og at der ikke skal hentes. + * + * En tom krop bruges ellers som tegn på, at det her er en listerække — serveren + * tømmer `body` på dem med vilje. Men en *nyoprettet* note er også tom, og den + * er hel. Uden det her blev den lukket ud som en halv note: editoren blev pillet + * af skærmen, noten hentet igen, og editoren sat op på ny. I det hul står + * `selected` som null, og `save()` går tavst tilbage uden at gemme — så tekst + * skrevet der forsvandt sporløst. + */ + async function open(note, { whole = false } = {}) { clearTimeout(timer); if (!note) { selectedId = null; @@ -577,9 +587,9 @@ // id'et være det samme begge gange, så den anden aldrig blev vist. Man ville // sidde med en tom note, der lige havde haft en titel. selectedId = note.id; - if (note.body) { + if (whole || note.body) { selected = note; - draft = note.body; + draft = note.body ?? ''; return; } selected = null; @@ -691,7 +701,8 @@ try { const note = await api.createNote({ body: '' }); notes = [note, ...notes]; - open(note); + // Svaret er hele noten, så den skal ikke hentes igen — se open(). + await open(note, { whole: true }); document.querySelector('.editor textarea')?.focus(); } catch (e) { app.toast(humanMessage(e));