diff --git a/packages/enscribe/test/theme-consumption.test.js b/packages/enscribe/test/theme-consumption.test.js index 11a5d831..0b17de35 100644 --- a/packages/enscribe/test/theme-consumption.test.js +++ b/packages/enscribe/test/theme-consumption.test.js @@ -8,14 +8,16 @@ // - #452 cell F: a website MASTER's `` reaches every page's head (composeWebsiteShellPage). // - #456: a website master's `` builds the static site sidebar (parity with live). // theme-variant is guarded by theme-variant-multipage.test.js (#431) + master-website-live.test.js (#443, -// the live website); the live-book theme (applyDocumentTheme) rides the live mount, covered by -// live-book-parity.test.js. Byte-stability of the DEFAULT (no theme / no sidebar) is asserted here too: -// every branch keeps the unset case free of the new markup, so the committed goldens are untouched. +// the live website); the live-book theme (applyDocumentTheme) is asserted in this file (#471) via a +// jsdom mountLiveShell of a themed master. Byte-stability of the DEFAULT (no theme / no sidebar) is +// asserted here too: every branch keeps the unset case free of the new markup, so the committed +// goldens are untouched. import assert from 'node:assert'; import { readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; +import { JSDOM } from 'jsdom'; import { VFile } from 'vfile'; import { buildEnscribePipeline, @@ -25,6 +27,7 @@ import { buildWebsiteSidebar, getThemeCss, } from '../src/interpreter/index.js'; +import { mountLiveShell } from '../src/interpreter/browser.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); const BOOK_DIR = join(__dirname, 'fixtures', 'master-book'); @@ -33,7 +36,7 @@ const ASSETS_DIR = join(__dirname, 'fixtures', 'assets'); // A stable marker of the Tufte theme tokens (the theme CSS names itself, and retunes the serif to Palatino). const TUFTE_MARK = /Palatino|Tufte theme/; -export function run() { +export async function run() { // ── #452 cell E — a book's tokens reach every separate-pages chapter page ────────── { const base = readFileSync(join(BOOK_DIR, 'master-book.emd'), 'utf8'); @@ -98,4 +101,49 @@ export function run() { 'default (no sidebar) ⇒ the single-column body is byte-unchanged (no sidebar wrapper or nav element)'); console.log('PASS: #456 — builds the static website sidebar; default stays single-column'); } + + // ── #452 cell E (live half) / #471 — live book injects #enscribe-doc-theme ────────── + { + const themedMaster = readFileSync(join(BOOK_DIR, 'master-book.emd'), 'utf8') + .replace('', ''); + const SERVED = Object.fromEntries( + ['preface.emd', 'chapter-1.emd', 'chapter-2.emd', 'appendix.emd'].map((n) => [ + n, readFileSync(join(BOOK_DIR, n), 'utf8'), + ]), + ); + SERVED['master-book.emd'] = themedMaster; + + const dom = new JSDOM('
', { + url: 'https://example.com/book/', + }); + const orig = { + window: global.window, document: global.document, + location: global.location, history: global.history, fetch: global.fetch, + }; + global.window = dom.window; + global.document = dom.window.document; + Object.defineProperty(global, 'location', { value: dom.window.location, configurable: true, writable: true }); + Object.defineProperty(global, 'history', { value: dom.window.history, configurable: true, writable: true }); + global.fetch = async (url) => { + const name = String(url).split('/').pop(); + if (Object.prototype.hasOwnProperty.call(SERVED, name)) { + return { ok: true, status: 200, statusText: 'OK', text: async () => SERVED[name] }; + } + return { ok: false, status: 404, statusText: 'Not Found', text: async () => '' }; + }; + try { + await mountLiveShell('#root', 'master-book.emd', { edit: false }); + const style = document.getElementById('enscribe-doc-theme'); + assert.ok(style, '#471: live book mount injects #enscribe-doc-theme for '); + assert.ok(TUFTE_MARK.test(style.textContent || ''), + '#471: #enscribe-doc-theme carries the Tufte theme CSS tokens'); + console.log('PASS: #471 — live book injects #enscribe-doc-theme head style'); + } finally { + global.window = orig.window; + global.document = orig.document; + Object.defineProperty(global, 'location', { value: orig.location, configurable: true, writable: true }); + Object.defineProperty(global, 'history', { value: orig.history, configurable: true, writable: true }); + global.fetch = orig.fetch; + } + } }