import { afterEach, describe, expect, it } from 'bun:test'; import { mkdtempSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import type { UnifiedConfig } from '../../../../src/config/unified-config-types'; import { runBrowserSetup, type BrowserSetupDeps } from '../../../../src/utils/browser/browser-setup'; function createUnifiedConfig(userDataDir: string): UnifiedConfig { return { version: 12, default: undefined, profiles: {}, profile_targets: {}, copilot: { enabled: false, prompt: '', command: '', args: [], env: {}, auto_install: false, }, cursor: { enabled: false, model: '', port: 3891, daemon_mode: false, auth: { token: '', }, }, websearch: { enabled: false, providers: {}, }, browser: { claude: { enabled: false, user_data_dir: userDataDir, devtools_port: 9222, }, codex: { enabled: true, }, }, image_analysis: { enabled: false, providers: {}, }, global_env: {}, cliproxy_server: { mode: 'local', remote: { enabled: false, host: '', port: 0, protocol: 'http', auth_token: '', management_key: '', }, local: { port: 8085, auto_start: true, }, }, cliproxy_safety: { concurrent_limit: 1, cooldown_seconds: 0, shared_responsibility: false, }, quota_management: { enabled: false, }, thinking: { mode: 'auto', show_warnings: true, }, official_channels: { enabled: false, selected: [], unattended: false, }, dashboard_auth: { enabled: false, users: [], session_secret: '', }, logging: { enabled: true, profile_starts: true, delegation_calls: true, proxy_requests: false, quota_polls: false, }, }; } describe('browser setup', () => { let tempDir = ''; afterEach(() => { if (tempDir) { rmSync(tempDir, { recursive: true, force: true }); tempDir = ''; } }); it('enables Claude browser attach and prepares the managed default path', async () => { tempDir = mkdtempSync(join(tmpdir(), 'ccs-browser-setup-')); const config = createUnifiedConfig(join(tempDir, 'browser-profile')); config.browser.claude.user_data_dir = ''; const deps: BrowserSetupDeps = { getBrowserConfig: () => config.browser, mutateConfig: (mutator) => { mutator(config); return config; }, ensureBrowserMcp: () => true, getBrowserStatus: async () => ({ claude: { enabled: true, source: 'config', overrideActive: false, state: 'ready', title: 'Claude Browser Attach is ready.', detail: 'ready', nextStep: 'Launch Claude.', effectiveUserDataDir: config.browser.claude.user_data_dir, recommendedUserDataDir: config.browser.claude.user_data_dir, devtoolsPort: 9222, managedMcpServerName: 'ccs-browser', managedMcpServerPath: '/tmp/ccs-browser-server.cjs', launchCommands: { darwin: 'open -na "Google Chrome" --args', linux: 'google-chrome --remote-debugging-port=9222', win32: 'chrome.exe --remote-debugging-port=9222', }, }, codex: { enabled: true, state: 'enabled', title: 'Codex Browser Tools are enabled.', detail: 'ready', nextStep: 'Use Codex.', serverName: 'ccs_browser', supportsConfigOverrides: true, binaryPath: '/usr/local/bin/codex', }, }) as Awaited>, }; const result = await runBrowserSetup(deps); expect(result.configUpdated).toBe(true); expect(result.createdUserDataDir).toBe(true); expect(result.ready).toBe(true); expect(config.browser.claude.enabled).toBe(true); expect(config.browser.claude.user_data_dir).not.toBe(''); }); it('does not create a custom override path during setup', async () => { tempDir = mkdtempSync(join(tmpdir(), 'ccs-browser-setup-')); const config = createUnifiedConfig(join(tempDir, 'browser-profile')); config.browser.claude.enabled = true; const deps: BrowserSetupDeps = { getBrowserConfig: () => config.browser, mutateConfig: (mutator) => { mutator(config); return config; }, ensureBrowserMcp: () => true, getBrowserStatus: async () => ({ claude: { enabled: true, source: 'CCS_BROWSER_USER_DATA_DIR', overrideActive: true, state: 'browser_not_running', title: 'Claude Browser Attach could not find a running browser session.', detail: 'override active', nextStep: 'Run `ccs browser setup` to configure and start the managed browser session.', effectiveUserDataDir: config.browser.claude.user_data_dir, recommendedUserDataDir: config.browser.claude.user_data_dir, devtoolsPort: 9222, managedMcpServerName: 'ccs-browser', managedMcpServerPath: '/tmp/ccs-browser-server.cjs', launchCommands: { darwin: 'open -na "Google Chrome" --args', linux: 'google-chrome --remote-debugging-port=9222', win32: 'chrome.exe --remote-debugging-port=9222', }, }, codex: { enabled: true, state: 'enabled', title: 'Codex Browser Tools are enabled.', detail: 'ready', nextStep: 'Use Codex.', serverName: 'ccs_browser', supportsConfigOverrides: true, binaryPath: '/usr/local/bin/codex', }, }) as Awaited>, }; const result = await runBrowserSetup(deps); expect(result.createdUserDataDir).toBe(false); expect(result.overrideActive).toBe(false); expect(result.ready).toBe(false); expect(result.notes[0]).toContain('did not create the current browser user-data dir'); }); });