/** * Playwright Test Fixture for Chaos Testing * * Usage: * ```typescript * import { test, expect } from '@playwright/test'; * import { chaosTest, withChaos } from 'chaosbringer/fixture'; * * // Option 1: Use chaosTest directly * chaosTest('chaos test homepage', async ({ page, chaos }) => { * const result = await chaos.testPage(page, 'http://localhost:3000'); * expect(result.errors).toHaveLength(0); * }); * * // Option 2: Extend your existing test * const test = base.extend(withChaos()); * test('my test', async ({ page, chaos }) => { ... }); * ``` */ import { type Page } from "@playwright/test"; import { ChaosCrawler } from "./crawler.js"; import type { ChaosTestOptions, PageResult, CrawlReport } from "./types.js"; import { type InvestigateResult } from "./recipes/investigate.js"; import { RecipeStore, type RecipeStoreOptions } from "./recipes/store.js"; import type { RecipeVars } from "./recipes/templating.js"; import type { ActionRecipe } from "./recipes/types.js"; import type { FailureContext } from "./recipes/goals.js"; import type { SnapshotPolicy } from "./recipes/composition.js"; export interface ChaosFixture { /** Test a single page with chaos testing */ testPage(page: Page, url: string): Promise; /** Crawl multiple pages starting from a URL */ crawl(startUrl: string): Promise; /** Assert no errors were found */ expectNoErrors(result: PageResult | CrawlReport): void; /** * Assert the crawl discovered no dead links. Prints each dead link's * source page so the reviewer can find the broken anchor without * cross-referencing the full report. */ expectNoDeadLinks(result: CrawlReport): void; /** Get the underlying crawler instance */ crawler: ChaosCrawler; } export interface ChaosFixtures { chaos: ChaosFixture; chaosOptions: ChaosTestOptions; } /** * Create chaos fixture with custom options */ export declare function withChaos(defaultOptions?: ChaosTestOptions): { chaosOptions: [ChaosTestOptions, { option: true; }]; chaos: ({ page, chaosOptions }: { page: Page; chaosOptions: ChaosTestOptions; }, use: (fixture: ChaosFixture) => Promise) => Promise; }; /** * Pre-configured test with chaos fixture */ export declare const chaosTest: import("playwright/test").TestType; export interface RecipesFixture { /** Shared `RecipeStore` instance — same store across the test. */ store: RecipeStore; /** * Replay a verified recipe by name. Throws when the recipe doesn't * exist or replay fails. `requires` chain is honoured by default. */ runRecipe(name: string, opts?: RunRecipeFixtureOptions): Promise; /** * Harvest scenarios the current page self-declares on * `window.__chaosbringer` (WebMCP-style). Returns the candidate * recipes; the caller decides whether to upsert. */ harvestPageScenarios(opts?: { trustPublisher?: boolean; }): Promise; /** * Run the Phase-D investigator against a captured failure. Returns * the InvestigateResult — the regression recipe (if any) is also * upserted into the fixture's store. */ investigate(failure: FailureContext, opts?: InvestigateFixtureOptions): Promise; } export interface RunRecipeFixtureOptions { /** Template variables for `{{var}}` substitution. */ vars?: RecipeVars; /** Skip `requires` chaining (default: chained). */ chainRequires?: boolean; /** Storage-state snapshot policy. */ snapshot?: boolean | SnapshotPolicy; } export interface InvestigateFixtureOptions { /** Max actions to spend reproducing. Default: 20. */ budget?: number; /** Drives the investigator; required if you want a real AI replay. */ driver?: import("./drivers/types.js").Driver; /** Run minimisation (1-minimal delta debugging). */ minimize?: boolean; } export interface RecipesFixtureOptions { /** `RecipeStore` options. Defaults to `localDir: "./chaosbringer-recipes"`. */ store?: RecipeStoreOptions; /** * Re-use a pre-built store. If set, `store` options are ignored. * Useful when you want every test to see the same in-memory cache * accumulated by a `beforeAll`. */ storeInstance?: RecipeStore; } export interface RecipesFixtures { store: RecipeStore; runRecipe: RecipesFixture["runRecipe"]; harvestPageScenarios: RecipesFixture["harvestPageScenarios"]; investigate: RecipesFixture["investigate"]; } /** * Build the recipes fixture set. Extend an existing Playwright Test * with: * * const test = base.extend(withRecipes()); * test("buy flow", async ({ runRecipe }) => { * await runRecipe("shop/buy-tshirt", { vars: { email: "..." } }); * }); */ export declare function withRecipes(defaults?: RecipesFixtureOptions): { store: ({ page: _page }: { page: Page; }, use: (s: RecipeStore) => Promise) => Promise; runRecipe: ({ page, store }: { page: Page; store: RecipeStore; }, use: (fn: RecipesFixture["runRecipe"]) => Promise) => Promise; harvestPageScenarios: ({ page, store }: { page: Page; store: RecipeStore; }, use: (fn: RecipesFixture["harvestPageScenarios"]) => Promise) => Promise; investigate: ({ store }: { store: RecipeStore; }, use: (fn: RecipesFixture["investigate"]) => Promise) => Promise; }; /** * Pre-configured test with both chaos AND recipes fixtures. Use this * when you want a single `test` symbol with everything wired. */ export declare const recipesTest: import("playwright/test").TestType; /** * Helper to run chaos test on current page */ export declare function runChaosTest(page: Page, options?: ChaosTestOptions): Promise; /** * Expect helper for chaos results */ export declare const chaosExpect: { toHaveNoErrors(result: PageResult | CrawlReport): void; toHaveNoExceptions(result: PageResult | CrawlReport): void; toLoadWithin(result: PageResult, maxMs: number): void; toHaveNoDeadLinks(result: CrawlReport): void; }; //# sourceMappingURL=fixture.d.ts.map