Files
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

162 lines
6.0 KiB
JavaScript

/**
* --------------------------------------------------------------------
* docmd : the zero-config documentation engine.
*
* Phase 3 PR 3.C — Validate rewrite + workspace errors + init example
*
* Tests:
* - M-1: `docmd validate` trailing-slash false-positives
* - F8: workspace validation throws raw stack traces
* - F9: default init `index.md` has a broken `::: button` example
*
* Run: `node tests/runner.js`
* --------------------------------------------------------------------
*/
import {
DOCMD,
setup,
writeFile,
exitCodeOf,
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: 'Validate rewrite + workspace errors + init example (Phase 3 PR 3.C — F8, F9, M-1)',
emoji: '📐',
run: () => {
// M-1 — `validate` must not false-positive on a valid link with a
// trailing slash. Pre-fix: `[page 2](/page-2/)` was reported as
// broken because the code did `fs.existsSync('docs/page-2/.md')`
// (always false). Post-fix: the trailing slash is stripped before
// the existence checks, and the link resolves to `docs/page-2.md`.
{
const dir = setup('validate-workspace-28-m1-trailing-slash-ok');
writeFile(dir, 'docs/index.md', '# P1\n\n[page 2](/page-2/).\n');
writeFile(dir, 'docs/page-2.md', '# P2\n');
const code = exitCodeOf(`node ${DOCMD} validate`, dir);
assert(code === 0, 'M-1: trailing-slash link to existing .md is valid (exit 0)');
}
// M-1 — genuine broken link is still caught.
{
const dir = setup('validate-workspace-28-m1-broken-still-caught');
writeFile(dir, 'docs/index.md', '# P1\n\n[bad](/nope/)\n');
const code = exitCodeOf(`node ${DOCMD} validate`, dir);
assert(code === 1, 'M-1: genuinely broken link still exits 1');
}
// F8 — workspace validation errors exit 1 with a clean TUI message,
// not a raw stack trace.
{
const dir = setup('validate-workspace-28-f8-workspace-error');
writeFile(dir, 'docmd.config.json', JSON.stringify({
title: 'F8',
src: './docs',
out: './site',
workspace: {
projects: [{ src: './totally-missing-f8', prefix: '/' }]
}
}));
const code = exitCodeOf(`node ${DOCMD} build`, dir);
assert(code === 1, 'F8: workspace with missing source dir exits 1');
}
// F8 — duplicate-prefix error also exits 1.
{
const dir = setup('validate-workspace-28-f8-workspace-duplicate');
writeFile(dir, 'docmd.config.json', JSON.stringify({
title: 'F8 dup',
src: './docs',
out: './site',
workspace: {
projects: [
{ src: './docs', prefix: '/api' },
{ src: './docs', prefix: '/api' }
]
}
}));
const code = exitCodeOf(`node ${DOCMD} build`, dir);
assert(code === 1, 'F8: duplicate workspace prefix exits 1');
}
// F9 — default init `index.md` must NOT contain the F2 trap pattern
// (`::: card ... ::: button ... :::` with the orphan `:::`).
// We check the bundled `initProject` source rather than running
// `init` (which would write to disk) — we just confirm the
// template string no longer teaches the F2 pattern.
{
const initSrc = fs.readFileSync(
path.resolve(import.meta.dirname, '..', '..', 'packages/core/dist/commands/init.js'),
'utf8'
);
// The broken pattern was: `::: button "View Documentation" https://...`
// followed by a `:::` close. The replacement uses
// `[View the docs →](https://docmd.io){.docmd-button}` instead.
assert(!/button "View Documentation"/.test(initSrc), 'F9: bundled init no longer contains broken `::: button ... :::` trap');
assert(/\{\.docmd-button\}/.test(initSrc), 'F9: bundled init uses `{.docmd-button}` styled link');
}
// M-2 — workspace config without a root project must show an
// actionable error message: explains the requirement, shows a
// valid example, and points at the docs. The old message was
// a single bare sentence with no example.
{
const dir = setup('validate-workspace-28-m2-workspace-no-root-message');
// The source dirs must exist so the per-project existence check
// does not fire first and mask the "no root project" failure.
writeFile(dir, 'docs/index.md', '# Root\n');
writeFile(dir, 'docmd.config.json', JSON.stringify({
title: 'M2',
src: './docs',
out: './site',
workspace: {
projects: [
{ src: './docs', prefix: '/api/' },
{ src: './docs', prefix: '/blog/' }
]
}
}));
let captured = '';
let code = -1;
try {
execSync(`node ${DOCMD} build`, { cwd: dir, stdio: 'pipe', encoding: 'utf8' });
} catch (e) {
code = e.status == null ? -1 : e.status;
const stderr = typeof e.stderr === 'string' ? e.stderr : (e.stderr ? e.stderr.toString() : '');
const stdout = typeof e.stdout === 'string' ? e.stdout : (e.stdout ? e.stdout.toString() : '');
captured = stderr + stdout;
}
assert(code === 1, 'M-2: workspace with no root project exits 1');
assert(/root project with prefix "\/"/.test(captured), 'M-2: error message states the root prefix requirement');
assert(/Example:/.test(captured), 'M-2: error message includes an Example block');
assert(/"prefix": "\/"/.test(captured), 'M-2: error message example shows prefix "/"');
assert(/docs\.docmd\.io/.test(captured), 'M-2: error message links to the workspace guide');
}
}
});
export const results = {
get passed() { return passed; },
get failed() { return failed; },
get failures() { return [...failures]; }
};