import { Page, Response } from '@playwright/test'; import { ElementRepository } from '@civitas-cerebrum/element-repository'; import { EmailClientConfig, EmailSendOptions, EmailReceiveOptions, ReceivedEmail, EmailMarkAction, EmailFilter } from '@civitas-cerebrum/email-client'; import { ApiResponse } from '@civitas-cerebrum/wasapi'; import { SqlResult, QueryBuilder } from '@civitas-cerebrum/sql-client'; import { StepOptions, DropdownSelectOptions, TextVerifyOptions, CountVerifyOptions, DragAndDropOptions, ListedElementMatch, VerifyListedOptions, GetListedDataOptions, FillFormValue, GetAllOptions, ScreenshotOptions, IsVisibleOptions, StorageVerifyOptions, WindowVerifyOptions, VisualMatchOptions } from '../enum/Options'; import { BrowserResponse, BrowserRequestOptions } from '../interactions/BrowserRequest'; import { ExpectNoRequestOptions, WaitUntilState, WaitForNetworkIdleOptions, LoadState } from '../interactions/Navigation'; import { ElementAction } from './ElementAction'; import { ExpectBuilder } from './ExpectMatchers'; /** * The `Steps` class serves as a unified Facade for test orchestration. * It combines element acquisition (via `@civitas-cerebrum/element-repository`) with * Playwright interactions, navigation, and verifications to keep test files clean, * readable, and free of raw locators. */ export declare class Steps { private repo; private page; private interact; private navigate; private extract; private verify; private request; private utils; private email; private apiClients; /** Lazily-built SqlClient cache, keyed by provider name (constructed on first DB step). */ private dbClients; /** Provider name → connection string. Clients are built on first use so a missing driver fails at the first DB step, not at fixture setup. */ private dbConfigs; private dbConnectTimeoutMs?; private timeout?; private interceptionRetry?; /** * Initializes the Steps class with the element repository. * The Playwright Page is obtained from the repository's driver. * @param repo - An initialized instance of `ElementRepository` containing your locators and the bound driver. * @param options - Optional configuration: emailCredentials, timeout, interceptionRetry, apiBaseUrl, and/or apiProviders. */ constructor(repo: ElementRepository, options?: { emailCredentials?: EmailClientConfig; timeout?: number; /** * When a click is intercepted by an overlaying element, retry it as a * dispatched DOM click event. Default `true` (compat). Set `false` so * genuine overlay bugs (stuck modals, cookie walls) fail the click. */ interceptionRetry?: boolean; apiBaseUrl?: string; apiProviders?: Record; dbUrl?: string; dbProviders?: Record; /** * Connect-timeout (ms) applied to every SQL client, so a wrong/unreachable * `dbUrl` fails fast in CI instead of hanging on the first query. */ dbConnectTimeoutMs?: number; }); /** * Maps StepOptions to ElementResolutionOptions for the repository. */ private toResolutionOptions; /** * Returns resolution options that force the ALL strategy (no .first() narrowing). * Used by collection-based methods like getCount, verifyCount, getAll, verifyOrder. */ private toAllResolutionOptions; /** * Resolves an element from the repository and narrows its type to * `WebElement`. This package is Playwright-only, so every resolved element * is in practice a `WebElement`. Calling this once at the repo boundary * lets every downstream call use the richer `WebElement` type (with its * `locator` / `rightClick` / `selectOption` / `getAllAttributes`) without * per-call casts. */ private getWebElement; /** * Same as `getWebElement` but forces the ALL strategy. For collection-based * methods (getCount, verifyOrder, verifyImages, etc.). */ private getAllWebElement; /** * Returns a fluent `ElementAction` with the caller's `StepOptions` strategy * applied via the fluent strategy selectors. Lets the legacy positional * `verify*` methods delegate into the matcher tree without losing the * `{ strategy: 'random' | 'index' | 'text' | 'attribute' }` escape hatch. */ private actionWithStrategy; /** * Returns a fluent builder for performing actions on a repository element. * Chain a strategy selector (optional) and terminate with an action. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @returns An `ElementAction` builder. * * @example * ```ts * await steps.on('mainNavItems', 'HomePage').first().hover(); * await steps.on('subcategoryItems', 'HomePage').random().click({ withoutScrolling: true }); * await steps.on('productCards', 'CollectionsPage').verifyPresence(); * const price = await steps.on('price', 'ProductPage').nth(0).getText(); * ``` */ on(elementName: string, pageName: string): ElementAction; /** * Navigates the browser to the specified URL. * Optionally appends query parameters and/or chooses the lifecycle state to * wait for. * @param url - The URL or path to navigate to (e.g. `'/dashboard'` or `'https://example.com'`). * @param options - Optional settings. `query` is a key-value map appended as * query parameters. `waitUntil` chooses the page lifecycle state to wait * for (default `'load'`); pass `'domcontentloaded'` for SPA navigations * that stall a cold WebKit/Safari on the full `load` event. * @returns The navigation `Response` (last redirect's response), or `null` * when navigation triggered no network request (same-document hash nav). * Read `res.status()` to assert 404 / redirect contracts; ignore the * return value when you only care about side-effects. */ navigateTo(url: string, options?: { query?: Record; waitUntil?: WaitUntilState; }): Promise; /** * Returns the current page URL (the full href). The value-returning * companion to {@link verifyUrlContains} — use it when a test needs the live * URL to compute a path, diff against a start URL, or build a pattern. */ getUrl(): string; /** * Returns the `pathname` of the current page URL (no origin, query, or hash). * Convenience over `new URL(steps.getUrl()).pathname`. */ getCurrentPath(): string; /** * Waits until the page URL matches `url`. A string is a glob pattern, a * RegExp is a contains-style match, and a predicate receives the live `URL`. * * Pass `action` to arm the wait **before** the navigation-triggering action * runs (issued concurrently via `Promise.all`) so a fast client-side route * change cannot complete in the gap between acting and waiting — the * race-safe form for rapid navigations. * * @param url - Glob string, RegExp, or `(url: URL) => boolean` predicate. * @param action - Optional navigation-triggering action, run concurrently. * Its return value is ignored, so a value-returning call (e.g. * `() => steps.navigateTo('/x')`, which now resolves a `Response | null`) * is accepted without a `void`-assignability error. * @param options - Optional `{ timeout, waitUntil }`. */ waitForUrl(url: string | RegExp | ((url: URL) => boolean), action?: () => Promise, options?: { timeout?: number; waitUntil?: WaitUntilState; }): Promise; /** * Refreshes (reloads) the current page. */ refresh(): Promise; /** * Navigates the browser history backwards or forwards. * @param direction - The direction to navigate: `'back'` or `'forward'`. */ backOrForward(direction: 'back' | 'forward'): Promise; /** * Sets the browser viewport to the specified dimensions. * @param width - The viewport width in pixels. * @param height - The viewport height in pixels. */ setViewport(width: number, height: number): Promise; /** * Executes an action that opens a new browser tab/window, waits for it to load, * and returns the new Page object. * @param action - An async function that triggers the new tab (e.g. a click). * @returns The newly opened Page object. */ switchToNewTab(action: () => Promise): Promise; /** * Closes the specified tab (or the current page's tab) and returns the remaining page. * @param targetPage - The page to close. Defaults to the current page. * @returns The page that received focus after closing. */ closeTab(targetPage?: Page): Promise; /** * Returns the number of open tabs/pages in the current browser context. * @returns The count of open pages. */ getTabCount(): number; /** * Clicks on an element identified by page and element name from the repository. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution and click modifiers. */ click(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Clicks a random visible element from a group of elements matching the locator. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options. * @throws Error if no visible element is found for the given locator. */ clickRandom(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Clicks on an element only if it is present in the DOM. * Does nothing and returns false if the element is not found. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ clickIfPresent(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Right-clicks on an element identified by page and element name from the repository. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ rightClick(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Double-clicks on an element identified by page and element name from the repository. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ doubleClick(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Checks a checkbox or radio button. Idempotent. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ check(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Unchecks a checkbox. Idempotent. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ uncheck(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Hovers over an element, triggering any hover-based UI effects. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ hover(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Scrolls the specified element into the visible viewport. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ scrollIntoView(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Clears the input field and fills it with the specified text. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param text - The text to fill into the input field. * @param options - Optional step options for element resolution. */ fill(elementName: string, pageName: string, text: string, options?: StepOptions): Promise; /** * Uploads one or more files to a file input element. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param filePath - Path to the file, or an array of paths for multi-file inputs. * @param options - Optional step options for element resolution. */ uploadFile(elementName: string, pageName: string, filePath: string | string[], options?: StepOptions): Promise; /** * Simulates dropping files onto a drop-zone element by dispatching * `dragenter`, `dragover`, and `drop` events with a populated `DataTransfer`. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param filenames - File name(s) to include in the drop (basename only; no real file is read). * @param options - Optional `mimeType` (default `'application/octet-stream'`) and step options. */ dropFiles(elementName: string, pageName: string, filenames: string[], options?: { mimeType?: string; } & StepOptions): Promise; /** * Selects an option from a `` element by their `value` attributes. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param values - An array of `value` attribute strings to select simultaneously. * @param options - Optional step options for element resolution. * @returns An array of the actually selected `value` strings. */ selectMultiple(elementName: string, pageName: string, values: string[], options?: StepOptions): Promise; /** * Retrieves the visible text content of an element. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. * @returns The text content of the element, or `null` if unavailable. */ getText(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Retrieves the value of a specific HTML attribute from an element. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param attributeName - The name of the attribute to retrieve. * @param options - Optional step options for element resolution. * @returns The attribute value, or `null` if the attribute does not exist. */ getAttribute(elementName: string, pageName: string, attributeName: string, options?: StepOptions): Promise; /** * Returns the number of DOM elements matching the locator. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. * @returns The count of matching elements. */ getCount(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Retrieves the current value of an input, textarea, or select element. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. * @returns The current value of the input. */ getInputValue(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Retrieves a computed CSS property value from an element. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param property - The CSS property name. * @param options - Optional step options for element resolution. * @returns The computed value as a string. */ getCssProperty(elementName: string, pageName: string, property: string, options?: StepOptions): Promise; /** * Returns the element's bounding box (`{ x, y, width, height }` in CSS * pixels, relative to the main frame) or `null` when it is not rendered. * Use for geometry the DOM doesn't surface: overlap, off-screen placement, * collapsed (`0×0`) regions. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ getBoundingBox(elementName: string, pageName: string, options?: StepOptions): Promise<{ x: number; y: number; width: number; height: number; } | null>; /** * Retrieves the raw HTML of an element. Defaults to `innerHTML`; pass * `{ outer: true }` to get the element's `outerHTML` (the tag itself plus its subtree). * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - `outer` switches between innerHTML/outerHTML; other fields control strategy. */ getHtml(elementName: string, pageName: string, options?: StepOptions & { outer?: boolean; }): Promise; /** * Retrieves the HTML of the current page. Defaults to `document.body.innerHTML`; * pass `{ outer: true }` to get the full `` document outerHTML (including ``). * * Use this for page-level scans where no single element is the natural scope — * e.g. confirming an injected payload was HTML-escaped anywhere on the page. */ getPageHtml(options?: { outer?: boolean; }): Promise; /** * Retrieves the rendered text of the current page (`document.body.innerText`). * The text companion to {@link getPageHtml} — use for page-level text * assertions where no single element is the natural scope (e.g. a 404 body). * * @example * ```ts * await steps.navigateTo('/no-such-route'); * expect(await steps.getPageText()).toContain('Page not found'); * ``` */ getPageText(): Promise; /** * Reads a `window`-level value by dotted path — e.g. `'__XSS_FIRED'`, * `'dataLayer.length'`, `'document.title'`. Walks the path key-by-key and * returns `undefined` for any missing segment (never throws on a missing * path). Use to assert window-state the DOM doesn't surface: analytics * layers, injected sentinels, feature flags. * * @example * ```ts * const fired = await steps.getWindowProperty('__XSS_FIRED'); * const n = await steps.getWindowProperty('dataLayer.length'); * const title = await steps.getWindowProperty('document.title'); * ``` */ getWindowProperty(path: string): Promise; /** * Sets a `window`-level value by dotted path, creating intermediate objects * as needed — the mutating companion to {@link getWindowProperty}. Use to * seed window-level state a test depends on. * * @example * ```ts * await steps.setWindowProperty('__test.flag', true); * ``` */ setWindowProperty(path: string, value: unknown): Promise; /** * The SINGLE labelled escape hatch for arbitrary in-page JavaScript: * `page.evaluate(fn, arg)`, typed and logged. This is the LAST RESORT — * prefer the targeted steps (`getWindowProperty`, `verifyWindowProperty`, * the matcher tree, scoped queries) which stay named, retrying, and * grep-able. Reach here only when no targeted step expresses the read. * * @example * ```ts * const links = await steps.evaluateScript(() => document.querySelectorAll('a').length); * ``` */ evaluateScript(fn: (arg?: unknown) => T | Promise, arg?: unknown): Promise; /** * Reads a value from the browser's `window.localStorage`. Returns `null` * when the key is absent — same contract as the native `getItem`. * * Use for state the framework cannot reach through the DOM: persisted * theme preference, dismissed-banner flag, feature toggle, auth tokens, etc. * * @example * ```ts * await steps.click('themeToggle', 'NavBar'); * expect(await steps.getLocalStorage('theme')).toBe('dark'); * ``` */ getLocalStorage(key: string): Promise; /** * Reads a value from the browser's `window.sessionStorage`. Returns `null` * when the key is absent — same contract as the native `getItem`. */ getSessionStorage(key: string): Promise; /** * Returns every key currently set in `window.localStorage`. The enumerating * companion to {@link getLocalStorage} — use when the test needs to know * *which* keys exist (e.g. asserting a logout cleared persisted state) * rather than reading one known key. * * @example * ```ts * await steps.click('logout', 'NavBar'); * expect(await steps.getLocalStorageKeys()).not.toContain('authToken'); * ``` */ getLocalStorageKeys(): Promise; /** * Returns every key currently set in `window.sessionStorage`. The * enumerating companion to {@link getSessionStorage}. */ getSessionStorageKeys(): Promise; /** * Writes a value to the browser's `window.localStorage` — the mutating * companion to {@link getLocalStorage}. Use to seed persisted state a test * depends on, or to drive resilience checks with deliberately malformed * values (e.g. corrupt JSON the app must tolerate). * * @example * ```ts * await steps.setLocalStorage('wishlist', 'not-json-{[bogus'); * await steps.refresh(); * await steps.verifyPresence('wishlistEmptyState', 'WishlistPage'); * ``` */ setLocalStorage(key: string, value: string): Promise; /** * Writes a value to the browser's `window.sessionStorage` — the mutating * companion to {@link getSessionStorage}. */ setSessionStorage(key: string, value: string): Promise; /** * Removes a single key from `window.localStorage` (no-op when absent — * native `removeItem` contract). Use to clear one piece of persisted state * without disturbing the rest. */ removeLocalStorage(key: string): Promise; /** * Removes a single key from `window.sessionStorage` (no-op when absent — * native `removeItem` contract). */ removeSessionStorage(key: string): Promise; /** * Removes every key from `window.localStorage` (native `clear` contract). * Use to reset persisted state between phases of a test. */ clearLocalStorage(): Promise; /** * Removes every key from `window.sessionStorage` (native `clear` contract). */ clearSessionStorage(): Promise; /** * Extracts text content or attribute values from all elements matching the locator. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param getAllOptions - Optional extraction configuration. * @param options - Optional step options for element resolution. * @returns An array of extracted strings. */ getAll(elementName: string, pageName: string, getAllOptions?: GetAllOptions, options?: StepOptions): Promise; /** * Asserts that the element is present and visible in the DOM. * * Equivalent to the fluent form `steps.on(elementName, pageName).verifyPresence()` — * both share the same underlying implementation (the matcher tree). Use whichever * form is more readable in the call site. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. */ verifyPresence(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Asserts that every element in the list is visible in the DOM, running all * checks concurrently. Equivalent to calling `verifyPresence` for each entry * inside a `Promise.all`, but with a single log line and no boilerplate. * * Use this when a test needs to assert the presence of many independent * elements on the same already-loaded page — the parallel resolution * removes the per-step serial overhead without changing the underlying * assertion semantics. * * @param targets - Array of `{ elementName, pageName, options? }` descriptors. * @example * await steps.verifyAllPresent([ * { elementName: 'productTitle', pageName: 'ProductDetailsPage' }, * { elementName: 'productPrice', pageName: 'ProductDetailsPage' }, * { elementName: 'addToCart', pageName: 'ProductDetailsPage' }, * ]); */ verifyAllPresent(targets: Array<{ elementName: string; pageName: string; options?: StepOptions; }>): Promise; /** * Checks whether an element is currently present and visible in the DOM. * Returns a boolean instead of throwing. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options for element resolution. * @returns `true` if the element is visible, `false` otherwise. */ isPresent(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Unified visibility entry point. Returns a `VisibleChain` that is both: * * - **awaitable as `Promise`** — the probe, never throws. Backwards * compatible with the old `isVisible(): Promise` signature — * `await steps.isVisible('banner', 'Page', { timeout: 500 })` still * resolves to a boolean at runtime. * - **chainable with action methods and the matcher tree** — the gate, * silently skips when the element is hidden. Replaces `steps.on(...).ifVisible()`. * * Every probe and gate decision is logged under `tester:visible` with a * `[probe]` or `[gate]` tag so silently-skipped actions stay debuggable. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - `{ timeout?: 2000, containsText?: string }`. * * @example * ```ts * // Probe — returns boolean * const ok = await steps.isVisible('banner', 'Page', { timeout: 500 }); * * // Gate — skips when hidden * await steps.isVisible('cookieBanner', 'Page').click(); * * // Gate + containsText * await steps.isVisible('promo', 'Page', { containsText: '50% off' }).click(); * * // Matcher tree — silently skipped when hidden * await steps.isVisible('banner', 'Page').text.toBe('Hello'); * ``` */ isVisible(elementName: string, pageName: string, options?: IsVisibleOptions): import("./VisibleChain").VisibleChain; /** * Asserts that the element is not present in the DOM. * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param options - Optional step options (strategy not applicable for absence checks). */ verifyAbsence(elementName: string, pageName: string, options?: StepOptions): Promise; /** * Asserts that an element's text content matches the expected value. * * Call with no `expectedText` to assert the element has any non-empty text: * `await steps.verifyText('status', 'Page');` * * Equivalent to the fluent form `steps.on(elementName, pageName).verifyText(expectedText)`. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param expectedText - The exact text to match against. Omit to assert "not empty". * @param verifyOptions - Optional verification options. Passing `{ notEmpty: true }` * is redundant — omit `expectedText` to get the same behavior. The `notEmpty` * flag on `TextVerifyOptions` is itself deprecated. * @param options - Optional step options for element resolution. */ verifyText(elementName: string, pageName: string, expectedText?: string, verifyOptions?: TextVerifyOptions, options?: StepOptions): Promise; /** * Asserts the number of elements matching the locator satisfies the given condition. * * Equivalent to `steps.on(elementName, pageName).verifyCount(countOptions)`. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param countOptions - Count condition. * @param options - Optional step options for element resolution. */ verifyCount(elementName: string, pageName: string, countOptions: CountVerifyOptions, options?: StepOptions): Promise; /** * Asserts that all image elements matching the locator have loaded successfully. * * Equivalent to `steps.on(elementName, pageName).verifyImages(scroll, options)`. * * By default checks visibility, `src` attribute, and non-zero `naturalWidth`. * Pass `{ verifyDecoded: true }` to also run `Image.decode()` per image — * this adds a CDP round-trip per image and is most useful for thoroughness testing * rather than smoke checks. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param scroll - Whether to scroll each image into view before checking. Defaults to `true`. * @param options - Step options for element resolution, plus `verifyDecoded` to run `Image.decode()` per image. */ verifyImages(elementName: string, pageName: string, scroll?: boolean, options?: StepOptions & { verifyDecoded?: boolean; }): Promise; /** * Asserts that an element's text content contains the specified substring. * * Equivalent to `steps.on(elementName, pageName).verifyTextContains(expectedText)`. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param expectedText - The substring expected to be found within the element's text. * @param options - Optional step options for element resolution. */ verifyTextContains(elementName: string, pageName: string, expectedText: string, options?: StepOptions): Promise; /** * Asserts that an element is in the specified state. * * Equivalent to `steps.on(elementName, pageName).verifyState(state)`. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param state - The expected state. * @param timeout - Optional timeout in milliseconds. When omitted, the fixture default is used. */ verifyState(elementName: string, pageName: string, state: 'enabled' | 'disabled' | 'editable' | 'checked' | 'focused' | 'visible' | 'hidden' | 'attached' | 'inViewport', timeout?: number): Promise; /** * Asserts that an element has a specific HTML attribute with the expected value. * * Equivalent to `steps.on(elementName, pageName).verifyAttribute(attributeName, expectedValue)`. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param attributeName - The name of the HTML attribute to check. * @param expectedValue - The expected value of the attribute. * @param options - Optional step options for element resolution. */ verifyAttribute(elementName: string, pageName: string, attributeName: string, expectedValue: string, options?: StepOptions): Promise; /** * Asserts that an element's HTML equals the expected string exactly. * Defaults to `innerHTML`; pass `{ outer: true }` for `outerHTML`. * * Equivalent to `steps.on(elementName, pageName).verifyHtml(expected, htmlOptions)`. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param expected - The expected HTML string. * @param htmlOptions - `outer` switches between innerHTML/outerHTML. * @param options - Optional step options for element resolution. */ verifyHtml(elementName: string, pageName: string, expected: string, htmlOptions?: { outer?: boolean; }, options?: StepOptions): Promise; /** * Asserts that an element's HTML contains the specified substring. * Defaults to `innerHTML`; pass `{ outer: true }` for `outerHTML`. * * Equivalent to `steps.on(elementName, pageName).verifyHtmlContains(substring, htmlOptions)`. * * @param elementName - The element name as defined under the given page. * @param pageName - The page name as defined in `page-repository.json`. * @param substring - The substring expected to appear in the element's HTML. * @param htmlOptions - `outer` switches between innerHTML/outerHTML. * @param options - Optional step options for element resolution. */ verifyHtmlContains(elementName: string, pageName: string, substring: string, htmlOptions?: { outer?: boolean; }, options?: StepOptions): Promise; /** * Asserts that an element's HTML matches a regular expression. * Defaults to `innerHTML`; pass `{ outer: true }` for `outerHTML`. * * Equivalent to `steps.on(elementName, pageName).verifyHtmlMatches(regex, htmlOptions)`. */ verifyHtmlMatches(elementName: string, pageName: string, regex: RegExp, htmlOptions?: { outer?: boolean; }, options?: StepOptions): Promise; /** * Asserts that the page-level HTML equals the expected string exactly. * Defaults to `document.body.innerHTML`; pass `{ outer: true }` for the full * `` document outerHTML. * * @param expected - The expected HTML string. * @param options - `outer` switches between body.innerHTML / documentElement.outerHTML; * `negated` flips the assertion; `timeout` overrides the default; `errorMessage` adds a header. */ verifyPageHtml(expected: string, options?: { outer?: boolean; negated?: boolean; timeout?: number; errorMessage?: string; }): Promise; /** * Asserts that the page-level HTML contains the specified substring. * Defaults to `document.body.innerHTML`; pass `{ outer: true }` for the full document outerHTML. * * Use this to confirm an injected payload appears unescaped (`negated: false`) * or was correctly escaped (`negated: true`) anywhere on the rendered page. * * @example * ```ts * // XSS probe — payload must NOT appear raw in rendered HTML * await steps.verifyPageHtmlContains('', { negated: true }); * ``` */ verifyPageHtmlContains(substring: string, options?: { outer?: boolean; negated?: boolean; timeout?: number; errorMessage?: string; }): Promise; /** * Asserts that the page-level HTML matches a regular expression. * Defaults to `document.body.innerHTML`; pass `{ outer: true }` for the full document outerHTML. */ verifyPageHtmlMatches(regex: RegExp, options?: { outer?: boolean; negated?: boolean; timeout?: number; errorMessage?: string; }): Promise; /** * Asserts a property of `localStorage[key]`. Pick one matcher: `equals` * (exact match), `contains` (substring), `matches` (regex), or `present` * (existence). The chosen matcher is enforced at the type level by the * `StorageVerifyOptions` discriminated union — passing two is a type error. * * Polls until the predicate holds or the timeout expires, so this survives * the race between a UI action firing and its persistence side-effect. * * @example * ```ts * await steps.verifyLocalStorage('theme', { equals: 'dark' }); * await steps.verifyLocalStorage('flag', { contains: 'enabled' }); * await steps.verifyLocalStorage('build', { matches: /^v\d+$/ }); * await steps.verifyLocalStorage('seen', { present: true }); * await steps.verifyLocalStorage('seen', { present: false }); // absence * await steps.verifyLocalStorage('seen', { present: true, negated: true }); // same * ``` */ verifyLocalStorage(key: string, options: StorageVerifyOptions): Promise; /** See `verifyLocalStorage` — same matcher shape, against `window.sessionStorage`. */ verifySessionStorage(key: string, options: StorageVerifyOptions): Promise; /** Single dispatcher for `verifyLocalStorage` / `verifySessionStorage`. */ private verifyStorage; /** * Retrying assertion over a `window`-level value read by dotted path. Pick * EXACTLY ONE matcher in the `WindowVerifyOptions` union: `equals` | * `contains` | `matches` (RegExp) | `present` (boolean) | `truthy` (boolean) * | `greaterThan` | `lessThan`. Supports `{ negated?, timeout?, errorMessage? }` * modifiers, exactly like the storage verifiers. Polls until the predicate * holds (or its negation) or the timeout expires. * * @example * ```ts * await steps.verifyWindowProperty('dataLayer.length', { greaterThan: 0 }); * await steps.verifyWindowProperty('__test.flag', { equals: true }); * await steps.verifyWindowProperty('__XSS_FIRED', { present: false }); * await steps.verifyWindowProperty('document.title', { matches: /Vue/i }); * ``` */ verifyWindowProperty(path: string, options: WindowVerifyOptions): Promise; /** Session-aware `GET`. Shares the browser context's cookies. */ requestGet(url: string, opts?: BrowserRequestOptions): Promise; /** Session-aware `POST`. Shares the browser context's cookies. */ requestPost(url: string, opts?: BrowserRequestOptions): Promise; /** Session-aware `PUT`. Shares the browser context's cookies. */ requestPut(url: string, opts?: BrowserRequestOptions): Promise; /** Session-aware `PATCH`. Shares the browser context's cookies. */ requestPatch(url: string, opts?: BrowserRequestOptions): Promise; /** Session-aware `DELETE`. Shares the browser context's cookies. */ requestDelete(url: string, opts?: BrowserRequestOptions): Promise; /** Session-aware `HEAD`. Shares the browser context's cookies. */ requestHead(url: string, opts?: BrowserRequestOptions): Promise; /** * Asserts a {@link BrowserResponse}'s status equals `code`. Simple throw * helper — not a retrying assertion (the response is already resolved). */ verifyRequestStatus(res: BrowserResponse, code: number): Promise; /** * Asserts a {@link BrowserResponse} carries a header. Name match is * case-insensitive (header names are, per RFC 9110). When `value` is * omitted, asserts presence only; a string asserts exact equality — * header VALUES are case-sensitive (ETags, redirect Location paths, * nonces), matching `verifyApiHeader`; use a RegExp with the `i` flag * for case-insensitive matching. */ verifyRequestHeader(res: BrowserResponse, name: string, value?: string | RegExp): Promise; /** Asserts a {@link BrowserResponse} is a 2xx success. Simple throw helper. */ verifyRequestOk(res: BrowserResponse): Promise; /** * Asserts that the current page URL contains the specified substring. * @param text - The substring expected to be found in the current URL. */ verifyUrlContains(text: string): Promise; /** * Asserts the document body contains the given text — the page-level mirror * of {@link verifyTextContains}. Accepts a substring or a RegExp and retries * with web-first semantics until the body matches or the timeout expires. * * Use for page-wide copy checks where no single element is the natural scope * (a flash message anywhere on the page, a "404 / niet gevonden" body, etc.). * * @param text - Substring or RegExp expected somewhere in the rendered body text. * @param options - `{ timeout?, errorMessage? }`. * @example * ```ts * await steps.verifyPageContainsText('Wishlist'); * await steps.verifyPageContainsText(/404|niet gevonden/i); * ``` */ verifyPageContainsText(text: string | RegExp, options?: { timeout?: number; errorMessage?: string; }): Promise; /** * Asserts the document body does NOT contain the given text — the negated * companion to {@link verifyPageContainsText}. Use for "not a 404" / * no-error-copy body checks. * * NOTE: this is a TEXT-level check (`toContainText` reads rendered text), * so it can never see raw markup — injected `