Files
claude-code/packages/workflow-engine/src/__tests__/namedWorkflows.test.ts
claude-code-best d236880bc3 feat(workflow): add workflow engine, /workflows panel, /ultracode skill
将 feat/sdk-backend 分支中 workflow 相关的 20 个 commit 压缩为单 commit:

- 工作流引擎核心:phase / agent / parallel / pipeline 编排原语(packages/workflow-engine/)
- /workflows 面板:三区焦点布局(顶部 run tabs + 左侧 phase 侧栏 + 右侧 agent 列表)
- /ultracode skill:多 agent workflow 编排入口
- 进度存储 / journal / notification 系统
- WorkflowService 生命周期管理 + SentryErrorBoundary
- 脚本沙箱:禁用 dynamic import()、JSON args 防御性归一化
- journal 与 named-workflow 路径统一在 projectRoot
- 错误处理:parallel/pipeline hooks 错误日志、failure routing、semaphore abort
- workflow 工具升级为 core 工具 + PascalCase 命名

Co-Authored-By: glm-5.1 <zai-org@claude-code-best.win>
2026-06-13 20:07:18 +08:00

69 lines
2.2 KiB
TypeScript

import { expect, test } from 'bun:test'
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import {
listNamedWorkflows,
resolveNamedWorkflow,
} from '../engine/namedWorkflows.js'
test('按扩展名优先级解析命名 workflow', async () => {
const dir = await mkdtemp(join(tmpdir(), 'wf-named-'))
try {
await writeFile(
join(dir, 'a.ts'),
'export const meta = { name: "a", description: "d" }\nreturn 1',
)
await writeFile(join(dir, 'b.js'), 'return 2')
await writeFile(join(dir, 'c.mjs'), 'return 3')
await writeFile(join(dir, 'ignore.md'), '# not a workflow')
const a = await resolveNamedWorkflow(dir, 'a')
expect(a?.path.endsWith('a.ts')).toBe(true)
expect(a?.content).toContain('meta')
expect(await resolveNamedWorkflow(dir, 'missing')).toBeNull()
const names = await listNamedWorkflows(dir)
expect(names).toEqual(['a', 'b', 'c']) // 不含 .md
} finally {
await rm(dir, { recursive: true, force: true })
}
})
test('listNamedWorkflows 不存在目录返回空数组', async () => {
expect(
await listNamedWorkflows(join(tmpdir(), 'wf-nope-' + Date.now())),
).toEqual([])
})
test('resolveNamedWorkflow 在 .ts 缺失时降级到 .js/.mjs', async () => {
const dir = await mkdtemp(join(tmpdir(), 'wf-named-'))
try {
await writeFile(join(dir, 'onlyjs.js'), 'return 1')
await writeFile(join(dir, 'onlymjs.mjs'), 'return 2')
expect(
(await resolveNamedWorkflow(dir, 'onlyjs'))?.path.endsWith('onlyjs.js'),
).toBe(true)
expect(
(await resolveNamedWorkflow(dir, 'onlymjs'))?.path.endsWith(
'onlymjs.mjs',
),
).toBe(true)
} finally {
await rm(dir, { recursive: true, force: true })
}
})
test('listNamedWorkflows 返回排序后的名字', async () => {
const dir = await mkdtemp(join(tmpdir(), 'wf-named-'))
try {
await writeFile(join(dir, 'zeta.ts'), 'return 1')
await writeFile(join(dir, 'alpha.js'), 'return 2')
await writeFile(join(dir, 'mid.mjs'), 'return 3')
expect(await listNamedWorkflows(dir)).toEqual(['alpha', 'mid', 'zeta'])
} finally {
await rm(dir, { recursive: true, force: true })
}
})