Files
Portfolio/tests/unit/build-contract.test.ts

110 lines
3.1 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { resolveViteAssetClosure } from '../../scripts/build-contract.mjs';
import type { ViteManifest } from '../../scripts/prerender.mjs';
const recursiveManifest = (): ViteManifest => ({
'index.html': {
file: 'assets/entry-a1.js',
src: 'index.html',
isEntry: true,
css: ['assets/entry-a1.css'],
assets: ['assets/entry-logo-a1.webp'],
imports: ['src/shared.ts'],
dynamicImports: ['src/lazy.ts'],
},
'src/shared.ts': {
file: 'assets/shared-b2.js',
src: 'src/shared.ts',
css: ['assets/shared-b2.css'],
imports: ['src/deep.ts'],
},
'src/deep.ts': {
file: 'assets/deep-c3.js',
src: 'src/deep.ts',
},
'src/lazy.ts': {
file: 'assets/lazy-d4.js',
src: 'src/lazy.ts',
css: ['assets/lazy-d4.css'],
},
});
describe('trusted Vite asset closure', () => {
it('resolves the exact recursive executable, preload, style, and Vite asset sets', () => {
expect(resolveViteAssetClosure(recursiveManifest())).toEqual({
entryModule: 'assets/entry-a1.js',
executableModules: [
'assets/deep-c3.js',
'assets/entry-a1.js',
'assets/lazy-d4.js',
'assets/shared-b2.js',
],
modulePreloads: [
'assets/deep-c3.js',
'assets/entry-a1.js',
'assets/shared-b2.js',
],
styles: [
'assets/entry-a1.css',
'assets/lazy-d4.css',
'assets/shared-b2.css',
],
viteAssets: ['assets/entry-logo-a1.webp'],
});
});
it('accepts Vite emitted-asset records when a reachable module owns the emitted file', () => {
const manifest = recursiveManifest();
manifest['index.html']!.assets = [
'assets/entry-logo-a1.webp',
'assets/geist-latin-a1.woff2',
];
manifest['node_modules/font/files/geist-latin.woff2'] = {
file: 'assets/geist-latin-a1.woff2',
src: 'node_modules/font/files/geist-latin.woff2',
};
expect(resolveViteAssetClosure(manifest).viteAssets).toEqual([
'assets/entry-logo-a1.webp',
'assets/geist-latin-a1.woff2',
]);
});
it.each([
{
name: 'a missing exact index.html entry',
mutate: (manifest: ViteManifest) => {
manifest['src/entry-client.ts'] = manifest['index.html']!;
delete manifest['index.html'];
},
error: /exact index\.html/i,
},
{
name: 'an unreachable manifest record',
mutate: (manifest: ViteManifest) => {
manifest['src/orphan.ts'] = { file: 'assets/orphan.js', src: 'src/orphan.ts' };
},
error: /unreachable manifest/i,
},
{
name: 'an unsafe emitted path',
mutate: (manifest: ViteManifest) => {
manifest['src/shared.ts']!.file = '../outside.js';
},
error: /unsafe.*path/i,
},
{
name: 'a missing recursive import',
mutate: (manifest: ViteManifest) => {
manifest['src/shared.ts']!.imports = ['src/missing.ts'];
},
error: /missing manifest import/i,
},
])('rejects $name', ({ mutate, error }) => {
const manifest = recursiveManifest();
mutate(manifest);
expect(() => resolveViteAssetClosure(manifest)).toThrow(error);
});
});