import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import { describe, expect, it } from 'vitest';
import { loadProductionInputs } from '@/content/load-production-inputs';
import { readProductionInputsSnapshot } from '@/entry-client';
import { render } from '@/entry-server';
import {
assemblePrerenderedHtml,
parseExactConfigArgument,
type ViteManifest,
} from '../../scripts/prerender.mjs';
const repositoryRoot = process.cwd();
const locations = {
contentJson: pathToFileURL(resolve(repositoryRoot, 'content/public/portfolio-content.json')),
assetManifestJson: pathToFileURL(resolve(repositoryRoot, 'content/public/asset-manifest.json')),
preparedAssetRoot: pathToFileURL(`${resolve(repositoryRoot, 'inputs/prepared-assets')}/`),
siteConfigJson: pathToFileURL(resolve(repositoryRoot, 'config/site.preview.json')),
};
const builtTemplate = `
Portfolio
`;
const manifest: ViteManifest = {
'index.html': {
file: 'assets/index-test.js',
src: 'index.html',
isEntry: true,
css: ['assets/index-test.css'],
},
};
const renderRawArtifact = async () => {
const inputs = await loadProductionInputs(locations);
const markup = await render('/', inputs);
const html = assemblePrerenderedHtml(builtTemplate, manifest, markup, inputs);
return { html, inputs };
};
describe('raw prerendered document', () => {
it('places complete semantic content and the inert snapshot before the executable module', async () => {
const { html, inputs } = await renderRawArtifact();
const document = new DOMParser().parseFromString(html, 'text/html');
const moduleScript = document.querySelector('script[type="module"]');
const snapshot = document.querySelector('#portfolio-inputs[type="application/json"]');
expect(document.documentElement.lang).toBe('en');
expect(document.title).toBe('Luca Pîslaru — System Administrator & Full-Stack Developer');
expect(document.querySelectorAll('h1')).toHaveLength(1);
expect(document.querySelector('h1')?.textContent).toBe('Luca Pîslaru');
expect(document.querySelector('h1 + p')?.textContent).toBe('System Administrator & Full-Stack Developer');
expect([...document.querySelectorAll('main > section')].map((section) => section.id)).toEqual([
'start', 'profile', 'experience', 'infrastructure', 'selected-builds', 'additional-work', 'toolkit', 'contact',
]);
expect(document.body.textContent).toContain('Secure self-hosted platform and lifecycle');
expect(document.body.textContent).toContain('Private self-hosted medication tracker');
expect(document.body.textContent).toContain('Linux');
expect(document.querySelector('a[href="mailto:luca.pislaru@gmail.com"]')?.textContent)
.toBe('Start a conversation');
expect(document.querySelector('nav a[href="#infrastructure"]')).not.toBeNull();
expect(snapshot).not.toBeNull();
expect(moduleScript).not.toBeNull();
expect(html.indexOf('id="portfolio-inputs"')).toBeLessThan(html.indexOf(' {
const { html } = await renderRawArtifact();
expect(html.match(/rel="modulepreload"/gu)).toHaveLength(1);
expect(html.match(/');
});
});
describe('strict prerender command line', () => {
it('accepts exactly one explicit safe repository-relative config path', () => {
expect(parseExactConfigArgument(['--config', 'config/site.preview.json']))
.toBe('config/site.preview.json');
});
it.each([
{ arguments_: [] },
{ arguments_: ['--config'] },
{ arguments_: ['--config', 'config/site.preview.json', '--config', 'config/site.preview.json'] },
{ arguments_: ['--config', 'config/site.preview.json', '--unknown'] },
{ arguments_: ['--config', '../site.preview.json'] },
{ arguments_: ['--config', '/tmp/site.preview.json'] },
{ arguments_: ['--config', 'config\\site.preview.json'] },
])('rejects missing, duplicate, unknown, or unsafe arguments: $arguments_', ({ arguments_ }) => {
expect(() => parseExactConfigArgument(arguments_)).toThrow(/exactly --config|safe repository-relative/i);
});
});
describe('approved build template', () => {
it('declares English and contains no executable input assignment', async () => {
const template = await readFile(resolve(repositoryRoot, 'index.html'), 'utf8');
expect(template).toContain('');
expect(template).not.toContain('window.__PORTFOLIO_INPUTS__');
});
});