teach/test/widgets.test.js
Ramon d02f7de72d
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 20s
feat: maak oefenklok visueel bedienbaar
2026-07-15 20:12:43 +02:00

74 lines
3.7 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {readFile} from 'node:fs/promises';
const ids=['birthday','numberline','sentence'];
const learningIds=['fractions','clock','placevalue','money','wordtypes','schedule','mood','poll'];
test('nieuwe widgets zijn geladen vóór het widgetregister', async()=>{
const html=await readFile('public/index.html','utf8');
const board=html.indexOf('js/board.js');
for(const id of ids){
const pos=html.indexOf(`js/widgets/${id}.js`);
assert.ok(pos>0 && pos<board, `${id} moet vóór board.js laden`);
}
});
test('nieuwe widgets zijn geregistreerd en bewaren state', async()=>{
const registry=await readFile('public/js/board.js','utf8');
for(const id of ids){
assert.match(registry,new RegExp(`id:"${id}"`));
const source=await readFile(`public/js/widgets/${id}.js`,'utf8');
assert.match(source,/getState/);
assert.doesNotMatch(source,/innerHTML\s*=.*(?:name|word\.value)/);
}
});
test('nieuwe widgetnamen en beschrijvingen zijn tweetalig', async()=>{
const core=await readFile('public/js/core.js','utf8');
for(const id of ids){
assert.equal((core.match(new RegExp(`wg_${id}:`,'g'))||[]).length,2);
assert.equal((core.match(new RegExp(`wg_${id}_d:`,'g'))||[]).length,2);
}
});
test('educatieve widgetmodule laadt en registreert alle acht widgets', async()=>{
const html=await readFile('public/index.html','utf8');
assert.ok(html.indexOf('js/widgets/learning.js')<html.indexOf('js/board.js'));
const [board,source]=await Promise.all([readFile('public/js/board.js','utf8'),readFile('public/js/widgets/learning.js','utf8')]);
for(const id of learningIds){
assert.match(board,new RegExp('id:"'+id+'"'));
const mount='mount'+id[0].toUpperCase()+id.slice(1);
assert.match(source,new RegExp('function '+mount+'\\('));
}
assert.equal((source.match(/getState:/g)||[]).length,learningIds.length);
});
test('nieuwe widgets zijn tweetalig beschreven', async()=>{
const core=await readFile('public/js/core.js','utf8');
for(const id of learningIds){
assert.equal((core.match(new RegExp('wg_'+id+':','g'))||[]).length,2,id);
assert.equal((core.match(new RegExp('wg_'+id+'_d:','g'))||[]).length,2,id);
}
});
test('widgetbibliotheek bevat zoeken favorieten sjablonen en borddata-acties', async()=>{
const [html,board]=await Promise.all([readFile('public/index.html','utf8'),readFile('public/js/board.js','utf8')]);
for(const id of ['gallerySearch','galleryFavOnly','galleryTemplates','boardUndo','boardRedo','boardExport','boardImport'])assert.match(html,new RegExp('id="'+id+'"'));
for(const feature of ['teachWidgetFavorites','structuredClone','application/json','widgetDuplicate','widgetLock','widgetPreview'])assert.ok(board.includes(feature),feature);
});
test('oefenklok biedt niveaus leerwijzen en meerdere spellen', async()=>{
const [source,core]=await Promise.all([readFile('public/js/widgets/learning.js','utf8'),readFile('public/js/core.js','utf8')]);
for(const value of ["'hour'","'quarter'","'five'","'minute'","'analogue'","'digital'","'words'","'both'","'set'","'read'","'choose'"])assert.ok(source.includes(value),value);
for(const key of ['clockLevel','clockLearningStyle','clockGame','clockScore'])assert.equal((core.match(new RegExp(key+':','g'))||[]).length,2,key);
});
test('analoge oefenklok is met aanwijzer en aanraking bedienbaar', async()=>{
const [source,css]=await Promise.all([readFile('public/js/widgets/learning.js','utf8'),readFile('public/css/teach.css','utf8')]);
for(const feature of ['onpointerdown','onpointermove','setPointerCapture','releasePointerCapture','getBoundingClientRect'])assert.ok(source.includes(feature),feature);
assert.match(css,/clock\.interactive[^}]*touch-action:none/);
});