// The theme preview box was hidden on error and hidden until an image loaded, // so a preview that failed and a preview that did not exist looked exactly the // same — an empty gap. That cost a diagnosis: the endpoint was working the // whole time and there was no way to tell from the page. // // The first view of a theme is a pptx render, a Gotenberg round trip and a // pdftoppm, so it is a second or so before anything appears. Silence for that // second reads as a missing feature. const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const read = f => fs.readFileSync(path.join(__dirname, '..', f), 'utf8'); const ui = read('public/js/myResources.js'); const fn = ui.slice(ui.indexOf('function showThemePreview'), ui.indexOf('function describeTheme')); test('a failed preview says so instead of vanishing', () => { assert.doesNotMatch(fn, /onerror = function \(\) \{ box\.hidden = true; \}/); assert.match(fn, /img\.onerror = function \(\)[\s\S]{0,200}note\.textContent = 'No preview just now/); }); test('it says it is working while the render happens', () => { assert.match(fn, /note\.textContent = 'Drawing a sample slide\.\.\.'/); assert.match(fn, /box\.hidden = false/); }); test('the note is replaced by the image, not left stacked above it', () => { assert.match(fn, /img\.onload = function \(\) \{ img\.style\.display = 'block'; note\.hidden = true; \}/); }); test('src is assigned after the handlers, so a cache hit is not missed', () => { // A cached preview can complete before a handler attached after the // assignment would exist, leaving the box stuck on "Drawing...". const onload = fn.indexOf('img.onload'); const onerror = fn.indexOf('img.onerror'); const src = fn.indexOf('img.src ='); assert.ok(onload > -1 && onerror > -1 && src > -1); assert.ok(src > onload && src > onerror, 'img.src must be set after both handlers'); }); test('no request for a theme that has not been chosen', () => { assert.match(fn, /if \(!select \|\| !select\.value \|\| !box\) return;/); }); test('the preview is requested once per change, not twice', () => { // describeTheme ends by calling it; a second call beside it fired an // identical request on every load. assert.equal((ui.match(/\n\s*showThemePreview\(\);/g) || []).length, 1); }); test('the route it calls exists and is the one that renders', () => { const route = read('src/routes/myResources.js'); assert.match(fn, /'\/api\/my-resources\/theme-preview\/' \+ encodeURIComponent\(select\.value\)/); assert.match(route, /router\.get\('\/my-resources\/theme-preview\/:id'/); // It must be registered before the '/my-resources/:id' catch-all, or that // would answer instead. assert.ok(route.indexOf("'/my-resources/theme-preview/:id'") < route.indexOf("router.get('/my-resources/:id'"), 'theme-preview must be registered before the :id route'); });