add search input to projects overview page

Filters the project table by name client-side, reusing the existing
filteredProjects computed and the dropdown search input styling.
Search is deliberately not persisted in the table state so a reload
never leaves the table silently filtered.
This commit is contained in:
AKolenda
2026-08-18 17:21:57 -06:00
committed by Gregor Vostrak
parent f00d48f1c3
commit 9958e1c09c
2 changed files with 48 additions and 1 deletions

View File

@@ -1288,3 +1288,31 @@ test.describe('Projects Pagination', () => {
await expect(page.getByText(prefix + '00')).not.toBeVisible();
});
});
test('test that searching projects by name works', async ({ page, ctx }) => {
const suffix = Math.floor(1 + Math.random() * 10000);
const matchingProjectName = 'Searchable Project ' + suffix;
const otherProjectName = 'Unrelated Work ' + suffix;
await createProjectViaApi(ctx, { name: matchingProjectName });
await createProjectViaApi(ctx, { name: otherProjectName });
await goToProjectsOverview(page);
await clearProjectTableState(page);
await page.reload();
await expect(page.getByText(matchingProjectName)).toBeVisible({ timeout: 10000 });
await expect(page.getByText(otherProjectName)).toBeVisible();
// Searching is case insensitive and matches part of the name
await page.getByTestId('project_search').fill('searchable project ' + suffix);
await expect(page.getByText(matchingProjectName)).toBeVisible();
await expect(page.getByText(otherProjectName)).not.toBeVisible();
// A term that matches nothing empties the table
await page.getByTestId('project_search').fill('no project has this name');
await expect(page.getByText(matchingProjectName)).not.toBeVisible();
// Clearing the search restores both projects
await page.getByTestId('project_search').fill('');
await expect(page.getByText(matchingProjectName)).toBeVisible();
await expect(page.getByText(otherProjectName)).toBeVisible();
});