content: publish evidence-led portfolio copy
This commit is contained in:
16
tests/fixtures/portfolio-content.valid.json
vendored
16
tests/fixtures/portfolio-content.valid.json
vendored
@@ -2,7 +2,9 @@
|
||||
"identity": {
|
||||
"name": "Luca Pîslaru",
|
||||
"role": "System Administrator & Full-Stack Developer",
|
||||
"valueProposition": "Building and operating reliable systems and software."
|
||||
"valueProposition": "Building and operating reliable systems and software.",
|
||||
"location": { "city": "Bucharest", "country": "Romania", "countryCode": "RO" },
|
||||
"availability": "Based in Bucharest and open to remote roles."
|
||||
},
|
||||
"navigation": [
|
||||
{ "id": "start", "label": "Start" },
|
||||
@@ -41,7 +43,13 @@
|
||||
{ "id": "identity-access", "title": "Identity and access", "summary": "Protected service access." },
|
||||
{ "id": "service-lifecycle", "title": "Service lifecycle", "summary": "Maintained representative services." },
|
||||
{ "id": "operations", "title": "Operations", "summary": "Resolved routine service issues." }
|
||||
]
|
||||
],
|
||||
"featuredOperation": {
|
||||
"title": "Synthetic stateful service migration",
|
||||
"context": "A representative migration preserved essential application state.",
|
||||
"actions": ["Prepared versions.", "Created recovery checkpoints.", "Validated the new service."],
|
||||
"outcome": "The synthetic migration retained expected service data."
|
||||
}
|
||||
},
|
||||
"projects": {
|
||||
"selected": [
|
||||
@@ -55,7 +63,8 @@
|
||||
"contribution": "Designed and maintained the application.",
|
||||
"technicalDecisions": ["Used a synchronised client and server design."],
|
||||
"outcome": "The work remains private.",
|
||||
"assetIds": ["selected-build-one"]
|
||||
"assetIds": ["selected-build-one"],
|
||||
"media": [{ "kind": "image", "assetId": "selected-build-one", "alt": "Synthetic project evidence." }]
|
||||
},
|
||||
{
|
||||
"id": "public-build-two",
|
||||
@@ -101,6 +110,7 @@
|
||||
"technologies": [{ "name": "Linux", "assetId": "toolkit-linux" }]
|
||||
}],
|
||||
"contact": {
|
||||
"introduction": "Open to System Administrator and Full-Stack Developer opportunities.",
|
||||
"email": "hello@example.test",
|
||||
"social": [{ "service": "GitHub", "url": "https://github.com/example" }],
|
||||
"cvMessage": "For a current CV or role-specific information, contact me directly."
|
||||
|
||||
@@ -15,10 +15,23 @@ describe('approved public portfolio projection', () => {
|
||||
new URL('file:///prepared-assets/'),
|
||||
);
|
||||
|
||||
expect(content.identity).toEqual(expect.objectContaining({
|
||||
expect(content.identity).toMatchObject({
|
||||
name: 'Luca Pîslaru',
|
||||
role: 'System Administrator & Full-Stack Developer',
|
||||
}));
|
||||
location: { city: 'Bucharest', country: 'Romania', countryCode: 'RO' },
|
||||
});
|
||||
expect(content.experience[0]).toMatchObject({
|
||||
organization: 'Trupa lui Răzuș',
|
||||
role: 'Full-Stack Developer & Hosting Administrator (Collaborator)',
|
||||
});
|
||||
expect(content.infrastructure.featuredOperation.outcome).toMatch(/without data loss.*roughly a year/iu);
|
||||
expect(content.projects.selected.map(({ id }) => id)).toEqual([
|
||||
'private-medication-tracker',
|
||||
'footy-tracker',
|
||||
'opinion-dynamics-simulation',
|
||||
]);
|
||||
expect(content.projects.selected[1]?.contribution).toMatch(/collaborator/iu);
|
||||
expect(content.projects.selected[1]?.outcome).toMatch(/0\.942 mAP@0\.5.*0\.198/iu);
|
||||
expect(content.systemsOperations.title).toBe('Professional systems operations');
|
||||
expect(content.infrastructure.title).toBe('Secure self-hosted platform and lifecycle');
|
||||
expect(content.projects.selected).toHaveLength(3);
|
||||
@@ -59,7 +72,9 @@ describe('approved public portfolio projection', () => {
|
||||
canonicalUrl: 'https://portfolio.localhost/',
|
||||
buildId: 'preview-semantic-v1',
|
||||
});
|
||||
expect(JSON.stringify(content)).not.toMatch(/Arch Linux|CV download|heatmap|expert|percent/i);
|
||||
expect(JSON.stringify(content)).not.toMatch(
|
||||
/Arch Linux|Mihai Razus PFA|DevOps collaborator|CV download|heatmap|fully secure|production-ready|expert|percent/iu,
|
||||
);
|
||||
});
|
||||
|
||||
it('publishes only the four verified owner repositories and no private project links', async () => {
|
||||
|
||||
@@ -37,6 +37,12 @@ const infrastructure: InfrastructureCaseStudy = {
|
||||
summary: "Routine maintenance and investigation.",
|
||||
},
|
||||
],
|
||||
featuredOperation: {
|
||||
title: "Synthetic stateful service migration",
|
||||
context: "A representative migration preserved application state.",
|
||||
actions: ["Prepared versions.", "Created recovery checkpoints.", "Validated the new service."],
|
||||
outcome: "The synthetic migration retained expected data.",
|
||||
},
|
||||
};
|
||||
|
||||
const privateProject: PublicProject = {
|
||||
@@ -159,6 +165,7 @@ describe("semantic section components", () => {
|
||||
|
||||
it("renders a visible mailto contact and safe verified social links", () => {
|
||||
const contact: ContactContent = {
|
||||
introduction: "Open to System Administrator and Full-Stack Developer opportunities.",
|
||||
email: "hello@example.test",
|
||||
cvMessage:
|
||||
"For a current CV or role-specific information, contact me directly.",
|
||||
|
||||
@@ -15,11 +15,23 @@ const validContent = fixture('portfolio-content.valid.json');
|
||||
const validManifest = fixture('asset-manifest.valid.json');
|
||||
const validSite = fixture('site-config.preview.json');
|
||||
type MutableContentFixture = {
|
||||
identity: {
|
||||
location: { city: string; country: string; countryCode: string };
|
||||
availability: string;
|
||||
};
|
||||
navigation: Array<{ id: string }>;
|
||||
profile: { introduction: string };
|
||||
contact: { social: Array<{ service: string; url: string }> };
|
||||
contact: { introduction: string; social: Array<{ service: string; url: string }> };
|
||||
infrastructure: { featuredOperation: { actions: string[] } };
|
||||
projects: {
|
||||
selected: Array<{ visibility: string; url?: string; assetIds: string[]; title: string }>;
|
||||
selected: Array<{
|
||||
visibility: string;
|
||||
url?: string;
|
||||
assetIds: string[];
|
||||
title: string;
|
||||
media?: Array<{ assetId: string; alt: string; kind: 'image' }>;
|
||||
mediaLayout?: 'single' | 'portrait-strip' | 'chart-pair';
|
||||
}>;
|
||||
additional: Array<{ assetIds: string[] }>;
|
||||
};
|
||||
toolkit: Array<{ technologies: Array<{ assetId?: string }> }>;
|
||||
@@ -41,6 +53,25 @@ describe('content schemas', () => {
|
||||
expect(parseSiteConfig(validSite).environment).toBe('preview');
|
||||
});
|
||||
|
||||
it('requires public availability, city-level location, featured operations evidence, and contact copy', () => {
|
||||
const content = cloneContent();
|
||||
expect(content.identity.location).toEqual({ city: 'Bucharest', country: 'Romania', countryCode: 'RO' });
|
||||
expect(content.identity.availability).toMatch(/Bucharest.*remote/iu);
|
||||
expect(content.infrastructure.featuredOperation.actions.length).toBeGreaterThanOrEqual(3);
|
||||
expect(content.contact.introduction).toMatch(/System Administrator.*Full-Stack Developer/iu);
|
||||
|
||||
delete (content.identity as Partial<typeof content.identity>).availability;
|
||||
expect(() => parsePortfolioContent(content)).toThrow();
|
||||
});
|
||||
|
||||
it('accepts only the approved project media layouts', () => {
|
||||
const content = cloneContent();
|
||||
content.projects.selected[0]!.mediaLayout = 'portrait-strip';
|
||||
expect(() => parsePortfolioContent(content)).not.toThrow();
|
||||
content.projects.selected[0]!.mediaLayout = 'carousel' as never;
|
||||
expect(() => parsePortfolioContent(content)).toThrow(/mediaLayout|unrecognized/iu);
|
||||
});
|
||||
|
||||
it('accepts an empty manifest before Phase 3 assets are prepared', () => {
|
||||
expect(parsePublicAssetManifest({ assets: [] })).toEqual({ assets: [] });
|
||||
});
|
||||
@@ -117,6 +148,7 @@ describe('content schemas', () => {
|
||||
const content = cloneContent();
|
||||
content.projects.selected[0]!.title = 'Private self-hosted medication tracker';
|
||||
for (const project of [...content.projects.selected, ...content.projects.additional]) project.assetIds = [];
|
||||
delete content.projects.selected[0]!.media;
|
||||
delete content.toolkit[0]!.technologies[0]!.assetId;
|
||||
delete content.metadata.socialPreviewAssetId;
|
||||
expect(() => validateProductionInputs(content, { assets: [] }, validSite, new URL('file:///prepared/'))).not.toThrow();
|
||||
@@ -126,6 +158,7 @@ describe('content schemas', () => {
|
||||
const content = cloneContent();
|
||||
content.projects.selected[0]!.title = 'Private self-hosted medication tracker';
|
||||
for (const project of [...content.projects.selected, ...content.projects.additional]) project.assetIds = [];
|
||||
delete content.projects.selected[0]!.media;
|
||||
content.toolkit[0]!.technologies[0]!.assetId = 'missing-toolkit-asset';
|
||||
expect(() => validateProductionInputs(content, { assets: [] }, validSite, new URL('file:///prepared/')))
|
||||
.toThrow(/unmanifested asset reference: missing-toolkit-asset/i);
|
||||
@@ -205,6 +238,7 @@ describe('content schemas', () => {
|
||||
it('rejects an asset reference absent from the manifest', () => {
|
||||
const content = cloneContent();
|
||||
content.projects.selected[0]!.assetIds = ['missing-asset'];
|
||||
content.projects.selected[0]!.media![0]!.assetId = 'missing-asset';
|
||||
expect(() => validateProductionInputs(content, validManifest, validSite, new URL('file:///prepared/')))
|
||||
.toThrow(/unmanifested asset/i);
|
||||
});
|
||||
@@ -217,6 +251,7 @@ describe('content schemas', () => {
|
||||
|
||||
const unreferencedManifestAsset = cloneContent();
|
||||
unreferencedManifestAsset.projects.selected[0]!.assetIds = [];
|
||||
delete unreferencedManifestAsset.projects.selected[0]!.media;
|
||||
expect(() => validateProductionInputs(unreferencedManifestAsset, validManifest, validSite, new URL('file:///prepared/')))
|
||||
.toThrow(/unreferenced manifest asset/i);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user