diff --git a/tests/release-demo.test.js b/tests/release-demo.test.js index 9bf5cae..c403ba3 100644 --- a/tests/release-demo.test.js +++ b/tests/release-demo.test.js @@ -168,9 +168,13 @@ test('release demo states the declared release delta on camera and proves it wit assert.match(demo, /TIMMY_RELEASE_DEMO_DELTA/); assert.match(demo, /This release: \$\{releaseDelta\}/); assert.match(demo, /no new feature is claimed/); - // A caption alone is not evidence; the demo must emit a machine-readable receipt of what rendered. + // A caption string alone is not evidence; each caption must be measured as a painted bar, and the + // receipt must carry that per-caption measurement. assert.match(demo, /TIMMY_DEMO_CAPTIONS_OUT/); assert.match(demo, /captionsShown\.push\(text\)/); + assert.match(demo, /captionsVerified: captionEvidence/); + assert.match(demo, /Caption is not an on-screen bar/); + assert.match(demo, /Caption painted nothing into the caption band/); assert.match(demo, /writeFile\(captionsOut/); }); @@ -207,8 +211,10 @@ test('release demo exercises the photo lifecycle on camera without showing an im // Delete-all is actually performed, not just pointed at. assert.match(demo, /tap\('#delete-all'/); assert.match(demo, /no photo bytes may survive delete-all|JSON\.stringify\(localStorage\)\.includes\('data:image'\)/); - // Synthetic bytes only: a committed 1x1 PNG constant, never a real photo. + // Synthetic bytes only: a committed test-card PNG constant, never a real photo. A blank 1x1 pixel + // rendered as an empty white box on camera, which read as a broken image instead of a saved photo. assert.match(demo, /const SYNTHETIC_PHOTO = 'data:image\/png;base64,/); + assert.match(demo, /synthetic test card/); }); test('release builder refuses to publish without the on-camera delta receipt', async () => { @@ -219,10 +225,24 @@ test('release builder refuses to publish without the on-camera delta receipt', a assert.match(builder, /Release demo produced no on-camera caption receipt/); assert.match(builder, /Release demo did not state the declared release delta on camera/); assert.match(builder, /Release demo is missing a required on-camera caption/); + assert.match(builder, /Release demo caption never painted on screen/); + assert.match(builder, /recorded\.get\("captionsVerified"\)/); assert.match(builder, /"release_delta_visible_on_camera": "passed"/); assert.match(builder, /"release_delta": release_delta/); }); +test('caption styling survives the demo reloads instead of dying with the first document', async () => { + const demo = await readFile(demoPath, 'utf8'); + + // A stylesheet belongs to one document; the demo reloads the page, which stripped caption and touch + // styling and left later captions as clipped body text. Both now carry inline styles per node. + assert.doesNotMatch(demo, /page\.addStyleTag/); + assert.doesNotMatch(demo, /addInitScript/); + assert.match(demo, /In a stylesheet belongs to one document|a stylesheet belongs to one document/); + assert.match(demo, /node\.style\.cssText = 'position:fixed;left:16px;right:16px;top:14px;z-index:20000;'/); + assert.match(demo, /ring\.style\.cssText = 'position:fixed;z-index:20001/); +}); + test('release demo captions expire and the contact sheet spans the whole recording', async () => { const demo = await readFile(demoPath, 'utf8'); const builder = await readFile(builderPath, 'utf8');