From 8a6329bfc910879564fa656f932c8147a13df62c Mon Sep 17 00:00:00 2001 From: kristianwind Date: Thu, 8 Oct 2026 19:53:12 +0200 Subject: [PATCH] =?UTF-8?q?fix(pr=C3=B8ver):=20mark=C3=B8r-pr=C3=B8verne?= =?UTF-8?q?=20venter=20p=C3=A5=20mark=C3=B8ren=20i=20stedet=20for=20at=20h?= =?UTF-8?q?=C3=A5be?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI's End-to-end faldt på "en ny note åbner med markøren i overskriften" med `Expected: "h1", Received: null`, på en gren hvis eneste ændring siden forrige grønne kørsel var docs/openapi.yaml. Den kan ikke påvirke en editor, så fejlen lå i prøven. Den klikkede "Ny note" og læste markøren i ÉT snapshot med det samme. `click()` vender tilbage, så snart klikket er sendt, mens markøren sættes efter en netværksrundtur OG en gentegning. Lokalt er rundturen under et millisekund, så snapshottet ramte altid; på en travl runner ramte det null. main er grøn på netop den prøve, så den bestod ved held frem for ved regel — og den havde ligget og ventet på en travl runner i en fremmed PR, hvor den ville have lignet dén PRs fejl. Målt frem for ræsonneret: med 900 ms plantet på POST /notes fejler den gamle læsning med CI's ordlyd og `expect.poll` består. Tre af de fire havde samme svaghed. Kontrollen — "en note med indhold stjæler ikke markøren" — er bevidst IKKE lavet om: den forventer null, så en poll ville bestå på første læsning uanset hvad koden gjorde. Den ankrer sig på overskriftens tekst i stedet. Det står som kommentar i filen, så den ikke bliver "rettet" tilbage. E2E: 131 bestod, 0 netafbrydelser. Co-Authored-By: Claude Opus 5 --- web/e2e/smoke.spec.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/web/e2e/smoke.spec.js b/web/e2e/smoke.spec.js index 3fa115e..0216da2 100644 --- a/web/e2e/smoke.spec.js +++ b/web/e2e/smoke.spec.js @@ -5723,7 +5723,17 @@ test('en ny note åbner med markøren i overskriften', async ({ page }) => { await page.goto('/noter'); await page.getByRole('button', { name: 'Ny note' }).click(); - expect(await caretBlock(page), 'markøren skal stå i h1').toBe('h1'); + // `expect.poll` og ikke én læsning: `click()` vender tilbage, så snart klikket er + // sendt, mens markøren sættes efter en netværksrundtur OG en gentegning. Lokalt + // er rundturen under et millisekund, så ét snapshot ramte altid — på en runner + // ramte det `null`, og prøven bestod på main ved held frem for ved regel. + // + // Kontrollen nedenfor (`stjæler ikke markøren`) må IKKE laves om til en poll: + // den forventer null, så en poll ville bestå på første læsning, uanset hvad + // koden gjorde. Den ankrer sig i stedet på overskriftens tekst først. + await expect + .poll(() => caretBlock(page), { message: 'markøren skal stå i h1' }) + .toBe('h1'); // Og den står et sted, man kan skrive: det, der tastes, bliver titlen, og // titlen er det, listen kalder noten. @@ -5764,7 +5774,9 @@ test('urd-døren opfører sig ens: ny note, markør i overskriften', async ({ pa await expect(page).toHaveURL(/\/noter$/); await page.getByRole('button', { name: 'Ny note' }).click(); - expect(await caretBlock(page), 'markøren skal stå i h1 også i urd').toBe('h1'); + await expect + .poll(() => caretBlock(page), { message: 'markøren skal stå i h1 også i urd' }) + .toBe('h1'); expect(trouble).toEqual([]); }); @@ -5787,7 +5799,9 @@ test('en note oprettet fra et projekt åbner også med markøren i overskriften' await page.getByRole('button', { name: 'Ny note', exact: true }).click(); await expect(page).toHaveURL(/\/noter\?note=/); - expect(await caretBlock(page), 'markøren skal stå i h1 efter navigationen').toBe('h1'); + await expect + .poll(() => caretBlock(page), { message: 'markøren skal stå i h1 efter navigationen' }) + .toBe('h1'); await page.keyboard.type('Dæk og kort'); await expect(page.locator('.editor h1').first()).toHaveText('Dæk og kort');