refactor(catalog): derive desktop sort options from SORT_FIELD_LABELS #14
@@ -1,4 +1,5 @@
|
||||
import { test, expect, type Page } from '@playwright/test';
|
||||
import { SORT_FIELD_LABELS } from '../src/lib/mangaSort';
|
||||
|
||||
// These E2E tests run against the SvelteKit dev server, which proxies /api
|
||||
// to the backend. Playwright starts vite via `webServer` (see
|
||||
@@ -44,6 +45,35 @@ test('home page renders the Mangalord heading and search input', async ({ page }
|
||||
await expect(page.getByTestId('empty')).toContainText('No mangas yet');
|
||||
});
|
||||
|
||||
// Anti-drift guard: the desktop sort <select> and the mobile sort sheet must
|
||||
// both enumerate exactly SORT_FIELD_LABELS, in the same order. The desktop
|
||||
// select used to hard-code its <option>s, so a label rename in mangaSort.ts
|
||||
// would silently diverge the two surfaces. Comparing the rendered options to
|
||||
// the single source of truth makes that divergence fail loudly.
|
||||
test('desktop sort options stay in sync with SORT_FIELD_LABELS', async ({ page }) => {
|
||||
await mockAnonymous(page);
|
||||
await page.route('**/api/v1/mangas*', async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(emptyPage)
|
||||
});
|
||||
});
|
||||
|
||||
await page.goto('/');
|
||||
const select = page.getByTestId('sort-select');
|
||||
await expect(select).toBeVisible();
|
||||
|
||||
const options = select.locator('option');
|
||||
const labels = (await options.allTextContents()).map((s) => s.trim());
|
||||
const values = await options.evaluateAll((opts) =>
|
||||
opts.map((o) => (o as HTMLOptionElement).value)
|
||||
);
|
||||
|
||||
expect(values).toEqual(Object.keys(SORT_FIELD_LABELS));
|
||||
expect(labels).toEqual(Object.values(SORT_FIELD_LABELS));
|
||||
});
|
||||
|
||||
test('search updates the manga list', async ({ page }) => {
|
||||
await mockAnonymous(page);
|
||||
let lastSearch: string | null = null;
|
||||
|
||||
@@ -538,10 +538,11 @@
|
||||
<label class="sort">
|
||||
<span>Sort</span>
|
||||
<select bind:value={sort} onchange={onSortChange} data-testid="sort-select">
|
||||
<option value="updated">Last updated</option>
|
||||
<option value="created">Date added</option>
|
||||
<option value="title">Title</option>
|
||||
<option value="author">Author</option>
|
||||
<!-- Options derive from SORT_FIELD_LABELS — the same source the
|
||||
mobile sort sheet uses — so the two surfaces can't drift. -->
|
||||
{#each Object.entries(SORT_FIELD_LABELS) as [value, label] (value)}
|
||||
<option {value}>{label}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
<div class="sort">
|
||||
|
||||
Reference in New Issue
Block a user