860dcb1bf5
- DirectChatTurn 的 active 布尔改为三态 state(running / awaiting-start / finished),三态判定收在投影里、用身份而不是时间戳 - buildDirectChatTurns 新增 pendingUserItemId 入参;controller 的 beginTurnCommand / endTurnCommand 与 turnBusy 同生共死地维护它 - 新增 useDirectProjectTurnStatus 作为「在跑吗」的唯一派生入口:nativeRunning / commandInFlight / displayBusy / latestTurnState - DirectProjectChatView 不再手拼 busy:header 与 composer 读 displayBusy,「正在处理」卡片读 nativeRunning - DirectProjectConversation 的 running 入参改名 nativeRunning,语义写在类型注释里 - DirectProjectTurn 改读 turn.state;渲染条件保持不变,awaiting-start 仍按已结束渲染(空窗缺陷另开改动) - directTurnPresentation 的起点优先级与三态判定由嵌套三元改为逐级 if 覆盖 - 新增 directProjectTurnStatus 用例 4 条;directTurnPresentation 补三态用例 4 条并改按 state 断言 - ADR 补「活动回合唯一判据约束的是原生回合」澄清与代码指针 - decision-log 记录本次重构决策、未修的窗口期缺陷与验证证据
78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import { deriveDirectProjectTurnStatus } from '../src/view/project-development/chat/controller/useDirectProjectTurnStatus';
|
|
import type { DirectChatTurn } from '../src/view/project-development/chat/conversation/directTurnPresentation';
|
|
|
|
const turn = (key: string, state: DirectChatTurn['state']): DirectChatTurn => ({
|
|
key,
|
|
users: [],
|
|
process: [],
|
|
finals: [],
|
|
state,
|
|
startedAt: 1_800_000_000_000,
|
|
endedAt: 0,
|
|
});
|
|
|
|
describe('DirectProject 回合状态派生', () => {
|
|
it('displayBusy 是原生真相与本地命令在飞的并集', () => {
|
|
expect(
|
|
deriveDirectProjectTurnStatus({
|
|
turnRunning: true,
|
|
turnBusy: false,
|
|
turns: [],
|
|
}).displayBusy,
|
|
).toBe(true);
|
|
expect(
|
|
deriveDirectProjectTurnStatus({
|
|
turnRunning: false,
|
|
turnBusy: true,
|
|
turns: [],
|
|
}).displayBusy,
|
|
).toBe(true);
|
|
expect(
|
|
deriveDirectProjectTurnStatus({
|
|
turnRunning: false,
|
|
turnBusy: false,
|
|
turns: [],
|
|
}).displayBusy,
|
|
).toBe(false);
|
|
});
|
|
|
|
it('两个来源各自独立暴露,不被并集吃掉', () => {
|
|
const status = deriveDirectProjectTurnStatus({
|
|
turnRunning: true,
|
|
turnBusy: true,
|
|
turns: [],
|
|
});
|
|
expect(status.nativeRunning).toBe(true);
|
|
expect(status.commandInFlight).toBe(true);
|
|
});
|
|
|
|
it('latestTurnState 取最新一轮的三态;没有回合时为 null', () => {
|
|
expect(
|
|
deriveDirectProjectTurnStatus({
|
|
turnRunning: false,
|
|
turnBusy: false,
|
|
turns: [turn('u1', 'finished'), turn('u2', 'awaiting-start')],
|
|
}).latestTurnState,
|
|
).toBe('awaiting-start');
|
|
expect(
|
|
deriveDirectProjectTurnStatus({
|
|
turnRunning: false,
|
|
turnBusy: false,
|
|
turns: [],
|
|
}).latestTurnState,
|
|
).toBeNull();
|
|
});
|
|
|
|
it('本地命令在飞不等于原生在跑', () => {
|
|
const status = deriveDirectProjectTurnStatus({
|
|
turnRunning: false,
|
|
turnBusy: true,
|
|
turns: [turn('u1', 'awaiting-start')],
|
|
});
|
|
expect(status.nativeRunning).toBe(false);
|
|
expect(status.latestTurnState).toBe('awaiting-start');
|
|
});
|
|
});
|