@quitecode/chromium-automaton 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/browser/ChromiumManager.ts","../src/logging/Logger.ts","../src/core/Events.ts","../src/cdp/Connection.ts","../src/cdp/Session.ts","../src/core/Page.ts","../src/core/Waiter.ts","../src/core/Selectors.ts","../src/core/ShadowDom.ts","../src/core/Locator.ts","../src/core/Frame.ts","../src/core/UrlGuard.ts","../src/core/Browser.ts","../src/browser/Downloader.ts","../src/browser/Revision.ts","../src/cli.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport http from \"http\";\nimport { spawn } from \"child_process\";\nimport { Logger, LogLevel } from \"../logging/Logger.js\";\nimport { AutomationEvents } from \"../core/Events.js\";\nimport { Connection } from \"../cdp/Connection.js\";\nimport { Browser } from \"../core/Browser.js\";\nimport { detectPlatform, defaultCacheRoot, ensureDownloaded, fetchLatestRevision, Platform, chromiumVersion } from \"./Downloader.js\";\nimport { resolveRevision } from \"./Revision.js\";\n\nexport type LaunchOptions = {\n headless?: boolean;\n args?: string[];\n timeoutMs?: number;\n logLevel?: LogLevel;\n executablePath?: string;\n};\n\nexport type DownloadOptions = {\n latest?: boolean;\n};\n\nexport type ResolvedDownload = {\n cacheRoot: string;\n platform: Platform;\n revision: string;\n executablePath: string;\n revisionDir: string;\n chromiumVersion?: string;\n};\n\nexport class ChromiumManager {\n private logger: Logger;\n\n constructor(logger?: Logger) {\n const envLevel = (process.env.CHROMIUM_AUTOMATON_LOG_LEVEL as LogLevel | undefined) ?? \"info\";\n this.logger = logger ?? new Logger(envLevel);\n }\n\n getLogger() {\n return this.logger;\n }\n\n async download(options: DownloadOptions = {}): Promise<ResolvedDownload> {\n const platform = detectPlatform();\n const cacheRoot = this.resolveCacheRoot(platform);\n const overrideExecutable = process.env.CHROMIUM_AUTOMATON_EXECUTABLE_PATH;\n let revision = options.latest ? await fetchLatestRevision(platform) : resolveRevision(process.env.CHROMIUM_AUTOMATON_REVISION);\n let executablePath: string;\n let revisionDir = \"\";\n if (overrideExecutable) {\n executablePath = path.resolve(overrideExecutable);\n } else {\n const downloaded = await ensureDownloaded({\n cacheRoot,\n platform,\n revision,\n logger: this.logger\n });\n executablePath = downloaded.executablePath;\n revisionDir = downloaded.revisionDir;\n }\n\n if (!fs.existsSync(executablePath)) {\n throw new Error(`Chromium executable not found: ${executablePath}`);\n }\n\n const version = await chromiumVersion(executablePath);\n\n this.logger.info(\"Chromium cache root\", cacheRoot);\n this.logger.info(\"Platform\", platform);\n this.logger.info(\"Revision\", revision);\n this.logger.info(\"Chromium version\", version);\n\n return {\n cacheRoot,\n platform,\n revision,\n executablePath,\n revisionDir,\n chromiumVersion: version\n };\n }\n\n async launch(options: LaunchOptions = {}) {\n const logger = this.logger;\n if (options.logLevel) {\n logger.setLevel(options.logLevel);\n }\n\n const executablePath = options.executablePath || process.env.CHROMIUM_AUTOMATON_EXECUTABLE_PATH;\n let resolvedExecutable = executablePath;\n if (!resolvedExecutable) {\n const platform = detectPlatform();\n const cacheRoot = this.resolveCacheRoot(platform);\n const revision = resolveRevision(process.env.CHROMIUM_AUTOMATON_REVISION);\n const downloaded = await ensureDownloaded({\n cacheRoot,\n platform,\n revision,\n logger\n });\n resolvedExecutable = downloaded.executablePath;\n }\n\n if (!resolvedExecutable || !fs.existsSync(resolvedExecutable)) {\n throw new Error(`Chromium executable not found: ${resolvedExecutable}`);\n }\n const stats = fs.statSync(resolvedExecutable);\n if (!stats.isFile()) {\n throw new Error(`Chromium executable is not a file: ${resolvedExecutable}`);\n }\n ensureExecutable(resolvedExecutable);\n\n const args = [\n \"--remote-debugging-port=0\",\n \"--no-first-run\",\n \"--no-default-browser-check\",\n \"--disable-background-networking\",\n \"--disable-background-timer-throttling\",\n \"--disable-backgrounding-occluded-windows\",\n \"--disable-renderer-backgrounding\"\n ];\n if (process.platform === \"linux\") {\n args.push(\"--disable-crash-reporter\", \"--disable-crashpad\");\n }\n if (options.headless ?? true) {\n args.push(\"--headless=new\");\n }\n if (options.args) {\n args.push(...options.args);\n }\n\n logger.info(\"Launching Chromium\", resolvedExecutable);\n const child = spawn(resolvedExecutable, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\n const websocketUrl = await waitForWebSocketEndpoint(child, logger, options.timeoutMs ?? 30_000);\n const httpUrl = toHttpVersionUrl(websocketUrl);\n const wsEndpoint = await fetchWebSocketDebuggerUrl(httpUrl);\n\n const connection = new Connection(wsEndpoint, logger);\n const events = new AutomationEvents();\n const browser = new Browser(connection, child, logger, events);\n\n return browser;\n }\n\n private resolveCacheRoot(platform: Platform) {\n const envRoot = process.env.CHROMIUM_AUTOMATON_CACHE_DIR;\n if (envRoot && envRoot.trim()) {\n return path.resolve(envRoot.trim());\n }\n return defaultCacheRoot(platform);\n }\n}\n\nfunction ensureExecutable(executablePath: string) {\n if (process.platform === \"win32\") {\n return;\n }\n try {\n const stat = fs.statSync(executablePath);\n const isExecutable = (stat.mode & 0o111) !== 0;\n if (!isExecutable) {\n fs.chmodSync(executablePath, 0o755);\n }\n } catch {\n // ignore chmod errors\n }\n\n const dir = path.dirname(executablePath);\n const helpers = [\n \"chrome_crashpad_handler\",\n \"chrome_sandbox\",\n \"chrome-wrapper\",\n \"xdg-mime\",\n \"xdg-settings\"\n ];\n for (const name of helpers) {\n const helperPath = path.join(dir, name);\n if (!fs.existsSync(helperPath)) {\n continue;\n }\n try {\n const stat = fs.statSync(helperPath);\n const isExecutable = (stat.mode & 0o111) !== 0;\n if (!isExecutable) {\n fs.chmodSync(helperPath, 0o755);\n }\n } catch {\n // ignore chmod errors\n }\n }\n}\n\nfunction waitForWebSocketEndpoint(child: ReturnType<typeof spawn>, logger: Logger, timeoutMs: number): Promise<string> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n const timeout = setTimeout(() => {\n reject(new Error(\"Timed out waiting for DevTools endpoint\"));\n }, timeoutMs);\n\n const outputLines: string[] = [];\n const pushOutput = (data: Buffer) => {\n const text = data.toString();\n for (const line of text.split(/\\r?\\n/)) {\n if (!line.trim()) continue;\n outputLines.push(line);\n if (outputLines.length > 50) {\n outputLines.shift();\n }\n }\n };\n\n const onData = (data: Buffer) => {\n const text = data.toString();\n const match = text.match(/DevTools listening on (ws:\\/\\/[^\\s]+)/);\n if (match) {\n clearTimeout(timeout);\n cleanup();\n logger.info(\"DevTools endpoint\", match[1]);\n resolve(match[1]);\n }\n pushOutput(data);\n };\n\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n cleanup();\n const tail = outputLines.length ? `\\nChromium output:\\n${outputLines.join(\"\\n\")}` : \"\";\n reject(new Error(`Chromium exited early with code ${code ?? \"null\"} signal ${signal ?? \"null\"}${tail}`));\n };\n\n const cleanup = () => {\n child.stdout?.off(\"data\", onData);\n child.stderr?.off(\"data\", onData);\n child.off(\"exit\", onExit);\n };\n\n child.stdout?.on(\"data\", onData);\n child.stderr?.on(\"data\", onData);\n child.on(\"exit\", onExit);\n\n if (Date.now() - start > timeoutMs) {\n cleanup();\n }\n });\n}\n\nfunction toHttpVersionUrl(wsUrl: string) {\n try {\n const url = new URL(wsUrl);\n const port = url.port || \"9222\";\n return `http://127.0.0.1:${port}/json/version`;\n } catch {\n throw new Error(`Invalid DevTools endpoint: ${wsUrl}`);\n }\n}\n\nfunction fetchWebSocketDebuggerUrl(versionUrl: string): Promise<string> {\n return new Promise((resolve, reject) => {\n http.get(versionUrl, (res) => {\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`Failed to fetch /json/version: ${res.statusCode}`));\n return;\n }\n let data = \"\";\n res.on(\"data\", (chunk) => (data += chunk.toString()));\n res.on(\"end\", () => {\n try {\n const parsed = JSON.parse(data);\n if (!parsed.webSocketDebuggerUrl) {\n reject(new Error(\"webSocketDebuggerUrl missing\"));\n return;\n }\n resolve(parsed.webSocketDebuggerUrl);\n } catch (err) {\n reject(err);\n }\n });\n }).on(\"error\", reject);\n });\n}\n","export type LogLevel = \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\";\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n trace: 4\n};\n\nconst REDACT_KEYS = [\"password\", \"token\", \"secret\", \"authorization\", \"cookie\"];\n\nfunction redactValue(value: unknown): string {\n if (typeof value === \"string\") {\n try {\n const url = new URL(value);\n if (url.search) {\n url.search = \"?redacted\";\n }\n return url.toString();\n } catch {\n return value;\n }\n }\n if (value && typeof value === \"object\") {\n return JSON.stringify(value, (key, val) => {\n if (REDACT_KEYS.some((k) => key.toLowerCase().includes(k))) {\n return \"[redacted]\";\n }\n return val;\n });\n }\n return String(value);\n}\n\nexport class Logger {\n private level: LogLevel;\n\n constructor(level: LogLevel = \"info\") {\n this.level = level;\n }\n\n setLevel(level: LogLevel) {\n this.level = level;\n }\n\n error(message: string, ...args: unknown[]) {\n this.log(\"error\", message, ...args);\n }\n\n warn(message: string, ...args: unknown[]) {\n this.log(\"warn\", message, ...args);\n }\n\n info(message: string, ...args: unknown[]) {\n this.log(\"info\", message, ...args);\n }\n\n debug(message: string, ...args: unknown[]) {\n this.log(\"debug\", message, ...args);\n }\n\n trace(message: string, ...args: unknown[]) {\n this.log(\"trace\", message, ...args);\n }\n\n log(level: LogLevel, message: string, ...args: unknown[]) {\n if (LEVEL_ORDER[level] > LEVEL_ORDER[this.level]) {\n return;\n }\n const time = new Date().toISOString();\n const suffix = args.length ? \" \" + args.map(redactValue).join(\" \") : \"\";\n const line = `[${time}] [${level}] ${message}${suffix}`;\n if (level === \"error\") {\n console.error(line);\n } else if (level === \"warn\") {\n console.warn(line);\n } else {\n console.log(line);\n }\n }\n}\n","import { EventEmitter } from \"events\";\n\nexport type ActionEvent = {\n name: string;\n selector?: string;\n frameId?: string;\n durationMs?: number;\n};\n\nexport type AssertionEvent = {\n name: string;\n selector?: string;\n frameId?: string;\n durationMs?: number;\n};\n\nexport type AutomationEventMap = {\n \"action:start\": ActionEvent;\n \"action:end\": ActionEvent;\n \"assertion:start\": AssertionEvent;\n \"assertion:end\": AssertionEvent;\n};\n\nexport class AutomationEvents {\n private emitter = new EventEmitter();\n\n on<K extends keyof AutomationEventMap>(event: K, handler: (payload: AutomationEventMap[K]) => void) {\n this.emitter.on(event, handler);\n }\n\n off<K extends keyof AutomationEventMap>(event: K, handler: (payload: AutomationEventMap[K]) => void) {\n this.emitter.off(event, handler);\n }\n\n emit<K extends keyof AutomationEventMap>(event: K, payload: AutomationEventMap[K]) {\n this.emitter.emit(event, payload);\n }\n}\n","import WebSocket from \"ws\";\nimport { EventEmitter } from \"events\";\nimport { Logger } from \"../logging/Logger.js\";\nimport { Session } from \"./Session.js\";\n\nexport type CDPResponse = {\n id: number;\n result?: unknown;\n error?: { message: string; data?: unknown };\n sessionId?: string;\n};\n\nexport type CDPEvent = {\n method: string;\n params?: unknown;\n sessionId?: string;\n};\n\nexport class Connection {\n private ws: WebSocket;\n private id = 0;\n private callbacks = new Map<number, { resolve: (value: unknown) => void; reject: (reason?: unknown) => void; method: string; start: number }>();\n private sessions = new Map<string, Session>();\n private emitter = new EventEmitter();\n private logger: Logger;\n\n constructor(url: string, logger: Logger) {\n this.logger = logger;\n this.ws = new WebSocket(url);\n this.ws.on(\"message\", (data: WebSocket.RawData) => this.onMessage(data.toString()));\n this.ws.on(\"error\", (err: Error) => this.onError(err));\n }\n\n async waitForOpen() {\n if (this.ws.readyState === WebSocket.OPEN) {\n return;\n }\n await new Promise<void>((resolve, reject) => {\n this.ws.once(\"open\", () => resolve());\n this.ws.once(\"error\", (err: Error) => reject(err));\n });\n }\n\n createSession(sessionId: string): Session {\n const session = new Session(this, sessionId);\n this.sessions.set(sessionId, session);\n return session;\n }\n\n removeSession(sessionId: string) {\n this.sessions.delete(sessionId);\n }\n\n on(event: string, handler: (params: unknown) => void) {\n this.emitter.on(event, handler);\n }\n\n async send<T = unknown>(method: string, params: Record<string, unknown> = {}, sessionId?: string): Promise<T> {\n await this.waitForOpen();\n const id = ++this.id;\n const payload = sessionId ? { id, method, params, sessionId } : { id, method, params };\n const start = Date.now();\n const promise = new Promise<T>((resolve, reject) => {\n this.callbacks.set(id, { resolve: resolve as (value: unknown) => void, reject, method, start });\n });\n if (this.logger) {\n this.logger.trace(\"CDP send\", method);\n }\n this.ws.send(JSON.stringify(payload));\n return promise;\n }\n\n async close() {\n if (this.ws.readyState === WebSocket.CLOSED) {\n return;\n }\n await new Promise<void>((resolve) => {\n this.ws.once(\"close\", () => resolve());\n this.ws.close();\n });\n }\n\n private onError(err: unknown) {\n this.logger.error(\"CDP socket error\", err);\n }\n\n private onMessage(message: string) {\n const parsed = JSON.parse(message) as CDPResponse & CDPEvent;\n if (typeof parsed.id === \"number\") {\n const callback = this.callbacks.get(parsed.id);\n if (!callback) {\n return;\n }\n this.callbacks.delete(parsed.id);\n const duration = Date.now() - callback.start;\n this.logger.debug(\"CDP recv\", callback.method, `${duration}ms`);\n if (parsed.error) {\n callback.reject(new Error(parsed.error.message));\n } else {\n callback.resolve(parsed.result);\n }\n return;\n }\n\n if (parsed.sessionId) {\n const session = this.sessions.get(parsed.sessionId);\n if (session) {\n session.dispatch(parsed.method, parsed.params);\n }\n return;\n }\n\n if (parsed.method) {\n this.emitter.emit(parsed.method, parsed.params);\n }\n }\n}\n","import { EventEmitter } from \"events\";\nimport { Connection } from \"./Connection.js\";\n\nexport class Session {\n private connection: Connection;\n private sessionId: string;\n private emitter = new EventEmitter();\n\n constructor(connection: Connection, sessionId: string) {\n this.connection = connection;\n this.sessionId = sessionId;\n }\n\n on(event: string, handler: (params: unknown) => void) {\n this.emitter.on(event, handler);\n }\n\n once(event: string, handler: (params: unknown) => void) {\n this.emitter.once(event, handler);\n }\n\n async send<T = unknown>(method: string, params: Record<string, unknown> = {}): Promise<T> {\n return this.connection.send<T>(method, params, this.sessionId);\n }\n\n dispatch(method: string, params: unknown) {\n this.emitter.emit(method, params);\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { Session } from \"../cdp/Session.js\";\nimport { Logger } from \"../logging/Logger.js\";\nimport { AutomationEvents } from \"./Events.js\";\nimport { Frame } from \"./Frame.js\";\nimport { Locator } from \"./Locator.js\";\nimport { ensureAllowedUrl } from \"./UrlGuard.js\";\n\nexport type GotoOptions = {\n waitUntil?: \"domcontentloaded\" | \"load\";\n timeoutMs?: number;\n allowFileUrl?: boolean;\n};\n\nexport type ScreenshotOptions = {\n path?: string;\n format?: \"png\" | \"jpeg\";\n quality?: number;\n};\n\nexport class Page {\n private session: Session;\n private logger: Logger;\n private events: AutomationEvents;\n private framesById = new Map<string, Frame>();\n private mainFrameId?: string;\n private lifecycleEvents = new Map<string, Set<string>>();\n private defaultTimeout = 30_000;\n\n constructor(session: Session, logger: Logger, events: AutomationEvents) {\n this.session = session;\n this.logger = logger;\n this.events = events;\n }\n\n async initialize() {\n await this.session.send(\"Page.enable\");\n await this.session.send(\"DOM.enable\");\n await this.session.send(\"Runtime.enable\");\n await this.session.send(\"Network.enable\");\n await this.session.send(\"Page.setLifecycleEventsEnabled\", { enabled: true });\n\n this.session.on(\"Page.frameAttached\", (params) => this.onFrameAttached(params as any));\n this.session.on(\"Page.frameNavigated\", (params) => this.onFrameNavigated(params as any));\n this.session.on(\"Page.frameDetached\", (params) => this.onFrameDetached(params as any));\n this.session.on(\"Runtime.executionContextCreated\", (params) => this.onExecutionContextCreated(params as any));\n this.session.on(\"Runtime.executionContextDestroyed\", (params) => this.onExecutionContextDestroyed(params as any));\n this.session.on(\"Runtime.executionContextsCleared\", () => this.onExecutionContextsCleared());\n this.session.on(\"Page.lifecycleEvent\", (params) => this.onLifecycleEvent(params as any));\n\n const tree = await this.session.send<{ frameTree: { frame: { id: string; name?: string; url?: string; parentId?: string }; childFrames?: any[] } }>(\"Page.getFrameTree\");\n this.buildFrameTree(tree.frameTree);\n }\n\n frames() {\n return Array.from(this.framesById.values());\n }\n\n mainFrame() {\n if (!this.mainFrameId) {\n throw new Error(\"Main frame not initialized\");\n }\n const frame = this.framesById.get(this.mainFrameId);\n if (!frame) {\n throw new Error(\"Main frame missing\");\n }\n return frame;\n }\n\n frame(options: { name?: string; urlIncludes?: string; predicate?: (frame: Frame) => boolean }) {\n for (const frame of this.framesById.values()) {\n if (options.name && frame.name !== options.name) continue;\n if (options.urlIncludes && !frame.url?.includes(options.urlIncludes)) continue;\n if (options.predicate && !options.predicate(frame)) continue;\n return frame;\n }\n return null;\n }\n\n locator(selector: string, options?: { pierceShadowDom?: boolean }) {\n return new Locator(this.mainFrame(), selector, options);\n }\n\n async goto(url: string, options: GotoOptions = {}) {\n ensureAllowedUrl(url, { allowFileUrl: options.allowFileUrl });\n const waitUntil = options.waitUntil ?? \"load\";\n const lifecycleName = waitUntil === \"domcontentloaded\" ? \"DOMContentLoaded\" : \"load\";\n const timeoutMs = options.timeoutMs ?? this.defaultTimeout;\n\n this.events.emit(\"action:start\", { name: \"goto\", selector: url, frameId: this.mainFrameId });\n const start = Date.now();\n await this.session.send(\"Page.navigate\", { url });\n await this.waitForLifecycle(this.mainFrameId, lifecycleName, timeoutMs);\n const duration = Date.now() - start;\n this.events.emit(\"action:end\", { name: \"goto\", selector: url, frameId: this.mainFrameId, durationMs: duration });\n this.logger.info(\"Goto\", url, `${duration}ms`);\n }\n\n async query(selector: string, options?: { pierceShadowDom?: boolean }) {\n return this.mainFrame().query(selector, options);\n }\n\n async queryAll(selector: string, options?: { pierceShadowDom?: boolean }) {\n return this.mainFrame().queryAll(selector, options);\n }\n\n async queryXPath(selector: string, options?: { pierceShadowDom?: boolean }) {\n return this.mainFrame().queryXPath(selector, options);\n }\n\n async queryAllXPath(selector: string, options?: { pierceShadowDom?: boolean }) {\n return this.mainFrame().queryAllXPath(selector, options);\n }\n\n async click(selector: string, options?: { pierceShadowDom?: boolean; timeoutMs?: number }) {\n return this.mainFrame().click(selector, options);\n }\n\n async dblclick(selector: string, options?: { pierceShadowDom?: boolean; timeoutMs?: number }) {\n return this.mainFrame().dblclick(selector, options);\n }\n\n async type(selector: string, text: string, options?: { pierceShadowDom?: boolean; timeoutMs?: number }) {\n return this.mainFrame().type(selector, text, options);\n }\n\n async evaluate<T = unknown>(fnOrString: string | ((...args: any[]) => any), ...args: any[]): Promise<T> {\n return this.mainFrame().evaluate(fnOrString, ...args);\n }\n\n async screenshot(options: ScreenshotOptions = {}) {\n const start = Date.now();\n this.events.emit(\"action:start\", { name: \"screenshot\", frameId: this.mainFrameId });\n const result = await this.session.send<{ data: string }>(\"Page.captureScreenshot\", {\n format: options.format ?? \"png\",\n quality: options.quality,\n fromSurface: true\n });\n const buffer = Buffer.from(result.data, \"base64\");\n if (options.path) {\n const resolved = path.resolve(options.path);\n fs.writeFileSync(resolved, buffer);\n }\n const duration = Date.now() - start;\n this.events.emit(\"action:end\", { name: \"screenshot\", frameId: this.mainFrameId, durationMs: duration });\n return buffer;\n }\n\n async screenshotBase64(options: Omit<ScreenshotOptions, \"path\"> = {}) {\n const start = Date.now();\n this.events.emit(\"action:start\", { name: \"screenshotBase64\", frameId: this.mainFrameId });\n const result = await this.session.send<{ data: string }>(\"Page.captureScreenshot\", {\n format: options.format ?? \"png\",\n quality: options.quality,\n fromSurface: true\n });\n const duration = Date.now() - start;\n this.events.emit(\"action:end\", { name: \"screenshotBase64\", frameId: this.mainFrameId, durationMs: duration });\n return result.data;\n }\n\n getEvents() {\n return this.events;\n }\n\n getDefaultTimeout() {\n return this.defaultTimeout;\n }\n\n private buildFrameTree(tree: { frame: { id: string; name?: string; url?: string; parentId?: string }; childFrames?: any[] }) {\n const frame = this.ensureFrame(tree.frame.id);\n frame.setMeta({ name: tree.frame.name, url: tree.frame.url, parentId: tree.frame.parentId });\n if (!tree.frame.parentId) {\n this.mainFrameId = tree.frame.id;\n }\n if (tree.childFrames) {\n for (const child of tree.childFrames) {\n this.buildFrameTree(child);\n }\n }\n }\n\n private ensureFrame(id: string) {\n let frame = this.framesById.get(id);\n if (!frame) {\n frame = new Frame(id, this.session, this.logger, this.events);\n this.framesById.set(id, frame);\n }\n return frame;\n }\n\n private onFrameAttached(params: { frameId: string; parentFrameId?: string }) {\n const frame = this.ensureFrame(params.frameId);\n frame.setMeta({ parentId: params.parentFrameId });\n }\n\n private onFrameNavigated(params: { frame: { id: string; name?: string; url?: string; parentId?: string } }) {\n const frame = this.ensureFrame(params.frame.id);\n frame.setMeta({ name: params.frame.name, url: params.frame.url, parentId: params.frame.parentId });\n if (!params.frame.parentId) {\n this.mainFrameId = params.frame.id;\n }\n }\n\n private onFrameDetached(params: { frameId: string }) {\n this.framesById.delete(params.frameId);\n }\n\n private onExecutionContextCreated(params: { context: { id: number; auxData?: { frameId?: string } } }) {\n const frameId = params.context.auxData?.frameId;\n if (!frameId) {\n return;\n }\n const frame = this.ensureFrame(frameId);\n frame.setExecutionContext(params.context.id);\n }\n\n private onExecutionContextDestroyed(params: { executionContextId: number }) {\n for (const frame of this.framesById.values()) {\n if (frame.getExecutionContext() === params.executionContextId) {\n frame.setExecutionContext(undefined);\n }\n }\n }\n\n private onExecutionContextsCleared() {\n for (const frame of this.framesById.values()) {\n frame.setExecutionContext(undefined);\n }\n }\n\n private onLifecycleEvent(params: { frameId: string; name: string }) {\n if (!this.lifecycleEvents.has(params.frameId)) {\n this.lifecycleEvents.set(params.frameId, new Set());\n }\n this.lifecycleEvents.get(params.frameId)!.add(params.name);\n }\n\n private async waitForLifecycle(frameId: string | undefined, eventName: string, timeoutMs: number) {\n if (!frameId) {\n throw new Error(\"Missing frame id for lifecycle wait\");\n }\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const events = this.lifecycleEvents.get(frameId);\n if (events && events.has(eventName)) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n throw new Error(`Timeout waiting for lifecycle event: ${eventName}`);\n }\n}\n","export type WaitForOptions = {\n timeoutMs?: number;\n intervalMs?: number;\n description?: string;\n};\n\nexport async function waitFor<T>(predicate: () => Promise<T> | T, options: WaitForOptions = {}): Promise<NonNullable<T>> {\n const timeoutMs = options.timeoutMs ?? 30_000;\n const intervalMs = options.intervalMs ?? 100;\n const start = Date.now();\n\n let lastError: unknown;\n while (Date.now() - start < timeoutMs) {\n try {\n const result = await predicate();\n if (result) {\n return result as NonNullable<T>;\n }\n } catch (err) {\n lastError = err;\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n\n const description = options.description ? ` (${options.description})` : \"\";\n const error = new Error(`Timeout after ${timeoutMs}ms${description}`);\n (error as Error & { cause?: unknown }).cause = lastError;\n throw error;\n}\n","export type SelectorType = \"css\" | \"xpath\";\n\nexport type ParsedSelector = {\n type: SelectorType;\n value: string;\n};\n\nfunction isXPathSelector(input: string): boolean {\n if (input.startsWith(\"/\")) return true;\n if (input.startsWith(\"./\")) return true;\n if (input.startsWith(\".//\")) return true;\n if (input.startsWith(\"..\")) return true;\n if (input.startsWith(\"(\")) {\n const trimmed = input.trimStart();\n if (trimmed.startsWith(\"(\")) {\n const inner = trimmed.slice(1).trimStart();\n return inner.startsWith(\"/\") || inner.startsWith(\".\");\n }\n }\n return false;\n}\n\nexport function parseSelector(input: string): ParsedSelector {\n const value = input.trim();\n return {\n type: isXPathSelector(value) ? \"xpath\" : \"css\",\n value\n };\n}\n","export function querySelectorDeep(root: Document | ShadowRoot | Element, selector: string): Element | null {\n const elements = Array.from(root.querySelectorAll(\"*\"));\n for (const el of elements) {\n if (el.matches(selector)) {\n return el;\n }\n const shadow = (el as Element & { shadowRoot?: ShadowRoot }).shadowRoot;\n if (shadow) {\n const found = querySelectorDeep(shadow, selector);\n if (found) {\n return found;\n }\n }\n }\n return null;\n}\n\nexport function querySelectorAllDeep(root: Document | ShadowRoot | Element, selector: string): Element[] {\n const results: Element[] = [];\n const elements = Array.from(root.querySelectorAll(\"*\"));\n for (const el of elements) {\n if (el.matches(selector)) {\n results.push(el);\n }\n const shadow = (el as Element & { shadowRoot?: ShadowRoot }).shadowRoot;\n if (shadow) {\n results.push(...querySelectorAllDeep(shadow, selector));\n }\n }\n return results;\n}\n\nexport function serializeShadowDomHelpers() {\n return {\n querySelectorDeep: querySelectorDeep.toString(),\n querySelectorAllDeep: querySelectorAllDeep.toString()\n };\n}\n","import type { Frame } from \"./Frame.js\";\n\nexport type LocatorOptions = {\n pierceShadowDom?: boolean;\n};\n\nexport class Locator {\n private frame: Frame;\n private selector: string;\n private options: LocatorOptions;\n\n constructor(frame: Frame, selector: string, options: LocatorOptions = {}) {\n this.frame = frame;\n this.selector = selector;\n this.options = options;\n }\n\n async click(options: { timeoutMs?: number } = {}) {\n return this.frame.click(this.selector, { ...this.options, ...options });\n }\n\n async dblclick(options: { timeoutMs?: number } = {}) {\n return this.frame.dblclick(this.selector, { ...this.options, ...options });\n }\n\n async type(text: string, options: { timeoutMs?: number } = {}) {\n return this.frame.type(this.selector, text, { ...this.options, ...options });\n }\n\n async exists() {\n return this.frame.exists(this.selector, this.options);\n }\n\n async text() {\n return this.frame.text(this.selector, this.options);\n }\n}\n","import { Session } from \"../cdp/Session.js\";\nimport { Logger } from \"../logging/Logger.js\";\nimport { AutomationEvents } from \"./Events.js\";\nimport { waitFor } from \"./Waiter.js\";\nimport { parseSelector } from \"./Selectors.js\";\nimport { serializeShadowDomHelpers } from \"./ShadowDom.js\";\nimport { Locator } from \"./Locator.js\";\n\nexport type FrameSelectorOptions = {\n pierceShadowDom?: boolean;\n};\n\nexport type ClickOptions = FrameSelectorOptions & {\n timeoutMs?: number;\n};\n\nexport type TypeOptions = FrameSelectorOptions & {\n timeoutMs?: number;\n};\n\nexport type QueryResult = {\n objectId: string;\n contextId: number;\n};\n\ntype ElementBox = {\n x: number;\n y: number;\n width: number;\n height: number;\n visible: boolean;\n};\n\nexport class Frame {\n readonly id: string;\n name?: string;\n url?: string;\n parentId?: string;\n private session: Session;\n private logger: Logger;\n private events: AutomationEvents;\n private contextId?: number;\n private defaultTimeout = 30_000;\n\n constructor(id: string, session: Session, logger: Logger, events: AutomationEvents) {\n this.id = id;\n this.session = session;\n this.logger = logger;\n this.events = events;\n }\n\n setExecutionContext(contextId?: number) {\n this.contextId = contextId;\n }\n\n getExecutionContext() {\n return this.contextId;\n }\n\n setMeta(meta: { name?: string; url?: string; parentId?: string }) {\n this.name = meta.name;\n this.url = meta.url;\n this.parentId = meta.parentId;\n }\n\n async evaluate<T = unknown>(fnOrString: string | ((...args: any[]) => any), ...args: any[]): Promise<T> {\n return this.evaluateInContext(fnOrString, args);\n }\n\n async query(selector: string, options: FrameSelectorOptions = {}): Promise<QueryResult | null> {\n return this.querySelectorInternal(selector, options, false);\n }\n\n async queryAll(selector: string, options: FrameSelectorOptions = {}): Promise<QueryResult[]> {\n return this.querySelectorAllInternal(selector, options, false);\n }\n\n async queryXPath(selector: string, options: FrameSelectorOptions = {}): Promise<QueryResult | null> {\n return this.querySelectorInternal(selector, options, true);\n }\n\n async queryAllXPath(selector: string, options: FrameSelectorOptions = {}): Promise<QueryResult[]> {\n return this.querySelectorAllInternal(selector, options, true);\n }\n\n locator(selector: string, options: FrameSelectorOptions = {}) {\n return new Locator(this, selector, options);\n }\n\n async click(selector: string, options: ClickOptions = {}) {\n await this.performClick(selector, options, false);\n }\n\n async dblclick(selector: string, options: ClickOptions = {}) {\n await this.performClick(selector, options, true);\n }\n\n async type(selector: string, text: string, options: TypeOptions = {}) {\n const start = Date.now();\n this.events.emit(\"action:start\", { name: \"type\", selector, frameId: this.id });\n await waitFor(async () => {\n const box = await this.resolveElementBox(selector, options);\n if (!box || !box.visible) {\n return false;\n }\n return true;\n }, { timeoutMs: options.timeoutMs ?? this.defaultTimeout, description: `type ${selector}` });\n\n const helpers = serializeShadowDomHelpers();\n const focusExpression = `(function() {\n const querySelectorDeep = ${helpers.querySelectorDeep};\n const root = document;\n const selector = ${JSON.stringify(selector)};\n const el = ${options.pierceShadowDom ? \"querySelectorDeep(root, selector)\" : \"root.querySelector(selector)\"};\n if (!el) {\n return;\n }\n el.focus();\n })()`;\n const focusParams: Record<string, unknown> = {\n expression: focusExpression,\n returnByValue: true\n };\n if (this.contextId) {\n focusParams.contextId = this.contextId;\n }\n await this.session.send(\"Runtime.evaluate\", focusParams);\n\n await this.session.send(\"Input.insertText\", { text });\n const duration = Date.now() - start;\n this.events.emit(\"action:end\", { name: \"type\", selector, frameId: this.id, durationMs: duration });\n this.logger.debug(\"Type\", selector, `${duration}ms`);\n }\n\n async exists(selector: string, options: FrameSelectorOptions = {}) {\n const handle = await this.query(selector, options);\n if (handle) {\n await this.releaseObject(handle.objectId);\n return true;\n }\n return false;\n }\n\n async isVisible(selector: string, options: FrameSelectorOptions = {}) {\n const box = await this.resolveElementBox(selector, options);\n return Boolean(box && box.visible);\n }\n\n async text(selector: string, options: FrameSelectorOptions = {}) {\n const helpers = serializeShadowDomHelpers();\n const expression = `(function() {\n const querySelectorDeep = ${helpers.querySelectorDeep};\n const root = document;\n const selector = ${JSON.stringify(selector)};\n const el = ${options.pierceShadowDom ? \"querySelectorDeep(root, selector)\" : \"root.querySelector(selector)\"};\n return el ? el.textContent || \\\"\\\" : null;\n })()`;\n\n const params: Record<string, unknown> = {\n expression,\n returnByValue: true\n };\n if (this.contextId) {\n params.contextId = this.contextId;\n }\n const result = await this.session.send<{ result: { value?: string | null } }>(\"Runtime.evaluate\", params);\n return result.result.value ?? null;\n }\n\n async attribute(selector: string, name: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<string | null>(selector, options, false, `\n if (!el || !(el instanceof Element)) {\n return null;\n }\n return el.getAttribute(${JSON.stringify(name)});\n `);\n }\n\n async value(selector: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<string | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n if (\"value\" in el) {\n return el.value ?? \"\";\n }\n return el.getAttribute(\"value\");\n `);\n }\n\n async isEnabled(selector: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<boolean | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n const disabled = Boolean(el.disabled) || el.hasAttribute(\"disabled\");\n const ariaDisabled = el.getAttribute && el.getAttribute(\"aria-disabled\") === \"true\";\n return !(disabled || ariaDisabled);\n `);\n }\n\n async isChecked(selector: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<boolean | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n const aria = el.getAttribute && el.getAttribute(\"aria-checked\");\n if (aria === \"true\") {\n return true;\n }\n if (aria === \"false\") {\n return false;\n }\n if (\"checked\" in el) {\n return Boolean(el.checked);\n }\n return null;\n `);\n }\n\n async count(selector: string, options: FrameSelectorOptions = {}) {\n const parsed = parseSelector(selector);\n const pierce = Boolean(options.pierceShadowDom);\n const helpers = serializeShadowDomHelpers();\n const expression = parsed.type === \"xpath\"\n ? `(function() {\n const result = document.evaluate(${JSON.stringify(parsed.value)}, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n return result.snapshotLength;\n })()`\n : `(function() {\n const querySelectorAllDeep = ${helpers.querySelectorAllDeep};\n const root = document;\n const selector = ${JSON.stringify(parsed.value)};\n const nodes = ${pierce ? \"querySelectorAllDeep(root, selector)\" : \"root.querySelectorAll(selector)\"};\n return nodes.length;\n })()`;\n\n const params: Record<string, unknown> = {\n expression,\n returnByValue: true\n };\n if (this.contextId) {\n params.contextId = this.contextId;\n }\n const result = await this.session.send<{ result: { value?: number } }>(\"Runtime.evaluate\", params);\n return result.result.value ?? 0;\n }\n\n async classes(selector: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<string[] | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n if (!el.classList) {\n return [];\n }\n return Array.from(el.classList);\n `);\n }\n\n async css(selector: string, property: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<string | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n const style = window.getComputedStyle(el);\n return style.getPropertyValue(${JSON.stringify(property)}) || \"\";\n `);\n }\n\n async hasFocus(selector: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<boolean | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n return document.activeElement === el;\n `);\n }\n\n async isInViewport(selector: string, options: FrameSelectorOptions = {}, fully = false) {\n return this.evalOnSelector<boolean | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n const rect = el.getBoundingClientRect();\n const viewWidth = window.innerWidth || document.documentElement.clientWidth;\n const viewHeight = window.innerHeight || document.documentElement.clientHeight;\n if (${fully ? \"true\" : \"false\"}) {\n return rect.top >= 0 && rect.left >= 0 && rect.bottom <= viewHeight && rect.right <= viewWidth;\n }\n return rect.bottom > 0 && rect.right > 0 && rect.top < viewHeight && rect.left < viewWidth;\n `);\n }\n\n async isEditable(selector: string, options: FrameSelectorOptions = {}) {\n return this.evalOnSelector<boolean | null>(selector, options, false, `\n if (!el) {\n return null;\n }\n const disabled = Boolean(el.disabled) || el.hasAttribute(\"disabled\");\n const readOnly = Boolean(el.readOnly) || el.hasAttribute(\"readonly\");\n const ariaDisabled = el.getAttribute && el.getAttribute(\"aria-disabled\") === \"true\";\n return !(disabled || readOnly || ariaDisabled);\n `);\n }\n\n private async performClick(selector: string, options: ClickOptions, isDouble: boolean) {\n const start = Date.now();\n const actionName = isDouble ? \"dblclick\" : \"click\";\n this.events.emit(\"action:start\", { name: actionName, selector, frameId: this.id });\n const box = await waitFor(async () => {\n const result = await this.resolveElementBox(selector, options);\n if (!result || !result.visible) {\n return null;\n }\n return result;\n }, { timeoutMs: options.timeoutMs ?? this.defaultTimeout, description: `${actionName} ${selector}` });\n\n const centerX = box.x + box.width / 2;\n const centerY = box.y + box.height / 2;\n await this.session.send(\"Input.dispatchMouseEvent\", { type: \"mouseMoved\", x: centerX, y: centerY });\n await this.session.send(\"Input.dispatchMouseEvent\", { type: \"mousePressed\", x: centerX, y: centerY, button: \"left\", clickCount: 1, buttons: 1 });\n await this.session.send(\"Input.dispatchMouseEvent\", { type: \"mouseReleased\", x: centerX, y: centerY, button: \"left\", clickCount: 1, buttons: 0 });\n\n if (isDouble) {\n await this.session.send(\"Input.dispatchMouseEvent\", { type: \"mouseMoved\", x: centerX, y: centerY });\n await this.session.send(\"Input.dispatchMouseEvent\", { type: \"mousePressed\", x: centerX, y: centerY, button: \"left\", clickCount: 2, buttons: 1 });\n await this.session.send(\"Input.dispatchMouseEvent\", { type: \"mouseReleased\", x: centerX, y: centerY, button: \"left\", clickCount: 2, buttons: 0 });\n }\n\n const duration = Date.now() - start;\n this.events.emit(\"action:end\", { name: actionName, selector, frameId: this.id, durationMs: duration });\n this.logger.debug(\"Click\", selector, `${duration}ms`);\n }\n\n private async resolveElementBox(selector: string, options: FrameSelectorOptions): Promise<ElementBox | null> {\n const parsed = parseSelector(selector);\n const pierce = Boolean(options.pierceShadowDom);\n const helpers = serializeShadowDomHelpers();\n const expression = parsed.type === \"xpath\"\n ? `(function() {\n const result = document.evaluate(${JSON.stringify(parsed.value)}, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n if (!result || !(result instanceof Element)) {\n return null;\n }\n result.scrollIntoView({ block: 'center', inline: 'center' });\n const rect = result.getBoundingClientRect();\n const style = window.getComputedStyle(result);\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height, visible: rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none' && Number(style.opacity || '1') > 0 };\n })()`\n : `(function() {\n const querySelectorDeep = ${helpers.querySelectorDeep};\n const root = document;\n const selector = ${JSON.stringify(parsed.value)};\n const el = ${pierce ? \"querySelectorDeep(root, selector)\" : \"root.querySelector(selector)\"};\n if (!el) {\n return null;\n }\n el.scrollIntoView({ block: 'center', inline: 'center' });\n const rect = el.getBoundingClientRect();\n const style = window.getComputedStyle(el);\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height, visible: rect.width > 0 && rect.height > 0 && style.visibility !== 'hidden' && style.display !== 'none' && Number(style.opacity || '1') > 0 };\n })()`;\n\n const boxParams: Record<string, unknown> = {\n expression,\n returnByValue: true\n };\n if (this.contextId) {\n boxParams.contextId = this.contextId;\n }\n const result = await this.session.send<{ result: { value: ElementBox | null } }>(\"Runtime.evaluate\", boxParams);\n\n return result?.result?.value ?? null;\n }\n\n private async querySelectorInternal(selector: string, options: FrameSelectorOptions, forceXPath: boolean): Promise<QueryResult | null> {\n const parsed = forceXPath ? { type: \"xpath\", value: selector.trim() } : parseSelector(selector);\n const pierce = Boolean(options.pierceShadowDom);\n const helpers = serializeShadowDomHelpers();\n const expression = parsed.type === \"xpath\"\n ? `(function() {\n const result = document.evaluate(${JSON.stringify(parsed.value)}, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n return result || null;\n })()`\n : `(function() {\n const querySelectorDeep = ${helpers.querySelectorDeep};\n const root = document;\n const selector = ${JSON.stringify(parsed.value)};\n return ${pierce ? \"querySelectorDeep(root, selector)\" : \"root.querySelector(selector)\"};\n })()`;\n\n const queryParams: Record<string, unknown> = {\n expression,\n returnByValue: false\n };\n if (this.contextId) {\n queryParams.contextId = this.contextId;\n }\n const response = await this.session.send<{ result: { subtype?: string; objectId?: string } }>(\"Runtime.evaluate\", queryParams);\n\n if (response.result?.subtype === \"null\" || !response.result?.objectId) {\n return null;\n }\n\n return { objectId: response.result.objectId, contextId: this.contextId ?? 0 };\n }\n\n private async querySelectorAllInternal(selector: string, options: FrameSelectorOptions, forceXPath: boolean): Promise<QueryResult[]> {\n const parsed = forceXPath ? { type: \"xpath\", value: selector.trim() } : parseSelector(selector);\n const pierce = Boolean(options.pierceShadowDom);\n const helpers = serializeShadowDomHelpers();\n const expression = parsed.type === \"xpath\"\n ? `(function() {\n const result = document.evaluate(${JSON.stringify(parsed.value)}, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\n const nodes = [];\n for (let i = 0; i < result.snapshotLength; i += 1) {\n nodes.push(result.snapshotItem(i));\n }\n return nodes;\n })()`\n : `(function() {\n const querySelectorAllDeep = ${helpers.querySelectorAllDeep};\n const root = document;\n const selector = ${JSON.stringify(parsed.value)};\n return ${pierce ? \"querySelectorAllDeep(root, selector)\" : \"Array.from(root.querySelectorAll(selector))\"};\n })()`;\n\n const listParams: Record<string, unknown> = {\n expression,\n returnByValue: false\n };\n if (this.contextId) {\n listParams.contextId = this.contextId;\n }\n const response = await this.session.send<{ result: { objectId?: string } }>(\"Runtime.evaluate\", listParams);\n\n if (!response.result?.objectId) {\n return [];\n }\n\n const properties = await this.session.send<{ result: Array<{ name?: string; value?: { objectId?: string } }> }>(\"Runtime.getProperties\", {\n objectId: response.result.objectId,\n ownProperties: true\n });\n\n const handles: QueryResult[] = [];\n for (const prop of properties.result) {\n if (prop.name && !/^\\d+$/.test(prop.name)) {\n continue;\n }\n const objectId = prop.value?.objectId;\n if (objectId) {\n handles.push({ objectId, contextId: this.contextId ?? 0 });\n }\n }\n\n await this.releaseObject(response.result.objectId);\n return handles;\n }\n\n private async evaluateInContext(fnOrString: string | ((...args: any[]) => any), args: any[]): Promise<any> {\n if (typeof fnOrString === \"string\") {\n const params: Record<string, unknown> = {\n expression: fnOrString,\n returnByValue: true,\n awaitPromise: true\n };\n if (this.contextId) {\n params.contextId = this.contextId;\n }\n const result = await this.session.send<{ result: { value?: unknown } }>(\"Runtime.evaluate\", params);\n return result.result.value;\n }\n\n const serializedArgs = args.map((arg) => serializeArgument(arg)).join(\", \");\n const expression = `(${fnOrString.toString()})(${serializedArgs})`;\n const params: Record<string, unknown> = {\n expression,\n returnByValue: true,\n awaitPromise: true\n };\n if (this.contextId) {\n params.contextId = this.contextId;\n }\n const result = await this.session.send<{ result: { value?: unknown } }>(\"Runtime.evaluate\", params);\n return result.result.value;\n }\n\n private async releaseObject(objectId: string) {\n try {\n await this.session.send(\"Runtime.releaseObject\", { objectId });\n } catch {\n // ignore release errors\n }\n }\n\n private buildElementExpression(selector: string, options: FrameSelectorOptions, forceXPath: boolean, body: string) {\n const parsed = forceXPath ? { type: \"xpath\", value: selector.trim() } : parseSelector(selector);\n const pierce = Boolean(options.pierceShadowDom);\n const helpers = serializeShadowDomHelpers();\n if (parsed.type === \"xpath\") {\n return `(function() {\n const el = document.evaluate(${JSON.stringify(parsed.value)}, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\n ${body}\n })()`;\n }\n return `(function() {\n const querySelectorDeep = ${helpers.querySelectorDeep};\n const root = document;\n const selector = ${JSON.stringify(parsed.value)};\n const el = ${pierce ? \"querySelectorDeep(root, selector)\" : \"root.querySelector(selector)\"};\n ${body}\n })()`;\n }\n\n private async evalOnSelector<T>(selector: string, options: FrameSelectorOptions, forceXPath: boolean, body: string): Promise<T> {\n const expression = this.buildElementExpression(selector, options, forceXPath, body);\n const params: Record<string, unknown> = {\n expression,\n returnByValue: true\n };\n if (this.contextId) {\n params.contextId = this.contextId;\n }\n const result = await this.session.send<{ result: { value?: T } }>(\"Runtime.evaluate\", params);\n return result.result.value as T;\n }\n}\n\nfunction serializeArgument(value: unknown) {\n if (value === undefined) {\n return \"undefined\";\n }\n return JSON.stringify(value);\n}\n","export type UrlGuardOptions = {\n allowFileUrl?: boolean;\n};\n\nexport function ensureAllowedUrl(url: string, options: UrlGuardOptions = {}) {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw new Error(`Invalid URL: ${url}`);\n }\n if (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") {\n return;\n }\n if (parsed.protocol === \"file:\" && options.allowFileUrl) {\n return;\n }\n throw new Error(`URL protocol not allowed: ${parsed.protocol}`);\n}\n","import { ChildProcess } from \"child_process\";\nimport { Connection } from \"../cdp/Connection.js\";\nimport { Session } from \"../cdp/Session.js\";\nimport { Logger } from \"../logging/Logger.js\";\nimport { AutomationEvents } from \"./Events.js\";\nimport { Page } from \"./Page.js\";\n\nexport class Browser {\n private connection: Connection;\n private process: ChildProcess;\n private logger: Logger;\n private events: AutomationEvents;\n\n constructor(connection: Connection, child: ChildProcess, logger: Logger, events: AutomationEvents) {\n this.connection = connection;\n this.process = child;\n this.logger = logger;\n this.events = events;\n }\n\n on(event: \"action:start\" | \"action:end\" | \"assertion:start\" | \"assertion:end\", handler: (payload: any) => void) {\n this.events.on(event, handler as any);\n }\n\n async newPage() {\n const { targetId } = await this.connection.send<{ targetId: string }>(\"Target.createTarget\", { url: \"about:blank\" });\n const { sessionId } = await this.connection.send<{ sessionId: string }>(\"Target.attachToTarget\", { targetId, flatten: true });\n const session = this.connection.createSession(sessionId);\n const page = new Page(session, this.logger, this.events);\n await page.initialize();\n return page;\n }\n\n async close() {\n try {\n await this.connection.send(\"Browser.close\");\n } catch {\n // ignore\n }\n await this.connection.close();\n if (!this.process.killed) {\n this.process.kill();\n }\n }\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\nimport https from \"https\";\nimport { spawn } from \"child_process\";\nimport yauzl from \"yauzl\";\nimport { Logger } from \"../logging/Logger.js\";\n\nexport type Platform = \"linux\" | \"mac\" | \"win\";\n\nconst SNAPSHOT_BASE = \"https://commondatastorage.googleapis.com/chromium-browser-snapshots\";\n\nexport function detectPlatform(platform = process.platform): Platform {\n if (platform === \"linux\") return \"linux\";\n if (platform === \"darwin\") return \"mac\";\n if (platform === \"win32\") return \"win\";\n throw new Error(`Unsupported platform: ${platform}`);\n}\n\nexport function platformFolder(platform: Platform) {\n if (platform === \"linux\") return \"Linux_x64\";\n if (platform === \"mac\") return \"Mac\";\n return \"Win\";\n}\n\nexport function defaultCacheRoot(platform: Platform) {\n if (platform === \"win\") {\n const localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), \"AppData\", \"Local\");\n return path.join(localAppData, \"chromium-automaton\");\n }\n return path.join(os.homedir(), \".cache\", \"chromium-automaton\");\n}\n\nexport function ensureWithinRoot(root: string, target: string) {\n const resolvedRoot = path.resolve(root);\n const resolvedTarget = path.resolve(target);\n if (resolvedTarget === resolvedRoot) {\n return;\n }\n if (!resolvedTarget.startsWith(resolvedRoot + path.sep)) {\n throw new Error(`Path escapes cache root: ${resolvedTarget}`);\n }\n}\n\nexport function chromiumExecutableRelativePath(platform: Platform) {\n if (platform === \"linux\") return path.join(\"chrome-linux\", \"chrome\");\n if (platform === \"mac\") return path.join(\"chrome-mac\", \"Chromium.app\", \"Contents\", \"MacOS\", \"Chromium\");\n return path.join(\"chrome-win\", \"chrome.exe\");\n}\n\nexport async function fetchLatestRevision(platform: Platform): Promise<string> {\n const folder = platformFolder(platform);\n const url = `${SNAPSHOT_BASE}/${folder}/LAST_CHANGE`;\n return new Promise((resolve, reject) => {\n https.get(url, (res) => {\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`Failed to fetch LAST_CHANGE: ${res.statusCode}`));\n return;\n }\n let data = \"\";\n res.on(\"data\", (chunk) => (data += chunk.toString()));\n res.on(\"end\", () => resolve(data.trim()));\n }).on(\"error\", reject);\n });\n}\n\nexport type DownloadOptions = {\n cacheRoot: string;\n platform: Platform;\n revision: string;\n logger: Logger;\n};\n\nexport async function ensureDownloaded(options: DownloadOptions) {\n const { cacheRoot, platform, revision, logger } = options;\n ensureWithinRoot(cacheRoot, cacheRoot);\n const platformDir = path.join(cacheRoot, platform);\n const revisionDir = path.join(platformDir, revision);\n ensureWithinRoot(cacheRoot, revisionDir);\n\n const executablePath = path.join(revisionDir, chromiumExecutableRelativePath(platform));\n const markerFile = path.join(revisionDir, \"INSTALLATION_COMPLETE\");\n\n if (fs.existsSync(executablePath) && fs.existsSync(markerFile)) {\n return { executablePath, revisionDir };\n }\n\n fs.mkdirSync(revisionDir, { recursive: true });\n\n const folder = platformFolder(platform);\n const zipName = platform === \"win\" ? \"chrome-win.zip\" : platform === \"mac\" ? \"chrome-mac.zip\" : \"chrome-linux.zip\";\n const downloadUrl = `${SNAPSHOT_BASE}/${folder}/${revision}/${zipName}`;\n\n const tempZipPath = path.join(os.tmpdir(), `chromium-automaton-${platform}-${revision}.zip`);\n\n logger.info(\"Downloading Chromium snapshot\", downloadUrl);\n await downloadFile(downloadUrl, tempZipPath, logger);\n logger.info(\"Extracting Chromium snapshot\", tempZipPath);\n await extractZipSafe(tempZipPath, revisionDir);\n fs.writeFileSync(markerFile, new Date().toISOString());\n fs.unlinkSync(tempZipPath);\n\n if (!fs.existsSync(executablePath)) {\n throw new Error(`Executable not found after extraction: ${executablePath}`);\n }\n ensureExecutable(executablePath, platform);\n\n return { executablePath, revisionDir };\n}\n\nfunction downloadFile(url: string, dest: string, logger: Logger): Promise<void> {\n return new Promise((resolve, reject) => {\n const file = fs.createWriteStream(dest);\n https.get(url, (res) => {\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`Failed to download: ${res.statusCode}`));\n return;\n }\n const total = Number(res.headers[\"content-length\"] || 0);\n let downloaded = 0;\n let lastLoggedPercent = -1;\n let lastLoggedTime = Date.now();\n res.pipe(file);\n res.on(\"data\", (chunk) => {\n downloaded += chunk.length;\n if (!total) {\n const now = Date.now();\n if (now - lastLoggedTime > 2000) {\n logger.info(\"Download progress\", `${(downloaded / (1024 * 1024)).toFixed(1)} MB`);\n lastLoggedTime = now;\n }\n return;\n }\n const percent = Math.floor((downloaded / total) * 100);\n if (percent >= lastLoggedPercent + 5) {\n logger.info(\"Download progress\", `${percent}%`);\n lastLoggedPercent = percent;\n }\n });\n file.on(\"finish\", () => file.close(() => resolve()));\n }).on(\"error\", (err) => {\n fs.unlink(dest, () => reject(err));\n });\n });\n}\n\nexport async function extractZipSafe(zipPath: string, destDir: string): Promise<void> {\n return new Promise((resolve, reject) => {\n yauzl.open(zipPath, { lazyEntries: true }, (err, zipfile) => {\n if (err || !zipfile) {\n reject(err || new Error(\"Unable to open zip\"));\n return;\n }\n\n zipfile.readEntry();\n zipfile.on(\"entry\", (entry) => {\n const entryPath = entry.fileName.replace(/\\\\/g, \"/\");\n const targetPath = path.join(destDir, entryPath);\n try {\n ensureWithinRoot(destDir, targetPath);\n } catch (error) {\n zipfile.close();\n reject(error);\n return;\n }\n\n if (/\\/$/.test(entry.fileName)) {\n fs.mkdirSync(targetPath, { recursive: true });\n zipfile.readEntry();\n return;\n }\n\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n zipfile.openReadStream(entry, (streamErr, readStream) => {\n if (streamErr || !readStream) {\n zipfile.close();\n reject(streamErr || new Error(\"Unable to read zip entry\"));\n return;\n }\n const rawMode = entry.externalFileAttributes ? (entry.externalFileAttributes >>> 16) & 0xffff : 0;\n const mode = rawMode > 0 ? rawMode : undefined;\n const writeStream = fs.createWriteStream(targetPath);\n readStream.pipe(writeStream);\n writeStream.on(\"error\", (writeErr) => {\n zipfile.close();\n reject(writeErr);\n });\n writeStream.on(\"close\", () => {\n if (mode && mode <= 0o777) {\n try {\n fs.chmodSync(targetPath, mode);\n } catch {\n // ignore chmod errors\n }\n }\n zipfile.readEntry();\n });\n });\n });\n\n zipfile.on(\"end\", () => {\n zipfile.close();\n resolve();\n });\n\n zipfile.on(\"error\", (zipErr) => {\n zipfile.close();\n reject(zipErr);\n });\n });\n });\n}\n\nexport async function chromiumVersion(executablePath: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn(executablePath, [\"--version\"], { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let output = \"\";\n child.stdout.on(\"data\", (chunk) => (output += chunk.toString()));\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve(output.trim());\n } else {\n reject(new Error(`Failed to get Chromium version: ${code}`));\n }\n });\n child.on(\"error\", reject);\n });\n}\n\nfunction ensureExecutable(executablePath: string, platform: Platform) {\n if (platform === \"win\") {\n return;\n }\n try {\n const stat = fs.statSync(executablePath);\n const isExecutable = (stat.mode & 0o111) !== 0;\n if (!isExecutable) {\n fs.chmodSync(executablePath, 0o755);\n }\n } catch {\n // ignore chmod errors\n }\n}\n","export const PINNED_REVISION = \"1567454\";\n\nexport function resolveRevision(envRevision?: string) {\n if (envRevision && envRevision.trim()) {\n return envRevision.trim();\n }\n return PINNED_REVISION;\n}\n","import { ChromiumManager } from \"./browser/ChromiumManager.js\";\n\nfunction printHelp() {\n console.log(\"chromium-automaton download [--latest]\");\n}\n\nasync function main() {\n const [, , command, ...rest] = process.argv;\n if (!command || command === \"--help\" || command === \"-h\") {\n printHelp();\n process.exit(0);\n }\n\n if (command !== \"download\") {\n console.error(`Unknown command: ${command}`);\n printHelp();\n process.exit(1);\n }\n\n const latest = rest.includes(\"--latest\");\n const manager = new ChromiumManager();\n await manager.download({ latest });\n}\n\nmain().catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","spawn","EventEmitter","EventEmitter","EventEmitter","params","result","fs","path","path","fs","ensureExecutable","spawn"]}
@@ -0,0 +1,276 @@
1
+ type LogLevel = "error" | "warn" | "info" | "debug" | "trace";
2
+ declare class Logger {
3
+ private level;
4
+ constructor(level?: LogLevel);
5
+ setLevel(level: LogLevel): void;
6
+ error(message: string, ...args: unknown[]): void;
7
+ warn(message: string, ...args: unknown[]): void;
8
+ info(message: string, ...args: unknown[]): void;
9
+ debug(message: string, ...args: unknown[]): void;
10
+ trace(message: string, ...args: unknown[]): void;
11
+ log(level: LogLevel, message: string, ...args: unknown[]): void;
12
+ }
13
+
14
+ declare class Session {
15
+ private connection;
16
+ private sessionId;
17
+ private emitter;
18
+ constructor(connection: Connection, sessionId: string);
19
+ on(event: string, handler: (params: unknown) => void): void;
20
+ once(event: string, handler: (params: unknown) => void): void;
21
+ send<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
22
+ dispatch(method: string, params: unknown): void;
23
+ }
24
+
25
+ declare class Connection {
26
+ private ws;
27
+ private id;
28
+ private callbacks;
29
+ private sessions;
30
+ private emitter;
31
+ private logger;
32
+ constructor(url: string, logger: Logger);
33
+ waitForOpen(): Promise<void>;
34
+ createSession(sessionId: string): Session;
35
+ removeSession(sessionId: string): void;
36
+ on(event: string, handler: (params: unknown) => void): void;
37
+ send<T = unknown>(method: string, params?: Record<string, unknown>, sessionId?: string): Promise<T>;
38
+ close(): Promise<void>;
39
+ private onError;
40
+ private onMessage;
41
+ }
42
+
43
+ type ActionEvent = {
44
+ name: string;
45
+ selector?: string;
46
+ frameId?: string;
47
+ durationMs?: number;
48
+ };
49
+ type AssertionEvent = {
50
+ name: string;
51
+ selector?: string;
52
+ frameId?: string;
53
+ durationMs?: number;
54
+ };
55
+ type AutomationEventMap = {
56
+ "action:start": ActionEvent;
57
+ "action:end": ActionEvent;
58
+ "assertion:start": AssertionEvent;
59
+ "assertion:end": AssertionEvent;
60
+ };
61
+ declare class AutomationEvents {
62
+ private emitter;
63
+ on<K extends keyof AutomationEventMap>(event: K, handler: (payload: AutomationEventMap[K]) => void): void;
64
+ off<K extends keyof AutomationEventMap>(event: K, handler: (payload: AutomationEventMap[K]) => void): void;
65
+ emit<K extends keyof AutomationEventMap>(event: K, payload: AutomationEventMap[K]): void;
66
+ }
67
+
68
+ type LocatorOptions = {
69
+ pierceShadowDom?: boolean;
70
+ };
71
+ declare class Locator {
72
+ private frame;
73
+ private selector;
74
+ private options;
75
+ constructor(frame: Frame, selector: string, options?: LocatorOptions);
76
+ click(options?: {
77
+ timeoutMs?: number;
78
+ }): Promise<void>;
79
+ dblclick(options?: {
80
+ timeoutMs?: number;
81
+ }): Promise<void>;
82
+ type(text: string, options?: {
83
+ timeoutMs?: number;
84
+ }): Promise<void>;
85
+ exists(): Promise<boolean>;
86
+ text(): Promise<string | null>;
87
+ }
88
+
89
+ type FrameSelectorOptions = {
90
+ pierceShadowDom?: boolean;
91
+ };
92
+ type ClickOptions = FrameSelectorOptions & {
93
+ timeoutMs?: number;
94
+ };
95
+ type TypeOptions = FrameSelectorOptions & {
96
+ timeoutMs?: number;
97
+ };
98
+ type QueryResult = {
99
+ objectId: string;
100
+ contextId: number;
101
+ };
102
+ declare class Frame {
103
+ readonly id: string;
104
+ name?: string;
105
+ url?: string;
106
+ parentId?: string;
107
+ private session;
108
+ private logger;
109
+ private events;
110
+ private contextId?;
111
+ private defaultTimeout;
112
+ constructor(id: string, session: Session, logger: Logger, events: AutomationEvents);
113
+ setExecutionContext(contextId?: number): void;
114
+ getExecutionContext(): number | undefined;
115
+ setMeta(meta: {
116
+ name?: string;
117
+ url?: string;
118
+ parentId?: string;
119
+ }): void;
120
+ evaluate<T = unknown>(fnOrString: string | ((...args: any[]) => any), ...args: any[]): Promise<T>;
121
+ query(selector: string, options?: FrameSelectorOptions): Promise<QueryResult | null>;
122
+ queryAll(selector: string, options?: FrameSelectorOptions): Promise<QueryResult[]>;
123
+ queryXPath(selector: string, options?: FrameSelectorOptions): Promise<QueryResult | null>;
124
+ queryAllXPath(selector: string, options?: FrameSelectorOptions): Promise<QueryResult[]>;
125
+ locator(selector: string, options?: FrameSelectorOptions): Locator;
126
+ click(selector: string, options?: ClickOptions): Promise<void>;
127
+ dblclick(selector: string, options?: ClickOptions): Promise<void>;
128
+ type(selector: string, text: string, options?: TypeOptions): Promise<void>;
129
+ exists(selector: string, options?: FrameSelectorOptions): Promise<boolean>;
130
+ isVisible(selector: string, options?: FrameSelectorOptions): Promise<boolean>;
131
+ text(selector: string, options?: FrameSelectorOptions): Promise<string | null>;
132
+ attribute(selector: string, name: string, options?: FrameSelectorOptions): Promise<string | null>;
133
+ value(selector: string, options?: FrameSelectorOptions): Promise<string | null>;
134
+ isEnabled(selector: string, options?: FrameSelectorOptions): Promise<boolean | null>;
135
+ isChecked(selector: string, options?: FrameSelectorOptions): Promise<boolean | null>;
136
+ count(selector: string, options?: FrameSelectorOptions): Promise<number>;
137
+ classes(selector: string, options?: FrameSelectorOptions): Promise<string[] | null>;
138
+ css(selector: string, property: string, options?: FrameSelectorOptions): Promise<string | null>;
139
+ hasFocus(selector: string, options?: FrameSelectorOptions): Promise<boolean | null>;
140
+ isInViewport(selector: string, options?: FrameSelectorOptions, fully?: boolean): Promise<boolean | null>;
141
+ isEditable(selector: string, options?: FrameSelectorOptions): Promise<boolean | null>;
142
+ private performClick;
143
+ private resolveElementBox;
144
+ private querySelectorInternal;
145
+ private querySelectorAllInternal;
146
+ private evaluateInContext;
147
+ private releaseObject;
148
+ private buildElementExpression;
149
+ private evalOnSelector;
150
+ }
151
+
152
+ type GotoOptions = {
153
+ waitUntil?: "domcontentloaded" | "load";
154
+ timeoutMs?: number;
155
+ allowFileUrl?: boolean;
156
+ };
157
+ type ScreenshotOptions = {
158
+ path?: string;
159
+ format?: "png" | "jpeg";
160
+ quality?: number;
161
+ };
162
+ declare class Page {
163
+ private session;
164
+ private logger;
165
+ private events;
166
+ private framesById;
167
+ private mainFrameId?;
168
+ private lifecycleEvents;
169
+ private defaultTimeout;
170
+ constructor(session: Session, logger: Logger, events: AutomationEvents);
171
+ initialize(): Promise<void>;
172
+ frames(): Frame[];
173
+ mainFrame(): Frame;
174
+ frame(options: {
175
+ name?: string;
176
+ urlIncludes?: string;
177
+ predicate?: (frame: Frame) => boolean;
178
+ }): Frame | null;
179
+ locator(selector: string, options?: {
180
+ pierceShadowDom?: boolean;
181
+ }): Locator;
182
+ goto(url: string, options?: GotoOptions): Promise<void>;
183
+ query(selector: string, options?: {
184
+ pierceShadowDom?: boolean;
185
+ }): Promise<QueryResult | null>;
186
+ queryAll(selector: string, options?: {
187
+ pierceShadowDom?: boolean;
188
+ }): Promise<QueryResult[]>;
189
+ queryXPath(selector: string, options?: {
190
+ pierceShadowDom?: boolean;
191
+ }): Promise<QueryResult | null>;
192
+ queryAllXPath(selector: string, options?: {
193
+ pierceShadowDom?: boolean;
194
+ }): Promise<QueryResult[]>;
195
+ click(selector: string, options?: {
196
+ pierceShadowDom?: boolean;
197
+ timeoutMs?: number;
198
+ }): Promise<void>;
199
+ dblclick(selector: string, options?: {
200
+ pierceShadowDom?: boolean;
201
+ timeoutMs?: number;
202
+ }): Promise<void>;
203
+ type(selector: string, text: string, options?: {
204
+ pierceShadowDom?: boolean;
205
+ timeoutMs?: number;
206
+ }): Promise<void>;
207
+ evaluate<T = unknown>(fnOrString: string | ((...args: any[]) => any), ...args: any[]): Promise<T>;
208
+ screenshot(options?: ScreenshotOptions): Promise<Buffer<ArrayBuffer>>;
209
+ screenshotBase64(options?: Omit<ScreenshotOptions, "path">): Promise<string>;
210
+ getEvents(): AutomationEvents;
211
+ getDefaultTimeout(): number;
212
+ private buildFrameTree;
213
+ private ensureFrame;
214
+ private onFrameAttached;
215
+ private onFrameNavigated;
216
+ private onFrameDetached;
217
+ private onExecutionContextCreated;
218
+ private onExecutionContextDestroyed;
219
+ private onExecutionContextsCleared;
220
+ private onLifecycleEvent;
221
+ private waitForLifecycle;
222
+ }
223
+
224
+ type ExpectSelectorOptions = {
225
+ timeoutMs?: number;
226
+ pierceShadowDom?: boolean;
227
+ };
228
+ declare class ElementExpectation {
229
+ private frame;
230
+ private selector;
231
+ private options;
232
+ private negate;
233
+ private events;
234
+ constructor(frame: Frame, selector: string, options: ExpectSelectorOptions, negate: boolean, events: AutomationEvents);
235
+ get not(): ElementExpectation;
236
+ toExist(): Promise<void>;
237
+ toBeVisible(): Promise<void>;
238
+ toBeHidden(): Promise<void>;
239
+ toBeEnabled(): Promise<void>;
240
+ toBeDisabled(): Promise<void>;
241
+ toBeChecked(): Promise<void>;
242
+ toBeUnchecked(): Promise<void>;
243
+ toHaveText(textOrRegex: string | RegExp): Promise<void>;
244
+ toHaveExactText(textOrRegex: string | RegExp): Promise<void>;
245
+ toContainText(textOrRegex: string | RegExp): Promise<void>;
246
+ toHaveValue(valueOrRegex: string | RegExp): Promise<void>;
247
+ toHaveAttribute(name: string, valueOrRegex?: string | RegExp): Promise<void>;
248
+ toHaveId(idOrRegex: string | RegExp): Promise<void>;
249
+ toHaveName(nameOrRegex: string | RegExp): Promise<void>;
250
+ toHaveCount(expected: number): Promise<void>;
251
+ toHaveClass(nameOrRegex: string | RegExp): Promise<void>;
252
+ toHaveClasses(expected: string[]): Promise<void>;
253
+ toHaveCss(property: string, valueOrRegex: string | RegExp): Promise<void>;
254
+ toHaveFocus(): Promise<void>;
255
+ toBeInViewport(options?: {
256
+ fully?: boolean;
257
+ }): Promise<void>;
258
+ toBeEditable(): Promise<void>;
259
+ private assert;
260
+ }
261
+ declare class ExpectFrame {
262
+ private frame;
263
+ private events;
264
+ constructor(frame: Frame, events: AutomationEvents);
265
+ element(selector: string, options?: ExpectSelectorOptions): ElementExpectation;
266
+ }
267
+ declare function expect(page: Page): {
268
+ element: (selector: string, options?: ExpectSelectorOptions) => ElementExpectation;
269
+ frame: (options: {
270
+ name?: string;
271
+ urlIncludes?: string;
272
+ predicate?: (frame: Frame) => boolean;
273
+ }) => ExpectFrame;
274
+ };
275
+
276
+ export { AutomationEvents as A, Connection as C, type ExpectSelectorOptions as E, Frame as F, Logger as L, Page as P, type LogLevel as a, Locator as b, expect as e };
@@ -0,0 +1,45 @@
1
+ import { C as Connection, L as Logger, A as AutomationEvents, P as Page, a as LogLevel } from './expect-CBZIoH1D.js';
2
+ export { F as Frame, b as Locator, e as expect } from './expect-CBZIoH1D.js';
3
+ import { ChildProcess } from 'child_process';
4
+
5
+ declare class Browser {
6
+ private connection;
7
+ private process;
8
+ private logger;
9
+ private events;
10
+ constructor(connection: Connection, child: ChildProcess, logger: Logger, events: AutomationEvents);
11
+ on(event: "action:start" | "action:end" | "assertion:start" | "assertion:end", handler: (payload: any) => void): void;
12
+ newPage(): Promise<Page>;
13
+ close(): Promise<void>;
14
+ }
15
+
16
+ type LaunchOptions = {
17
+ headless?: boolean;
18
+ args?: string[];
19
+ timeoutMs?: number;
20
+ logLevel?: LogLevel;
21
+ executablePath?: string;
22
+ };
23
+
24
+ declare class AssertionError extends Error {
25
+ selector?: string;
26
+ timeoutMs?: number;
27
+ lastState?: unknown;
28
+ constructor(message: string, options?: {
29
+ selector?: string;
30
+ timeoutMs?: number;
31
+ lastState?: unknown;
32
+ });
33
+ }
34
+
35
+ type AutomatonLaunchOptions = LaunchOptions & {
36
+ logger?: Logger;
37
+ };
38
+ declare const automaton: {
39
+ launch(options?: AutomatonLaunchOptions): Promise<Browser>;
40
+ };
41
+ declare const chromium: {
42
+ launch(options?: AutomatonLaunchOptions): Promise<Browser>;
43
+ };
44
+
45
+ export { AssertionError, AutomationEvents, type AutomatonLaunchOptions, Browser, LogLevel, Logger, Page, automaton, chromium };