import assert from 'node:assert/strict' import test from 'node:test' import { buildApiContext, buildInventoryCheck, classifyCommit, makeFeatureCatalogKey, makeIdempotencyKey, normalizeRepoName, selectUniqueProject, validateStatusEvidence, } from '../../scripts/kaifa-progress-sync.mjs' test('builds the complete inventory check from the freshly fetched catalog state', () => { const context = { currentState: { featureInventoryPolicy: { catalogFeatureCount: 1 }, modules: [{ moduleId: 'module-1', name: '生产发布与团队协作', features: [{ featureId: 'feature-1', name: '钉钉账号登录与绑定', description: '让现有财务账号通过钉钉完成绑定和登录。', status: 'done', progressPercent: 100, }], }], }, } assert.deepEqual(buildInventoryCheck(context, '2026-09-03T10:00:00.000Z'), { reviewed_at: '2026-09-03T10:00:00.000Z', source_inventory_complete: true, source_feature_count: 1, catalog_feature_count: 1, items: [{ module_id: 'module-1', module_name: '生产发布与团队协作', feature_id: 'feature-1', feature_name: '钉钉账号登录与绑定', feature_description: '让现有财务账号通过钉钉完成绑定和登录。', status: 'done', progress_percent: 100, }], }) assert.throws(() => buildInventoryCheck({ currentState: { featureInventoryPolicy: { catalogFeatureCount: 1 }, modules: [] } }), /COUNT_MISMATCH/) }) test('keeps Git author filtering separate from the board developer identity', () => { assert.deepEqual(buildApiContext({ OWNER_EMAIL: '549727955@qq.com', DEVELOPER_CONTEXT: '魔礼红', PROJECT_DESCRIPTION: '真实项目介绍', DEPARTMENT: '财务中心', PROJECT: '财务系统', }), { department: '财务中心', project: '财务系统', developer: '魔礼红', project_description: '真实项目介绍', }) }) test('feature catalog idempotency changes with the exact requested definitions', () => { const first = makeFeatureCatalogKey('CaiWuXiTong', [{ moduleName: '快递与审批', featureName: 'E 签宝状态轮询' }]) const same = makeFeatureCatalogKey('CaiWuXiTong', [{ featureName: 'E 签宝状态轮询', moduleName: '快递与审批' }]) const second = makeFeatureCatalogKey('CaiWuXiTong', [{ moduleName: '快递与审批', featureName: '钉钉应付流程' }]) assert.equal(first, same) assert.notEqual(first, second) }) test('normalizes repository names and builds a stable idempotency key', () => { assert.equal(normalizeRepoName('http://git.example.com/team/CaiWuXiTong.git'), 'CaiWuXiTong') assert.equal(makeIdempotencyKey('CaiWuXiTong', 'abc123', 'testing'), 'CaiWuXiTong:abc123:testing') }) test('matches exactly one project and rejects ambiguous matches', () => { const project = { projectId: 'p1', projectName: '财务系统', department: '财务中心', repoName: 'CaiWuXiTong', productionUrl: 'https://218.93.190.75:8442', deploymentName: 'caiwuxitong', } const identity = { projectName: '财务系统', repoName: 'CaiWuXiTong', productionUrl: 'https://218.93.190.75:8442', deploymentName: 'caiwuxitong', } assert.equal(selectUniqueProject([project], identity).projectId, 'p1') assert.throws(() => selectUniqueProject([project, { ...project, projectId: 'p2' }], identity), /AMBIGUOUS/) }) test('assigns one primary feature and stops on ambiguous feature matches', () => { assert.equal(classifyCommit('财务经营报表增加安装明细', ['app/Models/Business/InstallationDetail.php']).rule.key, 'installation-details') assert.equal(classifyCommit('修复云数据库管理不支持 PostgreSQL 连接', ['app/Http/Controllers/SystemSettings/Databases.php']).rule.key, 'upstream-connections') const esign = classifyCommit('feat: add callback-free eSign status polling', ['app/Console/Commands/PollEsignSignatures.php']).rule assert.equal(esign.key, 'courier-esign') assert.equal(esign.featureName, 'E 签宝无回调状态轮询与归档') const dingtalkLogin = classifyCommit('feat: add DingTalk account login', ['app/Http/Controllers/Auth/DingTalkLogin.php']).rule assert.equal(dingtalkLogin.key, 'dingtalk-login') assert.equal(dingtalkLogin.featureName, '钉钉账号登录与绑定') assert.match(dingtalkLogin.featureDescription, /OAuth/) assert.equal( classifyCommit('feat: align taobao reconciliation headers', ['resources/views/store_receivables/zhongcai_reconciliations/partials/embedded-table.blade.php']).rule.key, 'zhongcai-reconciliation', ) assert.throws( () => classifyCommit('chore: shared update', ['app/Utilities/SystemDatabaseConfiguration.php', 'modules/EcommerceFinance/Services/UpstreamOdbcConnection.php']), /FEATURE_MATCH_AMBIGUOUS/, ) }) test('done requires passed tests and explicit acceptance evidence', () => { assert.throws(() => validateStatusEvidence('done', { testStatus: 'passed', acceptanceEvidence: '' }), /DONE_REQUIRES/) assert.doesNotThrow(() => validateStatusEvidence('done', { testStatus: 'passed', acceptanceEvidence: 'production SHA verified' })) })