open-design/apps/web/tests/artifacts/manifest.test.ts
PerishFire bbdd4e84b5
chore: enforce test directory conventions (#496)
* chore: enforce test directory conventions

Move package, app, and tool tests out of src and add guard enforcement so source directories stay source-only.

* ci: use guard and package-scoped tests

Run the new repository guard in CI and keep test execution aligned with package-scoped commands after removing root aliases.

* ci: align stable release guard check

Use the new repository guard in stable release verification after replacing the residual-JS-only script.

* chore: tighten test layout enforcement

Enforce sibling tests directories, typecheck moved test suites with dedicated configs, and refresh remaining guidance that pointed at src-based tests.

* chore: clarify no-emit test tsconfigs

Explicitly disable declaration-only emit in test tsconfigs so review tooling sees they are no-emit typecheck configs.
2026-05-05 15:34:22 +08:00

120 lines
3.7 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
artifactManifestNameFor,
createHtmlArtifactManifest,
inferLegacyManifest,
parseArtifactManifest,
} from '../../src/artifacts/manifest';
describe('parseArtifactManifest', () => {
it('returns null for malformed json', () => {
expect(parseArtifactManifest('{"version":1')).toBeNull();
});
it('returns null when required fields are missing', () => {
expect(parseArtifactManifest(JSON.stringify({ version: 1, kind: 'html' }))).toBeNull();
});
it('returns null for wrong version', () => {
const raw = JSON.stringify({
version: 2,
kind: 'html',
title: 'x',
entry: 'index.html',
renderer: 'html',
exports: ['html'],
});
expect(parseArtifactManifest(raw)).toBeNull();
});
it('defaults status to complete when missing', () => {
const raw = JSON.stringify({
version: 1,
kind: 'html',
title: 'x',
entry: 'index.html',
renderer: 'html',
exports: ['html'],
});
const out = parseArtifactManifest(raw);
expect(out?.status).toBe('complete');
});
it('preserves valid status when provided', () => {
const raw = JSON.stringify({
version: 1,
kind: 'html',
title: 'x',
entry: 'index.html',
renderer: 'html',
status: 'streaming',
exports: ['html'],
});
const out = parseArtifactManifest(raw);
expect(out?.status).toBe('streaming');
});
});
describe('inferLegacyManifest', () => {
it('infers markdown manifests for .md files', () => {
const out = inferLegacyManifest({ entry: 'README.md' });
expect(out?.kind).toBe('markdown-document');
expect(out?.renderer).toBe('markdown');
expect(out?.status).toBe('complete');
});
it('infers svg manifests for .svg files', () => {
const out = inferLegacyManifest({ entry: 'logo.svg' });
expect(out?.kind).toBe('svg');
expect(out?.renderer).toBe('svg');
expect(out?.status).toBe('complete');
});
it('returns null for non-artifact file types', () => {
expect(inferLegacyManifest({ entry: 'photo.png' })).toBeNull();
expect(inferLegacyManifest({ entry: 'archive.bin' })).toBeNull();
});
it('infers React component artifacts from JSX and TSX entries', () => {
expect(inferLegacyManifest({ entry: 'Card.jsx' })).toMatchObject({
kind: 'react-component',
renderer: 'react-component',
exports: ['jsx', 'html', 'zip'],
});
expect(inferLegacyManifest({ entry: 'Card.tsx' })).toMatchObject({
kind: 'react-component',
renderer: 'react-component',
exports: ['jsx', 'html', 'zip'],
});
});
});
describe('artifactManifestNameFor', () => {
it('handles names without extension', () => {
expect(artifactManifestNameFor('README')).toBe('README.artifact.json');
});
it('handles names with multiple dots', () => {
expect(artifactManifestNameFor('page.v2.final.html')).toBe('page.v2.final.html.artifact.json');
});
it('avoids collisions between different extensions', () => {
expect(artifactManifestNameFor('foo.html')).not.toBe(artifactManifestNameFor('foo.md'));
});
});
describe('createHtmlArtifactManifest', () => {
it('creates expected default html manifest shape', () => {
const out = createHtmlArtifactManifest({ entry: 'index.html', title: 'Landing' });
expect(out.version).toBe(1);
expect(out.kind).toBe('html');
expect(out.renderer).toBe('html');
expect(out.status).toBe('complete');
expect(out.exports).toEqual(['html', 'pdf', 'zip']);
expect(out.entry).toBe('index.html');
expect(out.title).toBe('Landing');
expect(typeof out.createdAt).toBe('string');
expect(typeof out.updatedAt).toBe('string');
});
});