88 lines
3.3 KiB
JavaScript
88 lines
3.3 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import test from 'node:test';
|
|
import { checkInternalLinks } from '../scripts/lib/internal-links.mjs';
|
|
|
|
async function withBuiltSite(run) {
|
|
const root = await mkdtemp(join(tmpdir(), 'incognito-links-'));
|
|
try {
|
|
await run(root);
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
test('reports a missing built internal route', async () => {
|
|
await withBuiltSite(async (root) => {
|
|
await writeFile(join(root, 'index.html'), '<a href="/missing/">Missing</a>');
|
|
const result = await checkInternalLinks({ distRoot: root, base: '/' });
|
|
assert.deepEqual(result.broken.map(({ href }) => href), ['/missing/']);
|
|
});
|
|
});
|
|
|
|
test('accepts an existing directory index route', async () => {
|
|
await withBuiltSite(async (root) => {
|
|
await mkdir(join(root, 'about'), { recursive: true });
|
|
await writeFile(join(root, 'index.html'), '<a href="/about/">About</a>');
|
|
await writeFile(join(root, 'about/index.html'), '<h1>About</h1>');
|
|
const result = await checkInternalLinks({ distRoot: root, base: '/' });
|
|
assert.equal(result.broken.length, 0);
|
|
});
|
|
});
|
|
|
|
test('maps the root route to the built root index', async () => {
|
|
await withBuiltSite(async (root) => {
|
|
await writeFile(join(root, 'index.html'), '<a href="/">Home</a>');
|
|
|
|
const result = await checkInternalLinks({ distRoot: root, base: '/' });
|
|
|
|
assert.equal(result.broken.length, 0);
|
|
});
|
|
});
|
|
|
|
test('removes the configured base prefix before resolving built routes', async () => {
|
|
await withBuiltSite(async (root) => {
|
|
await mkdir(join(root, 'about'), { recursive: true });
|
|
await writeFile(join(root, 'index.html'), [
|
|
'<a href="/wiki/about/">About</a>',
|
|
'<a href="/about/">Missing base prefix</a>',
|
|
].join(''));
|
|
await writeFile(join(root, 'about/index.html'), '<h1>About</h1>');
|
|
|
|
const result = await checkInternalLinks({ distRoot: root, base: '/wiki/' });
|
|
|
|
assert.deepEqual(result.broken.map(({ href }) => href), ['/about/']);
|
|
assert.equal(result.broken[0].resolvedPath, '/about/');
|
|
});
|
|
});
|
|
|
|
test('resolves relative routes from the source HTML route', async () => {
|
|
await withBuiltSite(async (root) => {
|
|
await mkdir(join(root, 'guide', 'install'), { recursive: true });
|
|
await mkdir(join(root, 'guide', 'about'), { recursive: true });
|
|
await writeFile(join(root, 'guide/install/index.html'), '<a href="../about/">About</a>');
|
|
await writeFile(join(root, 'guide/about/index.html'), '<h1>About</h1>');
|
|
|
|
const result = await checkInternalLinks({ distRoot: root, base: '/' });
|
|
|
|
assert.equal(result.broken.length, 0);
|
|
});
|
|
});
|
|
|
|
test('ignores fragments, remote protocols, and Astro-generated assets', async () => {
|
|
await withBuiltSite(async (root) => {
|
|
await writeFile(join(root, 'index.html'), [
|
|
'<a href="#section">Section</a>',
|
|
'<a href="mailto:info@example.com">Email</a>',
|
|
'<a href="tel:+31000000000">Call</a>',
|
|
'<a href="https://example.com/elsewhere">Remote</a>',
|
|
'<link href="/_astro/site.css" rel="stylesheet">',
|
|
].join(''));
|
|
|
|
const result = await checkInternalLinks({ distRoot: root, base: '/' });
|
|
|
|
assert.equal(result.broken.length, 0);
|
|
});
|
|
});
|