diff --git a/src/actions.ts b/src/actions.ts index 09e5a8a..f797c07 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -383,7 +383,7 @@ async function handleNavigate( async function handleClick(command: ClickCommand, browser: BrowserManager): Promise { // Support both refs (@e1) and regular selectors const locator = browser.getLocator(command.selector); - + await locator.click({ button: command.button, clickCount: command.clickCount, @@ -449,7 +449,13 @@ async function handleScreenshot( } async function handleSnapshot( - command: Command & { action: 'snapshot'; interactive?: boolean; maxDepth?: number; compact?: boolean; selector?: string }, + command: Command & { + action: 'snapshot'; + interactive?: boolean; + maxDepth?: number; + compact?: boolean; + selector?: string; + }, browser: BrowserManager ): Promise> { // Use enhanced snapshot with refs and optional filtering diff --git a/src/browser.test.ts b/src/browser.test.ts index 519ba96..9d40926 100644 --- a/src/browser.test.ts +++ b/src/browser.test.ts @@ -123,7 +123,9 @@ describe('BrowserManager', () => { it('should set cookie with domain', async () => { const page = browser.getPage(); const context = page.context(); - await context.addCookies([{ name: 'domainCookie', value: 'domainValue', domain: 'example.com', path: '/' }]); + await context.addCookies([ + { name: 'domainCookie', value: 'domainValue', domain: 'example.com', path: '/' }, + ]); const cookies = await context.cookies(); const testCookie = cookies.find((c) => c.name === 'domainCookie'); expect(testCookie?.value).toBe('domainValue'); diff --git a/src/browser.ts b/src/browser.ts index 03b17e4..0081f39 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -94,7 +94,7 @@ export class BrowserManager { if (!refData) return null; const page = this.getPage(); - + // Parse the selector and create locator if (refData.name) { return page.getByRole(refData.role as any, { name: refData.name }); diff --git a/src/daemon.ts b/src/daemon.ts index 27c241a..c7e52be 100644 --- a/src/daemon.ts +++ b/src/daemon.ts @@ -33,7 +33,7 @@ export function getSession(): string { function getPortForSession(session: string): number { let hash = 0; for (let i = 0; i < session.length; i++) { - hash = ((hash << 5) - hash) + session.charCodeAt(i); + hash = (hash << 5) - hash + session.charCodeAt(i); hash |= 0; } // Port range 49152-65535 (dynamic/private ports) @@ -90,7 +90,9 @@ export function isDaemonRunning(session?: string): boolean { * Get connection info for the current session * Returns { type: 'unix', path: string } or { type: 'tcp', port: number } */ -export function getConnectionInfo(session?: string): { type: 'unix'; path: string } | { type: 'tcp'; port: number } { +export function getConnectionInfo( + session?: string +): { type: 'unix'; path: string } | { type: 'tcp'; port: number } { const sess = session ?? currentSession; if (isWindows) { return { type: 'tcp', port: getPortForSession(sess) }; diff --git a/src/protocol.test.ts b/src/protocol.test.ts index 39f2a50..fe4c70e 100644 --- a/src/protocol.test.ts +++ b/src/protocol.test.ts @@ -252,7 +252,9 @@ describe('parseCommand', () => { }); it('should parse storage_get with specific key', () => { - const result = parseCommand(cmd({ id: '1', action: 'storage_get', type: 'local', key: 'mykey' })); + const result = parseCommand( + cmd({ id: '1', action: 'storage_get', type: 'local', key: 'mykey' }) + ); expect(result.success).toBe(true); if (result.success) { expect(result.command.key).toBe('mykey'); @@ -426,14 +428,16 @@ describe('parseCommand', () => { }); it('should parse snapshot with all options', () => { - const result = parseCommand(cmd({ - id: '1', - action: 'snapshot', - interactive: true, - compact: true, - maxDepth: 5, - selector: '.content', - })); + const result = parseCommand( + cmd({ + id: '1', + action: 'snapshot', + interactive: true, + compact: true, + maxDepth: 5, + selector: '.content', + }) + ); expect(result.success).toBe(true); if (result.success) { expect(result.command.interactive).toBe(true); @@ -487,7 +491,9 @@ describe('parseCommand', () => { describe('scroll', () => { it('should parse scroll command', () => { - const result = parseCommand(cmd({ id: '1', action: 'scroll', direction: 'down', amount: 300 })); + const result = parseCommand( + cmd({ id: '1', action: 'scroll', direction: 'down', amount: 300 }) + ); expect(result.success).toBe(true); }); @@ -521,7 +527,9 @@ describe('parseCommand', () => { }); it('should parse geolocation', () => { - const result = parseCommand(cmd({ id: '1', action: 'geolocation', latitude: 37.7749, longitude: -122.4194 })); + const result = parseCommand( + cmd({ id: '1', action: 'geolocation', latitude: 37.7749, longitude: -122.4194 }) + ); expect(result.success).toBe(true); }); @@ -572,7 +580,9 @@ describe('parseCommand', () => { }); it('should parse dialog accept with prompt text', () => { - const result = parseCommand(cmd({ id: '1', action: 'dialog', response: 'accept', promptText: 'hello' })); + const result = parseCommand( + cmd({ id: '1', action: 'dialog', response: 'accept', promptText: 'hello' }) + ); expect(result.success).toBe(true); if (result.success) { expect(result.command.promptText).toBe('hello'); diff --git a/src/snapshot.ts b/src/snapshot.ts index 3f517b8..072b22a 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -173,10 +173,10 @@ function processAriaTree(ariaTree: string, refs: RefMap, options: SnapshotOption for (const line of lines) { const match = line.match(/^(\s*-\s*)(\w+)(?:\s+"([^"]*)")?(.*)$/); if (!match) continue; - + const [, , role, name, suffix] = match; const roleLower = role.toLowerCase(); - + if (INTERACTIVE_ROLES.has(roleLower)) { const ref = nextRef(); refs[ref] = { @@ -184,12 +184,12 @@ function processAriaTree(ariaTree: string, refs: RefMap, options: SnapshotOption role: roleLower, name, }; - + let enhanced = `- ${role}`; if (name) enhanced += ` "${name}"`; enhanced += ` [ref=${ref}]`; if (suffix && suffix.includes('[')) enhanced += suffix; - + result.push(enhanced); } } @@ -223,11 +223,7 @@ function getIndentLevel(line: string): number { /** * Process a single line: add ref if needed, filter if requested */ -function processLine( - line: string, - refs: RefMap, - options: SnapshotOptions -): string | null { +function processLine(line: string, refs: RefMap, options: SnapshotOptions): string | null { const depth = getIndentLevel(line); // Check max depth @@ -302,27 +298,27 @@ function processLine( function compactTree(tree: string): string { const lines = tree.split('\n'); const result: string[] = []; - + // Simple pass: keep lines that have content or refs for (let i = 0; i < lines.length; i++) { const line = lines[i]; - + // Always keep lines with refs if (line.includes('[ref=')) { result.push(line); continue; } - + // Keep lines with text content (after :) if (line.includes(':') && !line.endsWith(':')) { result.push(line); continue; } - + // Check if this structural element has children with refs const currentIndent = getIndentLevel(line); let hasRelevantChildren = false; - + for (let j = i + 1; j < lines.length; j++) { const childIndent = getIndentLevel(lines[j]); if (childIndent <= currentIndent) break; @@ -331,12 +327,12 @@ function compactTree(tree: string): string { break; } } - + if (hasRelevantChildren) { result.push(line); } } - + return result.join('\n'); } @@ -359,17 +355,18 @@ export function parseRef(arg: string): string | null { /** * Get snapshot statistics */ -export function getSnapshotStats(tree: string, refs: RefMap): { +export function getSnapshotStats( + tree: string, + refs: RefMap +): { lines: number; chars: number; tokens: number; refs: number; interactive: number; } { - const interactive = Object.values(refs).filter(r => - INTERACTIVE_ROLES.has(r.role) - ).length; - + const interactive = Object.values(refs).filter((r) => INTERACTIVE_ROLES.has(r.role)).length; + return { lines: tree.split('\n').length, chars: tree.length,