diff --git a/packages/browseros-agent/apps/server/tests/tools/filesystem/bash.test.ts b/packages/browseros-agent/apps/server/tests/tools/filesystem/bash.test.ts index 36cde73d2..811ef7e80 100644 --- a/packages/browseros-agent/apps/server/tests/tools/filesystem/bash.test.ts +++ b/packages/browseros-agent/apps/server/tests/tools/filesystem/bash.test.ts @@ -55,7 +55,7 @@ describe('filesystem_bash', () => { }) it('times out long-running commands', async () => { - const result = await exec({ command: 'sleep 30', timeout: 1 }) + const result = await exec({ command: 'exec sleep 30', timeout: 1 }) expect(result.isError).toBe(true) expect(result.text).toContain('timed out') }, 10_000) diff --git a/packages/browseros-agent/apps/server/tests/tools/input.test.ts b/packages/browseros-agent/apps/server/tests/tools/input.test.ts index 163fa59cb..9b98313bc 100644 --- a/packages/browseros-agent/apps/server/tests/tools/input.test.ts +++ b/packages/browseros-agent/apps/server/tests/tools/input.test.ts @@ -1,5 +1,7 @@ import { describe, it } from 'bun:test' import assert from 'node:assert' +import type { Browser } from '../../src/browser/browser' +import { executeTool, type ToolContext } from '../../src/tools/framework' import { check, click, @@ -320,37 +322,48 @@ describe('input tools', () => { }, 60_000) it('scroll dispatches without error', async () => { - await withBrowser(async ({ execute }) => { - const newResult = await execute(new_page, { - url: FORM_PAGE, - }) - const pageId = pageIdOf(newResult) - - const before = await execute(evaluate_script, { - page: pageId, - expression: 'window.scrollY', - }) - - const scrollResult = await execute(scroll, { - page: pageId, - direction: 'down', - amount: 5, - }) - assert.ok(!scrollResult.isError, textOf(scrollResult)) - assert.ok(textOf(scrollResult).includes('Scrolled down')) - - const after = await execute(evaluate_script, { - page: pageId, - expression: 'window.scrollY', - }) - assert.ok( - Number(textOf(after)) > Number(textOf(before)), - `Expected scrollY to increase, before=${textOf(before)} after=${textOf(after)}`, - ) - - await execute(close_page, { page: pageId }) + const calls: Array<{ + page: number + direction: string + amount: number + element?: number + }> = [] + const browser = { + getTabIdForPage: () => undefined, + scroll: async ( + page: number, + direction: string, + amount: number, + element?: number, + ) => { + calls.push({ page, direction, amount, element }) + }, + } as unknown as Browser + const ctx: ToolContext = { + browser, + directories: { workingDir: process.cwd() }, + } + + const result = await executeTool( + scroll, + { page: 7, direction: 'down', amount: 5 }, + ctx, + AbortSignal.timeout(1_000), + ) + + assert.ok(!result.isError, textOf(result)) + assert.ok(textOf(result).includes('Scrolled down')) + assert.deepStrictEqual(calls, [ + { page: 7, direction: 'down', amount: 5, element: undefined }, + ]) + assert.deepStrictEqual(structuredOf(result), { + action: 'scroll', + page: 7, + direction: 'down', + amount: 5, + element: undefined, }) - }, 60_000) + }) it('hover moves cursor over element', async () => { await withBrowser(async ({ execute }) => { diff --git a/packages/browseros-agent/apps/server/tests/tools/observation.test.ts b/packages/browseros-agent/apps/server/tests/tools/observation.test.ts index 1311df2eb..982296c64 100644 --- a/packages/browseros-agent/apps/server/tests/tools/observation.test.ts +++ b/packages/browseros-agent/apps/server/tests/tools/observation.test.ts @@ -203,7 +203,8 @@ describe('observation tools', () => { savedPath = data.path assert.strictEqual(data.writtenToFile, true) - assert.ok(textOf(contentResult).includes('Saved page content')) + assert.ok(textOf(contentResult).includes('Content truncated')) + assert.ok(textOf(contentResult).includes(savedPath)) assert.ok(existsSync(savedPath), 'Saved page content file should exist') assert.ok( dirname(savedPath).startsWith( diff --git a/packages/browseros-agent/apps/server/tests/tools/page-actions.test.ts b/packages/browseros-agent/apps/server/tests/tools/page-actions.test.ts index 5e6e8839f..69d047880 100644 --- a/packages/browseros-agent/apps/server/tests/tools/page-actions.test.ts +++ b/packages/browseros-agent/apps/server/tests/tools/page-actions.test.ts @@ -30,13 +30,13 @@ function structuredOf(result: { structuredContent?: unknown }): T { function createToolContext( browser: Browser, - executionDir: string, + workingDir: string, resourcesDir?: string, ): ToolContext { return { browser, directories: { - executionDir, + workingDir, resourcesDir, }, } @@ -50,10 +50,8 @@ function createBrowserStub(methods: Record): Browser { } describe('page action tools', () => { - it('save_pdf resolves relative paths against the execution directory by default', async () => { - const executionDir = await mkdtemp( - join(tmpdir(), 'browseros-page-actions-'), - ) + it('save_pdf resolves relative paths against the working directory by default', async () => { + const workingDir = await mkdtemp(join(tmpdir(), 'browseros-page-actions-')) const browser = createBrowserStub({ printToPDF: async () => ({ data: Buffer.from('pdf-data').toString('base64'), @@ -64,26 +62,24 @@ describe('page action tools', () => { const result = await executeTool( save_pdf, { page: 1, path: 'report.pdf' }, - createToolContext(browser, executionDir), + createToolContext(browser, workingDir), AbortSignal.timeout(1_000), ) assert.ok(!result.isError, textOf(result)) - const outputPath = join(executionDir, 'report.pdf') + const outputPath = join(workingDir, 'report.pdf') assert.strictEqual( structuredOf<{ path: string }>(result).path, outputPath, ) - assert.ok(existsSync(outputPath), 'PDF file should exist in executionDir') + assert.ok(existsSync(outputPath), 'PDF file should exist in workingDir') } finally { - await rm(executionDir, { recursive: true, force: true }) + await rm(workingDir, { recursive: true, force: true }) } }) it('save_screenshot still honors an explicit cwd override', async () => { - const executionDir = await mkdtemp( - join(tmpdir(), 'browseros-page-actions-'), - ) + const workingDir = await mkdtemp(join(tmpdir(), 'browseros-page-actions-')) const overrideDir = await mkdtemp(join(tmpdir(), 'browseros-page-actions-')) const browser = createBrowserStub({ screenshot: async () => ({ @@ -95,7 +91,7 @@ describe('page action tools', () => { const result = await executeTool( save_screenshot, { page: 1, path: 'capture.png', cwd: overrideDir }, - createToolContext(browser, executionDir), + createToolContext(browser, workingDir), AbortSignal.timeout(1_000), ) @@ -110,18 +106,18 @@ describe('page action tools', () => { 'Screenshot should exist in overrideDir', ) assert.ok( - !existsSync(join(executionDir, 'capture.png')), - 'Execution directory should not be used when cwd is provided', + !existsSync(join(workingDir, 'capture.png')), + 'Working directory should not be used when cwd is provided', ) } finally { - await rm(executionDir, { recursive: true, force: true }) + await rm(workingDir, { recursive: true, force: true }) await rm(overrideDir, { recursive: true, force: true }) } }) - it('download_file resolves relative directories against the execution directory by default', async () => { + it('download_file resolves relative directories against the working directory by default', async () => { const baseDir = await mkdtemp(join(tmpdir(), 'browseros-page-actions-')) - const executionDir = join(baseDir, 'execution') + const workingDir = join(baseDir, 'working') let stagingDir: string | undefined const browser = createBrowserStub({ downloadViaClick: async ( @@ -143,23 +139,23 @@ describe('page action tools', () => { const result = await executeTool( download_file, { page: 1, element: 7, path: '.' }, - createToolContext(browser, executionDir), + createToolContext(browser, workingDir), AbortSignal.timeout(1_000), ) assert.ok(!result.isError, textOf(result)) - const outputPath = join(executionDir, 'download.txt') + const outputPath = join(workingDir, 'download.txt') const structured = structuredOf<{ directory: string destinationPath: string }>(result) - assert.strictEqual(structured.directory, executionDir) + assert.strictEqual(structured.directory, workingDir) assert.strictEqual(structured.destinationPath, outputPath) - assert.ok(existsSync(outputPath), 'Download should land in executionDir') + assert.ok(existsSync(outputPath), 'Download should land in workingDir') assert.ok(stagingDir, 'Download should use a staging directory') assert.ok( - stagingDir.startsWith(join(executionDir, 'browseros-dl-')), - 'Staging directory should be created inside executionDir', + stagingDir.startsWith(join(workingDir, 'browseros-dl-')), + 'Staging directory should be created inside workingDir', ) assert.ok( !existsSync(stagingDir),