Files
nexu-io__open-design/apps/daemon/tests/browser-use-diagnostics.test.ts
Joey-nexu f1a0b60c6c chore: unify product name display to OpenDesign repo-wide (#6998)
* chore: unify product name display to OpenDesign repo-wide

Rename the user-facing product name from "Open Design" to "OpenDesign"
across documentation, web/desktop UI strings, i18n locales, prompts,
plugin/skill/design-system content, changelogs, and specs, matching the
landing-page rename already in flight.

Deliberately excluded so installed-app identity stays untouched:
- packages/release PRODUCT_NAME and everything derived from it
  (app bundle names, installer/registry identity, updater feeds)
- tools/pack, tools/release, apps/packaged, landing page (PR #6983)
- mocks/ recorded traces and LICENSE
- test fixtures and comments that encode real on-disk install paths
  (Open Design.app, Program Files\Open Design, AppData paths)

Validated with pnpm guard, pnpm typecheck, and targeted web/desktop/host
test runs over the renamed strings.

* fix(web): keep two-letter author monogram for CamelCase brand names

authorInitials split words on whitespace only, so the renamed single-token
author name "OpenDesign" produced a one-letter monogram. Treat lower-to-upper
CamelCase boundaries as word breaks so the avatar fallback stays "OD".

* fix(release): restore spaced Windows source artifact names in win.ps1

tools/pack still derives builder outputs from the unchanged PRODUCT_NAME
("Open Design"), so the asset script must look for the spaced filenames.
Matches the mac/mac-intel/linux asset scripts, which were already kept on
the original names.

---------

Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com>
2026-08-18 07:09:45 +00: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/index.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 OpenDesign Browser menu', () => {
expect(isBrowserUseRequested('hello')).toBe(false);
expect(isBrowserUseRequested('@agent-browser\n\nBrowser tab context:')).toBe(true);
expect(isBrowserUseRequested('Use the selected OpenDesign 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');
});
});