content: integrate approved project evidence

This commit is contained in:
2026-09-04 23:57:29 +03:00
parent 4735ceffe5
commit 2fce0cedee
15 changed files with 564 additions and 25 deletions

View File

@@ -81,14 +81,17 @@ describe('raw prerendered document', () => {
expect(readProductionInputsSnapshot(document)).toEqual(inputs);
});
it('emits one canonical, one safe ProfilePage, and no fabricated preview image', async () => {
const { html } = await renderRawArtifact();
it('emits one canonical, one safe ProfilePage, and the approved preview image', async () => {
const { html, inputs } = await renderRawArtifact();
const document = new DOMParser().parseFromString(html, 'text/html');
const jsonLdNodes = document.querySelectorAll('script[type="application/ld+json"]');
const previewAsset = inputs.manifest.assets.find(({ id }) => id === inputs.content.metadata.socialPreviewAssetId)!;
expect(document.querySelectorAll('link[rel="canonical"]')).toHaveLength(1);
expect(document.querySelector('link[rel="canonical"]')?.getAttribute('href')).toBe('https://portfolio.localhost/');
expect(document.querySelectorAll('meta[property="og:image"]')).toHaveLength(0);
expect(document.querySelectorAll('meta[property="og:image"]')).toHaveLength(1);
expect(document.querySelector('meta[property="og:image"]')?.getAttribute('content'))
.toBe(`https://portfolio.localhost/assets/${previewAsset.fileName}`);
expect(jsonLdNodes).toHaveLength(1);
const jsonLd = JSON.parse(jsonLdNodes[0]!.textContent ?? '');
expect(jsonLd['@type']).toBe('ProfilePage');

View File

@@ -1,12 +1,66 @@
import { readFile } from 'node:fs/promises';
import { describe, expect, it } from 'vitest';
import { validateProductionInputs } from '@/content/schemas';
import { parsePortfolioContent, validateProductionInputs } from '@/content/schemas';
const repositoryRoot = process.cwd();
const readJson = async (relativePath: string): Promise<unknown> =>
JSON.parse(await readFile(`${repositoryRoot}/${relativePath}`, 'utf8')) as unknown;
describe('approved public portfolio projection', () => {
it('attaches only the approved project evidence in its reviewed presentation order', async () => {
const content = parsePortfolioContent(await readJson('content/public/portfolio-content.json'));
const medication = content.projects.selected[0]!;
const footy = content.projects.selected[1]!;
const opinion = content.projects.selected[2]!;
const currency = content.projects.additional.find((project) => project.id === 'currency-converter')!;
expect(medication).toMatchObject({
id: 'private-medication-tracker',
mediaLayout: 'portrait-strip',
assetIds: [
'medication-mobile-logs',
'medication-mobile-data-settings',
'medication-mobile-notification-settings',
],
});
expect(medication.media).toHaveLength(3);
expect(medication.media?.every(({ alt }) => /fictional|demo/iu.test(alt))).toBe(true);
expect(medication.url).toBeUndefined();
expect(footy.assetIds).toEqual([]);
expect(footy.media).toBeUndefined();
expect(footy.mediaLayout).toBeUndefined();
expect(opinion).toMatchObject({
mediaLayout: 'chart-pair',
assetIds: ['opinion-polarization-chart', 'opinion-final-distribution-chart'],
});
expect(opinion.media).toHaveLength(2);
expect(opinion.media?.every(({ kind }) => kind === 'chart')).toBe(true);
expect(opinion.media?.[0]).toMatchObject({
kind: 'chart',
assetId: 'opinion-polarization-chart',
chart: {
table: {
columns: ['Step', 'Polarization index'],
rows: [['0', '0.765'], ['14', '0.932']],
},
},
});
expect(opinion.media?.[1]).toMatchObject({
kind: 'chart',
assetId: 'opinion-final-distribution-chart',
});
if (opinion.media?.[1]?.kind === 'chart') expect(opinion.media[1].chart.table).toBeUndefined();
expect(currency).toMatchObject({
mediaLayout: 'single',
assetIds: ['currency-converter-interface'],
media: [{ kind: 'image', assetId: 'currency-converter-interface' }],
});
expect(content.metadata.socialPreviewAssetId).toBe('social-preview-nightdrive');
});
it('contains approved identity and balanced evidence without prohibited surfaces', async () => {
const { content, manifest, site } = validateProductionInputs(
await readJson('content/public/portfolio-content.json'),