chore: import upstream snapshot with attribution
docmd CI verification / verify (push) Failing after 0s
docmd CI verification / verify (push) Failing after 0s
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* docmd : the zero-config documentation engine.
|
||||
*
|
||||
* N-2 — `docmd deploy --force` flag must do something.
|
||||
*
|
||||
* Before the fix, `--force` was accepted in the CLI flags but never
|
||||
* read in the deployer. Every `docmd deploy --docker` silently
|
||||
* overwrote an existing `Dockerfile`. The fix: `--force` opts in to
|
||||
* overwriting; the default behaviour skips existing files with a
|
||||
* clear `TUI` line.
|
||||
*
|
||||
* Run: `node tests/runner.js --only=deploy`
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
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: 'Deploy --force honours overwrite (N-2)',
|
||||
emoji: '🚢',
|
||||
run: () => {
|
||||
|
||||
// N-2 — without --force, an existing Dockerfile is preserved.
|
||||
{
|
||||
const dir = setup('deploy-29-n2-no-force-skip');
|
||||
writeFile(dir, 'docs/index.md', '# Hi\n');
|
||||
writeFile(dir, 'docmd.config.json', JSON.stringify({ title: 'N2', src: './docs', out: './site' }, null, 2) + '\n');
|
||||
// Pre-seed a Dockerfile so the deployer would overwrite it.
|
||||
const existing = 'FROM existing:keep-me\n';
|
||||
writeFile(dir, 'Dockerfile', existing);
|
||||
|
||||
let output = '';
|
||||
try {
|
||||
output = execSync(`node ${DOCMD} deploy --docker`, { cwd: dir, stdio: 'pipe', encoding: 'utf8' });
|
||||
} catch (e) {
|
||||
output = (typeof e.stdout === 'string' ? e.stdout : (e.stdout ? e.stdout.toString() : '')) +
|
||||
(typeof e.stderr === 'string' ? e.stderr : (e.stderr ? e.stderr.toString() : ''));
|
||||
}
|
||||
|
||||
const after = fs.readFileSync(path.join(dir, 'Dockerfile'), 'utf8');
|
||||
assert(after === existing, 'N-2: without --force, existing Dockerfile is preserved');
|
||||
assert(/skipped.*--force/i.test(output), 'N-2: TUI mentions --force when skipping');
|
||||
}
|
||||
|
||||
// N-2 — with --force, an existing Dockerfile is overwritten.
|
||||
{
|
||||
const dir = setup('deploy-29-n2-force-overwrite');
|
||||
writeFile(dir, 'docs/index.md', '# Hi\n');
|
||||
writeFile(dir, 'docmd.config.json', JSON.stringify({ title: 'N2', src: './docs', out: './site' }, null, 2) + '\n');
|
||||
writeFile(dir, 'Dockerfile', 'FROM existing:keep-me\n');
|
||||
|
||||
execSync(`node ${DOCMD} deploy --docker --force`, { cwd: dir, stdio: 'pipe' });
|
||||
const after = fs.readFileSync(path.join(dir, 'Dockerfile'), 'utf8');
|
||||
assert(after !== 'FROM existing:keep-me\n', 'N-2: with --force, existing Dockerfile is overwritten');
|
||||
assert(/FROM .+/.test(after), 'N-2: overwritten Dockerfile contains a real FROM directive');
|
||||
}
|
||||
|
||||
// N-2 — without --force and no existing file, the deployer writes
|
||||
// a fresh Dockerfile (regression guard for the skip path).
|
||||
{
|
||||
const dir = setup('deploy-29-n2-no-force-fresh');
|
||||
writeFile(dir, 'docs/index.md', '# Hi\n');
|
||||
writeFile(dir, 'docmd.config.json', JSON.stringify({ title: 'N2', src: './docs', out: './site' }, null, 2) + '\n');
|
||||
|
||||
execSync(`node ${DOCMD} deploy --docker`, { cwd: dir, stdio: 'pipe' });
|
||||
assert(fs.existsSync(path.join(dir, 'Dockerfile')), 'N-2: without --force and no existing file, Dockerfile is created');
|
||||
}
|
||||
|
||||
// T-Z9 — generated `netlify.toml` must NOT contain a SPA catch-all
|
||||
// redirect with `from = "/*" status = 200`. That pattern soft-404s
|
||||
// every missing route by serving the home page with HTTP 200, which
|
||||
// hides errors and hurts SEO. docmd generates real HTML per route,
|
||||
// so the redirect is unnecessary — Netlify serves the bundled
|
||||
// 404.html with 404 status for any path that doesn't have a file.
|
||||
{
|
||||
const dir = setup('deploy-29-tz9-no-soft-404');
|
||||
writeFile(dir, 'docs/index.md', '# Hi\n');
|
||||
writeFile(dir, 'docmd.config.json', JSON.stringify({ title: 'TZ9', src: './docs', out: './site', layout: { spa: true } }, null, 2) + '\n');
|
||||
|
||||
execSync(`node ${DOCMD} deploy --netlify`, { cwd: dir, stdio: 'pipe' });
|
||||
const toml = fs.readFileSync(path.join(dir, 'netlify.toml'), 'utf8');
|
||||
assert(!/\[\[redirects\]\]/.test(toml), 'T-Z9: no [[redirects]] block in generated netlify.toml');
|
||||
assert(!/from\s*=\s*"\/\*"\s*\n\s*to\s*=\s*"\/index\.html"/m.test(toml), 'T-Z9: no catch-all redirect to /index.html');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const results = {
|
||||
get passed() { return passed; },
|
||||
get failed() { return failed; },
|
||||
get failures() { return [...failures]; }
|
||||
};
|
||||
Reference in New Issue
Block a user