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>
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
import { chromium, type Browser, type Page, type BrowserContext } from 'playwright-core';
|
|
import { e2eConfig } from '../playwright.config';
|
|
import { afterAll, beforeAll, beforeEach, afterEach } from 'vitest';
|
|
import { execSync } from 'child_process';
|
|
|
|
let browser: Browser;
|
|
let context: BrowserContext;
|
|
let page: Page;
|
|
|
|
/**
|
|
* Find the Chromium executable installed by Playwright.
|
|
*/
|
|
function findChromium(): string {
|
|
// Check standard Playwright cache locations
|
|
const cacheDir = process.env.PLAYWRIGHT_BROWSERS_PATH
|
|
|| `${process.env.HOME}/Library/Caches/ms-playwright`;
|
|
|
|
try {
|
|
const result = execSync(
|
|
`find "${cacheDir}" -name "headless_shell" -type f 2>/dev/null | head -1`,
|
|
{ encoding: 'utf-8' }
|
|
).trim();
|
|
if (result) return result;
|
|
} catch {}
|
|
|
|
try {
|
|
const result = execSync(
|
|
`find "${cacheDir}" -name "chromium" -type f -not -path "*/node_modules/*" 2>/dev/null | head -1`,
|
|
{ encoding: 'utf-8' }
|
|
).trim();
|
|
if (result) return result;
|
|
} catch {}
|
|
|
|
// Fall back to system Chrome
|
|
const systemChrome = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
return systemChrome;
|
|
}
|
|
|
|
export function setupBrowser() {
|
|
beforeAll(async () => {
|
|
const executablePath = findChromium();
|
|
browser = await chromium.launch({
|
|
executablePath,
|
|
headless: true,
|
|
});
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
context = await browser.newContext({
|
|
viewport: e2eConfig.viewport,
|
|
colorScheme: e2eConfig.colorScheme,
|
|
baseURL: e2eConfig.baseURL,
|
|
});
|
|
page = await context.newPage();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await context?.close();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await browser?.close();
|
|
});
|
|
|
|
return {
|
|
getPage: () => page,
|
|
getContext: () => context,
|
|
getBrowser: () => browser,
|
|
};
|
|
}
|