50 Playwright E2E tests across 13 spec files covering all routes and user flows (items CRUD, check-out/in, locations, labels, scanning, search/filter). Uses vitest as runner with playwright-core for browser automation (bun-compatible alternative to @playwright/test). Includes Gherkin .feature files as living documentation, test support infrastructure (IDB seeding, item factories, assertion helpers, layout measurement), and HANDOFF.md covering project state, deployment, and open design decisions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
3.7 KiB
TypeScript
113 lines
3.7 KiB
TypeScript
/**
|
|
* @feature Item Detail
|
|
* @see e2e/features/pages/item-detail.feature
|
|
*/
|
|
import { describe, test } from 'vitest';
|
|
import { setupBrowser } from '../../support/browser';
|
|
import { waitForAppReady, seedItems } from '../../support/seed';
|
|
import { buildItem, buildConsumableItem } from '../../support/item-factory';
|
|
import { expectVisible, expectText } from '../../support/expect';
|
|
|
|
const { getPage } = setupBrowser();
|
|
|
|
describe('Item Detail', () => {
|
|
test('item details are displayed', async () => {
|
|
const page = getPage();
|
|
const item = buildItem({ name: 'Drill', category: 'Tools' });
|
|
await page.goto('/');
|
|
await waitForAppReady(page);
|
|
await seedItems(page, [item]);
|
|
await page.goto('/items');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByText('Drill').click();
|
|
await expectText(page.getByRole('heading', { level: 1 }), 'Drill');
|
|
await expectVisible(page.getByText('Tools'));
|
|
await expectVisible(page.getByText('Type'));
|
|
await expectVisible(page.getByText('Storage Tier'));
|
|
});
|
|
|
|
test('custody badge shows checked-in state', async () => {
|
|
const page = getPage();
|
|
const item = buildItem({ name: 'Drill', category: 'Tools' });
|
|
await page.goto('/');
|
|
await waitForAppReady(page);
|
|
await seedItems(page, [item]);
|
|
await page.goto('/items');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByText('Drill').click();
|
|
await expectVisible(page.getByText('Home'));
|
|
});
|
|
|
|
test('check out form appears on button click', async () => {
|
|
const page = getPage();
|
|
const item = buildItem({ name: 'Drill', category: 'Tools' });
|
|
await page.goto('/');
|
|
await waitForAppReady(page);
|
|
await seedItems(page, [item]);
|
|
await page.goto('/items');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByText('Drill').click();
|
|
await page.getByRole('button', { name: 'Check Out' }).click();
|
|
|
|
await expectVisible(page.getByText('Reason'));
|
|
await expectVisible(page.getByText('Destination'));
|
|
});
|
|
|
|
test('edit button enters edit mode', async () => {
|
|
const page = getPage();
|
|
const item = buildItem({ name: 'Drill', category: 'Tools' });
|
|
await page.goto('/');
|
|
await waitForAppReady(page);
|
|
await seedItems(page, [item]);
|
|
await page.goto('/items');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByText('Drill').click();
|
|
await page.getByRole('button', { name: 'Edit' }).click();
|
|
|
|
await expectVisible(page.getByText('Edit Item'));
|
|
await expectVisible(page.getByText('Save Changes'));
|
|
});
|
|
|
|
test('delete requires confirmation', async () => {
|
|
const page = getPage();
|
|
const item = buildItem({ name: 'Drill', category: 'Tools' });
|
|
await page.goto('/');
|
|
await waitForAppReady(page);
|
|
await seedItems(page, [item]);
|
|
await page.goto('/items');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByText('Drill').click();
|
|
await page.getByRole('button', { name: 'Delete' }).click();
|
|
|
|
await expectVisible(page.getByText('Confirm Delete'));
|
|
});
|
|
|
|
test('quantity bar shown for consumables', async () => {
|
|
const page = getPage();
|
|
const item = buildConsumableItem({ name: 'Coffee Beans', currentQuantity: 3, originalQuantity: 10 });
|
|
await page.goto('/');
|
|
await waitForAppReady(page);
|
|
await seedItems(page, [item]);
|
|
await page.goto('/items');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByText('Coffee Beans').click();
|
|
await expectVisible(page.getByText('Quantity'));
|
|
});
|
|
|
|
test('item not found shows error', async () => {
|
|
const page = getPage();
|
|
await page.goto('/');
|
|
await waitForAppReady(page);
|
|
await page.goto('/items/nonexistent');
|
|
await waitForAppReady(page);
|
|
|
|
await expectVisible(page.getByText('Item not found'));
|
|
await expectVisible(page.getByText('Back to items'));
|
|
});
|
|
});
|