fix(browser): bootstrap managed attach profile setup

This commit is contained in:
Tam Nhu Tran committed 2026-04-18 17:18:14 -04:00
1 parent eaa37c749e
commit b52503300b
9 files changed
+388 -18

No files matched your search

@@ -1,10 +1,13 @@
import { afterEach, beforeEach, describe, expect, it, spyOn } from 'bun:test';
import { mkdtempSync, rmSync } from 'node:fs';
import { existsSync, mkdirSync, mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { mutateUnifiedConfig } from '../../../../src/config/unified-config-loader';
import * as chromeReuse from '../../../../src/utils/browser/chrome-reuse';
import { getBrowserStatus } from '../../../../src/utils/browser/browser-status';
import {
getBrowserStatus,
} from '../../../../src/utils/browser/browser-status';
import { resolveOptionalBrowserAttachRuntime } from '../../../../src/utils/browser/browser-settings';
import * as codexDetector from '../../../../src/targets/codex-detector';
describe('browser status', () => {
@@ -86,6 +89,48 @@ describe('browser status', () => {
}
});
it('bootstraps the managed default browser profile dir before reporting attach readiness', async () => {
mutateUnifiedConfig((config) => {
config.browser = {
claude: {
enabled: true,
user_data_dir: '',
devtools_port: 9222,
},
codex: {
enabled: true,
},
};
});
const runtimeSpy = spyOn(chromeReuse, 'resolveBrowserRuntimeEnv').mockRejectedValue(
new Error(
`Chrome reuse metadata not found: ${join(tempHome, '.ccs', 'browser', 'chrome-user-data', 'DevToolsActivePort')}`
)
);
const codexSpy = spyOn(codexDetector, 'getCodexBinaryInfo').mockReturnValue({
path: '/usr/local/bin/codex',
needsShell: false,
version: 'codex-cli 0.120.0',
features: ['config-overrides'],
});
try {
const status = await getBrowserStatus();
expect(status.claude.state).toBe('browser_not_running');
expect(status.claude.title).toBe(
'Claude Browser Attach is waiting for a managed Chrome session.'
);
expect(status.claude.detail).toContain('CCS created the managed browser profile');
expect(status.claude.nextStep).toContain('--remote-debugging-port=9222');
expect(existsSync(join(tempHome, '.ccs', 'browser', 'chrome-user-data'))).toBe(true);
} finally {
runtimeSpy.mockRestore();
codexSpy.mockRestore();
}
});
it('prefers CCS_BROWSER_USER_DATA_DIR over config when an env override is present', async () => {
mutateUnifiedConfig((config) => {
config.browser = {
@@ -169,6 +214,26 @@ describe('browser status', () => {
}
});
it('returns a managed attach warning when the configured DevTools port is unreachable', async () => {
const managedDir = join(tempHome, '.ccs', 'browser', 'chrome-user-data');
mkdirSync(managedDir, { recursive: true });
const runtime = await resolveOptionalBrowserAttachRuntime({
enabled: true,
source: 'config',
overrideActive: false,
userDataDir: managedDir,
devtoolsPort: 43123,
hasExplicitDevtoolsPort: true,
});
expect(runtime.runtimeEnv).toBeUndefined();
expect(runtime.warning).toContain(
'could not reach the attach-mode DevTools endpoint for the managed browser profile'
);
expect(runtime.warning).toContain('continue without browser tools');
});
it('preserves legacy metadata-based port discovery when only CCS_BROWSER_PROFILE_DIR is set', async () => {
process.env.CCS_BROWSER_PROFILE_DIR = '/legacy-browser';