import test from 'node:test'; import assert from 'node:assert/strict'; import {readFile} from 'node:fs/promises'; import {runInNewContext} from 'node:vm'; async function coloringContext(){ const [extra,widget]=await Promise.all([ readFile('public/js/widgets/coloring-scenes-extra.js','utf8'),readFile('public/js/widgets/coloring.js','utf8') ]),source=extra+'\n'+widget; const context={}; runInNewContext(source+`; globalThis.__coloring={ pages:COLORING_PAGES, themes:COLORING_THEME_KEYS, pagesFor:coloringPagesFor, pencilWidth:coloringPencilWidth, safeColor:coloringSafeColor }`,context); return{source,api:context.__coloring}; } test('kleurplatenwidget laadt vóór het bord en is als creatieve leerlingwidget geregistreerd',async()=>{ const [html,board,pupil,cast,core,css]=await Promise.all([ readFile('public/index.html','utf8'),readFile('public/js/board.js','utf8'), readFile('public/js/pupil.js','utf8'),readFile('public/js/cast.js','utf8'), readFile('public/js/core.js','utf8'),readFile('public/css/coloring.css','utf8') ]); assert.ok(html.indexOf('js/widgets/coloring-scenes-extra.js')>0); assert.ok(html.indexOf('js/widgets/coloring-scenes-extra.js')0); assert.ok(html.indexOf('js/widgets/coloring.js'){ const {api}=await coloringContext(); const pages=JSON.parse(JSON.stringify(api.pages)); assert.equal(pages.length,28); assert.equal(new Set(pages.map(page=>page.id)).size,pages.length); const added=[ 'farmyard','rainbow-weather','construction-site','forest-picnic', 'dinosaur-valley','spring-nest','fire-station','bee-meadow', 'coral-reef','mountain-camp','robot-workshop','canal-street', 'solar-observatory','savanna-web','japanese-garden' ]; assert.equal(added.filter(id=>pages.some(page=>page.id===id)).length,15); for(let year=1;year<=8;year++){ const suitable=JSON.parse(JSON.stringify(api.pagesFor(year))); assert.equal(suitable.length,7,`groep ${year} heeft zeven kleurplaten`); assert.ok(suitable.every(page=>year>=page.years[0]&&year<=page.years[1])); assert.equal(new Set(suitable.map(page=>page.theme)).size,5,`groep ${year} heeft alle vijf thema's`); } for(const page of pages){ assert.ok(api.themes[page.theme],page.id+' heeft een bekend thema'); assert.ok(page.title.nl&&page.title.en,page.id+' heeft een tweetalige titel'); const parts=[...page.svg.matchAll(/data-part="([^"]+)"/g)].map(match=>match[1]); const details=(page.svg.match(/class="coloring-detail"/g)||[]).length; const openFillablePaths=[...page.svg.matchAll(/]*data-fillable="true"[^>]*data-part="([^"]+)"[^>]* d="([^"]+)"/g)] .filter(match=>!/[zZ]\s*$/.test(match[2])).map(match=>match[1]); assert.ok(parts.length>=14,page.id+' heeft voldoende afzonderlijke kleurvakken'); assert.equal(new Set(parts).size,parts.length,page.id+' heeft unieke kleurvakken'); assert.deepEqual(openFillablePaths,[],page.id+' heeft alleen gesloten aanklikbare paden'); assert.ok(details>=4,page.id+' heeft voldoende herkenbaar binnenlijnwerk'); assert.match(page.svg,/class="coloring-sheet"[^>]*preserveAspectRatio="xMidYMid meet"/); assert.match(page.svg,/data-role="backdrop"/,page.id+' heeft een subtiel buitenkader'); assert.match(page.svg,new RegExp(`data-scene="${page.id}"`)); assert.match(page.svg,/data-level="2"/); assert.match(page.svg,/data-level="3"/); assert.doesNotMatch(page.svg,/item.id===id); names.forEach(name=>assert.ok(page.svg.includes(`data-part="${name}"`),`${id} mist ${name}`)); } assert.equal(api.pagesFor(5,'science').length,2); assert.equal(api.pagesFor(3,'science').length,1); }); test('potlood reageert op echte pendruk en de bovenste inktlaag houdt lijnen zichtbaar',async()=>{ const {source,api}=await coloringContext(); assert.ok(api.pencilWidth(7,.9,'pen')>api.pencilWidth(7,.2,'pen')); assert.equal(api.pencilWidth(7,0,'mouse'),7); assert.equal(api.safeColor('#AABBCC'),'#aabbcc'); assert.equal(api.safeColor('red'),'#e0554d'); for(const feature of ['getCoalescedEvents','event.pressure','erase?1:.27','quadraticCurveTo','Math.random()'])assert.ok(source.includes(feature),feature); const css=await readFile('public/css/coloring.css','utf8'); assert.match(css,/mix-blend-mode:multiply/); assert.match(source,/class="coloring-art"><\/div>]+><\/canvas>