From 7f5fe2bf4789e155792b2309c0d47fbac656560c Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 9 Aug 2024 11:16:43 -0400 Subject: [PATCH 1/2] normalize _observablehq hashes during testing --- test/build-test.ts | 35 ++++++++++++++++--- test/mocks/observableApi.ts | 8 ++--- test/output/build/404/404.html | 8 ++--- .../404/_observablehq/client.00000001.js | 0 .../404/_observablehq/runtime.00000002.js | 0 .../404/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 .../_observablehq/client.00000001.js | 0 .../_observablehq/runtime.00000002.js | 0 .../_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/archives.posix/tar.html | 10 +++--- test/output/build/archives.posix/zip.html | 10 +++--- .../config/_observablehq/client.00000001.js | 0 .../config/_observablehq/runtime.00000002.js | 0 .../config/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/config/closed/page.html | 8 ++--- test/output/build/config/index.html | 8 ++--- test/output/build/config/one.html | 8 ++--- test/output/build/config/sub/two.html | 8 ++--- test/output/build/config/toc-override.html | 8 ++--- test/output/build/config/toc.html | 8 ++--- .../draft/_observablehq/client.00000001.js | 0 .../draft/_observablehq/runtime.00000002.js | 0 .../draft/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/draft/index.html | 8 ++--- test/output/build/draft/page-published.html | 8 ++--- .../build/fetches/_import/foo/foo.6fd063d5.js | 2 +- .../build/fetches/_import/top.d8f5cc36.js | 2 +- .../fetches/_observablehq/client.00000001.js | 0 .../fetches/_observablehq/runtime.00000002.js | 0 .../fetches/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/fetches/foo.html | 10 +++--- test/output/build/fetches/top.html | 10 +++--- .../files/_observablehq/client.00000001.js | 0 .../files/_observablehq/runtime.00000002.js | 0 .../files/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/files/files.html | 10 +++--- .../build/files/subsection/subfiles.html | 10 +++--- .../_observablehq/client.00000001.js | 0 .../_observablehq/runtime.00000002.js | 0 .../_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/fragments/index.html | 8 ++--- .../imports/_observablehq/client.00000001.js | 0 .../imports/_observablehq/runtime.00000002.js | 0 .../imports/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/imports/foo/foo.html | 10 +++--- test/output/build/imports/script.html | 8 ++--- .../_observablehq/client.00000001.js | 0 .../_observablehq/runtime.00000002.js | 0 .../_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/missing-file/index.html | 10 +++--- .../_observablehq/client.00000001.js | 0 .../_observablehq/runtime.00000002.js | 0 .../_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/missing-import/index.html | 8 ++--- .../multi/_observablehq/client.00000001.js | 0 .../multi/_observablehq/runtime.00000002.js | 0 .../multi/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/multi/index.html | 10 +++--- test/output/build/multi/subsection/index.html | 8 ++--- .../pager/_observablehq/client.00000001.js | 0 .../pager/_observablehq/runtime.00000002.js | 0 .../pager/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/pager/index.html | 8 ++--- test/output/build/pager/null.html | 8 ++--- test/output/build/pager/sub/index.html | 8 ++--- test/output/build/pager/sub/page0.html | 8 ++--- test/output/build/pager/sub/page1..10.html | 8 ++--- test/output/build/pager/sub/page1.html | 8 ++--- test/output/build/pager/sub/page2.html | 8 ++--- test/output/build/pager/sub/page3.html | 8 ++--- test/output/build/pager/sub/page4.html | 8 ++--- test/output/build/pager/sub/page5.html | 8 ++--- test/output/build/pager/sub/page6.html | 8 ++--- test/output/build/pager/sub/page7.html | 8 ++--- test/output/build/pager/sub/page8.html | 8 ++--- .../scripts/_observablehq/client.00000001.js | 0 .../scripts/_observablehq/runtime.00000002.js | 0 .../scripts/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/scripts/index.html | 8 ++--- test/output/build/scripts/sub/index.html | 8 ++--- .../_observablehq/client.00000001.js | 0 .../_observablehq/client.0425226e.js | 1 - .../_observablehq/minisearch.00000002.json | 0 .../_observablehq/minisearch.55535b23.json | 1 - .../_observablehq/runtime.00000003.js | 0 .../_observablehq/runtime.c45c72e0.js | 7 ---- .../_observablehq/search.00000004.js | 0 .../_observablehq/search.2515eb68.js | 1 - .../_observablehq/stdlib.00000005.js | 0 .../_observablehq/stdlib.1b8a97c3.js | 1 - .../theme-air,near-midnight.00000006.css | 0 .../theme-air,near-midnight.e68849dc.css | 1 - test/output/build/search-public/page1.html | 8 ++--- test/output/build/search-public/page3.html | 8 ++--- .../output/build/search-public/sub/page2.html | 8 ++--- .../_observablehq/client.00000001.js | 0 .../_observablehq/client.0425226e.js | 1 - .../_observablehq/runtime.00000002.js | 0 .../_observablehq/runtime.c45c72e0.js | 7 ---- .../_observablehq/stdlib.00000003.js | 0 .../_observablehq/stdlib.1b8a97c3.js | 1 - .../theme-air,near-midnight.00000004.css | 0 .../theme-air,near-midnight.e68849dc.css | 1 - test/output/build/simple-public/index.html | 8 ++--- .../simple/_observablehq/client.00000001.js | 0 .../simple/_observablehq/runtime.00000002.js | 0 .../simple/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/simple/simple.html | 10 +++--- .../_observablehq/client.00000001.js | 0 .../_observablehq/runtime.00000002.js | 0 .../_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/space-page/a space.html | 8 ++--- test/output/build/space-page/index.html | 8 ++--- .../subtitle/_observablehq/client.00000001.js | 0 .../_observablehq/runtime.00000002.js | 0 .../subtitle/_observablehq/stdlib.00000003.js | 0 .../theme-air,near-midnight.00000004.css | 0 test/output/build/subtitle/index.html | 8 ++--- 133 files changed, 227 insertions(+), 222 deletions(-) create mode 100644 test/output/build/404/_observablehq/client.00000001.js create mode 100644 test/output/build/404/_observablehq/runtime.00000002.js create mode 100644 test/output/build/404/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/404/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/archives.posix/_observablehq/client.00000001.js create mode 100644 test/output/build/archives.posix/_observablehq/runtime.00000002.js create mode 100644 test/output/build/archives.posix/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/archives.posix/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/config/_observablehq/client.00000001.js create mode 100644 test/output/build/config/_observablehq/runtime.00000002.js create mode 100644 test/output/build/config/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/config/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/draft/_observablehq/client.00000001.js create mode 100644 test/output/build/draft/_observablehq/runtime.00000002.js create mode 100644 test/output/build/draft/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/draft/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/fetches/_observablehq/client.00000001.js create mode 100644 test/output/build/fetches/_observablehq/runtime.00000002.js create mode 100644 test/output/build/fetches/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/fetches/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/files/_observablehq/client.00000001.js create mode 100644 test/output/build/files/_observablehq/runtime.00000002.js create mode 100644 test/output/build/files/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/files/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/fragments/_observablehq/client.00000001.js create mode 100644 test/output/build/fragments/_observablehq/runtime.00000002.js create mode 100644 test/output/build/fragments/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/fragments/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/imports/_observablehq/client.00000001.js create mode 100644 test/output/build/imports/_observablehq/runtime.00000002.js create mode 100644 test/output/build/imports/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/imports/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/missing-file/_observablehq/client.00000001.js create mode 100644 test/output/build/missing-file/_observablehq/runtime.00000002.js create mode 100644 test/output/build/missing-file/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/missing-file/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/missing-import/_observablehq/client.00000001.js create mode 100644 test/output/build/missing-import/_observablehq/runtime.00000002.js create mode 100644 test/output/build/missing-import/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/missing-import/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/multi/_observablehq/client.00000001.js create mode 100644 test/output/build/multi/_observablehq/runtime.00000002.js create mode 100644 test/output/build/multi/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/multi/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/pager/_observablehq/client.00000001.js create mode 100644 test/output/build/pager/_observablehq/runtime.00000002.js create mode 100644 test/output/build/pager/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/pager/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/scripts/_observablehq/client.00000001.js create mode 100644 test/output/build/scripts/_observablehq/runtime.00000002.js create mode 100644 test/output/build/scripts/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/scripts/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/search-public/_observablehq/client.00000001.js delete mode 100644 test/output/build/search-public/_observablehq/client.0425226e.js create mode 100644 test/output/build/search-public/_observablehq/minisearch.00000002.json delete mode 100644 test/output/build/search-public/_observablehq/minisearch.55535b23.json create mode 100644 test/output/build/search-public/_observablehq/runtime.00000003.js delete mode 100644 test/output/build/search-public/_observablehq/runtime.c45c72e0.js create mode 100644 test/output/build/search-public/_observablehq/search.00000004.js delete mode 100644 test/output/build/search-public/_observablehq/search.2515eb68.js create mode 100644 test/output/build/search-public/_observablehq/stdlib.00000005.js delete mode 100644 test/output/build/search-public/_observablehq/stdlib.1b8a97c3.js create mode 100644 test/output/build/search-public/_observablehq/theme-air,near-midnight.00000006.css delete mode 100644 test/output/build/search-public/_observablehq/theme-air,near-midnight.e68849dc.css create mode 100644 test/output/build/simple-public/_observablehq/client.00000001.js delete mode 100644 test/output/build/simple-public/_observablehq/client.0425226e.js create mode 100644 test/output/build/simple-public/_observablehq/runtime.00000002.js delete mode 100644 test/output/build/simple-public/_observablehq/runtime.c45c72e0.js create mode 100644 test/output/build/simple-public/_observablehq/stdlib.00000003.js delete mode 100644 test/output/build/simple-public/_observablehq/stdlib.1b8a97c3.js create mode 100644 test/output/build/simple-public/_observablehq/theme-air,near-midnight.00000004.css delete mode 100644 test/output/build/simple-public/_observablehq/theme-air,near-midnight.e68849dc.css create mode 100644 test/output/build/simple/_observablehq/client.00000001.js create mode 100644 test/output/build/simple/_observablehq/runtime.00000002.js create mode 100644 test/output/build/simple/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/simple/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/space-page/_observablehq/client.00000001.js create mode 100644 test/output/build/space-page/_observablehq/runtime.00000002.js create mode 100644 test/output/build/space-page/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/space-page/_observablehq/theme-air,near-midnight.00000004.css create mode 100644 test/output/build/subtitle/_observablehq/client.00000001.js create mode 100644 test/output/build/subtitle/_observablehq/runtime.00000002.js create mode 100644 test/output/build/subtitle/_observablehq/stdlib.00000003.js create mode 100644 test/output/build/subtitle/_observablehq/theme-air,near-midnight.00000004.css diff --git a/test/build-test.ts b/test/build-test.ts index 0a82f8f43..0367efa3a 100644 --- a/test/build-test.ts +++ b/test/build-test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import {existsSync, readdirSync, statSync} from "node:fs"; -import {mkdir, mkdtemp, readFile, rm, writeFile} from "node:fs/promises"; +import {mkdir, mkdtemp, open, readFile, rm, unlink, writeFile} from "node:fs/promises"; import os from "node:os"; import {join, normalize, relative} from "node:path/posix"; import {PassThrough} from "node:stream"; @@ -15,6 +15,16 @@ const silentEffects = { output: {write() {}} }; +function getHashNormalizer() { + const hashes = new Map(); + let nextHashId = 0; + return (key: string) => { + let hash = hashes.get(key); + if (!hash) hashes.set(key, (hash = String(++nextHashId).padStart(8, "0"))); + return hash; + }; +} + describe("build", () => { before(() => setCurrentDate(new Date("2024-01-10T16:00:00"))); mockJsDelivr(); @@ -40,15 +50,32 @@ describe("build", () => { const expectedDir = join(outputRoot, outname); const generate = !existsSync(expectedDir) && process.env.CI !== "true"; const outputDir = generate ? expectedDir : actualDir; + const normalizeHash = getHashNormalizer(); await rm(actualDir, {recursive: true, force: true}); if (generate) console.warn(`! generating ${expectedDir}`); const config = {...(await readConfig(undefined, path)), output: outputDir}; await build({config}, new TestEffects(outputDir, join(config.root, ".observablehq", "cache"))); - // For non-public tests (most of them), we don’t want to test the contents - // of the _observablehq files because they change often. - if (!name.endsWith("-public")) await rm(join(outputDir, "_observablehq"), {recursive: true, force: true}); + // Replace any hashed files in _observablehq with empty files, and + // renumber the hashes so they are sequential. This way we don’t have to + // update the test snapshots whenever Framework’s client code changes. + for (let path of findFiles(join(actualDir, "_observablehq"))) { + const match = /^((.+)\.[0-9a-f]{8})\.(\w+)$/.exec(path); + if (match) { + const [, key, name, ext] = match; + await unlink(join(actualDir, "_observablehq", path)); + path = `${name}.${normalizeHash(key)}.${ext}`; + } + await (await open(join(actualDir, "_observablehq", path), "w")).close(); + } + + // Replace any reference to re-numbered files in _observablehq. + for (const path of findFiles(actualDir)) { + const actual = await readFile(join(actualDir, path), "utf8"); + const normalized = actual.replace(/\/_observablehq\/((\w+)\.[0-9a-f]{8})\.js\b/g, (match, key, name) => `/_observablehq/${name}.${normalizeHash(key)}.js`); // prettier-ignore + if (normalized !== actual) await writeFile(join(actualDir, path), normalized); + } if (generate) return; diff --git a/test/mocks/observableApi.ts b/test/mocks/observableApi.ts index 72ac97123..f4c0b4145 100644 --- a/test/mocks/observableApi.ts +++ b/test/mocks/observableApi.ts @@ -284,10 +284,10 @@ class ObservableApiMock { expectStandardFiles(options: Omit) { return this.expectFileUpload({...options, path: "index.html"}) - .expectFileUpload({...options, path: "_observablehq/theme-air,near-midnight.e68849dc.css"}) - .expectFileUpload({...options, path: "_observablehq/client.0425226e.js"}) - .expectFileUpload({...options, path: "_observablehq/runtime.c45c72e0.js"}) - .expectFileUpload({...options, path: "_observablehq/stdlib.1b8a97c3.js"}); + .expectFileUpload({...options, path: "_observablehq/client.00000001.js"}) + .expectFileUpload({...options, path: "_observablehq/runtime.00000002.js"}) + .expectFileUpload({...options, path: "_observablehq/stdlib.00000003.js"}) + .expectFileUpload({...options, path: "_observablehq/theme-air,near-midnight.00000004.css"}); } /** Register a file that is expected to be uploaded. Also includes that file in diff --git a/test/output/build/404/404.html b/test/output/build/404/404.html index 2b5b37e92..1dd1f8872 100644 --- a/test/output/build/404/404.html +++ b/test/output/build/404/404.html @@ -8,9 +8,9 @@ - - - + + +