070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
116 lines
3.5 KiB
TypeScript
116 lines
3.5 KiB
TypeScript
import { mkdtemp, rm, utimes, writeFile } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
|
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
buildBrowserUseRunState,
|
|
collectBrowserUseDiscoveryFacts,
|
|
isBrowserUseRequested,
|
|
renderBrowserUseUnavailablePrompt,
|
|
} from '../src/browser-use-diagnostics.js';
|
|
|
|
let tempDir: string;
|
|
|
|
beforeEach(async () => {
|
|
tempDir = await mkdtemp(join(tmpdir(), 'browser-use-diagnostics-test-'));
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await rm(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('browser use diagnostics', () => {
|
|
it('detects Browser Use prompts from the Open Design Browser menu', () => {
|
|
expect(isBrowserUseRequested('hello')).toBe(false);
|
|
expect(isBrowserUseRequested('@agent-browser\n\nBrowser tab context:')).toBe(true);
|
|
expect(isBrowserUseRequested('Use the selected Open Design Browser tab as the bound target.')).toBe(true);
|
|
});
|
|
|
|
it('returns a missing-registry snapshot without reading socket contents', () => {
|
|
const facts = collectBrowserUseDiscoveryFacts({
|
|
registryPath: join(tempDir, 'missing'),
|
|
now: 1_000,
|
|
});
|
|
|
|
expect(facts).toMatchObject({
|
|
registryExists: false,
|
|
socketCount: 0,
|
|
candidateCount: 0,
|
|
staleCount: 0,
|
|
currentSessionIdPresent: null,
|
|
probeFailureCategory: 'registry-missing',
|
|
});
|
|
});
|
|
|
|
it('counts socket candidates and stale entries from the registry directory', async () => {
|
|
const fresh = join(tempDir, 'fresh-session.sock');
|
|
const stale = join(tempDir, 'old-session.sock');
|
|
await writeFile(fresh, '', 'utf8');
|
|
await writeFile(stale, '', 'utf8');
|
|
await writeFile(join(tempDir, 'note.txt'), 'not a socket', 'utf8');
|
|
await utimes(fresh, new Date(10_000), new Date(10_000));
|
|
await utimes(stale, new Date(1_000), new Date(1_000));
|
|
|
|
const facts = collectBrowserUseDiscoveryFacts({
|
|
registryPath: tempDir,
|
|
now: 11_000,
|
|
currentSessionId: 'fresh-session',
|
|
staleThresholdMs: 5_000,
|
|
});
|
|
|
|
expect(facts).toMatchObject({
|
|
registryExists: true,
|
|
socketCount: 2,
|
|
candidateCount: 2,
|
|
staleCount: 1,
|
|
currentSessionIdPresent: true,
|
|
probeFailureCategory: 'not-probed',
|
|
newestSocketAgeMs: 1_000,
|
|
staleThresholdMs: 5_000,
|
|
});
|
|
});
|
|
|
|
it('builds a typed unavailable state for Codex browser requests', () => {
|
|
const state = buildBrowserUseRunState({
|
|
requested: true,
|
|
agentId: 'codex',
|
|
diagnostics: collectBrowserUseDiscoveryFacts({
|
|
registryPath: join(tempDir, 'missing'),
|
|
}),
|
|
});
|
|
|
|
expect(state).toMatchObject({
|
|
requested: true,
|
|
available: false,
|
|
reason: 'no-matching-browser-backend',
|
|
});
|
|
});
|
|
|
|
it('leaves non-Codex browser requests outside this Codex-specific state', () => {
|
|
expect(buildBrowserUseRunState({
|
|
requested: true,
|
|
agentId: 'amr',
|
|
diagnostics: collectBrowserUseDiscoveryFacts({
|
|
registryPath: join(tempDir, 'missing'),
|
|
}),
|
|
})).toBeNull();
|
|
});
|
|
|
|
it('renders a prompt guard that blocks raw Chrome fallback', () => {
|
|
const state = buildBrowserUseRunState({
|
|
requested: true,
|
|
agentId: 'codex',
|
|
diagnostics: collectBrowserUseDiscoveryFacts({
|
|
registryPath: join(tempDir, 'missing'),
|
|
}),
|
|
});
|
|
|
|
const prompt = renderBrowserUseUnavailablePrompt(state);
|
|
|
|
expect(prompt).toContain('no-matching-browser-backend');
|
|
expect(prompt).toContain('Do not use raw Google Chrome headless');
|
|
});
|
|
});
|