Files
eleith 5e9c949801
ci/woodpecker/pr/cli Pipeline was successful
ci/woodpecker/pr/config Pipeline was successful
ci/woodpecker/pr/web Pipeline was successful
Adopt SvelteKit 3 APIs
2026-11-03 06:54:26 -08:00

114 lines
4.7 KiB
TypeScript

import { expect, test } from '@playwright/test';
import { startServer, type TestServer } from './support/server.js';
const configuration = `site:
title: Household directory
links:
photos:
title: Family photos
url: https://photos.example.test/
group: Media
tags: [family]
requires_auth: true
music:
title: Music
url: https://music.example.test/
group: Media
tags: [family]
notes:
title: Notes
url: https://notes.example.test/
group: Tools
requires_auth: true
`;
let server: TestServer;
test.beforeAll(async () => {
server = await startServer({ configuration });
await server.ready();
});
test.afterAll(async () => {
if (server) expect(await server.stop()).toEqual({ code: 0, signal: null });
});
test('search finds a bookmark, opens its details and clears back to browsing', async ({ page }) => {
await page.goto(server.url);
const search = page.getByRole('searchbox', { name: 'Search', exact: true });
const results = page.getByRole('list', { name: 'Search results', exact: true });
await expect(search).toBeEnabled();
await expect(page.getByRole('heading', { level: 2 })).toHaveText(['Media', 'Tools']);
const label = page.locator('label[for="directory-search"]');
await expect(label).toHaveCount(1);
await label.click();
await expect(search).toBeFocused();
await search.fill('photos');
await expect(results.getByRole('link')).toHaveCount(1);
await expect(results.getByRole('link')).toContainText('Family photos');
await expect(page).toHaveURL(`${server.url}/?q=photos`);
// Async shallow routing must not rewrite an in-place edit or move its caret to the end.
await search.press('End');
await search.press('ArrowLeft');
await search.press('x');
await expect(search).toHaveValue('photoxs');
await expect(page).toHaveURL(`${server.url}/?q=photoxs`);
await expect(search).toBeFocused();
await expect(search).toHaveJSProperty('selectionStart', 6);
await expect(search).toHaveJSProperty('selectionEnd', 6);
await search.press('Backspace');
await expect(search).toHaveValue('photos');
await expect(page).toHaveURL(`${server.url}/?q=photos`);
await page.reload();
await expect(search).toHaveValue('photos');
await expect(results.getByRole('link')).toHaveCount(1);
await results.getByRole('link').press('Enter');
const details = page.getByRole('dialog', { name: 'Family photos', exact: true });
await expect(details).toBeVisible();
await expect(details.getByRole('button', { name: /^(Previous|Next) bookmark$/ })).toHaveCount(0);
await expect(
details.getByRole('link', { name: 'Open Family photos (opens in a new tab)', exact: true })
).toHaveAttribute('href', 'https://photos.example.test/');
await details.getByRole('button', { name: 'Close', exact: true }).click();
await expect(results.getByRole('link')).toBeFocused();
await expect(search).toHaveValue('photos');
await search.fill('zzzxxyyqqq');
await expect(page.getByRole('status')).toHaveText('No bookmarks found.');
await expect(results).toHaveCount(0);
await page.getByRole('button', { name: 'Clear search', exact: true }).click();
await expect(search).toHaveValue('');
await expect(search).toBeFocused();
await expect(page).toHaveURL(`${server.url}/`);
await expect(page.getByRole('heading', { level: 2 })).toHaveText(['Media', 'Tools']);
await expect(page.getByRole('main').getByRole('link')).toHaveCount(3);
});
for (const { filter, query, titles } of [
{ filter: 'tag: family', query: 'tag:family', titles: ['Family photos', 'Music'] },
{ filter: 'access: login', query: 'access:login', titles: ['Family photos', 'Notes'] }
]) {
test(`selecting ${filter} in details replaces the current search`, async ({ page }) => {
await page.goto(`${server.url}/?q=photos`);
const search = page.getByRole('searchbox', { name: 'Search', exact: true });
const results = page.getByRole('list', { name: 'Search results', exact: true });
await expect(results.getByRole('link')).toHaveCount(1);
await results.getByRole('link').click();
const details = page.getByRole('dialog', { name: 'Family photos', exact: true });
await details.getByRole('button', { name: `Filter by ${filter}`, exact: true }).click();
await expect(details).toHaveCount(0);
await expect(search).toBeFocused();
await expect(search).toHaveValue(query);
await expect(page).toHaveURL(`${server.url}/?${new URLSearchParams({ q: query })}`);
await expect(results.getByRole('link')).toHaveCount(titles.length);
await expect(results.getByRole('link')).toContainText(titles);
await results.getByRole('link').first().click();
await page.getByRole('button', { name: 'Next bookmark', exact: true }).click();
await expect(page.getByRole('dialog', { name: titles[1]!, exact: true })).toBeVisible();
await expect(page).toHaveURL((url) => url.searchParams.get('q') === query);
});
}