Files
documentation/scripts/measurement-pages.test.mjs
jarvis-at-skic f7a68d7e37
Build and publish Eldorado documentation / build (pull_request) Successful in 42s
docs: [verified] connect Strategy through practical Delivery journey
2026-10-08 13:29:59 +00:00

46 lines
3.2 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {readFileSync, existsSync, readdirSync} from 'node:fs';
import {createHash} from 'node:crypto';
import {calculate} from './ai-kpi.mjs';
const read = p => readFileSync(p, 'utf8');
test('each original metric survives exactly once on its own canonical Measurement page', () => {
const manifest = JSON.parse(read('research/ai-adoption/measurement-migration.json'));
const model = JSON.parse(read('research/ai-adoption/strategy-model.json'));
const report = calculate(JSON.parse(read('scripts/fixtures/ai-kpi-synthetic.json')));
assert.equal(manifest.metrics.length, 16);
assert.deepEqual(manifest.metrics.map(m => m.title), model.kpis.map(k => k.name));
assert.equal(new Set(manifest.metrics.map(m => m.docId)).size, 16);
assert.equal(manifest.metrics.filter(m => m.status === 'prototype').length, 9);
assert.equal(manifest.metrics.filter(m => m.status === 'unimplemented').length, 7);
const overview = read('docs/strategy/measurement/index.mdx');
for (const metric of manifest.metrics) {
const page = read(`docs/strategy/${metric.docId}.mdx`);
assert.equal(metric.url, `/strategy/${metric.docId}/`);
assert.equal(metric.oldAnchor, metric.docId.split('/').at(-1));
assert(page.includes(`slug: /${metric.docId}`));
assert(overview.includes(`./${metric.oldAnchor}.mdx`));
assert(page.includes('./collection-and-safeguards.mdx'));
assert(page.includes('not installed collection'));
assert(page.includes(metric.status === 'prototype' ? 'Prototype calculation' : 'Unimplemented metric'));
assert.equal(Object.hasOwn(report.kpis, metric.calculationId), metric.status === 'prototype');
const contract = page.split('{/* contract:start */}\n')[1]?.split('\n{/* contract:end */}')[0];
assert(contract, metric.title);
assert.equal(createHash('sha256').update(contract).digest('hex'), metric.contractSha256, metric.title);
for (const field of ['Numerator','Denominator','Expression','Aggregation','Unit','Eligible population','Exclusions','Events and source','Owner / cadence','Missing evidence','Gaming and limits']) assert.equal(contract.split(`| ${field} |`).length, 2, `${metric.title}: ${field}`);
}
assert.equal(readdirSync('docs/strategy/measurement').filter(p => p.endsWith('.mdx')).length, 19);
assert(!existsSync('docs/strategy/reference/measurement-contracts.mdx'));
for (const part of manifest.shared) {
const page = read(`docs/strategy/measurement/${part.slug}.mdx`);
const body = page.split('{/* preserved:start */}\n')[1]?.split('\n{/* preserved:end */}')[0];
// Only the cross-page navigation wording changes; hash all original substance.
const original = body.replace('Use the [metric definitions](./index.mdx#metric-definitions)', 'Use the metric contracts below')
// The old navigation named nonexistent roadmap gates. Restore only that
// historical sentence for the migration hash; metric substance stays exact.
.replace('Use these safeguards throughout the [Stage 01 journey](../stage-01-skills-adoption.mdx)', 'Introduction depends on the [roadmap gates](../roadmap.mdx)');
assert.equal(createHash('sha256').update(original).digest('hex'), part.sha256);
}
});