From 5c2a49841f0f4c626bde54f97bb5cd4917ab1c8a Mon Sep 17 00:00:00 2001 From: John Dvorak Date: Thu, 21 May 2026 10:24:32 -0700 Subject: [PATCH] refactor: extract public-types.ts from public.ts (interfaces and options) Moved ImhotepUi, ImhotepExpect, CompatibilityCheck, CompatibilityReport, ComponentOptions, StoryOptions, FixtureOptions, PropertyRunHandle, PropertyRunReportOptions, FixturePropertyRunHandle, ComponentPropertyRunHandle into dedicated public-types.ts module. public.ts re-exports everything for backward compatibility. --- .../imhotep-playwright/src/public-types.ts | 175 +++++++++++++++++ packages/imhotep-playwright/src/public.ts | 179 +++--------------- 2 files changed, 200 insertions(+), 154 deletions(-) create mode 100644 packages/imhotep-playwright/src/public-types.ts diff --git a/packages/imhotep-playwright/src/public-types.ts b/packages/imhotep-playwright/src/public-types.ts new file mode 100644 index 0000000..797ab24 --- /dev/null +++ b/packages/imhotep-playwright/src/public-types.ts @@ -0,0 +1,175 @@ +/** + * Public API types for imhotep-playwright. + * + * These interfaces define the contract for the Imhotep UI handle, + * entry-point options, property-run handles, and compatibility reporting. + * They are extracted from public.ts to reduce the file's size and make + * the public contract independently reviewable. + */ + +import type { Page } from 'playwright' +import type { FluentAssertion, FluentRelation, FluentQuantifier } from 'imhotep-dsl' +import type { ImhotepPage, ImhotepPageOptions, StateMaterializationNote, MaterializeStateOptions } from './page.js' +import type { ImhotepRuntime } from './runtime.js' +import type { SubjectReference, ExecutionContext, ImhotepDiagnostic, ImhotepResult, ClauseResult, NormalizedContract } from 'imhotep-core' +import type { EnvironmentCase } from './environment.js' +import type { RendererDescriptor } from './renderers.js' +import type { FastCheckAdapter } from './fast-check-adapter.js' +import type { InputDomain } from 'imhotep-core/property-contracts' +import type { EnumeratedRunResult, SampledRunResult } from 'imhotep-core/property-results' + +// --------------------------------------------------------------------------- +// Core Public Interfaces +// --------------------------------------------------------------------------- + +export interface ImhotepUi { + /** Fluent assertion builder bound to this page context. */ + expect: ImhotepExpect + + /** Add dense string-contract assertions to this check batch. */ + spec(source: string): ImhotepUi + + /** Add a fluent FOL quantifier assertion to this check batch. */ + quantifier(q: FluentQuantifier): ImhotepUi + + /** Parse all accumulated assertions and report syntax/validation errors without browser extraction. */ + validate(): Array<{ type: string; line?: number; message: string; code?: string; suggestedFix?: { action: string; value?: string; rationale: string } }> + + /** Evaluate all accumulated assertions and return results. */ + checkAll(options?: { format?: 'default'; includeNormalized?: boolean }): Promise + checkAll(options: { format: 'llm' }): Promise + checkAll(options?: { format?: 'default' | 'llm'; includeNormalized?: boolean }): Promise + + /** Access the underlying Imhotep page wrapper. */ + page: ImhotepPage + + /** Access the underlying Playwright page. */ + playwrightPage: Page + + /** Clear the geometry snapshot cache for this session. */ + clearCache(): void + + /** Extract geometry data for elements matching the selector or subject reference. */ + extract(subject: string | SubjectReference): Promise + + /** Materialize a UI state snapshot on the given selector. */ + materializeState(selector: string, state: string, options?: MaterializeStateOptions): Promise + + /** + * Apply an environment case to the page. + * + * Supported axes: + * - viewport: required — { width: number; height: number } + * - colorScheme: optional — 'light' | 'dark' | 'no-preference' + * - pointerType: optional — 'mouse' | 'touch' | 'fine' | 'coarse' + * - reducedMotion: optional — 'reduce' | 'no-preference' + * - deviceScaleFactor: optional — number + * - locale: optional — string (e.g. 'en-US') + */ + applyEnvironment(env: EnvironmentCase): Promise + + /** Resolve a subject by ARIA role (and optional accessible name). */ + getByRole(role: string, options?: { name?: string }): SubjectReference + + /** Resolve a subject by visible text content. */ + getByText(text: string): SubjectReference + + /** Resolve a subject by associated label text. */ + getByLabelText(label: string): SubjectReference + + /** Resolve a subject by data-testid attribute. */ + getByTestId(testId: string): SubjectReference + + /** Resolve a subject by explicit CSS selector (fallback). */ + locator(selector: string): SubjectReference + + /** Execution context controlling ids, clocks, and rng for this session. */ + context: ExecutionContext + + /** Runtime capability checks for version-skew diagnosis. */ + compatibilityReport(): CompatibilityReport +} + +export interface ImhotepExpect { + (subject: string | SubjectReference): FluentAssertion + all(subject: string | SubjectReference): FluentAssertion + any(subject: string | SubjectReference): FluentAssertion + none(subject: string | SubjectReference): FluentAssertion +} + +export interface CompatibilityCheck { + id: string + ok: boolean + details: string +} + +export interface CompatibilityReport { + ok: boolean + generatedAt: string + checks: CompatibilityCheck[] + packageFingerprints: Array<{ name: string; version: string; resolvedFrom: string }> +} + +// --------------------------------------------------------------------------- +// Entry-Point Options +// --------------------------------------------------------------------------- + +export interface ComponentOptions { + renderer: RendererDescriptor + props?: unknown + env?: ImhotepPageOptions + fc?: FastCheckAdapter +} + +export interface StoryOptions { + storybookUrl: string + args?: unknown + env?: ImhotepPageOptions + fc?: FastCheckAdapter +} + +export interface FixtureOptions { + env?: ImhotepPageOptions + fc?: FastCheckAdapter + /** Directory to resolve fixture IDs against. */ + fixturesDir?: string +} + +// --------------------------------------------------------------------------- +// Property Run Handles +// --------------------------------------------------------------------------- + +/** @deprecated Use FixturePropertyRunHandle or ComponentPropertyRunHandle instead. */ +export type PropertyRunHandle = FixturePropertyRunHandle + +export interface PropertyRunReportOptions { + reportMode?: 'compact' | 'verbose' +} + +export interface FixturePropertyRunHandle { + /** Run assertions exhaustively over all enumerated input combinations. */ + exhaustivelyForAllInputs( + runtime: Page | ImhotepRuntime, + domain: InputDomain, + runner: (scene: ImhotepUi, ctx: { caseId: string; input: unknown }) => Promise | void, + options?: PropertyRunReportOptions + ): Promise + + /** Run assertions over all generated input combinations (sampled). */ + forAllInputs( + runtime: Page | ImhotepRuntime, + domain: InputDomain, + runner: (scene: ImhotepUi, ctx: { caseId: string; input: unknown }) => Promise | void, + options?: PropertyRunReportOptions + ): Promise +} + +export interface ComponentPropertyRunHandle { + /** Run assertions over all generated prop combinations (sampled). */ + forAllProps( + runtime: Page | ImhotepRuntime, + domain: InputDomain, + runner: (scene: ImhotepUi, ctx: { caseId: string; input: unknown }) => Promise | void, + options?: PropertyRunReportOptions + ): Promise +} diff --git a/packages/imhotep-playwright/src/public.ts b/packages/imhotep-playwright/src/public.ts index d7388d7..5728c91 100644 --- a/packages/imhotep-playwright/src/public.ts +++ b/packages/imhotep-playwright/src/public.ts @@ -68,101 +68,36 @@ import { getDefaultCacheDir, } from 'imhotep-core' import type { EnvironmentCase } from './environment.js' +import type { + ImhotepUi, + ImhotepExpect, + CompatibilityCheck, + CompatibilityReport, + ComponentOptions, + StoryOptions, + FixtureOptions, + PropertyRunHandle, + PropertyRunReportOptions, + FixturePropertyRunHandle, + ComponentPropertyRunHandle, +} from './public-types.js' -export interface ImhotepUi { - /** Fluent assertion builder bound to this page context. */ - expect: ImhotepExpect - - /** Add dense string-contract assertions to this check batch. */ - spec(source: string): ImhotepUi - - /** Add a fluent FOL quantifier assertion to this check batch. */ - quantifier(q: FluentQuantifier): ImhotepUi - - /** Parse all accumulated assertions and report syntax/validation errors without browser extraction. */ - validate(): Array<{ type: string; line?: number; message: string; code?: string; suggestedFix?: { action: string; value?: string; rationale: string } }> - - /** Evaluate all accumulated assertions and return results. */ - checkAll(options?: { format?: 'default'; includeNormalized?: boolean }): Promise - checkAll(options: { format: 'llm' }): Promise - checkAll(options?: { format?: 'default' | 'llm'; includeNormalized?: boolean }): Promise - - /** Access the underlying Imhotep page wrapper. */ - page: ImhotepPage - - /** Access the underlying Playwright page. */ - playwrightPage: Page - - /** Clear the geometry snapshot cache for this session. */ - clearCache(): void - - /** Extract geometry data for elements matching the selector or subject reference. */ - extract(subject: string | SubjectReference): Promise - - /** Materialize a UI state snapshot on the given selector. */ - materializeState(selector: string, state: string, options?: MaterializeStateOptions): Promise - - /** - * Apply an environment case to the page. - * - * Supported axes: - * - viewport: required — { width: number; height: number } - * - colorScheme: optional — 'light' | 'dark' | 'no-preference' - * - pointerType: optional — 'mouse' | 'touch' | 'fine' | 'coarse' - * - reducedMotion: optional — 'reduce' | 'no-preference' - * - deviceScaleFactor: optional — number - * - locale: optional — string (e.g. 'en-US') - */ - applyEnvironment(env: EnvironmentCase): Promise - - // --------------------------------------------------------------------------- - // Semantic Subject Resolution (Stream 7) - // --------------------------------------------------------------------------- - - /** Resolve a subject by ARIA role (and optional accessible name). */ - getByRole(role: string, options?: { name?: string }): SubjectReference - - /** Resolve a subject by visible text content. */ - getByText(text: string): SubjectReference - - /** Resolve a subject by associated label text. */ - getByLabelText(label: string): SubjectReference - - /** Resolve a subject by data-testid attribute. */ - getByTestId(testId: string): SubjectReference - - /** Resolve a subject by explicit CSS selector (fallback). */ - locator(selector: string): SubjectReference - - /** Execution context controlling ids, clocks, and rng for this session. */ - context: ExecutionContext - - /** Runtime capability checks for version-skew diagnosis. */ - compatibilityReport(): CompatibilityReport -} - -export interface CompatibilityCheck { - id: string - ok: boolean - details: string -} - -export interface CompatibilityReport { - ok: boolean - generatedAt: string - checks: CompatibilityCheck[] - packageFingerprints: Array<{ name: string; version: string; resolvedFrom: string }> +export type { + ImhotepUi, + ImhotepExpect, + CompatibilityCheck, + CompatibilityReport, + ComponentOptions, + StoryOptions, + FixtureOptions, + PropertyRunHandle, + PropertyRunReportOptions, + FixturePropertyRunHandle, + ComponentPropertyRunHandle, } const cjsRequire = createRequire(import.meta.url) -export interface ImhotepExpect { - (subject: string | SubjectReference): FluentAssertion - all(subject: string | SubjectReference): FluentAssertion - any(subject: string | SubjectReference): FluentAssertion - none(subject: string | SubjectReference): FluentAssertion -} - // Internal assertion accumulator per UI handle const assertionStore = new WeakMap() const specStore = new WeakMap() @@ -200,70 +135,6 @@ function maybeInstallExtractionStatsHook(): void { }) } -// --------------------------------------------------------------------------- -// Component / Story / Fixture Entry Point Options -// --------------------------------------------------------------------------- - -export interface ComponentOptions { - renderer: RendererDescriptor - props?: unknown - env?: ImhotepPageOptions - fc?: FastCheckAdapter -} - -export interface StoryOptions { - storybookUrl: string - args?: unknown - env?: ImhotepPageOptions - fc?: FastCheckAdapter -} - -export interface FixtureOptions { - env?: ImhotepPageOptions - fc?: FastCheckAdapter - /** Directory to resolve fixture IDs against. */ - fixturesDir?: string -} - -// --------------------------------------------------------------------------- -// Property Run Handles -// --------------------------------------------------------------------------- - -/** @deprecated Use FixturePropertyRunHandle or ComponentPropertyRunHandle instead. */ -export type PropertyRunHandle = FixturePropertyRunHandle - -export interface PropertyRunReportOptions { - reportMode?: 'compact' | 'verbose' -} - -export interface FixturePropertyRunHandle { - /** Run assertions exhaustively over all enumerated input combinations. */ - exhaustivelyForAllInputs( - runtime: Page | ImhotepRuntime, - domain: InputDomain, - runner: (scene: ImhotepUi, ctx: { caseId: string; input: unknown }) => Promise | void, - options?: PropertyRunReportOptions - ): Promise - - /** Run assertions over all generated input combinations (sampled). */ - forAllInputs( - runtime: Page | ImhotepRuntime, - domain: InputDomain, - runner: (scene: ImhotepUi, ctx: { caseId: string; input: unknown }) => Promise | void, - options?: PropertyRunReportOptions - ): Promise -} - -export interface ComponentPropertyRunHandle { - /** Run assertions over all generated prop combinations (sampled). */ - forAllProps( - runtime: Page | ImhotepRuntime, - domain: InputDomain, - runner: (scene: ImhotepUi, ctx: { caseId: string; input: unknown }) => Promise | void, - options?: PropertyRunReportOptions - ): Promise -} - // --------------------------------------------------------------------------- // Runtime normalization helper (accepts Page for backward compat) // ---------------------------------------------------------------------------