import assert from 'node:assert/strict' import fs from 'node:fs/promises' import os from 'node:os' import path from 'node:path' // eslint-disable-next-line test/no-import-node-test -- Exercise the generated site's real filesystem and HTML links. import test from 'node:test' import { checkSiteLinks } from '../scripts/site-build/links.ts' async function fixture(t, lookup = { a: { l: 'target.html#中文' } }) { const root = await fs.mkdtemp(path.join(os.tmpdir(), 'artplayer-site-links-')) t.after(async () => { assert.equal(path.dirname(path.resolve(root)), path.resolve(os.tmpdir())) assert(path.basename(root).startsWith('artplayer-site-links-')) await fs.rm(root, { recursive: true, force: true }) }) await fs.mkdir(path.join(root, 'document/assets/chunks'), { recursive: true }) await fs.writeFile(path.join(root, 'package.json'), '{"type":"module"}') await fs.writeFile(path.join(root, 'document/assets/chunks/virtual_search-data.test.js'), `export default ${JSON.stringify({ PREVIEW_LOOKUP: lookup })}`) await fs.writeFile(path.join(root, 'document/index.html'), 'targetexternalemail') await fs.writeFile(path.join(root, 'document/target.html'), '

Heading

legacyhome

Entity

entity') await fs.writeFile(path.join(root, 'image.svg'), '') await fs.writeFile(path.join(root, 'script.js'), '') return root } test('built pages and the shipped search index resolve encoded anchors, assets and directory URLs', async (t) => { const report = await checkSiteLinks(await fixture(t)) assert.equal(report.pages, 2) assert.equal(report.searchEntries, 1) assert.equal(report.localReferences, 7) assert.deepEqual(report.externalUrls, ['https://example.com/unchecked']) assert.deepEqual(report.issues, []) }) test('broken assets, ordinary anchors and actual search-index anchors fail independently', async (t) => { const root = await fixture(t, { a: { l: 'target.html#absent' }, b: { l: 'missing.html' } }) await fs.appendFile(path.join(root, 'document/index.html'), 'badinvalid') const report = await checkSiteLinks(root) assert.equal(report.pageIssues, 3) assert.equal(report.searchIssues, 2) assert(report.issues.some(issue => issue.source === 'search:a' && issue.reason.includes('Missing anchor'))) assert(report.issues.some(issue => issue.source === 'search:b' && issue.reason === 'Missing local file')) }) test('missing, ambiguous or malformed search modules cannot silently pass', async (t) => { const root = await fixture(t, { a: {} }) await assert.rejects(checkSiteLinks(root), /Missing search URL/) const chunks = path.join(root, 'document/assets/chunks') await fs.copyFile(path.join(chunks, 'virtual_search-data.test.js'), path.join(chunks, 'virtual_search-data.extra.js')) await assert.rejects(checkSiteLinks(root), /exactly one/) await fs.unlink(path.join(chunks, 'virtual_search-data.extra.js')) await fs.unlink(path.join(chunks, 'virtual_search-data.test.js')) await assert.rejects(checkSiteLinks(root), /exactly one/) })