✨ feat(vscode): handoff 纯决策与 state/UI payload
Claude-Session: https://claude.ai/code/session_011cEyL6k351U2BzX1Qmygph
This commit is contained in:
1 parent
bffdcb4d42
commit
f7b97bbe9e
2 files changed
+206
No files matched your search
@@ -0,0 +1,111 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
canAcceptHandoff,
|
||||
canStartHandoff,
|
||||
checkWorktreePushed,
|
||||
handoffAcceptedStateExtra,
|
||||
handoffAcceptedUiPatch,
|
||||
handoffStartedStateExtra,
|
||||
handoffStartedUiPatch,
|
||||
} from './handoff'
|
||||
|
||||
describe('canStartHandoff', () => {
|
||||
it('gitea 工单、非 done、无待接管 → true', () => {
|
||||
expect(canStartHandoff({ column: 'in-progress' })).toBe(true)
|
||||
expect(canStartHandoff({ column: 'todo', source: 'gitea' })).toBe(true)
|
||||
})
|
||||
it('done / youtrack / 已在移交中 → false', () => {
|
||||
expect(canStartHandoff({ column: 'done' })).toBe(false)
|
||||
expect(canStartHandoff({ column: 'review', source: 'youtrack' })).toBe(false)
|
||||
expect(canStartHandoff({ column: 'review', handoffAttachmentId: '9' })).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('canAcceptHandoff', () => {
|
||||
it('有附件且 assignee 含我 → true', () => {
|
||||
expect(canAcceptHandoff({ handoffAttachmentId: '9', assignees: ['me', 'x'] }, 'me')).toBe(true)
|
||||
})
|
||||
it('无附件 / 不是我的 / 身份未知 / youtrack → false', () => {
|
||||
expect(canAcceptHandoff({ assignees: ['me'] }, 'me')).toBe(false)
|
||||
expect(canAcceptHandoff({ handoffAttachmentId: '9', assignees: ['x'] }, 'me')).toBe(false)
|
||||
expect(canAcceptHandoff({ handoffAttachmentId: '9', assignees: ['me'] }, undefined)).toBe(false)
|
||||
expect(canAcceptHandoff({ source: 'youtrack', handoffAttachmentId: '9', assignees: ['me'] }, 'me')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('checkWorktreePushed', () => {
|
||||
it('干净且 HEAD 与远端一致 → ok', () => {
|
||||
expect(checkWorktreePushed({ statusPorcelain: '', localHead: 'abc', remoteHead: 'abc' })).toEqual({ ok: true })
|
||||
})
|
||||
it('有未提交改动 → 拒绝', () => {
|
||||
const r = checkWorktreePushed({ statusPorcelain: ' M a.ts\n', localHead: 'abc', remoteHead: 'abc' })
|
||||
expect(r.ok).toBe(false)
|
||||
if (!r.ok)
|
||||
expect(r.reason).toMatch(/未提交/)
|
||||
})
|
||||
it('本地领先远端 → 拒绝', () => {
|
||||
const r = checkWorktreePushed({ statusPorcelain: '', localHead: 'abc', remoteHead: 'def' })
|
||||
expect(r.ok).toBe(false)
|
||||
if (!r.ok)
|
||||
expect(r.reason).toMatch(/push/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('payloads', () => {
|
||||
it('移交落盘:两个共享字段 + 本机字段全部墓碑', () => {
|
||||
expect(handoffStartedStateExtra(9, 'chw')).toEqual({
|
||||
handoffAttachmentId: '9',
|
||||
handoffFrom: 'chw',
|
||||
sessionId: '',
|
||||
implementSessionId: '',
|
||||
reviewSessionId: '',
|
||||
testSessionId: '',
|
||||
profilePath: '',
|
||||
brainstormProfilePath: '',
|
||||
testProfilePath: '',
|
||||
worktreePath: '',
|
||||
prDiffFile: '',
|
||||
})
|
||||
})
|
||||
it('移交 UI patch 用 null 清字段并更新 assignees', () => {
|
||||
expect(handoffStartedUiPatch(9, 'chw', 'me')).toEqual({
|
||||
handoffAttachmentId: '9',
|
||||
handoffFrom: 'chw',
|
||||
assignees: ['me'],
|
||||
sessionId: null,
|
||||
implementSessionId: null,
|
||||
reviewSessionId: null,
|
||||
testSessionId: null,
|
||||
worktreePath: null,
|
||||
worktreeExists: false,
|
||||
})
|
||||
})
|
||||
it('接管落盘:清两个共享字段,写本机 sid / profile / worktree', () => {
|
||||
expect(handoffAcceptedStateExtra({
|
||||
sessions: { implementSessionId: 'i', reviewSessionId: 'r' },
|
||||
profiles: { profilePath: '/p.json' },
|
||||
worktreePath: '/wt',
|
||||
})).toEqual({
|
||||
handoffAttachmentId: '',
|
||||
handoffFrom: '',
|
||||
implementSessionId: 'i',
|
||||
reviewSessionId: 'r',
|
||||
profilePath: '/p.json',
|
||||
worktreePath: '/wt',
|
||||
})
|
||||
})
|
||||
it('接管 UI patch', () => {
|
||||
expect(handoffAcceptedUiPatch({
|
||||
sessions: { sessionId: 's' },
|
||||
profiles: {},
|
||||
worktreePath: '/wt',
|
||||
worktreeExists: true,
|
||||
})).toEqual({
|
||||
handoffAttachmentId: null,
|
||||
handoffFrom: null,
|
||||
sessionId: 's',
|
||||
worktreePath: '/wt',
|
||||
worktreeExists: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user