265 lines
5.4 KiB
JavaScript
265 lines
5.4 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
|
|
import {
|
|
buildImpactPlanTemplate,
|
|
getUnpassedReviewFiles,
|
|
getFeatureDirectory,
|
|
getInvalidFeatureEvidence,
|
|
getRequiredFeatureFiles,
|
|
validateFeatureId,
|
|
} from './feature-record.mjs';
|
|
|
|
const VALID_FEATURE_REPORTS = new Map([
|
|
[
|
|
'development-summary.md',
|
|
`# 开发总结
|
|
|
|
## 原始开发需求
|
|
|
|
建立可自动执行的质量门禁。
|
|
|
|
## 需求与范围变化
|
|
|
|
范围未变化,仍只处理治理与请求脚手架。
|
|
|
|
## 实际完成需求
|
|
|
|
完成独立总结和证据校验。
|
|
|
|
## 修复缺陷
|
|
|
|
本次没有修复既有业务缺陷,只补足治理能力。
|
|
|
|
## 未完成与延期项
|
|
|
|
AI Provider 延期到独立功能,不属于本次范围。
|
|
|
|
## 关键提交
|
|
|
|
记录中文提交 SHA 与摘要。
|
|
|
|
## 验证证据
|
|
|
|
记录测试、构建和 Review 结果。
|
|
`,
|
|
],
|
|
[
|
|
'design.md',
|
|
`# 设计
|
|
|
|
## 8. 安全策略与评估
|
|
|
|
说明信任边界和残余风险。
|
|
|
|
## 9. 性能目标与评估
|
|
|
|
说明预算和验证强度。
|
|
`,
|
|
],
|
|
[
|
|
'test-plan.md',
|
|
`# 测试
|
|
|
|
## 安全验证
|
|
|
|
验证脱敏错误。
|
|
|
|
## 性能验证
|
|
|
|
比较构建体积。
|
|
`,
|
|
],
|
|
[
|
|
'gitnexus/impact-plan.md',
|
|
`# 影响
|
|
|
|
## 直接与间接影响
|
|
|
|
列出消费者和执行流。
|
|
|
|
## 跨模块同步修改
|
|
|
|
逐项判断契约、缓存和进程。
|
|
`,
|
|
],
|
|
[
|
|
'review/code-review.md',
|
|
`# Review
|
|
|
|
## 安全与残余风险
|
|
|
|
错误信息经过脱敏,残余风险已记录。
|
|
|
|
## 性能与资源影响
|
|
|
|
包体增量经过测量并可接受。
|
|
|
|
## GitNexus 与同步修改
|
|
|
|
实际影响符合开发前计划。
|
|
|
|
最终结论:passed
|
|
`,
|
|
],
|
|
[
|
|
'review/standards-review.md',
|
|
`# 规范 Review
|
|
|
|
## 安全、性能与架构检查
|
|
|
|
逐项核对并符合规范。
|
|
|
|
## GitNexus 与开发总结检查
|
|
|
|
前后影响和完成事实证据齐全。
|
|
|
|
最终结论:passed
|
|
`,
|
|
],
|
|
]);
|
|
|
|
test('接受带业务域和三位序号的功能编号', () => {
|
|
assert.equal(validateFeatureId('FEAT-MO-001'), true);
|
|
assert.equal(validateFeatureId('GOV-001'), true);
|
|
});
|
|
|
|
test('拒绝无法追溯或格式含糊的功能编号', () => {
|
|
assert.equal(validateFeatureId('market-overview'), false);
|
|
assert.equal(validateFeatureId('FEAT-MO-1'), false);
|
|
assert.equal(validateFeatureId('../FEAT-MO-001'), false);
|
|
});
|
|
|
|
test('将功能编号和短名称解析到固定的功能档案目录', () => {
|
|
assert.equal(
|
|
getFeatureDirectory('/repo', 'FEAT-MO-001', 'market-overview'),
|
|
'/repo/docs/features/FEAT-MO-001-market-overview',
|
|
);
|
|
});
|
|
|
|
test('返回开发完成前必须存在的完整追溯文件清单', () => {
|
|
assert.deepEqual(getRequiredFeatureFiles(), [
|
|
'manifest.yaml',
|
|
'prd.md',
|
|
'requirements.md',
|
|
'design.md',
|
|
'implementation-plan.md',
|
|
'test-plan.md',
|
|
'development-summary.md',
|
|
'gitnexus/before.md',
|
|
'gitnexus/impact-plan.md',
|
|
'gitnexus/detected-changes.md',
|
|
'gitnexus/after.md',
|
|
'gitnexus/comparison.md',
|
|
'qa/test-results.md',
|
|
'qa/visual-qa.md',
|
|
'review/code-review.md',
|
|
'review/standards-review.md',
|
|
'release-notes.md',
|
|
'rollback.md',
|
|
]);
|
|
});
|
|
|
|
test('只有两份 Review 都明确通过时才允许发布', () => {
|
|
const reports = new Map([
|
|
['review/code-review.md', '# 代码 Review\n\n最终结论:passed\n'],
|
|
['review/standards-review.md', '# 规范 Review\n\n状态:pending\n'],
|
|
]);
|
|
|
|
assert.deepEqual(getUnpassedReviewFiles(reports), [
|
|
'review/standards-review.md',
|
|
]);
|
|
|
|
reports.set(
|
|
'review/standards-review.md',
|
|
'# 规范 Review\n\n最终结论:passed\n',
|
|
);
|
|
assert.deepEqual(getUnpassedReviewFiles(reports), []);
|
|
});
|
|
|
|
test('完整质量证据和带序号的二级标题可以通过门禁', () => {
|
|
assert.deepEqual(getInvalidFeatureEvidence(VALID_FEATURE_REPORTS), []);
|
|
});
|
|
|
|
test('一次列出缺失、空白和无解释占位的全部证据章节', () => {
|
|
const reports = new Map(VALID_FEATURE_REPORTS);
|
|
reports.set(
|
|
'development-summary.md',
|
|
`# 开发总结
|
|
|
|
## 原始开发需求
|
|
|
|
建立质量门禁。
|
|
|
|
## 需求与范围变化
|
|
|
|
无
|
|
|
|
## 实际完成需求
|
|
|
|
完成结构校验。
|
|
|
|
## 修复缺陷
|
|
|
|
N/A
|
|
|
|
## 未完成与延期项
|
|
|
|
|
|
## 关键提交
|
|
|
|
记录提交。
|
|
|
|
## 验证证据
|
|
|
|
记录测试。
|
|
`,
|
|
);
|
|
reports.set(
|
|
'test-plan.md',
|
|
`# 测试
|
|
|
|
## 安全验证
|
|
|
|
验证脱敏错误。
|
|
`,
|
|
);
|
|
|
|
assert.deepEqual(getInvalidFeatureEvidence(reports), [
|
|
'development-summary.md:需求与范围变化',
|
|
'development-summary.md:修复缺陷',
|
|
'development-summary.md:未完成与延期项',
|
|
'test-plan.md:性能验证',
|
|
]);
|
|
});
|
|
|
|
test('带具体理由和边界的不适用说明不是空壳证据', () => {
|
|
const reports = new Map(VALID_FEATURE_REPORTS);
|
|
reports.set(
|
|
'test-plan.md',
|
|
`# 测试
|
|
|
|
## 安全验证
|
|
|
|
验证脱敏错误。
|
|
|
|
## 性能验证
|
|
|
|
不适用:本功能不进入生产请求路径,边界仅为开发门禁。
|
|
`,
|
|
);
|
|
|
|
assert.deepEqual(getInvalidFeatureEvidence(reports), []);
|
|
});
|
|
|
|
test('开发前影响计划骨架要求记录风险、消费者和跨模块同步修改', () => {
|
|
const template = buildImpactPlanTemplate('FEAT-MO-001');
|
|
|
|
assert.match(template, /功能编号:FEAT-MO-001/);
|
|
assert.match(template, /^## 直接与间接影响$/m);
|
|
assert.match(template, /query、context、upstream impact、消费者和执行流/);
|
|
assert.match(template, /^## 跨模块同步修改$/m);
|
|
assert.match(template, /HTTP\/OpenAPI、Web API、消息契约、数据库、Redis/);
|
|
assert.match(template, /API、Scheduler、Worker、配置部署、测试和文档/);
|
|
});
|