From cc4a8aed1466434e3004a73062c20bf5222eb17b Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 19 May 2026 23:13:47 +0200 Subject: [PATCH] test(transcription): de-flake one-fetch @mention test via searchbox fill userEvent.type(@Walter) types 7 keys; CI jitter can space the gaps past the 150 ms debounce and fire 2+ fetches, even though the request-token guard discards the stale response. fill() collapses the input into one event so the assertion (exactly 1 fetch) becomes deterministic. Sara #1 on PR #629. Co-Authored-By: Claude Opus 4.7 --- .../PersonMentionEditor.svelte.spec.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/frontend/src/lib/shared/discussion/PersonMentionEditor.svelte.spec.ts b/frontend/src/lib/shared/discussion/PersonMentionEditor.svelte.spec.ts index cbbf692f..4262f3bc 100644 --- a/frontend/src/lib/shared/discussion/PersonMentionEditor.svelte.spec.ts +++ b/frontend/src/lib/shared/discussion/PersonMentionEditor.svelte.spec.ts @@ -219,20 +219,30 @@ describe('PersonMentionEditor — AC-2/3: search input drives fetch', () => { expect(fetchesAfterSearch).toBe(1); }); - it('fires exactly one /api/persons fetch when the user types @Walter (debounced)', async () => { + it('fires exactly one /api/persons fetch when the user searches for Walter (debounced)', async () => { const fetchMock = vi .fn() .mockResolvedValue({ ok: true, json: vi.fn().mockResolvedValue([AUGUSTE]) }); vi.stubGlobal('fetch', fetchMock); renderHost(); - await userEvent.type(page.getByRole('textbox'), '@Walter'); + // Open the dropdown first so the search input is reachable. `fill` then + // drives the searchbox in one input event — sidesteps per-keystroke + // debounce timing on CI that Sara flagged on PR #629 round 2. + await userEvent.type(page.getByRole('textbox'), '@'); + await vi.waitFor(async () => { + await expect.element(page.getByRole('searchbox')).toBeVisible(); + }); + + const fetchesBeforeSearch = fetchMock.mock.calls.length; + + await page.getByRole('searchbox').fill('Walter'); await new Promise((r) => setTimeout(r, SEARCH_DEBOUNCE_MS + POST_DEBOUNCE_SLACK_MS)); - const personsFetches = fetchMock.mock.calls.filter( - ([url]) => typeof url === 'string' && url.startsWith('/api/persons') - ); + const personsFetches = fetchMock.mock.calls + .slice(fetchesBeforeSearch) + .filter(([url]) => typeof url === 'string' && url.startsWith('/api/persons')); expect(personsFetches.length).toBe(1); });