/** * Playwright test fixtures for Imhotep. * * Provides a native Playwright fixture that injects an Imhotep page * wrapper into every test, enabling fluent relational assertions * directly within Playwright test suites. */ import { test as baseTest } from '@playwright/test' import type { TestFixture, WorkerFixture, Fixtures, PlaywrightTestArgs, PlaywrightWorkerArgs } from '@playwright/test' import { ImhotepPage, ImhotepPageOptions } from './page.js' import { ImhotepRuntime, createRuntime } from './runtime.js' import { EnvironmentCase } from './environment.js' /** * Extended Playwright test type with Imhotep fixtures. * * Usage: * * ```js * import { test } from 'imhotep-playwright' * * test('product page layout', async ({ page, imhotepPage }) => { * await page.goto('/products/123') * // Use imhotepPage for assertions... * }) * ``` */ export interface ImhotepFixtures { /** * The Imhotep runtime for the current worker process. * * One runtime is created per worker and manages pooled browser * contexts and pages. */ imhotepRuntime: ImhotepRuntime /** * The Imhotep page wrapper borrowed for the current test. * * This is automatically borrowed from the worker runtime and * returned after the test completes. */ imhotepPage: ImhotepPage /** * Optional environment case applied before the test begins. * * If provided, the fixture will configure the page viewport, * color scheme, pointer type, and reduced-motion preference. */ imhotepEnvironment: EnvironmentCase | undefined /** * Options passed to the Imhotep runtime and page wrappers. */ imhotepOptions: ImhotepPageOptions } /** Internal test-scoped fixtures for type safety. */ interface ImhotepTestFixtures { imhotepPage: ImhotepPage imhotepEnvironment: EnvironmentCase | undefined } /** Internal worker-scoped fixtures for type safety. */ interface ImhotepWorkerFixtures { imhotepRuntime: ImhotepRuntime imhotepOptions: ImhotepPageOptions } /** * Default environment case used when none is explicitly provided. */ export const defaultEnvironment: EnvironmentCase = { viewport: { width: 1280, height: 720 }, colorScheme: 'no-preference', reducedMotion: 'no-preference', } // --------------------------------------------------------------------------- // Individual fixture definitions with explicit types. // --------------------------------------------------------------------------- const imhotepOptionsFixture: WorkerFixture = async ( {}, use ) => { await use({ injectRuntime: true }) } const imhotepEnvironmentFixture: TestFixture = async ( {}, use ) => { await use(defaultEnvironment) } const imhotepRuntimeFixture: WorkerFixture = async ( { browser, imhotepOptions }, use ) => { const runtime = await createRuntime(browser, { pageOptions: imhotepOptions }) await use(runtime) await runtime.shutdown() } const imhotepPageFixture: TestFixture = async ( { imhotepRuntime, imhotepEnvironment }, use ) => { const page = await imhotepRuntime.createPage() if (imhotepEnvironment) { await page.applyEnvironment(imhotepEnvironment) } await use(page) await imhotepRuntime.releasePage(page) } /** * The base Imhotep fixtures object. * * Extend this with `test.extend()` if you need to add custom fixtures * or override defaults for a specific test file. */ export const imhotepFixtures: Fixtures = { imhotepOptions: [imhotepOptionsFixture, { scope: 'worker', option: true }], imhotepEnvironment: [imhotepEnvironmentFixture, { option: true }], imhotepRuntime: [imhotepRuntimeFixture, { scope: 'worker' }], imhotepPage: [imhotepPageFixture, { scope: 'test' }], } /** * Pre-extended Playwright test object with Imhotep fixtures. * * Import this instead of `@playwright/test` to get Imhotep support * out of the box. */ export const test = baseTest.extend(imhotepFixtures) /** * Re-export `expect` from Playwright so that test files only need * one import. */ export { expect } from '@playwright/test'