项目文件夹

文件
wehub-resource-sync 6db8fca185
docmd CI verification / verify (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:31:55 +08:00

183 行
6.7 KiB
JavaScript

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
/**
* --------------------------------------------------------------------
* docmd : the zero-config documentation engine.
*
* Slice D — i18n + workspace fixes
*
* Covers:
* M-6 config.versions.list is accepted as an alias for
* config.versions.all. The audit reported "i18n + explicit
* versions: 0 pages" — the real cause was users writing
* `list` (a common JSON shape) when the schema only accepted
* `all`, so the versioning branch was silently never entered.
* T-Z6 Missing current-version directory is now a hard error with
* a clear pointer to the missing path. Previously the build
* silently produced 0 pages.
*
* Run: `node tests/runner.js --only=i18n`
* --------------------------------------------------------------------
*/
import {
DOCMD,
setup,
writeFile,
runTestFile
} from '../shared.js';
import { execSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
let passed = 0;
let failed = 0;
const failures = [];
function assert(condition, message) {
if (!condition) {
failed++;
failures.push(message);
console.log(` ❌ ${message}`);
} else {
passed++;
console.log(` ✅ ${message}`);
}
}
export const test = runTestFile({
name: 'i18n + workspace schema fixes (Slice D — M-6, T-Z6)',
emoji: '🌐',
run: () => {
// M-6 — config.versions.list is accepted as an alias for
// config.versions.all. With correct structure (locales in
// subdirectories, current version with a real dir), the build
// produces pages for both versions of both locales.
{
const dir = setup('i18n-d-m6-list-alias');
writeFile(dir, 'docs/en/index.md', '# Home\n');
writeFile(dir, 'docs/ar/index.md', '# Home\n');
writeFile(dir, 'v1/en/index.md', '# v1 Home\n');
writeFile(dir, 'v1/ar/index.md', '# v1 Home\n');
writeFile(dir, 'v2/en/index.md', '# v2 Home\n');
writeFile(dir, 'v2/ar/index.md', '# v2 Home\n');
writeFile(dir, 'docmd.config.json', JSON.stringify({
title: 'M-6',
src: './docs',
out: './site',
i18n: {
default: 'en',
locales: [{ id: 'en' }, { id: 'ar' }]
},
versions: {
// Using `list` instead of `all` — the alias should kick in.
list: [
{ id: 'v1', label: '1.x', dir: 'v1' },
{ id: 'v2', label: '2.x', dir: 'v2' }
],
current: 'v2'
}
}, null, 2) + '\n');
let output = '';
let code = -1;
try {
output = execSync(`node ${DOCMD} build`, { cwd: dir, stdio: 'pipe', encoding: 'utf8' });
// Successful execSync returns null status on some Node versions when
// the child process calls process.exit() with no error. Treat any
// successful invocation as code=0.
code = 0;
} catch (e) {
output = (typeof e.stdout === 'string' ? e.stdout : '') + (typeof e.stderr === 'string' ? e.stderr : '');
code = e.status == null ? 1 : e.status;
}
assert(code === 0, 'M-6: build with versions.list (alias) succeeds (was 0 pages before)');
const pages = (() => {
try {
return fs.readdirSync(path.join(dir, 'site')).filter((n) => n.endsWith('.html') || fs.statSync(path.join(dir, 'site', n)).isDirectory());
} catch { return []; }
})();
// 2 locales × 2 versions = 4 page directories (current version
// for each locale renders at root/{locale}/ and non-current at
// root/{locale}/{v}/).
assert(pages.length >= 4, 'M-6: build produces 4 page directories (2 locales × 2 versions)');
}
// T-Z6 — current version directory missing → build fails with a
// clear error, not a silent 0-page build.
{
const dir = setup('i18n-d-tz6-missing-current-version');
writeFile(dir, 'docs/index.md', '# Home\n');
writeFile(dir, 'v1/index.md', '# v1 Home\n');
writeFile(dir, 'docmd.config.json', JSON.stringify({
title: 'T-Z6',
src: './docs',
out: './site',
versions: {
all: [
{ id: 'v1', label: '1.x', dir: 'v1' },
// v2 dir is intentionally absent — the bug per the report.
{ id: 'v2', label: '2.x', dir: 'v2-nonexistent' }
],
current: 'v2'
}
}, null, 2) + '\n');
let output = '';
let code = -1;
try {
output = execSync(`node ${DOCMD} build`, { cwd: dir, stdio: 'pipe', encoding: 'utf8' });
code = 0;
} catch (e) {
output = (typeof e.stdout === 'string' ? e.stdout : '') + (typeof e.stderr === 'string' ? e.stderr : '');
code = e.status == null ? 0 : e.status;
}
// The TUI's process.exit(0) at the end of a clean build sometimes
// surfaces to execSync as status=null rather than 0, depending on
// signal-handling. We treat a null status as success.
assert(code === 1, 'T-Z6: build exits 1 when current version directory is missing (was 0 before)');
assert(/Current version directory missing/.test(output), 'T-Z6: error message names the missing directory concept');
assert(/v2/.test(output), 'T-Z6: error message includes the version id');
}
// T-Z6 — old (non-current) version directory missing → soft warn,
// build continues with the current version.
{
const dir = setup('i18n-d-tz6-missing-old-version');
writeFile(dir, 'docs/index.md', '# Home\n');
writeFile(dir, 'v2/index.md', '# v2 Home\n');
writeFile(dir, 'docmd.config.json', JSON.stringify({
title: 'T-Z6-old',
src: './docs',
out: './site',
versions: {
all: [
{ id: 'v1', label: '1.x', dir: 'v1-nonexistent' },
{ id: 'v2', label: '2.x', dir: 'v2' }
],
current: 'v2'
}
}, null, 2) + '\n');
let output = '';
let code = -1;
try {
output = execSync(`node ${DOCMD} build`, { cwd: dir, stdio: 'pipe', encoding: 'utf8' });
code = 0;
} catch (e) {
output = (typeof e.stdout === 'string' ? e.stdout : '') + (typeof e.stderr === 'string' ? e.stderr : '');
code = e.status == null ? 0 : e.status;
}
assert(code === 0, 'T-Z6: build succeeds when only old (non-current) version is missing');
assert(/Skipping missing version: v1/.test(output), 'T-Z6: missing old version surfaces a soft warning');
assert(fs.existsSync(path.join(dir, 'site/index.html')), 'T-Z6: current version still builds when old version is missing');
}
}
});
export const results = {
get passed() { return passed; },
get failed() { return failed; },
get failures() { return [...failures]; }
};