test(browser): guard the identity capability and harden two weak assertions

Pins the mixed-version guarantee that had no test: browser.identity.v1 is advertised when the identity store is initialized and absent when it is not. Verified discriminating -- advertising it unconditionally fails the test.

The profileCreate rejection test asserted ok:false against a runtime with no browserProfileCreate, so that assertion passed even when the retired field was accepted. It now stubs a working runtime method, making ok:false load-bearing, and asserts the runtime is never reached.

Removes the persistence fixture's dead failIdentityWrite branch on writeFileAtomically: nothing on that path calls it, so it implied a second write mechanism that does not exist. Failure is injected through node:fs, which is what the identity write actually uses.
This commit is contained in:
Brennan Benson
2026-09-14 19:20:44 -07:00
parent f8cf6b4d86
commit 13a346147d
3 changed files with 32 additions and 5 deletions
@@ -164,10 +164,9 @@ function installModuleMocks(
fsState.files.set(targetKey, value)
}
}),
// Nothing on this path calls writeFileAtomically; it is here only to keep the module shape
// complete. The identity write goes through node:fs above, which is where failure is injected.
writeFileAtomically: vi.fn((pathValue: string, data: string) => {
if (failIdentityWrite && pathValue.endsWith('browser-identity-mode.json')) {
throw new Error('read-only userData')
}
const key = fsKey(pathValue)
fsState.files.set(key, data)
fsState.present.add(key)
@@ -23,8 +23,29 @@ import {
attachClientBrowserHost,
publishClientHostedPage
} from '../orca-runtime-test-scenario-builders.spec'
import { mkdtempSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import {
initializeBrowserIdentityModeStore,
resetBrowserIdentityModeStoreForTests
} from '../../browser/browser-identity-mode-store'
describe('OrcaRuntimeService', () => {
// The mixed-version guarantee: a host that never initialized the identity store must not
// advertise a method that can only throw there.
it('advertises the browser identity capability only where an identity store exists', () => {
resetBrowserIdentityModeStoreForTests()
expect(createRuntime().getStatus().capabilities).not.toContain('browser.identity.v1')
initializeBrowserIdentityModeStore(mkdtempSync(join(tmpdir(), 'orca-identity-capability-')))
try {
expect(createRuntime().getStatus().capabilities).toContain('browser.identity.v1')
} finally {
resetBrowserIdentityModeStoreForTests()
}
})
it('advertises headless browser capability when an offscreen backend backs a windowless host', () => {
const runtime = createRuntime()
runtime.setOffscreenBrowserBackend({ createTab: vi.fn(), closeTab: vi.fn() })
+9 -2
View File
@@ -77,8 +77,12 @@ describe('browser RPC methods', () => {
// The schema check above proves the shape; this proves an older client actually gets the
// rejection over the wire instead of a success with the field quietly dropped.
it('rejects the retired profile user-agent field through the dispatcher', async () => {
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: params parsing fails before any runtime member is read.
const runtime = { getRuntimeId: () => 'test-runtime' } as unknown as OrcaRuntimeService
const browserProfileCreate = vi.fn().mockResolvedValue({ id: 'profile-1' })
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the dispatcher reads only getRuntimeId and the single browser method stubbed here.
const runtime = {
getRuntimeId: () => 'test-runtime',
browserProfileCreate
} as unknown as OrcaRuntimeService
const dispatcher = new RpcDispatcher({ runtime, methods: BROWSER_CORE_METHODS })
const response = await dispatcher.dispatch(
@@ -89,8 +93,11 @@ describe('browser RPC methods', () => {
})
)
// Why a working runtime stub: if the field were accepted and stripped again the call would
// succeed, so every assertion below is load-bearing rather than passing on a missing method.
expect(response).toMatchObject({ ok: false })
expect(JSON.stringify(response)).toContain('browser_profile_user_agent_mode_is_now_app_wide')
expect(browserProfileCreate).not.toHaveBeenCalled()
})
it('routes core browser automation commands to the runtime server', async () => {