test(tag-input): rename waitForDebounce to waitForFetch and reduce to 50ms
fetchSuggestions has no debounce; the wait is purely for the async mock to resolve. The old name implied semantics that don't exist and added ~4.5s to the suite (13 uses × 350ms). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page, userEvent } from 'vitest/browser';
|
||||
import TagInput, { type Tag } from './TagInput.svelte';
|
||||
|
||||
const waitForDebounce = () => new Promise((r) => setTimeout(r, 350));
|
||||
const waitForFetch = () => new Promise((r) => setTimeout(r, 50));
|
||||
const tick = () => new Promise((r) => setTimeout(r, 0));
|
||||
|
||||
function mockFetchWithTagObjects(tags: Tag[]) {
|
||||
@@ -168,7 +168,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Fa');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
await expect.element(page.getByRole('option', { name: 'Familie' })).toBeInTheDocument();
|
||||
await expect.element(page.getByRole('option', { name: 'Freunde' })).toBeInTheDocument();
|
||||
await page.screenshot({ path: 'test-results/screenshots/tag-input-suggestions.png' });
|
||||
@@ -179,7 +179,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('F');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
expect(fetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -188,7 +188,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [{ name: 'Familie' }], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Fr');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
await expect.element(page.getByRole('option', { name: 'Familie' })).not.toBeInTheDocument();
|
||||
await expect.element(page.getByRole('option', { name: 'Freunde' })).toBeInTheDocument();
|
||||
});
|
||||
@@ -198,7 +198,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Fa');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
document.querySelector<HTMLElement>('[role="option"]')!.click();
|
||||
await tick();
|
||||
await expect.element(page.getByText('Familie')).toBeInTheDocument();
|
||||
@@ -211,7 +211,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('__');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
await userEvent.keyboard('{ArrowDown}'); // index 0 → Aachen
|
||||
await userEvent.keyboard('{ArrowDown}'); // index 1 → Berlin
|
||||
await userEvent.keyboard('{Enter}');
|
||||
@@ -223,7 +223,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Fa');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
await expect.element(page.getByRole('option', { name: 'Familie' })).toBeInTheDocument();
|
||||
document.body.click();
|
||||
await tick();
|
||||
@@ -238,7 +238,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('El');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
const options = Array.from(document.querySelectorAll('[role="option"]'));
|
||||
const texts = options.map((el) => el.textContent?.replace(/›/g, '').trim() ?? '');
|
||||
expect(texts.indexOf('Eltern')).toBeLessThan(texts.indexOf('Kind'));
|
||||
@@ -252,7 +252,7 @@ describe('TagInput – autocomplete', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Fa');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
await expect.element(page.getByRole('listbox')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -269,7 +269,7 @@ describe('TagInput – tree-aware ordering', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Brief');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
const options = Array.from(document.querySelectorAll('[role="option"]'));
|
||||
const texts = options.map((el) => el.textContent?.replace(/›/g, '').trim() ?? '');
|
||||
expect(texts).toContain('Briefe');
|
||||
@@ -287,7 +287,7 @@ describe('TagInput – tree-aware ordering', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Hochzeit');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
const options = Array.from(document.querySelectorAll('[role="option"]'));
|
||||
const texts = options.map((el) => el.textContent?.replace(/›/g, '').trim() ?? '');
|
||||
expect(texts.indexOf('Briefe')).toBeLessThan(texts.indexOf('Hochzeit'));
|
||||
@@ -305,7 +305,7 @@ describe('TagInput – tree-aware ordering', () => {
|
||||
render(TagInput, { tags: [], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Hochzeit');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
await userEvent.keyboard('{ArrowDown}'); // first item: Briefe (context ancestor)
|
||||
await userEvent.keyboard('{Enter}');
|
||||
// successful add clears the input; if .tag unwrap is missing, addTag returns early
|
||||
@@ -320,7 +320,7 @@ describe('TagInput – tree-aware ordering', () => {
|
||||
render(TagInput, { tags: [{ id: 'p1', name: 'Briefe' }], allowCreation: true });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Fa');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
await expect.element(page.getByRole('option', { name: 'Familienbriefe' })).toBeInTheDocument();
|
||||
// the already-selected parent must not appear as a suggestion
|
||||
const optionNames = Array.from(document.querySelectorAll('[role="option"]')).map(
|
||||
@@ -356,7 +356,7 @@ describe('TagInput – onTextInput callback', () => {
|
||||
render(TagInput, { tags: [], allowCreation: false, onTextInput });
|
||||
const input = page.getByRole('textbox');
|
||||
await input.fill('Ka');
|
||||
await waitForDebounce();
|
||||
await waitForFetch();
|
||||
const option = page.getByRole('option', { name: 'Kaufvertrag' });
|
||||
await option.click();
|
||||
await expect.poll(() => onTextInput.mock.calls.at(-1)).toEqual(['']);
|
||||
|
||||
Reference in New Issue
Block a user