hl-api-changelog/tests/changelog-path-aliases.test.mjs
Mimingguang 3c099dca2f
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s
fix(changelog): 清理悬空路径别名
修改原因:远端 b140269 已删除 #5216/#5262 两个非法旧文件名,遗留 alias 配置会令 source 测试失败。

修改内容:移除指向已删除物理文件的 repository alias;保留临时 fixture 对 alias 解析、状态同步和安全校验的覆盖,并更新仓库清单回归断言。

实际验证:source npm test 46 项、check:path-aliases 与 git diff --check 通过。Changelog:#5216、#5262 路径兼容清理。
2026-07-28 14:41:02 +08:00

133 行
4.3 KiB
JavaScript

import assert from 'node:assert/strict';
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import path from 'node:path';
import test from 'node:test';
import {
loadPathAliasManifest,
parsePathAliasManifest,
resolveChangelogPath,
transitionAliasedFrontendState,
validatePathAliases,
} from '../scripts/changelog-path-aliases.mjs';
import { parseFrontmatter } from '../scripts/validate-changelog-frontmatter.mjs';
const OLD_5216 = 'changelogs-v2/2026-07/24_5216_派车看板补充槽位接送路线与就绪摘要-修改接口-前端待处理-管理后台.md';
const CURRENT_5216 = 'changelogs-v2/2026-07/24_5216_派车看板补充槽位接送路线与就绪摘要-修改接口-管理后台.md';
function document({ canonicalPath = '', status = 'claimed', owner = 'frontend-team', frontendRef = '' } = {}) {
const canonicalLine = canonicalPath ? `canonical_path: "${canonicalPath}"\n` : '';
return `---
schema: "hl-changelog/v2"
ticket: "5216"
title: "路径兼容测试"
consumer: "admin"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "${status}"
frontend_owner: "${owner}"
frontend_ref: "${frontendRef}"
target_release: ""
verified_at: ""
${canonicalLine}updated_at: "2026-07-26"
base: "dev-v3"
---
# 路径兼容测试
## 变更接口
- 无业务接口变化。
## 验证证据
- 自动化测试。
`;
}
function createFixture() {
const root = mkdtempSync(path.join(tmpdir(), 'hl-changelog-alias-'));
const manifest = {
schema: 'hl-changelog-path-aliases/v1',
aliases: [{
ticket: '5216',
alias: OLD_5216,
canonical: CURRENT_5216,
reason: '测试旧路径兼容',
}],
};
writeFileSync(path.join(root, 'changelog-path-aliases.json'), JSON.stringify(manifest, null, 2));
for (const repoPath of [OLD_5216, CURRENT_5216]) {
const absolute = path.join(root, ...repoPath.split('/'));
mkdirSync(path.dirname(absolute), { recursive: true });
writeFileSync(absolute, document({
canonicalPath: repoPath === OLD_5216 ? CURRENT_5216 : '',
}));
}
return root;
}
test('repository manifest has no dangling aliases after illegal legacy paths are removed', () => {
const manifest = loadPathAliasManifest();
assert.equal(resolveChangelogPath(OLD_5216, manifest), OLD_5216);
assert.equal(resolveChangelogPath(CURRENT_5216, manifest), CURRENT_5216);
assert.deepEqual(validatePathAliases().errors, []);
});
test('rejects unsafe paths, duplicate aliases and alias chains', () => {
assert.throws(() => parsePathAliasManifest(JSON.stringify({
schema: 'hl-changelog-path-aliases/v1',
aliases: [{
ticket: '5216',
alias: '../outside.md',
canonical: CURRENT_5216,
reason: 'unsafe',
}],
})), /POSIX|规范路径/);
assert.throws(() => parsePathAliasManifest(JSON.stringify({
schema: 'hl-changelog-path-aliases/v1',
aliases: [
{ ticket: '5216', alias: OLD_5216, canonical: CURRENT_5216, reason: 'one' },
{ ticket: '5216', alias: OLD_5216, canonical: CURRENT_5216, reason: 'two' },
],
})), /重复/);
});
test('frontend status transition updates alias group once and is idempotent', () => {
const root = createFixture();
try {
const first = transitionAliasedFrontendState(root, OLD_5216, {
status: 'implemented',
owner: 'frontend-team',
frontendRef: 'mmg/hl-ui@abc1234',
}, {
now: new Date('2026-07-26T04:00:00Z'),
write: true,
});
assert.deepEqual(new Set(first.changedPaths), new Set([OLD_5216, CURRENT_5216]));
assert.deepEqual(validatePathAliases(root).errors, []);
for (const repoPath of [OLD_5216, CURRENT_5216]) {
const text = readFileSync(path.join(root, ...repoPath.split('/')), 'utf8');
const { metadata } = parseFrontmatter(text);
assert.equal(metadata.frontend_status, 'implemented');
assert.equal(metadata.frontend_owner, 'frontend-team');
assert.equal(metadata.frontend_ref, 'mmg/hl-ui@abc1234');
}
const second = transitionAliasedFrontendState(root, OLD_5216, {
status: 'implemented',
owner: 'frontend-team',
frontendRef: 'mmg/hl-ui@abc1234',
}, {
now: new Date('2026-07-26T04:00:00Z'),
write: true,
});
assert.deepEqual(second.changedPaths, []);
} finally {
rmSync(root, { recursive: true, force: true });
}
});