mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 12:55:51 +00:00
Squashed merge of: 1. fix/mcp-tsc-errors — 修复上游 MCP 重构后的 tsc 错误和测试失败 2. feat/pipe-mute-disconnect — Pipe IPC 逻辑断开、/lang 命令、mute 状态机 3. feat/stub-recovery-all — 实现全部 stub 恢复 (task 001-012) 4. feat/kairos-activation — KAIROS 激活解除阻塞 + 工具实现 5. codex/openclaw-autonomy-pr — 自治权限系统、运行记录、managed flows Additional: 6. daemon/job 命令层级化重构 (subcommand 架构) 7. 跨平台后台引擎抽象 (detached/tmux engines) 8. 修复 src/ 中 43 个预存在的 TypeScript 类型错误 9. 修复 langfuse isolated test mock 完整性 10. 修复 CodeRabbit 审查的 Critical/Major/Minor 问题 11. remote-control-server logger 抽象 (测试 stderr 静默化) 12. /simplify 审查修复 (代码复用、质量、效率)
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
/**
|
|
* Tests for src/jobs/state.ts
|
|
*
|
|
* Uses real temp directories and CLAUDE_CONFIG_DIR env var
|
|
* instead of mocking fs, to avoid cross-test mock pollution.
|
|
*/
|
|
import { describe, expect, test, beforeEach, afterAll } from 'bun:test'
|
|
import { mkdtempSync, rmSync, readFileSync, existsSync } from 'fs'
|
|
import { join } from 'path'
|
|
import { tmpdir } from 'os'
|
|
|
|
// ─── setup: real temp dir via env var ──────────────────────────────────────
|
|
|
|
const tempBase = mkdtempSync(join(tmpdir(), 'jobs-state-test-'))
|
|
|
|
beforeEach(() => {
|
|
// Each test gets a fresh config dir
|
|
const tempHome = mkdtempSync(join(tempBase, 'home-'))
|
|
process.env.CLAUDE_CONFIG_DIR = tempHome
|
|
})
|
|
|
|
afterAll(() => {
|
|
delete process.env.CLAUDE_CONFIG_DIR
|
|
try {
|
|
rmSync(tempBase, { recursive: true, force: true })
|
|
} catch {
|
|
// best-effort cleanup
|
|
}
|
|
})
|
|
|
|
// ─── import ─────────────────────────────────────────────────────────────────
|
|
|
|
const { createJob, readJobState, appendJobReply, getJobDir } = await import(
|
|
'../state.js'
|
|
)
|
|
|
|
// ─── tests ──────────────────────────────────────────────────────────────────
|
|
|
|
describe('createJob', () => {
|
|
test('creates job directory and writes state, template, and input files', () => {
|
|
const dir = createJob('job-1', 'my-template', '# Template', 'hello', [
|
|
'--flag',
|
|
])
|
|
expect(dir).toContain('job-1')
|
|
expect(existsSync(dir)).toBe(true)
|
|
|
|
const stateFile = join(dir, 'state.json')
|
|
expect(existsSync(stateFile)).toBe(true)
|
|
const state = JSON.parse(readFileSync(stateFile, 'utf-8'))
|
|
expect(state.jobId).toBe('job-1')
|
|
expect(state.templateName).toBe('my-template')
|
|
expect(state.status).toBe('created')
|
|
expect(state.args).toEqual(['--flag'])
|
|
|
|
expect(readFileSync(join(dir, 'template.md'), 'utf-8')).toBe('# Template')
|
|
expect(readFileSync(join(dir, 'input.txt'), 'utf-8')).toBe('hello')
|
|
})
|
|
})
|
|
|
|
describe('readJobState', () => {
|
|
test('returns null when job does not exist', () => {
|
|
expect(readJobState('nonexistent')).toBeNull()
|
|
})
|
|
|
|
test('returns parsed state when job exists', () => {
|
|
createJob('job-2', 'tpl', 'content', 'input', [])
|
|
const result = readJobState('job-2')
|
|
expect(result).not.toBeNull()
|
|
expect(result!.jobId).toBe('job-2')
|
|
expect(result!.status).toBe('created')
|
|
})
|
|
})
|
|
|
|
describe('appendJobReply', () => {
|
|
test('returns false when job does not exist', () => {
|
|
expect(appendJobReply('no-job', 'hello')).toBe(false)
|
|
})
|
|
|
|
test('appends reply and updates state', () => {
|
|
createJob('job-3', 'tpl', 'content', 'input', [])
|
|
|
|
const result = appendJobReply('job-3', 'my reply')
|
|
expect(result).toBe(true)
|
|
|
|
const dir = getJobDir('job-3')
|
|
const repliesPath = join(dir, 'replies.jsonl')
|
|
expect(existsSync(repliesPath)).toBe(true)
|
|
const replyLine = JSON.parse(readFileSync(repliesPath, 'utf-8').trim())
|
|
expect(replyLine.text).toBe('my reply')
|
|
})
|
|
})
|