/** * Matching controls on Google's own pages by accessible role and name. * * Google's pages carry no stable test ids, so every browser-driven step in * this module matches controls by accessible role and name. This is the single * most brittle part of the whole integration, so a miss is designed to fail * loudly and specifically, "looked for a button named X, the page showed * these N controls instead", rather than silently clicking the wrong thing. * * Nothing here drives a browser. The flows are written against * `GoogleBrowserPort` (see `types.ts`), a six-method surface a product * implements over whatever automation it actually has: one product supplies a * Playwright-backed implementation, a test supplies a fake page, and neither * is visible from here. That is what makes the console walkthrough, the * app-password page and the calendar-settings page all runnable with no * browser at all. * * One honest limitation carried over from the first implementation: an * accessibility snapshot does not always report the DOM tag name of an * element, so `tag` on a `GoogleBrowserElement` may be a best-effort guess * derived from the accessible role (see `deriveTagFromRole`). Every flow * matches by role and name; `tag` in a `GoogleElementQuery` is an optional * extra filter, never load-bearing. */ import type { GoogleBrowserElement } from './types.js'; export interface GoogleElementQuery { readonly role?: string; readonly nameIncludes?: string; readonly namePattern?: RegExp; readonly tag?: string; } /** The first element in `elements` matching every part of `query`, or null. */ export declare function findElement(elements: readonly GoogleBrowserElement[], query: GoogleElementQuery): GoogleBrowserElement | null; /** A short, human-readable listing of elements actually present, for diagnostics. */ export declare function describeElements(elements: readonly GoogleBrowserElement[], limit?: number): string; export interface GoogleElementFound { readonly found: true; readonly element: GoogleBrowserElement; } export interface GoogleElementNotFound { readonly found: false; readonly query: GoogleElementQuery; readonly candidateCount: number; /** Plain-language failure statement: what was looked for, what was there instead. */ readonly message: string; } export type GoogleElementLookup = GoogleElementFound | GoogleElementNotFound; /** * Like `findElement`, but the miss carries a typed, descriptive result instead * of `null`, the failure mode this module exists to make impossible to get * wrong silently. */ export declare function requireElement(elements: readonly GoogleBrowserElement[], query: GoogleElementQuery): GoogleElementLookup; /** * True when the page looks like Google's sign-in flow rather than the page * the flow expected: either the url landed on accounts.google.com's sign-in * route, or the snapshot shows an actual password input (the redirect * sometimes keeps the original url briefly, so the url check alone is not * sufficient). * * The password-field check is deliberately scoped to `role: 'textbox'` * (a real input) rather than matching "password" anywhere in any element's * name, Google's own pages routinely use the word in headings and buttons * ("App passwords", "Create app password"), and matching those would * misreport a normal page as a sign-in redirect. */ export declare function looksLikeGoogleSignIn(url: string, elements: readonly GoogleBrowserElement[]): boolean; /** * The shared role-to-tag guess. * * Exported because every `GoogleBrowserPort` implementation faces the same * problem, an accessibility snapshot reports a role, not a tag, and the * guess should be one shared answer rather than re-invented per surface. * Returns `'div'` for any role with no better guess. */ export declare function deriveTagFromRole(role: string): string; //# sourceMappingURL=browser-elements.d.ts.map