mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-15 12:53:31 +08:00
Run required server and contract suites in credential-free sandboxes, fail closed on incomplete coverage or test output, and preserve the desktop active-turn permission guard across stale tab interactions.\n\nTested: bun run check:policy (115 pass); bun run check:server (1605 pass before final runner evidence check); bun run check:desktop; bun run check:provider-contract; bun run check:chat-contract\nConfidence: high\nScope-risk: broad
107 lines
3.9 KiB
TypeScript
107 lines
3.9 KiB
TypeScript
import { describe, expect, test } from 'bun:test'
|
|
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import {
|
|
createOfflineTestEnvironment,
|
|
createSandboxedTestEnvironment,
|
|
} from './test-environment'
|
|
|
|
describe('offline test environment', () => {
|
|
test('keeps ordinary runtime variables while removing credentials and local provider state', () => {
|
|
const environment = createOfflineTestEnvironment({
|
|
HOME: '/tmp/test-home',
|
|
XDG_CONFIG_HOME: '/tmp/test-home/.config',
|
|
CLAUDE_CONFIG_DIR: '/tmp/test-home/.claude',
|
|
}, {
|
|
Path: '/usr/bin',
|
|
CI: 'true',
|
|
DATABASE_URL: 'postgres://user:secret@database.example/app',
|
|
GITHUB_TOKEN: 'real-token',
|
|
ANTHROPIC_API_KEY: 'real-key',
|
|
ANTHROPIC_BASE_URL: 'https://provider.example',
|
|
CLAUDE_CLI_PATH: '/real/claude',
|
|
CC_HAHA_TRACE_PROVIDER_ID: 'real-provider',
|
|
Home: '/real/home',
|
|
HTTP_PROXY: 'http://proxy.example',
|
|
SSH_AUTH_SOCK: '/tmp/real-agent.sock',
|
|
XDG_CONFIG_HOME: '/real/config',
|
|
})
|
|
|
|
expect(environment.PATH).toBe('/usr/bin')
|
|
expect(environment.CI).toBe('true')
|
|
expect(environment.HOME).toBe('/tmp/test-home')
|
|
expect(environment.Home).toBeUndefined()
|
|
expect(environment.XDG_CONFIG_HOME).toBe('/tmp/test-home/.config')
|
|
expect(environment.CLAUDE_CONFIG_DIR).toBe('/tmp/test-home/.claude')
|
|
expect(environment.DATABASE_URL).toBeUndefined()
|
|
expect(environment.GITHUB_TOKEN).toBeUndefined()
|
|
expect(environment.ANTHROPIC_API_KEY).toBeUndefined()
|
|
expect(environment.ANTHROPIC_BASE_URL).toBeUndefined()
|
|
expect(environment.CLAUDE_CLI_PATH).toBeUndefined()
|
|
expect(environment.CC_HAHA_TRACE_PROVIDER_ID).toBeUndefined()
|
|
expect(environment.HTTP_PROXY).toBeUndefined()
|
|
expect(environment.SSH_AUTH_SOCK).toBeUndefined()
|
|
})
|
|
|
|
test('routes cross-platform user and temporary directories into one sandbox', () => {
|
|
const sandboxHome = mkdtempSync(join(tmpdir(), 'cc-haha-test-env-'))
|
|
try {
|
|
const environment = createSandboxedTestEnvironment(sandboxHome, {}, {
|
|
PATH: '/usr/bin',
|
|
APPDATA: '/real/app-data',
|
|
LOCALAPPDATA: '/real/local-app-data',
|
|
XDG_DATA_HOME: '/real/xdg-data',
|
|
})
|
|
|
|
expect(environment.APPDATA).toBe(join(sandboxHome, '.config'))
|
|
expect(environment.LOCALAPPDATA).toBe(join(sandboxHome, '.local'))
|
|
expect(environment.XDG_DATA_HOME).toBe(join(sandboxHome, '.local', 'share'))
|
|
expect(environment.TMPDIR).toBe(join(sandboxHome, 'tmp'))
|
|
expect(environment.NODE_ENV).toBe('test')
|
|
expect(environment.BUN_OPTIONS).toBe('--no-env-file')
|
|
expect(existsSync(environment.TMPDIR)).toBe(true)
|
|
} finally {
|
|
rmSync(sandboxHome, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
test('prevents descendant Bun processes from loading a workspace dotenv file', async () => {
|
|
const sandboxHome = mkdtempSync(join(tmpdir(), 'cc-haha-test-env-'))
|
|
const workspace = join(sandboxHome, 'workspace')
|
|
mkdirSync(workspace)
|
|
writeFileSync(
|
|
join(workspace, '.env'),
|
|
'CC_HAHA_DESCENDANT_DOTENV_SENTINEL=leaked\n',
|
|
'utf8',
|
|
)
|
|
|
|
try {
|
|
const proc = Bun.spawn(
|
|
[
|
|
'bun',
|
|
'-e',
|
|
'process.stdout.write(process.env.CC_HAHA_DESCENDANT_DOTENV_SENTINEL ?? "clean")',
|
|
],
|
|
{
|
|
cwd: workspace,
|
|
env: createSandboxedTestEnvironment(sandboxHome),
|
|
stdout: 'pipe',
|
|
stderr: 'pipe',
|
|
},
|
|
)
|
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
new Response(proc.stdout).text(),
|
|
new Response(proc.stderr).text(),
|
|
proc.exited,
|
|
])
|
|
|
|
expect(exitCode).toBe(0)
|
|
expect(stderr).toBe('')
|
|
expect(stdout).toBe('clean')
|
|
} finally {
|
|
rmSync(sandboxHome, { recursive: true, force: true })
|
|
}
|
|
})
|
|
})
|