Files
nexu-io--open-design/apps/daemon/tests/browser-use-diagnostics.test.ts
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:00:47 +08:00

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');
});
});