mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
test: exercise boundary assertions and repair audit fixtures (#33483)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
@@ -85,7 +85,11 @@ describe('agent TypeScript LSP diagnostics bridge', () => {
|
||||
|
||||
it('re-pulls open documents when the server asks for a refresh', () => {
|
||||
const { bridge, client, server, flush, pulls } = harness({})
|
||||
bridge.fromClient(edit(1))
|
||||
bridge.fromClient({
|
||||
jsonrpc: '2.0',
|
||||
method: 'textDocument/didOpen',
|
||||
params: { textDocument: { uri, version: 1, languageId: 'typescript', text: 'v1' } }
|
||||
})
|
||||
flush()
|
||||
bridge.fromServer({ jsonrpc: '2.0', id: 'srv-1', method: 'workspace/diagnostic/refresh' })
|
||||
flush()
|
||||
@@ -113,18 +117,20 @@ describe('agent TypeScript LSP diagnostics bridge', () => {
|
||||
encodeLspMessage({ id: 2 })
|
||||
])
|
||||
read(frames.subarray(0, 7))
|
||||
read(frames.subarray(7, 30))
|
||||
read(frames.subarray(30))
|
||||
const split = frames.indexOf(Buffer.from('é')) + 1
|
||||
read(frames.subarray(7, split))
|
||||
read(frames.subarray(split))
|
||||
expect(received).toEqual([{ id: 1, text: 'héllo' }, { id: 2 }])
|
||||
})
|
||||
|
||||
it('is the server every committed agent config launches', () => {
|
||||
it('wires Claude and OpenCode to the repository language server', () => {
|
||||
const plugin = JSON.parse(
|
||||
readFileSync(join(repoRoot, 'config/agent-plugins/orca-typescript/.lsp.json'), 'utf8')
|
||||
)
|
||||
const opencode = JSON.parse(readFileSync(join(repoRoot, 'opencode.json'), 'utf8'))
|
||||
const script = 'config/scripts/agent-typescript-lsp.mjs'
|
||||
expect(existsSync(join(repoRoot, script))).toBe(true)
|
||||
expect(plugin['orca-typescript'].command).toBe('node')
|
||||
expect(plugin['orca-typescript'].args).toEqual([`\${CLAUDE_PROJECT_DIR}/${script}`])
|
||||
expect(opencode.lsp['orca-typescript'].command).toEqual(['node', script])
|
||||
})
|
||||
|
||||
@@ -31,7 +31,12 @@ it('limits typecheck to the projects a tree reaches', () => {
|
||||
'config/tsconfig.node.json',
|
||||
'config/tsconfig.tc.web.json'
|
||||
])
|
||||
expect(plan(['src/packages/process-host/src/run-process.ts']).typecheckProjects).toHaveLength(4)
|
||||
expect(plan(['src/packages/process-host/src/run-process.ts']).typecheckProjects).toEqual([
|
||||
'config/tsconfig.node.json',
|
||||
'config/tsconfig.tc.web.json',
|
||||
'config/tsconfig.tc.cli.json',
|
||||
'src/packages/process-host/tsconfig.test.json'
|
||||
])
|
||||
})
|
||||
|
||||
it('keeps Vitest full-run triggers out of the related set and runs their colocated tests', () => {
|
||||
|
||||
@@ -78,16 +78,19 @@ describe('dropInheritedDevInstanceEnv', () => {
|
||||
ORCA_USER_DATA_PATH: '/profiles/parent',
|
||||
ORCA_DEV_USER_DATA_PATH: '/profiles/parent'
|
||||
}
|
||||
dropInheritedDevInstanceEnv(inherited, '/worktrees/child')
|
||||
expect(inherited).toEqual({ ORCA_USER_DATA_PATH: '/profiles/parent' })
|
||||
|
||||
const explicit = { ...inherited, ORCA_DEV_USER_DATA_PATH: '/profiles/mine' }
|
||||
dropInheritedDevInstanceEnv(explicit, '/worktrees/child')
|
||||
expect(explicit.ORCA_DEV_USER_DATA_PATH).toBe('/profiles/mine')
|
||||
|
||||
const same = { ...inherited }
|
||||
dropInheritedDevInstanceEnv(same, '/worktrees/parent')
|
||||
expect(same).toEqual(inherited)
|
||||
|
||||
const explicit = { ...inherited, ORCA_DEV_USER_DATA_PATH: '/profiles/mine' }
|
||||
dropInheritedDevInstanceEnv(explicit, '/worktrees/child')
|
||||
expect(explicit).toEqual({
|
||||
ORCA_USER_DATA_PATH: '/profiles/parent',
|
||||
ORCA_DEV_USER_DATA_PATH: '/profiles/mine'
|
||||
})
|
||||
|
||||
dropInheritedDevInstanceEnv(inherited, '/worktrees/child')
|
||||
expect(inherited).toEqual({ ORCA_USER_DATA_PATH: '/profiles/parent' })
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { DatabaseSync } from 'node:sqlite'
|
||||
import { tmpdir } from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { createDefaultLocalOrcaProfile } from '../../src/shared/orca-profiles'
|
||||
import { seedDevProfile } from './dev-profile-seed.mjs'
|
||||
|
||||
const roots = []
|
||||
@@ -27,14 +28,15 @@ function hashTree(dir) {
|
||||
function createSourceProfile() {
|
||||
const root = mkdtempSync(path.join(tmpdir(), 'orca-seed-source-'))
|
||||
roots.push(root)
|
||||
const profileDir = path.join(root, 'profiles', 'local-default')
|
||||
const profile = createDefaultLocalOrcaProfile(0)
|
||||
const profileDir = path.join(root, 'profiles', profile.id)
|
||||
mkdirSync(profileDir, { recursive: true })
|
||||
writeFileSync(
|
||||
path.join(root, 'orca-profile-index.json'),
|
||||
JSON.stringify({
|
||||
schemaVersion: 1,
|
||||
activeProfileId: 'local-default',
|
||||
profiles: [{ id: 'local-default' }]
|
||||
activeProfileId: profile.id,
|
||||
profiles: [profile]
|
||||
})
|
||||
)
|
||||
writeFileSync(path.join(profileDir, 'account-session.json.enc'), '{"ciphertext":"x"}')
|
||||
@@ -57,7 +59,7 @@ function createSourceProfile() {
|
||||
}
|
||||
|
||||
describe('seedDevProfile', () => {
|
||||
it('writes an importable slim profile and never changes the source', async () => {
|
||||
it('copies durable profile domains and the account file without changing the source', async () => {
|
||||
const source = createSourceProfile()
|
||||
const before = hashTree(source)
|
||||
const target = path.join(mkdtempSync(path.join(tmpdir(), 'orca-seed-target-')), 'profile')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { existsSync, mkdirSync, mkdtempSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join, resolve } from 'node:path'
|
||||
import { dirname, join, resolve } from 'node:path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { legacy7zaRelativePath, resolve7zaPath } from './resolve-7za-path.mjs'
|
||||
@@ -26,13 +26,23 @@ describe('7za path resolution for the Windows signing gates (#6487)', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('prefers a real legacy binary over the downloaded toolset', async () => {
|
||||
// Only meaningful if a transitive dep reintroduces the package.
|
||||
const legacy = join(projectRoot, ...legacy7zaRelativePath())
|
||||
if (!existsSync(legacy)) {
|
||||
return
|
||||
it('prefers an existing legacy file over the downloaded toolset', async () => {
|
||||
const scratch = mkdtempSync(join(tmpdir(), 'orca 7za legacy '))
|
||||
const previous = process.env.ELECTRON_BUILDER_7ZIP_PATH
|
||||
try {
|
||||
delete process.env.ELECTRON_BUILDER_7ZIP_PATH
|
||||
const legacy = join(scratch, ...legacy7zaRelativePath())
|
||||
mkdirSync(dirname(legacy), { recursive: true })
|
||||
writeFileSync(legacy, 'legacy binary fixture')
|
||||
await expect(resolve7zaPath(scratch)).resolves.toBe(legacy)
|
||||
} finally {
|
||||
if (previous === undefined) {
|
||||
delete process.env.ELECTRON_BUILDER_7ZIP_PATH
|
||||
} else {
|
||||
process.env.ELECTRON_BUILDER_7ZIP_PATH = previous
|
||||
}
|
||||
rmSync(scratch, { recursive: true, force: true })
|
||||
}
|
||||
await expect(resolve7zaPath(projectRoot)).resolves.toBe(legacy)
|
||||
})
|
||||
|
||||
it('resolves an executable 7za that can extract an archive', async () => {
|
||||
|
||||
@@ -65,7 +65,7 @@ async function prepared() {
|
||||
}
|
||||
|
||||
describe('WSL SQLite runtime preparation', () => {
|
||||
it('returns immediately, coalesces distro aliases, and uses an actual guest SQLite probe', async () => {
|
||||
it('returns immediately, coalesces distro aliases, and requests the guest SQLite probe', async () => {
|
||||
let release: (value: ReturnType<typeof success>) => void = () => {}
|
||||
mocks.run.mockReturnValueOnce(
|
||||
new Promise((resolve) => {
|
||||
@@ -128,7 +128,7 @@ describe('WSL SQLite runtime preparation', () => {
|
||||
await prepared()
|
||||
})
|
||||
|
||||
it('rejects a guest Node without the SyncDatabase surface and tolerates its stderr warning', async () => {
|
||||
it('checks the generated SQLite probe against missing API and stderr warnings locally', async () => {
|
||||
await prepared()
|
||||
const probe = mocks.run.mock.calls.find(([spec]) => spec.program === 'node')?.[0]
|
||||
expect(probe?.args[0]).toBe('-e')
|
||||
@@ -161,7 +161,7 @@ describe('WSL SQLite runtime preparation', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('falls back to the pinned Node in the runtimes/ store, verified in the guest, with literal argv', async () => {
|
||||
it('requests pinned runtime verification and preserves literal argv', async () => {
|
||||
const expected = NODE_RUNTIME_ASSETS['linux-arm64-musl'].executableSha256
|
||||
mocks.run.mockImplementation(async (spec) => {
|
||||
if (spec.script?.startsWith('data=')) {
|
||||
@@ -278,7 +278,7 @@ describe('WSL SQLite runtime preparation', () => {
|
||||
})
|
||||
|
||||
it.skipIf(process.platform === 'win32').each(['opencode', 'zcode'] as const)(
|
||||
'prepares a %s-only distro despite unrelated OpenCode overrides',
|
||||
'presence script finds %s-only data despite unrelated OpenCode overrides',
|
||||
async (agent) => {
|
||||
await prepared()
|
||||
const script = mocks.run.mock.calls[0]?.[0].script
|
||||
|
||||
@@ -72,13 +72,20 @@ describe('runtime AI Vault session scanner', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('surfaces project scope truncation from the runtime transport bound', async () => {
|
||||
it('caps forwarded project paths and reports scope truncation', async () => {
|
||||
const scopePaths = Array.from({ length: 80 }, (_, index) => `/srv/repo-${index}`)
|
||||
|
||||
const scanResult = await scanRuntimeAiVaultSessions('/user-data', 'env-1', {
|
||||
scopePaths
|
||||
})
|
||||
|
||||
expect(mocks.callRuntimeEnvironment).toHaveBeenCalledWith(
|
||||
'/user-data',
|
||||
'env-1',
|
||||
'aiVault.listSessions',
|
||||
expect.objectContaining({ scopePaths: scopePaths.slice(0, 64) }),
|
||||
undefined
|
||||
)
|
||||
expect(scanResult.issues).toContainEqual(
|
||||
expect.objectContaining({
|
||||
kind: 'scope',
|
||||
|
||||
@@ -18,7 +18,7 @@ const ROVO_ROOT = join(HOME, '.rovodev', 'sessions')
|
||||
const GROK_ROOT = join(HOME, '.grok', 'sessions')
|
||||
|
||||
describe('validateAiVaultSessionDeleteTarget', () => {
|
||||
it('allows a canonical Cline manifest and removes its whole session directory', () => {
|
||||
it('plans whole session-directory removal for a canonical Cline manifest', () => {
|
||||
const root = join('/tmp', 'cline-sessions')
|
||||
const sessionId = '1786466194549_xrzrl'
|
||||
const sessionDir = join(root, sessionId)
|
||||
@@ -312,7 +312,7 @@ describe('validateAiVaultSessionDeleteTarget', () => {
|
||||
})
|
||||
|
||||
describe('directory-shaped agents', () => {
|
||||
it('plans claude companions before the transcript, so a failure keeps the row', () => {
|
||||
it('plans claude companions before the transcript', () => {
|
||||
const filePath = join(CLAUDE_ROOT, '-proj', 'sess-1.jsonl')
|
||||
const result = validateAiVaultSessionDeleteTarget({
|
||||
agent: 'claude',
|
||||
@@ -403,7 +403,7 @@ describe('directory-shaped agents', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("removes rovo's session directory, not just the metadata.json inside it", () => {
|
||||
it("plans removal of rovo's whole session directory", () => {
|
||||
const result = validateAiVaultSessionDeleteTarget({
|
||||
agent: 'rovo',
|
||||
filePath: join(ROVO_ROOT, 'sess-1', 'metadata.json'),
|
||||
@@ -419,7 +419,7 @@ describe('directory-shaped agents', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("removes grok's session directory under its encoded-cwd group", () => {
|
||||
it("plans removal of grok's session directory under its encoded-cwd group", () => {
|
||||
const result = validateAiVaultSessionDeleteTarget({
|
||||
agent: 'grok',
|
||||
filePath: join(GROK_ROOT, '-Users-me-proj', 'sess-1', 'summary.json'),
|
||||
|
||||
@@ -167,7 +167,7 @@ describe('deleteAiVaultSessionFile', () => {
|
||||
expect(tryDeleteWslUncPathMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('delegates a WSL UNC file to tryDeleteWslUncPath (non-recursive) and never calls trashItem', async () => {
|
||||
it('uses a successful WSL-helper result before local file trash', async () => {
|
||||
const filePath = join(GEMINI_ROOT, 'project-a', 'session-1.json')
|
||||
tryDeleteWslUncPathMock.mockResolvedValue(true)
|
||||
|
||||
@@ -182,7 +182,7 @@ describe('deleteAiVaultSessionFile', () => {
|
||||
expect(trashItemMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('deletes a WSL UNC directory-shaped session recursively, never via trashItem', async () => {
|
||||
it('requests recursive helper removal for a directory-shaped session', async () => {
|
||||
// WSL UNC volumes cannot use Trash and may give unreliable 9P stats.
|
||||
tryDeleteWslUncPathMock.mockResolvedValue(true)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ beforeEach(() => {
|
||||
reader.v2.mockReset().mockResolvedValue({ firstUserPrompt: 'full second-schema prompt' })
|
||||
})
|
||||
|
||||
it('asks the host reader for the full prompt instead of opening SQLite in the calling process', async () => {
|
||||
it('requests the full prompt through the host reader', async () => {
|
||||
expect(
|
||||
await readAiVaultFirstUserPrompt({
|
||||
agent: 'opencode',
|
||||
@@ -74,7 +74,7 @@ it('does not substitute local history for a remote session', async () => {
|
||||
expect(reader.v1).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('degrades a failed guest read to an unavailable prompt', async () => {
|
||||
it('degrades a failed host-reader request to an unavailable prompt', async () => {
|
||||
reader.v1.mockRejectedValue(new Error('guest stopped'))
|
||||
expect(
|
||||
await readAiVaultFirstUserPrompt({
|
||||
|
||||
@@ -351,6 +351,9 @@ describe('session parse cache persistence', () => {
|
||||
resume: null
|
||||
})
|
||||
await vi.advanceTimersByTimeAsync(1_000)
|
||||
if (second === 14) {
|
||||
expect(write).toHaveBeenCalledOnce()
|
||||
}
|
||||
}
|
||||
expect(write).toHaveBeenCalledOnce()
|
||||
await flushSessionParseCachePersist()
|
||||
|
||||
Reference in New Issue
Block a user