Files
redefined-designs/frontend/tests/e2e/admin-taxonomy.spec.ts
T
bermudalambandClaude Opus 5 895c08d1a7 test(e2e): replace unchecked lookups, widen the assertion timeout, restore the skipped test (#241)
Tasks 2 to 4 of the plan. Nine `collection.find(...)` dereferences become findOrFail, so a missing row fails as a named assertion naming what was wanted and how many rows were searched, rather than "Cannot read properties of undefined" pointing at test plumbing. Where the old code followed the lookup with expect(x).toBeTruthy(), that assertion is dropped: findOrFail already guarantees it, and with a better message.

The expect timeout goes from Playwright's default 5s to 10s. It costs nothing on a green run — it bounds how long a failing assertion waits, not how long a passing one takes — and #239 died reporting exactly Timeout: 5000ms on a runner that also builds, migrates and runs three other suites.

The admin-save happy path comes back from the #245 skip. It is the only end-to-end check that adding an item reaches the database rather than merely firing a toast, and it passed both full parallel runs and in isolation.

filters.spec.ts:216 is deliberately untouched: its .find() searches CSS class names on a string array, not test data, and has no missing-row failure mode.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 20:04:43 -05:00

60 lines
2.2 KiB
TypeScript

import { test, expect, uniqueSuffix, findOrFail } from './fixtures';
// The e2e database is shared and never reset, so every fixture name carries a
// unique suffix and assertions are scoped to the nodes this run created. The
// suffix is generated per test rather than per module: a worker can run this
// file more than once, and a module-level constant would collide with itself.
test.describe('Admin taxonomy', () => {
test('creates a category and a nested child that stays visible', async ({
page,
admin,
adminTaxonomy
}) => {
const RUN = `a${uniqueSuffix()}`;
await admin.open('Categories');
await adminTaxonomy.addCategory(`Furniture ${RUN}`);
await expect(page.getByText(`Furniture ${RUN}`)).toBeVisible();
await adminTaxonomy.addChildCategory(`Furniture ${RUN}`, `Tables ${RUN}`);
// The tree is mounted before this branch exists, so the child is only
// visible if expansion follows newly created nodes rather than the state
// captured at first render.
await expect(page.getByText(`Tables ${RUN}`)).toBeVisible();
});
test('creates a tag with an automatically assigned colour', async ({
page,
admin,
adminTaxonomy
}) => {
const RUN = `a${uniqueSuffix()}`;
await admin.open('Tags');
await adminTaxonomy.addTag(`vintage-${RUN}`);
// Clicking OK only dispatches the request; wait for the confirmation so the
// lookup below can't race the create.
await expect(adminTaxonomy.tagAddedNotice).toBeVisible();
// The table paginates and the shared database holds many tags, so the new
// row is confirmed through the API rather than hunted for across pages.
const tags = await (await page.request.get('/api/admin/tags')).json();
const created = findOrFail(
tags,
(tag: { name: string }) => tag.name === `vintage-${RUN}`,
`the tag vintage-${RUN}`
);
expect(created.color).toBeTruthy();
});
test('offers category and tag fields on the item form', async ({ admin, adminInventory }) => {
await admin.goto();
await adminInventory.openItemForm();
await expect(adminInventory.formDialog.getByText('Category', { exact: true })).toBeVisible();
await expect(adminInventory.formDialog.getByText('Pick existing tags')).toBeVisible();
});
});