Files
Portfolio/tests/performance/budgets.test.ts

253 lines
11 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
classifyArtifact,
evaluateBudgetTotals,
evaluateMediaAssetBudget,
evaluateRuntimeBudgetEvidence,
evaluateRuntimeTraceBudgetEvidence,
validateRuntimeBudgetTraceReport,
calculatePeakRequestConcurrency,
normalizeDetectedMediaType,
PERFORMANCE_BUDGETS,
resolveBudgetGateMode,
} from '../../scripts/lib/bundle-budgets.mjs';
describe('release budgets', () => {
it('normalizes codec-qualified Opus detection to its manifest container type', () => {
expect(normalizeDetectedMediaType('audio/ogg; codecs=opus')).toBe('audio/ogg');
expect(normalizeDetectedMediaType('audio/mpeg')).toBe('audio/mpeg');
expect(normalizeDetectedMediaType(null)).toBeNull();
});
it('fails closed unless the caller explicitly selects a runtime trace or transfer-only mode', () => {
expect(() => resolveBudgetGateMode({ transferOnly: false, runtimeTracePath: null }))
.toThrow(/runtime trace is required/u);
expect(resolveBudgetGateMode({ transferOnly: true, runtimeTracePath: null }))
.toEqual({ kind: 'transfer-only' });
expect(resolveBudgetGateMode({ transferOnly: false, runtimeTracePath: '/tmp/runtime.json' }))
.toEqual({ kind: 'full', runtimeTracePath: '/tmp/runtime.json' });
expect(() => resolveBudgetGateMode({ transferOnly: true, runtimeTracePath: '/tmp/runtime.json' }))
.toThrow(/cannot be combined/u);
});
it('pins every exact section 14 threshold', () => {
expect(PERFORMANCE_BUDGETS.deferredAudio).toBe(16 * 1024 * 1024);
expect(PERFORMANCE_BUDGETS).toMatchObject({
initialHtmlCriticalCss: 100 * 1024,
initialApplicationJs: 120 * 1024,
heroPoster: 220 * 1024,
initialFonts: 120 * 1024,
firstLiveScene: 650 * 1024,
projectVideo: 2.5 * 1024 * 1024,
projectVideoDurationSeconds: 10,
projectVideoWidth: 1280,
projectVideoHeight: 720,
projectStill: 400 * 1024,
chart: 100 * 1024,
deferredProjectVisuals: 2.5 * 1024 * 1024,
highTierExtras: 750 * 1024,
deferredNonVideo: 3.5 * 1024 * 1024,
deferredAudio: 16 * 1024 * 1024,
imageSceneConcurrency: 2,
videoConcurrency: 1,
mobileTextureDimension: 2048,
lowTierGpuEstimate: 96 * 1024 * 1024,
highTierGpuEstimate: 192 * 1024 * 1024,
});
});
it('classifies every artifact once and keeps the scene chunk deferred', () => {
expect(classifyArtifact('index.html', '<script src="/assets/index-a.js"></script>')).toBe('initial-html');
expect(classifyArtifact('assets/index-a.css', '')).toBe('critical-css');
expect(classifyArtifact('assets/index-a.js', 'import("./environment-b.js")')).toBe('initial-application-js');
expect(classifyArtifact('assets/environment-b.js', 'three scene')).toBe('first-live-scene');
expect(classifyArtifact('assets/nightdrive-grand-tourer-a.glb', '')).toBe('first-live-scene');
expect(classifyArtifact('assets/nightdrive-main.opus', '')).toBe('soundtrack-audio');
expect(classifyArtifact('assets/nightdrive-intro.mp3', '')).toBe('soundtrack-audio');
expect(classifyArtifact('assets/nightdrive-afterglow.opus', '')).toBe('soundtrack-audio');
expect(classifyArtifact('assets/nightdrive-afterglow.mp3', '')).toBe('soundtrack-audio');
expect(classifyArtifact('assets/nightdrive-drive-lift.opus', '')).toBe('soundtrack-audio');
expect(classifyArtifact('assets/nightdrive-drive-lift.mp3', '')).toBe('soundtrack-audio');
expect(classifyArtifact('assets/high-tier-b.js', 'optional bloom')).toBe('high-tier-extras');
expect(() => classifyArtifact('assets/mystery.bin', '')).toThrow(/unclassified/u);
});
it('fails exact byte boundaries and accepts equality', () => {
expect(evaluateBudgetTotals({ initialHtmlCriticalCss: 100 * 1024 }).violations).toEqual([]);
expect(evaluateBudgetTotals({ initialHtmlCriticalCss: 100 * 1024 + 1 }).violations).toContainEqual(expect.objectContaining({ budget: 'initialHtmlCriticalCss' }));
});
it('rejects an undersized transfer when its video delivery rendition is 20s at 1920x1080', () => {
const result = evaluateMediaAssetBudget({
id: 'project-demo',
mediaType: 'video/webm',
width: 1_920,
height: 1_080,
durationMs: 20_000,
}, {
mediaType: 'video/webm',
width: 1_920,
height: 1_080,
durationMs: 20_000,
}, 1_024);
expect(result.violations.map((violation) => violation.budget)).toEqual(expect.arrayContaining([
'projectVideoDurationSeconds',
'projectVideoWidth',
'projectVideoHeight',
]));
});
it('fails closed when non-empty media dimensions cannot be deterministically probed', () => {
expect(() => evaluateMediaAssetBudget({
id: 'project-still',
mediaType: 'image/webp',
width: 1_280,
height: 720,
}, null, 1_024)).toThrow(/probe evidence/u);
});
it('rejects excessive high-tier extras and request concurrency', () => {
expect(evaluateBudgetTotals({ highTierExtras: PERFORMANCE_BUDGETS.highTierExtras! + 1 }).violations)
.toContainEqual(expect.objectContaining({ budget: 'highTierExtras' }));
expect(evaluateRuntimeBudgetEvidence({
schema: 'portfolio-runtime-budget-evidence/v1',
peakRequests: { imageScene: 3, video: 2 },
tiers: [
{ tier: 'low', textures: [], geometryBytes: 0, renderTargets: [] },
{ tier: 'high', textures: [], geometryBytes: 0, renderTargets: [] },
],
}).violations.map((violation) => violation.budget)).toEqual(expect.arrayContaining([
'imageSceneConcurrency',
'videoConcurrency',
]));
});
it('validates soundtrack duration without visual dimensions and budgets aggregate transfer', () => {
const asset = {
id: 'soundtrack-main-opus',
mediaType: 'audio/ogg',
width: null,
height: null,
durationMs: 178_605,
};
expect(evaluateMediaAssetBudget(asset, { ...asset }, 4 * 1024 * 1024, 'soundtrack-audio').violations).toEqual([]);
expect(() => evaluateMediaAssetBudget({ ...asset, width: 1 }, { ...asset, width: 1 }, 1_024, 'soundtrack-audio'))
.toThrow(/audio dimensions/i);
expect(() => evaluateMediaAssetBudget({ ...asset, durationMs: null }, { ...asset, durationMs: null }, 1_024, 'soundtrack-audio'))
.toThrow(/verified duration/i);
expect(evaluateBudgetTotals({ deferredAudio: PERFORMANCE_BUDGETS.deferredAudio! + 1 }).violations)
.toContainEqual(expect.objectContaining({ budget: 'deferredAudio' }));
});
it('derives decoded texture and GPU bytes from allocation formulas', () => {
const result = evaluateRuntimeBudgetEvidence({
schema: 'portfolio-runtime-budget-evidence/v1',
peakRequests: { imageScene: 0, video: 0 },
tiers: [
{
tier: 'low',
textures: [{ id: 'oversized', width: 4_096, height: 4_096, bytesPerPixel: 4, layers: 1, mipmapped: true }],
geometryBytes: 40 * 1024 * 1024,
renderTargets: [{ id: 'framebuffer', width: 2_048, height: 2_048, bytesPerPixel: 8, attachments: 2, samples: 1 }],
},
{ tier: 'high', textures: [], geometryBytes: 0, renderTargets: [] },
],
});
expect(result.tiers[0]?.textureBytes).toBe(Math.ceil(4_096 * 4_096 * 4 * 4 / 3));
expect(result.violations.map((violation) => violation.budget)).toEqual(expect.arrayContaining([
'mobileTextureDimension',
'lowTierGpuEstimate',
]));
});
it('fails closed when either named tier allocation ledger is absent', () => {
expect(() => evaluateRuntimeBudgetEvidence({
schema: 'portfolio-runtime-budget-evidence/v1',
peakRequests: { imageScene: 0, video: 0 },
tiers: [{ tier: 'low', textures: [], geometryBytes: 0, renderTargets: [] }],
})).toThrow(/exactly one Low and High/u);
});
it('counts peak concurrency from actual production resource timing intervals', () => {
const peak = calculatePeakRequestConcurrency([
{ name: '/assets/a.webp', initiatorType: 'img', startTime: 0, responseEnd: 50 },
{ name: '/assets/b.webp', initiatorType: 'img', startTime: 10, responseEnd: 60 },
{ name: '/assets/environment-a.js', initiatorType: 'script', startTime: 20, responseEnd: 70 },
{ name: '/assets/a.webm', initiatorType: 'video', startTime: 0, responseEnd: 50 },
{ name: '/assets/b.mp4', initiatorType: 'video', startTime: 10, responseEnd: 60 },
]);
expect(peak).toEqual({ imageScene: 3, video: 2 });
expect(evaluateRuntimeTraceBudgetEvidence({
schema: 'portfolio-runtime-trace-evidence/v1',
peakRequests: peak,
allocation: { tier: 'low', textures: [], geometryBytes: 0, renderTargets: [] },
}).violations.map((item) => item.budget)).toEqual(expect.arrayContaining(['imageSceneConcurrency', 'videoConcurrency']));
});
it('recomputes actual trace allocations and ignores a forged low total', () => {
const result = evaluateRuntimeTraceBudgetEvidence({
schema: 'portfolio-runtime-trace-evidence/v1',
peakRequests: { imageScene: 0, video: 0 },
allocation: {
tier: 'low',
textures: [{ id: 'actual-production-texture', width: 4_096, height: 4_096, bytesPerPixel: 4, layers: 1, mipmapped: true }],
geometryBytes: 0,
renderTargets: [{ id: 'default-framebuffer', width: 390, height: 844, bytesPerPixel: 4, attachments: 2, samples: 1 }],
totalBytes: 1,
},
});
expect(result.tier.totalBytes).toBeGreaterThan(PERFORMANCE_BUDGETS.lowTierGpuEstimate!);
expect(result.violations.map((item) => item.budget)).toEqual(expect.arrayContaining(['mobileTextureDimension', 'lowTierGpuEstimate']));
});
it('accepts only a production-path High capture whose framebuffer matches the observed DPR cap', () => {
const report = {
schema: 'runtime-budget-trace.v1',
evidenceKind: 'authenticated-test-build-production-path',
gatingReferenceResult: false,
profile: 'desktop-high',
tier: 'high',
observed: {
viewport: { width: 1_440, height: 900 },
devicePixelRatio: 2,
rendererPixelRatio: 1.5,
},
runtimeBudgetEvidence: {
schema: 'portfolio-runtime-trace-evidence/v1',
peakRequests: { imageScene: 1, video: 0 },
allocation: {
tier: 'high',
textures: [],
geometryBytes: 0,
renderTargets: [
{ id: 'default-framebuffer', width: 2_160, height: 1_350, bytesPerPixel: 4, attachments: 2, samples: 4 },
],
},
},
};
expect(validateRuntimeBudgetTraceReport(report).violations).toEqual([]);
expect(() => validateRuntimeBudgetTraceReport({
...report,
runtimeBudgetEvidence: {
...report.runtimeBudgetEvidence,
allocation: {
...report.runtimeBudgetEvidence.allocation,
renderTargets: [
{ id: 'default-framebuffer', width: 1_440, height: 900, bytesPerPixel: 4, attachments: 2, samples: 4 },
],
},
},
})).toThrow(/framebuffer dimensions/u);
expect(() => validateRuntimeBudgetTraceReport({
schema: 'portfolio-runtime-budget-evidence/v1',
peakRequests: { imageScene: 0, video: 0 },
tiers: [],
})).toThrow(/authenticated production-path/u);
});
});