diff --git a/demo/bundle-freshness.mjs b/demo/bundle-freshness.mjs index 1f72a8da..f3078948 100644 --- a/demo/bundle-freshness.mjs +++ b/demo/bundle-freshness.mjs @@ -1,8 +1,24 @@ +import { existsSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { pathToFileURL } from 'node:url'; import { sourceFingerprint } from '../scripts/source-fingerprint.mjs'; +const fingerprintForTree = async (root) => { + const modulePath = resolve(root, 'scripts/source-fingerprint.mjs'); + if (!existsSync(modulePath)) return sourceFingerprint(root); + const module = await import(pathToFileURL(modulePath).href); + if (typeof module.sourceFingerprint !== 'function') { + throw new Error(`${modulePath} does not export sourceFingerprint`); + } + return module.sourceFingerprint(root); +}; + /** Refuse measurements/screenshots made by a committed bundle from old source. */ export async function assertFreshDemoBundle(page, root = process.cwd()) { - const expected = sourceFingerprint(root); + // A comparative performance run may load an older tree whose fingerprint + // contract is intentionally different from the candidate's. Validate that + // tree with the implementation that built it, not with today's algorithm. + const expected = await fingerprintForTree(root); const loaded = await page.evaluate(() => globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__ ?? null); if (loaded !== expected) { throw new Error( diff --git a/test/bundle-freshness.test.mjs b/test/bundle-freshness.test.mjs index 235b81c5..dc67ff68 100644 --- a/test/bundle-freshness.test.mjs +++ b/test/bundle-freshness.test.mjs @@ -39,3 +39,19 @@ test('bundle freshness rejects a missing or stale fingerprint', async () => { rmSync(root, { recursive: true, force: true }); } }); + +test('bundle freshness uses the target tree fingerprint contract', async () => { + const root = fixtureRoot(); + try { + mkdirSync(resolve(root, 'scripts'), { recursive: true }); + writeFileSync( + resolve(root, 'scripts/source-fingerprint.mjs'), + "export const sourceFingerprint = () => 'legacy-tree-fingerprint';\n", + 'utf8', + ); + const page = { evaluate: async () => 'legacy-tree-fingerprint' }; + assert.equal(await assertFreshDemoBundle(page, root), 'legacy-tree-fingerprint'); + } finally { + rmSync(root, { recursive: true, force: true }); + } +});