refactor(data): 收口关系表运行时数据源
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
- 移除已迁移业务 AppData 运行时 fallback,改走领域 API 和关系表快读 - 补齐需求产品负责人、版本计划任务 JSON 和成员 username 回填迁移 - 统一治理字典入口,并补充 AI provider、数据源契约和领域服务测试 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
50
apps/web/lib/version-plan-owner-source.test.ts
Normal file
50
apps/web/lib/version-plan-owner-source.test.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import test from 'node:test';
|
||||
|
||||
const rootFile = (path: string) => readFileSync(join(process.cwd(), path), 'utf8');
|
||||
|
||||
test('plan auto-start effect only persists the same pending plan once', () => {
|
||||
const text = rootFile('components/version/PlanTab.tsx');
|
||||
|
||||
assert.match(text, /useRef/);
|
||||
assert.match(text, /autoStartedPlanIds/);
|
||||
assert.match(text, /!autoStartedPlanIds\.current\.has\(plan\.id\)/);
|
||||
assert.match(text, /autoStartedPlanIds\.current\.add\(plan\.id\)/);
|
||||
});
|
||||
|
||||
test('plan owner UI resolves stored member ids to display names and filters transfer choices by member reference', () => {
|
||||
const text = rootFile('components/version/PlanTab.tsx');
|
||||
|
||||
assert.match(text, /resolveMemberDisplayName/);
|
||||
assert.match(text, /isMemberReference/);
|
||||
assert.match(text, /ownerLabel/);
|
||||
assert.doesNotMatch(text, />\{plan\.owner\}<\/span>/);
|
||||
assert.doesNotMatch(text, />\{plan\.owner\}<\/dd>/);
|
||||
assert.doesNotMatch(text, /member\.name !== plan\.owner/);
|
||||
});
|
||||
|
||||
test('version detail passes relation-backed member candidates to plan tabs for id display resolution', () => {
|
||||
const text = rootFile('app/versions/[id]/page.tsx');
|
||||
|
||||
assert.match(text, /username: member\.username/);
|
||||
assert.match(text, /currentUserReference=\{user\?\.username/);
|
||||
assert.match(text, /allMembers=\{memberCandidates\}/);
|
||||
});
|
||||
|
||||
test('plan create response merge preserves optimistic auto-start fields from the current local row', () => {
|
||||
const text = rootFile('stores/useVersionPlanStore.ts');
|
||||
|
||||
assert.match(text, /mergeCreatedVersionPlan/);
|
||||
assert.doesNotMatch(text, /\{\s*\.\.\.plan,\s*\.\.\.result\.item,\s*tasks: plan\.tasks\s*\}/);
|
||||
});
|
||||
|
||||
test('requirement product owner is sent to the relation API instead of staying as a local-only field', () => {
|
||||
const requirementStore = rootFile('stores/useRequirementStore.ts');
|
||||
const domainApi = rootFile('lib/domain-api.ts');
|
||||
|
||||
assert.doesNotMatch(requirementStore, /delete domainPatch\.productOwner/);
|
||||
assert.match(domainApi, /productOwnerId/);
|
||||
assert.match(domainApi, /data\.productOwner/);
|
||||
});
|
||||
Reference in New Issue
Block a user