test: remove low-value provider and renderer assertions (#40279)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-11-09 10:11:48 +00:00
committed by GitHub
co-authored by OrcaWin
parent 0684ef586f
commit 19afa64ee7
20 changed files with 5 additions and 944 deletions
File diff suppressed because one or more lines are too long
@@ -1,79 +0,0 @@
import { mkdtemp, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { AgentSessionJournalIdentity } from '../../shared/agent-session/journal/agent-session-journal-identity'
import { openAgentSessionJournal } from '../native-chat/agent-session-journal/journal-store-factory'
import { createDeferredStructuredAgentSessionEventSink } from '../native-chat/agent-session-wire/journal-ingress/structured-agent-session-event-sink'
import { createClaudeJournalTranslator } from './structured/journal/claude-structured-journal-translation'
import {
closeTestJournalHostDatabases,
openTestJournalHostDatabase
} from '../native-chat/agent-session-journal/store-lifecycle/journal-host-database-test-support'
import { testEventSinkLogging } from '../native-chat/agent-session-wire/host/testing/structured-agent-session-logger-test-support'
import { claudeProviderHandle } from '../../shared/agent-session/lifecycle/agent-session-provider-handle-encoding'
const IDENTITY: AgentSessionJournalIdentity = {
sessionId: 'session-1',
workspaceId: 'workspace-1',
hostId: 'host-1',
agent: 'claude',
providerHandle: claudeProviderHandle('provider-1', 'leaf-1')
}
/** Informational frame shape from CLI 2.1.280. */
function informational(
level: 'info' | 'notice' | 'suggestion' | 'warning',
content: string
): Record<string, unknown> {
return {
type: 'system',
subtype: 'informational',
content,
level,
uuid: `5d3c1f0e-7a2b-4c6d-9e8f-00000000000${level.length}`,
session_id: 'provider-1'
}
}
let root = ''
beforeEach(async () => {
root = await mkdtemp(join(tmpdir(), 'orca-claude-informational-'))
})
afterEach(async () => {
await closeTestJournalHostDatabases()
await rm(root, { recursive: true, force: true })
})
async function itemsFor(frames: Record<string, unknown>[]) {
const journal = await openAgentSessionJournal({
identity: IDENTITY,
database: openTestJournalHostDatabase(root),
now: () => 1_700_000_000_000,
mintEpoch: () => 'epoch-1'
})
const deferred = createDeferredStructuredAgentSessionEventSink(testEventSinkLogging())
deferred.bind({ journal, fence: 1, publish: vi.fn() })
const translator = createClaudeJournalTranslator({ sink: deferred.sink, fallbackIdPrefix: '1' })
for (const frame of frames) {
translator.handle({ type: 'message', sessionId: 'orca-session', message: frame })
await deferred.drained()
}
return journal.snapshot().items.map((item) => item.body)
}
describe('a Claude informational frame', () => {
it.each(['info', 'notice', 'suggestion'] as const)('writes no row at level %s', async (level) => {
expect(await itemsFor([informational(level, `A ${level} note`)])).toEqual([])
})
it('writes its own words as one warning row at level warning', async () => {
const content =
'UserPromptSubmit operation blocked by hook: secrets are not allowed\n\nOriginal prompt: deploy it'
const items = await itemsFor([informational('warning', content)])
expect(items).toEqual([{ kind: 'status', tone: 'warning', text: content }])
})
})
@@ -55,7 +55,6 @@ describe('claude model catalog probe', () => {
it.each([
[[], [], ['/orca-probe', '/orca-probe'], 'user,project,local'],
[['node_modules/claude/cli.js'], [], ['/chat-a', '/chat-b'], 'user'],
[['--env-file=work env', '--', 'claude'], [], ['/chat-a', '/chat-b'], 'user'],
[[], ['--settings', 'settings.json'], ['/chat-a', '/chat-b'], 'user']
])(
'lists prefix %j with arguments %j from %j, reading %s settings',
@@ -14,7 +14,7 @@ import { HOST_TEST_SESSION as SESSION } from '../../native-chat/agent-session-wi
const claudeTurnEnds = (connection: Parameters<typeof claudeFrame>[0]) =>
claudeFrame(connection, { type: 'system', subtype: 'session_state_changed', state: 'idle' })
it.each(['low', 'high', undefined])(
it.each(['high', undefined])(
'admits accepted high independently of resolved effort (effective %s)',
async (effective) => {
const models = [
@@ -46,16 +46,6 @@ const SETTINGS = {
effective: { model: 'haiku' },
sources: [{ source: 'userSettings', settings: { model: 'haiku' } }],
applied: { model: 'claude-haiku-4-5-20251001', effort: null, advisor: null, ultracode: false }
},
envSonnet: {
effective: {},
sources: [],
applied: { model: 'claude-sonnet-5', effort: 'high', advisor: null, ultracode: false }
},
settingsHaikuEnvSonnet: {
effective: { model: 'haiku' },
sources: [{ source: 'userSettings', settings: { model: 'haiku' } }],
applied: { model: 'claude-sonnet-5', effort: 'high', advisor: null, ultracode: false }
}
}
@@ -69,29 +59,7 @@ function startedWithoutATurn(settings: unknown) {
})
}
async function readCurrent(settings: unknown) {
const adapter = await acquired(startedWithoutATurn(settings))
return (await adapter.readOptions({ sessionId: 'session-1', fence: 7 })).current
}
describe('Claude model before the first turn', () => {
it.each([
['nothing overrides the default', SETTINGS.noOverride, 'claude-opus-5-5[1m]', 'medium'],
['settings name a model', SETTINGS.settingsHaiku, 'claude-haiku-4-5-20251001', undefined],
['the env names a model', SETTINGS.envSonnet, 'claude-sonnet-5', 'high'],
['the env overrides the settings', SETTINGS.settingsHaikuEnvSonnet, 'claude-sonnet-5', 'high']
])(
'names what Claude will apply when %s, unconfirmed',
async (_case, settings, model, effort) => {
const current = await readCurrent(settings)
expect(current.model).toBe(model)
expect(current.effort).toBe(effort)
expect(current.confirmed ?? []).not.toContain('model')
expect(current.confirmed ?? []).not.toContain('effort')
}
)
it('uses native applied effort despite settings High, before and after a reply', async () => {
// Claude Code 2.1.318: no flag applies Medium; --effort low applies Low.
const claude = startedWithoutATurn({
@@ -156,13 +124,6 @@ describe('Claude model before the first turn', () => {
await adapter.closeAll()
})
it('marks an unknown applied model as defaulted for the host to resolve', async () => {
const current = await readCurrent({ effective: {}, sources: [] })
expect(current.defaulted).toEqual(['model'])
expect(current.effort).toBeUndefined()
})
it('lets the first turn confirm or correct it', async () => {
const claude = startedWithoutATurn(SETTINGS.settingsHaiku)
const adapter = await acquired(claude)
@@ -3,7 +3,6 @@ import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, expect, it, vi } from 'vitest'
import {
claudeChildEnv,
resolveClaudeChildEnvSources,
withOrcaClaudeEntrypoint
} from './claude-structured-child-env'
@@ -32,21 +31,6 @@ it('resolves a custom Claude command against the login shell PATH', async () =>
}
})
it('names Orca as the Claude client unless the launch environment sets one', () => {
const sources = {
command: 'claude',
prefixArgs: [],
overlay: undefined,
inheritedEnv: { CLAUDE_CODE_ENTRYPOINT: 'cli' }
}
const options = { runtimeOnPath: false }
expect(claudeChildEnv(sources, undefined, options).CLAUDE_CODE_ENTRYPOINT).toBe('orca')
const overlay = { CLAUDE_CODE_ENTRYPOINT: 'custom' }
expect(claudeChildEnv({ ...sources, overlay }, undefined, options).CLAUDE_CODE_ENTRYPOINT).toBe(
'custom'
)
})
it('keeps a differently cased Windows launch value over the Orca default', () => {
const inherited = { Claude_Code_Entrypoint: 'cli', PATH: 'C:\\bin' }
expect(
@@ -15,12 +15,7 @@ const MODEL_ROW = {
}
describe('codex model catalog probe', () => {
it.each([
[[]],
[['node_modules/@openai/codex/bin/codex.js']],
[['--env-file=work env', '--', 'codex']],
[['-c', 'model_instructions_file="./prompt.md"']]
])(
it.each([[[]]])(
"lists a command line with arguments %j from Orca's folder for every chat",
async (prefixArgs) => {
// The chat's repo never picks the list, so no listing runs in a chat's folder.
@@ -1,167 +0,0 @@
import { EventEmitter } from 'node:events'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
const { childSpawnMock, resolveCodexCommandMock, ptySpawnMock } = vi.hoisted(() => ({
childSpawnMock: vi.fn(),
resolveCodexCommandMock: vi.fn(),
ptySpawnMock: vi.fn()
}))
// Keep child-process assertions in this suite; worker transport is covered separately.
vi.mock(
'../../../worker-thread-child-process/worker-thread-child-process',
() =>
import('../../../worker-thread-child-process/worker-thread-child-process-in-process.test-fixtures')
)
vi.mock('node:child_process', () => ({
spawn: childSpawnMock
}))
// Mock recovery so its process-table import does not require real execFile.
vi.mock('../../../codex/history/index/codex-state-db-backfill-recovery', () => ({
startCodexStateDbBackfillRecoveryInBackground: vi.fn()
}))
vi.mock('../../../codex-cli/command', () => ({
resolveCodexCommand: resolveCodexCommandMock
}))
vi.mock('node-pty', () => ({
spawn: ptySpawnMock
}))
vi.mock('./codex-auth-presence', () => ({
probeCodexAuthPresence: vi.fn(() => 'present')
}))
import { fetchCodexRateLimits } from './codex-fetcher'
function makeRpcChild() {
const child = new EventEmitter() as EventEmitter & {
stdout: EventEmitter
stderr: EventEmitter
stdin: EventEmitter & { write: ReturnType<typeof vi.fn>; end: ReturnType<typeof vi.fn> }
kill: ReturnType<typeof vi.fn>
exitCode: number | null
}
child.stdout = new EventEmitter()
child.stderr = new EventEmitter()
// Graceful shutdown must wait for EOF/signal to produce exit, as real app-server does.
const exitNow = (): void => {
child.exitCode = 0
child.emit('exit', 0, null)
}
child.stdin = Object.assign(new EventEmitter(), { write: vi.fn(), end: vi.fn(exitNow) })
child.exitCode = null
child.kill = vi.fn(() => {
exitNow()
return true
})
return child
}
describe('fetchCodexRateLimits auth errors', () => {
beforeEach(() => {
vi.useFakeTimers()
vi.clearAllMocks()
resolveCodexCommandMock.mockReturnValue('codex')
vi.stubGlobal('fetch', vi.fn())
})
afterEach(() => {
vi.unstubAllGlobals()
})
it('returns Codex RPC auth refresh errors without masking them behind a fallback', async () => {
const rpcChild = makeRpcChild()
const authError =
'Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.'
childSpawnMock.mockReturnValue(rpcChild)
rpcChild.stdin.write.mockImplementation((line: string) => {
const msg = JSON.parse(line) as { id?: number; method?: string }
if (msg.method === 'initialize') {
setTimeout(() => {
rpcChild.stdout.emit(
'data',
Buffer.from(`${JSON.stringify({ jsonrpc: '2.0', id: msg.id, result: {} })}\n`)
)
}, 0)
}
if (msg.method === 'account/rateLimits/read') {
setTimeout(() => {
rpcChild.stdout.emit(
'data',
Buffer.from(
`${JSON.stringify({
jsonrpc: '2.0',
id: msg.id,
error: { code: -32000, message: authError }
})}\n`
)
)
}, 0)
}
})
const resultPromise = fetchCodexRateLimits()
await vi.advanceTimersByTimeAsync(1)
await vi.advanceTimersByTimeAsync(1)
await expect(resultPromise).resolves.toMatchObject({
provider: 'codex',
session: null,
weekly: null,
status: 'error',
error: authError
})
expect(fetch).not.toHaveBeenCalled()
expect(ptySpawnMock).not.toHaveBeenCalled()
})
it('returns the app-server chatgpt-auth-required error without falling back', async () => {
const rpcChild = makeRpcChild()
const authError = 'chatgpt authentication required to read rate limits'
childSpawnMock.mockReturnValue(rpcChild)
rpcChild.stdin.write.mockImplementation((line: string) => {
const msg = JSON.parse(line) as { id?: number; method?: string }
if (msg.method === 'initialize') {
setTimeout(() => {
rpcChild.stdout.emit(
'data',
Buffer.from(`${JSON.stringify({ jsonrpc: '2.0', id: msg.id, result: {} })}\n`)
)
}, 0)
}
if (msg.method === 'account/rateLimits/read') {
setTimeout(() => {
rpcChild.stdout.emit(
'data',
Buffer.from(
`${JSON.stringify({
jsonrpc: '2.0',
id: msg.id,
error: { code: -32600, message: authError }
})}\n`
)
)
}, 0)
}
})
const resultPromise = fetchCodexRateLimits()
await vi.advanceTimersByTimeAsync(1)
await vi.advanceTimersByTimeAsync(1)
await expect(resultPromise).resolves.toMatchObject({
provider: 'codex',
session: null,
weekly: null,
status: 'error',
error: authError
})
expect(fetch).not.toHaveBeenCalled()
expect(ptySpawnMock).not.toHaveBeenCalled()
})
})
@@ -1,206 +0,0 @@
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type * as RunProcess from '@orca/process-host'
const { ptySpawnMock, resolveCodexCommandMock, stubScript } = vi.hoisted(() => ({
stubScript: { path: '' },
ptySpawnMock: vi.fn(),
resolveCodexCommandMock: vi.fn()
}))
// Run the Node fixture through the real process chokepoint; worker transport has separate coverage.
vi.mock(
'../../../worker-thread-child-process/worker-thread-child-process',
() =>
import('../../../worker-thread-child-process/worker-thread-child-process-in-process.test-fixtures')
)
vi.mock('@orca/process-host', async (importOriginal) => {
const actual = await importOriginal<typeof RunProcess>()
return {
...actual,
spawnProcess: (spec: Parameters<typeof actual.spawnProcess>[0]) =>
actual.spawnProcess({
...spec,
program: process.execPath,
args: [stubScript.path, ...(spec.args ?? [])]
})
}
})
vi.mock('../../../codex-cli/command', () => ({
resolveCodexCommand: resolveCodexCommandMock
}))
vi.mock('node-pty', () => ({
spawn: ptySpawnMock
}))
vi.mock('./codex-auth-presence', () => ({
probeCodexAuthPresence: vi.fn(() => 'present')
}))
vi.mock('../../../codex/history/index/codex-state-db', () => ({
isCodexStateDbBackfillPending: vi.fn(() => false)
}))
vi.mock('../../../codex/history/index/codex-state-db-backfill-recovery', () => ({
startCodexStateDbBackfillRecoveryInBackground: vi.fn(() => Promise.resolve(null))
}))
import { fetchCodexRateLimits } from './codex-fetcher'
const STUB_CODEX_SOURCE = `
const expectedArgs = [
'-c',
'approval_policy=never',
'-c',
'features.plugins=false',
'-s',
'read-only',
'-a',
'never',
'app-server'
]
if (JSON.stringify(process.argv.slice(2)) !== JSON.stringify(expectedArgs)) {
process.stderr.write(
"error: invalid value 'untrusted' for '--ask-for-approval <APPROVAL_POLICY>'\\n" +
' [possible values: on-request, never]\\n'
)
process.exit(2)
}
if (process.env.CODEX_HOME !== process.env.ORCA_EXPECTED_CODEX_HOME) {
process.stderr.write('managed CODEX_HOME was not preserved\\n')
process.exit(3)
}
if (process.env.ORCA_EXPECTED_PROXY_ENV) {
for (const [key, value] of Object.entries(JSON.parse(process.env.ORCA_EXPECTED_PROXY_ENV))) {
if (process.env[key] !== value) {
process.stderr.write('probe proxy environment mismatch: ' + key + '\\n')
process.exit(4)
}
}
}
let buffer = ''
function send(message) {
process.stdout.write(JSON.stringify(message) + '\\n')
}
process.stdin.setEncoding('utf8')
process.stdin.on('data', (chunk) => {
buffer += chunk
let newlineIndex
while ((newlineIndex = buffer.indexOf('\\n')) !== -1) {
const line = buffer.slice(0, newlineIndex).trim()
buffer = buffer.slice(newlineIndex + 1)
if (!line) continue
const message = JSON.parse(line)
if (message.method === 'initialize') {
send({ id: message.id, result: { userAgent: 'codex-contract/0.149.0' } })
continue
}
if (message.method === 'account/rateLimits/read') {
send({
id: message.id,
result: {
rateLimits: {
primary: { usedPercent: 17, windowDurationMins: 300 },
secondary: { usedPercent: 29, windowDurationMins: 10080 }
}
}
})
}
}
})
process.stdin.on('end', () => process.exit(0))
`
let tempRoot: string
let stubPath: string
let previousExpectedHome: string | undefined
describe('Codex rate-limit process contract', () => {
beforeEach(() => {
tempRoot = mkdtempSync(join(tmpdir(), 'orca-codex-rate-limit-contract-'))
stubPath = join(tempRoot, 'codex-contract.cjs')
writeFileSync(stubPath, STUB_CODEX_SOURCE)
previousExpectedHome = process.env.ORCA_EXPECTED_CODEX_HOME
process.env.ORCA_EXPECTED_CODEX_HOME = join(tempRoot, 'managed-codex-home')
resolveCodexCommandMock.mockReturnValue('codex')
stubScript.path = stubPath
})
afterEach(() => {
vi.unstubAllEnvs()
if (previousExpectedHome === undefined) {
delete process.env.ORCA_EXPECTED_CODEX_HOME
} else {
process.env.ORCA_EXPECTED_CODEX_HOME = previousExpectedHome
}
rmSync(tempRoot, { recursive: true, force: true })
vi.clearAllMocks()
})
it('starts a read-only non-interactive app-server with the managed home', async () => {
await expect(
fetchCodexRateLimits({
codexHomePath: process.env.ORCA_EXPECTED_CODEX_HOME
})
).resolves.toMatchObject({
provider: 'codex',
session: { usedPercent: 17, windowMinutes: 300 },
weekly: { usedPercent: 29, windowMinutes: 10080 },
status: 'ok',
error: null
})
expect(ptySpawnMock).not.toHaveBeenCalled()
})
it.each(['localhost;*.fixture.invalid', ''])(
'passes configured proxy and bypass %j to the actual probe',
async (bypassRules) => {
const proxy = 'http://proxy.fixture.invalid:8080'
const expected = {
HTTP_PROXY: proxy,
HTTPS_PROXY: proxy,
ALL_PROXY: proxy,
http_proxy: proxy,
https_proxy: proxy,
all_proxy: proxy,
NO_PROXY: bypassRules.replaceAll(';', ','),
no_proxy: bypassRules.replaceAll(';', ',')
}
vi.stubEnv('NO_PROXY', 'inherited.invalid')
vi.stubEnv('no_proxy', 'inherited.invalid')
vi.stubEnv('ORCA_EXPECTED_PROXY_ENV', JSON.stringify(expected))
await expect(
fetchCodexRateLimits({
codexHomePath: process.env.ORCA_EXPECTED_CODEX_HOME,
networkProxySettings: { httpProxyUrl: proxy, httpProxyBypassRules: bypassRules }
})
).resolves.toMatchObject({ status: 'ok', session: { usedPercent: 17 } })
expect(process.env.NO_PROXY).toBe('inherited.invalid')
}
)
it.each([undefined, { httpProxyUrl: '' }, { httpProxyUrl: 'file:///invalid-proxy' }])(
'preserves inherited proxy settings when app settings are unset or invalid: %j',
async (networkProxySettings) => {
const inherited = {
HTTPS_PROXY: 'http://inherited.fixture.invalid:8080',
NO_PROXY: 'fixture.invalid'
}
for (const [key, value] of Object.entries(inherited)) {
vi.stubEnv(key, value)
}
vi.stubEnv('ORCA_EXPECTED_PROXY_ENV', JSON.stringify(inherited))
await expect(
fetchCodexRateLimits({
codexHomePath: process.env.ORCA_EXPECTED_CODEX_HOME,
networkProxySettings
})
).resolves.toMatchObject({ status: 'ok', session: { usedPercent: 17 } })
}
)
})
@@ -86,29 +86,6 @@ describe('Codex RPC exit diagnostics', () => {
vi.clearAllMocks()
})
it('names the exit code and what the child reported', async () => {
const result = await runStub(
"error: invalid value 'untrusted' for '--ask-for-approval <APPROVAL_POLICY>'\n" +
" [possible values: on-request, never]\n\nFor more information, try '--help'.\n",
2
)
expect(result.error).toContain('Codex RPC process exited (exit code 2)')
expect(result.error).toContain("invalid value 'untrusted'")
expect(result.error).toContain("try '--help'")
})
it('classifies a dead refresh token so the re-auth warning fires', async () => {
const result = await runStub(
'2026-08-20T18:04:11.221Z INFO codex_core::auth: refreshing ChatGPT tokens\n' +
'ERROR: The ChatGPT access token could not be refreshed; please sign in again.\n',
1
)
expect(result.error).toBe('Your ChatGPT session could not be refreshed. Please sign in again.')
expect(isCodexAuthError(result.error)).toBe(true)
})
it('keeps the re-auth phrase that path redaction would swallow', async () => {
const result = await runStub(
`ERROR: /Users/haris/.codex/auth.json is stale — please sign in again.\n`,
@@ -6,16 +6,6 @@ function record(...fields: string[]): string {
}
describe('WSL Claude plugin metadata', () => {
it('decodes present files and retains missing files as null', () => {
const settings = JSON.stringify({ enabledPlugins: { 'plugin@market': true } })
const output = [
record('F', '0', '1', Buffer.from(settings).toString('base64')),
record('F', '1', '0', '')
].join('')
expect(parseWslClaudePluginMetadataOutput(output, 2)).toEqual([settings, null])
})
it('rejects malformed metadata responses', () => {
expect(() => parseWslClaudePluginMetadataOutput(record('F', '4', '1', ''), 1)).toThrow(
'invalid response'
@@ -1,4 +1,4 @@
import { chmod, lstat, mkdir, mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises'
import { chmod, mkdir, mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { gunzipSync, gzipSync } from 'node:zlib'
@@ -136,33 +136,6 @@ describe('skill package creation and extraction', () => {
).rejects.toThrow('skill-package-tar-truncated')
})
it('cancels during streamed extraction and removes partial bytes', async () => {
const root = await temporaryDirectory()
const created = await createSkillPackageArchive({
sourceDirectory: await createSkill(root),
archivePath: join(root, 'package.tar.gz'),
packageId: 'package_1',
versionId: 'version_1'
})
let checks = 0
const signal = {
get aborted() {
checks += 1
return checks >= 3
}
} as AbortSignal
const destinationDirectory = join(root, 'cancelled-extraction')
await expect(
extractSkillPackageArchive({
archivePath: created.archivePath,
destinationDirectory,
signal
})
).rejects.toThrow('skill-install-cancelled')
await expect(lstat(destinationDirectory)).rejects.toMatchObject({ code: 'ENOENT' })
})
it('rejects content checksum and SKILL identity mismatches', async () => {
const root = await temporaryDirectory()
const created = await createSkillPackageArchive({
@@ -69,23 +69,4 @@ describe('SkillSharePreparationService', () => {
expect(prepared.skills?.[0]?.executablePaths).toEqual(['run.sh'])
})
it('enforces the preparation cap while archives are still being created', async () => {
const { root, source } = await createSource()
const service = new SkillSharePreparationService(join(root, 'preparations'), {
findOwnedPackageId: nameIsFree,
publishVersion: vi.fn(),
createShare: vi.fn()
})
const results = await Promise.allSettled(
Array.from({ length: 9 }, () => service.prepare({ sourceDirectory: source }))
)
expect(results.filter((result) => result.status === 'fulfilled')).toHaveLength(8)
expect(results.filter((result) => result.status === 'rejected')).toHaveLength(1)
expect(results.find((result) => result.status === 'rejected')).toMatchObject({
reason: new Error('skill-share-preparation-limit')
})
})
})
@@ -102,28 +102,6 @@ it('keeps the branch checkout strip open after selecting a badge context-menu ac
expect(container.querySelector('form')?.textContent).toContain('Check out branch topic?')
})
it('renders converging branch lanes and a detached root without duplicate child keys', async () => {
const errors = vi.spyOn(console, 'error').mockImplementation(() => {})
getHistory.mockReset().mockResolvedValue({
...result,
items: [
{ id: 'a', subject: 'a', message: 'a', parentIds: ['root'] },
{ id: 'b', subject: 'b', message: 'b', parentIds: ['root'] },
{ id: 'c', subject: 'c', message: 'c', parentIds: ['root'] },
{ id: 'detached', subject: 'detached', message: 'detached', parentIds: [] },
{ id: 'root', subject: 'root', message: 'root', parentIds: [] }
]
})
await act(async () =>
root.render(
<TooltipProvider>
<GitGraphTab worktreeId={workspaceId} />
</TooltipProvider>
)
)
expect(errors.mock.calls.filter(([message]) => String(message).includes('same key'))).toEqual([])
})
it('recovers silently after each later token expiry and ignores refreshes for other worktrees', async () => {
let history: ReturnType<typeof useGitGraphHistory>
function History() {
@@ -18,9 +18,6 @@ import {
useNativeChatDisclosures
} from '../../messages/disclosure/native-chat-disclosure-store'
import { i18n } from '@/i18n/i18n'
import { TranslationScopeProvider } from '@/i18n/translation-scope-provider'
{
const QUESTION = 'What would you like me to do next in this repo?'
const ASK_INPUT = { questions: [{ question: QUESTION }] }
@@ -288,66 +285,3 @@ import { TranslationScopeProvider } from '@/i18n/translation-scope-provider'
})
})
}
{
function runHeader(container: HTMLElement): HTMLElement {
const header = container.querySelector('button')
if (!header) {
throw new Error('run header did not render')
}
return header
}
describe('tool run sentences', () => {
afterEach(async () => {
cleanup()
await i18n.changeLanguage('en')
})
it('relabels an already-mounted run and its rows when the UI language changes', async () => {
const blocks: NativeChatBlock[] = [
{ type: 'tool-call', name: 'Bash', input: { command: 'false' }, state: 'failed' },
{ type: 'tool-result', output: 'exit 1', isError: true },
{
type: 'tool-call',
name: 'Agent',
input: { description: 'explore settings' },
state: 'completed'
}
]
const { container } = render(
<NativeChatToolRun
blocks={blocks}
backgroundTasks={[
{
type: 'background-task',
taskId: 'workflow-1',
kind: 'workflow',
label: 'task',
state: 'blocked',
outputFile: '/tmp/result.txt'
}
]}
expandSignal
/>,
{ wrapper: TranslationScopeProvider }
)
const header = runHeader(container)
expect(header).toHaveTextContent('Ran 1 command and ran 1 agent · 1 failed')
expect(screen.getByText('Subagent')).toBeInTheDocument()
expect(screen.getByText('Background workflow')).toBeInTheDocument()
expect(screen.getByText('Output: /tmp/result.txt')).toBeInTheDocument()
await act(async () => {
await i18n.changeLanguage('es')
})
expect(header).toHaveTextContent('Se ejecutó 1 comando y se ejecutó 1 agente · 1 fallidas')
expect(header).toHaveAccessibleName(/Llamadas a herramientas fallidas: 1/)
expect(screen.getByText('Subagente')).toBeInTheDocument()
expect(screen.getByText('Flujo de trabajo en segundo plano')).toBeInTheDocument()
expect(screen.getByText('Salida: /tmp/result.txt')).toBeInTheDocument()
expect(screen.getByText('bloqueado · con error')).toBeInTheDocument()
})
})
}
@@ -1,57 +0,0 @@
import { afterAll, describe, expect, it } from 'vitest'
import { i18n } from '@/i18n/i18n'
import { getDeveloperPermissionsPaneSearchEntries } from './developer-permissions-search'
import { matchesSettingsSearch } from '../search/settings-search'
// Use macOS 26’s actual Local Network translations (SecurityPrivacyExtension LOCAL_NETWORK).
const MACOS_LOCAL_NETWORK_LABEL = {
en: 'local network',
es: 'red local',
ja: 'ローカルネットワーク',
ko: '로컬 네트워크',
zh: '本地网络'
} as const
function getLanEntry() {
const entry = getDeveloperPermissionsPaneSearchEntries().find((candidate) =>
candidate.keywords?.includes('usb')
)
if (!entry) {
throw new Error('LAN, USB, and Bluetooth search entry is missing')
}
return entry
}
async function searchInLocale(locale: string, query: string): Promise<boolean> {
await i18n.changeLanguage(locale)
return matchesSettingsSearch(query, getLanEntry())
}
describe('developer permissions LAN search', () => {
afterAll(async () => {
await i18n.changeLanguage('en')
})
it.each(Object.entries(MACOS_LOCAL_NETWORK_LABEL))(
'finds the LAN row from the macOS Local Network wording in %s',
async (locale, label) => {
expect(await searchInLocale(locale, label)).toBe(true)
}
)
it('keeps the English LAN aliases findable in every locale', async () => {
for (const locale of Object.keys(MACOS_LOCAL_NETWORK_LABEL)) {
for (const query of ['lan', 'local network', 'local-network']) {
expect(await searchInLocale(locale, query)).toBe(true)
}
}
})
it('keeps the localized LAN wording findable', async () => {
expect(await searchInLocale('zh', '局域网')).toBe(true)
expect(await searchInLocale('ja', 'LAN')).toBe(true)
expect(await searchInLocale('ko', 'LAN')).toBe(true)
expect(await searchInLocale('es', 'LAN')).toBe(true)
})
})
@@ -1,49 +0,0 @@
import { afterEach, describe, expect, it } from 'vitest'
import {
agentTabActionId,
getKeybindingDefinition
} from '../../../../../shared/keybindings/definitions'
import type {
KeybindingActionId,
KeybindingDefinition
} from '../../../../../shared/keybindings/types'
import { i18n } from '@/i18n/i18n'
import { localizeKeybindingDefinition } from './keybinding-title-copy'
function definition(actionId: KeybindingActionId): KeybindingDefinition {
const found = getKeybindingDefinition(actionId)
if (!found) {
throw new Error(`missing ${actionId}`)
}
return found
}
describe('localizeKeybindingDefinition', () => {
afterEach(async () => {
await i18n.changeLanguage('en')
})
it('localizes built-in titles, keeps English searchable, and leaves plugin titles alone', async () => {
await i18n.changeLanguage('ko')
const quickOpen = definition('worktree.quickOpen')
const localized = localizeKeybindingDefinition(quickOpen)
expect(localized.title).not.toBe(quickOpen.title)
expect(localized.group).not.toBe(quickOpen.group)
expect(localized.searchKeywords).toEqual(
expect.arrayContaining([quickOpen.title, quickOpen.group])
)
const agentTab = definition(agentTabActionId('claude'))
const agentTitle = localizeKeybindingDefinition(agentTab).title
expect(agentTitle).not.toBe(agentTab.title)
expect(agentTitle).toContain('Claude')
const plugin: KeybindingDefinition = {
...quickOpen,
id: 'plugin:orca-samples.tasks/open',
title: 'Open Tasks — Tasks',
group: 'Plugins'
}
expect(localizeKeybindingDefinition(plugin)).toBe(plugin)
})
})
@@ -1,49 +0,0 @@
// @vitest-environment happy-dom
import { cleanup, render, screen } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createGlobalSettingsFixture } from '../../../../../shared/global-settings-test-fixture'
import { useAppStore } from '../../../store'
import { TerminalInteractionSection } from './TerminalInteractionSection'
const i18nMock = vi.hoisted(() => {
const translations: Record<string, string> = {}
return { language: 'en', translations }
})
vi.mock('@/i18n/i18n', () => ({
translate: (key: string, defaultValue: string) => i18nMock.translations[key] ?? defaultValue,
i18n: i18nMock
}))
vi.mock('@/i18n/localized-catalog', () => ({
createLocalizedCatalog: (factory: () => unknown) => factory
}))
describe('TerminalInteractionSection scroll on input', () => {
beforeEach(() => {
useAppStore.setState({ settingsSearchQuery: '' })
})
afterEach(() => {
cleanup()
i18nMock.language = 'en'
i18nMock.translations = {}
})
it('keeps the row visible for a localized search keyword', () => {
i18nMock.language = 'de'
i18nMock.translations = { 'components.settings.terminal.search.snap': 'einrasten' }
useAppStore.setState({ settingsSearchQuery: 'einrasten' })
render(
<TerminalInteractionSection
settings={createGlobalSettingsFixture()}
updateSettings={vi.fn()}
searchQuery="einrasten"
/>
)
expect(screen.getByRole('switch', { name: 'Scroll to Bottom on Input' })).toBeTruthy()
})
})
@@ -2,12 +2,10 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { BrowserPage, BrowserWorkspace } from '../../../../../shared/browser-workspace-types'
import type { FolderWorkspace } from '../../../../../shared/folder-workspaces/folder-workspace-types'
import type { Tab, TabGroup } from '../../../../../shared/tab-types'
import type { Worktree } from '../../../../../shared/worktree/types'
import '../../../../../shared/constants'
import { ORCA_BROWSER_BLANK_URL } from '../../../../../shared/browser/browser-blank-page'
import { folderWorkspaceKey } from '../../../../../shared/workspace-scope'
import { useAppStore } from '@/store/index'
import type { AppState } from '@/store/types'
@@ -44,25 +42,6 @@ function makeWorktree(overrides: Partial<Worktree> = {}): Worktree {
}
}
function makeFolderWorkspace(overrides: Partial<FolderWorkspace> = {}): FolderWorkspace {
return {
id: 'folder-1',
projectGroupId: 'project-1',
name: 'Remote folder',
folderPath: '/workspace/folder-1',
linkedTask: null,
comment: '',
isArchived: false,
isUnread: false,
isPinned: false,
sortOrder: 0,
lastActivityAt: 0,
createdAt: 0,
updatedAt: 0,
...overrides
}
}
function makeWorkspace(overrides: Partial<BrowserWorkspace> = {}): BrowserWorkspace {
return {
id: 'ws-1',
@@ -150,26 +129,6 @@ describe('activateBrowserPagePaletteResult', () => {
seedStore()
})
it('activates an SSH worktree through its paired-runtime owner alias', () => {
seedStore({
worktreesByRepo: {
'repo-1': [
makeWorktree({
hostId: 'ssh:private-target',
runtimeOwnerEnvironmentId: 'paired-host'
})
]
}
})
expect(
activateBrowserPagePaletteResult({ ...target, executionHostId: 'runtime:paired-host' }).status
).toBe('activated')
expect(mocks.activateAndRevealWorkspace).toHaveBeenCalledWith('wt-1', {
executionHostId: 'runtime:paired-host'
})
})
it('rejects colliding child ids before mutating either host', () => {
seedStore({
worktreesByRepo: {
@@ -196,41 +155,6 @@ describe('activateBrowserPagePaletteResult', () => {
expect(mocks.activateAndRevealWorkspace).not.toHaveBeenCalled()
})
it('keeps browser workspaces with distinct unified tabs in multiple groups activatable', () => {
seedStore({
unifiedTabsByWorktree: {
'wt-1': [makeBrowserTab(), makeBrowserTab({ id: 'second-view', groupId: 'group-2' })]
},
groupsByWorktree: {
'wt-1': [
makeGroup(),
makeGroup({ id: 'group-2', activeTabId: 'second-view', tabOrder: ['second-view'] })
]
}
})
expect(activateBrowserPagePaletteResult(target).status).toBe('activated')
})
it('activates pages in remote folder workspaces', () => {
const worktreeId = folderWorkspaceKey('folder-1')
seedStore({
worktreesByRepo: {},
folderWorkspaces: [makeFolderWorkspace({ executionHostId: 'ssh:host-1' })],
browserTabsByWorktree: { [worktreeId]: [makeWorkspace({ worktreeId })] },
browserPagesByWorkspace: { 'ws-1': [makePage({ worktreeId })] },
unifiedTabsByWorktree: { [worktreeId]: [makeBrowserTab({ worktreeId })] },
groupsByWorktree: { [worktreeId]: [makeGroup({ worktreeId })] },
activeGroupIdByWorktree: { [worktreeId]: 'group-1' }
})
expect(
activateBrowserPagePaletteResult({ pageId: 'page-1', workspaceId: 'ws-1', worktreeId })
).toMatchObject({ status: 'activated' })
expect(mocks.activateAndRevealWorkspace).toHaveBeenCalledWith(worktreeId, {
executionHostId: 'ssh:host-1'
})
})
it('derives the focus target from the page url captured before worktree activation', () => {
seedStore({
browserPagesByWorkspace: {
@@ -608,32 +608,3 @@ it('replaces the full unaccepted extent, accepts once, and preserves promoted ch
expect(reopened.delegated).toEqual(expect.arrayContaining(['model', 'effort']))
expect(agentPickerEffectiveChoices(entry, reopened).model).toBeUndefined()
})
it('orders raw and control picks once and gives one-shot and sparse consumers the same choices', () => {
const selection = canonicalSourceControlActionSelection({ agentId: 'claude', agentArgs: '' })
for (const edits of [
[
{ kind: 'arguments', text: '--model sonnet --effort high --debug' },
{ kind: 'choice', patch: { model: 'opus' } }
],
[
{ kind: 'choice', patch: { model: 'opus' } },
{ kind: 'arguments', text: '--model sonnet --effort high --debug' }
]
] satisfies AgentPickerEdit[][]) {
const draft = acceptAgentPickerArguments(
entry,
edits.reduce(
(value, edit) => applyAgentPickerEdit(entry, value, edit),
sourceControlPickerDraft(selection, entry, 'terminal')
)
)
const saved = project(applySourceControlPickerDraft(selection, entry, draft))
const chat = agentPickerLaunchInputs({ ...draft, surface: 'chat' }, entry)
expect(saved.sessionOptions?.model).toBe(chat.sessionOptions?.model)
expect(saved.sessionOptions?.effort).toBe(chat.sessionOptions?.effort)
expect(saved.agentArgs).toBe('--debug')
expect(agentPickerLaunchInputs(draft, entry).agentArgs).toContain('--debug')
expect(draft.pendingArguments).toBeUndefined()
}
})