mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-23 00:35:51 +00:00
feat: 添加 GitHub 集成命令(issue、share、autofix-pr)
- /issue: 通过 gh CLI 创建 GitHub issue,支持标签/指派 - /share: 会话日志分享到 GitHub Gist,支持密钥脱敏 - /autofix-pr: 自动修复 CI 失败的 PR,进度追踪 - launchCommand: 共享命令启动器 Co-Authored-By: glm-5-turbo <zai-org@claude-code-best.win>
This commit is contained in:
79
src/commands/autofix-pr/__tests__/monitorState.test.ts
Normal file
79
src/commands/autofix-pr/__tests__/monitorState.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { beforeEach, describe, expect, test } from 'bun:test'
|
||||
import {
|
||||
clearActiveMonitor,
|
||||
getActiveMonitor,
|
||||
isMonitoring,
|
||||
setActiveMonitor,
|
||||
trySetActiveMonitor,
|
||||
} from '../monitorState.js'
|
||||
|
||||
function makeState(
|
||||
overrides?: Partial<Parameters<typeof setActiveMonitor>[0]>,
|
||||
) {
|
||||
return {
|
||||
taskId: 'task-1',
|
||||
owner: 'acme',
|
||||
repo: 'myrepo',
|
||||
prNumber: 42,
|
||||
abortController: new AbortController(),
|
||||
startedAt: Date.now(),
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
describe('monitorState', () => {
|
||||
beforeEach(() => {
|
||||
clearActiveMonitor()
|
||||
})
|
||||
|
||||
test('getActiveMonitor returns null when nothing set', () => {
|
||||
expect(getActiveMonitor()).toBeNull()
|
||||
})
|
||||
|
||||
test('setActiveMonitor stores state and getActiveMonitor returns it', () => {
|
||||
const state = makeState()
|
||||
setActiveMonitor(state)
|
||||
expect(getActiveMonitor()).toBe(state)
|
||||
})
|
||||
|
||||
test('clearActiveMonitor resets state to null', () => {
|
||||
setActiveMonitor(makeState())
|
||||
clearActiveMonitor()
|
||||
expect(getActiveMonitor()).toBeNull()
|
||||
})
|
||||
|
||||
test('isMonitoring returns true for matching owner/repo/prNumber', () => {
|
||||
setActiveMonitor(makeState())
|
||||
expect(isMonitoring('acme', 'myrepo', 42)).toBe(true)
|
||||
})
|
||||
|
||||
test('isMonitoring returns false when not monitoring', () => {
|
||||
expect(isMonitoring('acme', 'myrepo', 42)).toBe(false)
|
||||
})
|
||||
|
||||
test('setActiveMonitor throws when already active', () => {
|
||||
setActiveMonitor(makeState())
|
||||
expect(() => setActiveMonitor(makeState({ prNumber: 99 }))).toThrow(
|
||||
/Monitor already active/,
|
||||
)
|
||||
})
|
||||
|
||||
test('clearActiveMonitor calls abort on the controller', () => {
|
||||
const abortController = new AbortController()
|
||||
setActiveMonitor(makeState({ abortController }))
|
||||
clearActiveMonitor()
|
||||
expect(abortController.signal.aborted).toBe(true)
|
||||
})
|
||||
|
||||
test('trySetActiveMonitor returns true when no active monitor', () => {
|
||||
expect(trySetActiveMonitor(makeState())).toBe(true)
|
||||
expect(getActiveMonitor()).not.toBeNull()
|
||||
})
|
||||
|
||||
test('trySetActiveMonitor returns false when monitor already active', () => {
|
||||
expect(trySetActiveMonitor(makeState({ prNumber: 1 }))).toBe(true)
|
||||
expect(trySetActiveMonitor(makeState({ prNumber: 2 }))).toBe(false)
|
||||
// First state remains
|
||||
expect(getActiveMonitor()?.prNumber).toBe(1)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user