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>
79 lines
2.5 KiB
TypeScript
79 lines
2.5 KiB
TypeScript
/**
|
|
* @feature New Item Form
|
|
* @see e2e/features/pages/item-new.feature
|
|
*/
|
|
import { describe, test, expect } from 'vitest';
|
|
import { setupBrowser } from '../../support/browser';
|
|
import { waitForAppReady } from '../../support/seed';
|
|
import { expectVisible, expectNotVisible, expectText, expectDisabled } from '../../support/expect';
|
|
|
|
const { getPage } = setupBrowser();
|
|
|
|
describe('New Item Form', () => {
|
|
test('form displays all required fields', async () => {
|
|
const page = getPage();
|
|
await page.goto('/items/new');
|
|
await waitForAppReady(page);
|
|
|
|
await expectText(page.getByRole('heading', { level: 1 }), 'New Item');
|
|
await expectVisible(page.getByText('Name *'));
|
|
await expectVisible(page.getByText('Type'));
|
|
await expectVisible(page.getByText('Create Item'));
|
|
});
|
|
|
|
test('submit button disabled without name', async () => {
|
|
const page = getPage();
|
|
await page.goto('/items/new');
|
|
await waitForAppReady(page);
|
|
|
|
await expectDisabled(page.getByRole('button', { name: 'Create Item' }));
|
|
});
|
|
|
|
test('cancel returns to items list', async () => {
|
|
const page = getPage();
|
|
await page.goto('/items/new');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByRole('button', { name: 'Cancel' }).click();
|
|
expect(page.url()).toContain('/items');
|
|
});
|
|
|
|
test('consumable type shows quantity fields', async () => {
|
|
const page = getPage();
|
|
await page.goto('/items/new');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByLabel('Type').selectOption('consumable');
|
|
await expectVisible(page.getByText('Quantity Tracking'));
|
|
await expectVisible(page.getByText('Current'));
|
|
await expectVisible(page.getByText('Original'));
|
|
});
|
|
|
|
test('perishable type shows expiry date', async () => {
|
|
const page = getPage();
|
|
await page.goto('/items/new');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByLabel('Type').selectOption('perishable');
|
|
await expectVisible(page.getByText('Expiry Date'));
|
|
});
|
|
|
|
test('durable type hides quantity fields', async () => {
|
|
const page = getPage();
|
|
await page.goto('/items/new');
|
|
await waitForAppReady(page);
|
|
|
|
await page.getByLabel('Type').selectOption('durable');
|
|
await expectNotVisible(page.getByText('Quantity Tracking'));
|
|
});
|
|
|
|
test('storage tier buttons are visible', async () => {
|
|
const page = getPage();
|
|
await page.goto('/items/new');
|
|
await waitForAppReady(page);
|
|
|
|
await expectVisible(page.getByText('Hot'));
|
|
await expectVisible(page.getByText('Warm'));
|
|
await expectVisible(page.getByText('Cold'));
|
|
});
|
|
});
|