teach/test/curriculum-wiki.test.js
Ramon 9bab7f39c0
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 39s
feat: koppel widgets aan kerndoelen (v0.4.38-beta)
2026-07-19 21:46:38 +02:00

97 lines
5 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {readFile} from 'node:fs/promises';
import {runInNewContext} from 'node:vm';
import {PERMISSIONS} from '../src/permissions.js';
test('curriculumdataset bevat negen leergebieden en alle veertig kerndoelen',async()=>{
const source=await readFile('public/js/curriculum.js','utf8');
const context={};
runInNewContext(source+';globalThis.__curriculum=CURRICULUM_PO_2026',context);
const data=JSON.parse(JSON.stringify(context.__curriculum));
assert.equal(data.id,'slo-po-2026');
assert.equal(data.edition,'2026-07');
assert.match(data.tule,/slo\.nl/);
assert.match(data.progressions,/slo\.nl/);
assert.equal(data.areas.length,9);
const goals=data.areas.flatMap(area=>area.goals);
assert.deepEqual(goals.map(goal=>goal.id),Array.from({length:40},(_,index)=>index+1));
for(const area of data.areas){
assert.ok(area.title&&area.description&&area.page,area.id);
for(const goal of area.goals){
assert.ok(goal.domain&&goal.summary,goal.id);
assert.ok(goal.parts.length>=1,goal.id);
assert.ok(['partial','support','open'].includes(goal.coverage),goal.id);
assert.ok(Array.isArray(goal.widgets),goal.id);
}
}
});
test('iedere kerndoelkoppeling verwijst naar een bestaande widget en de informatieknop linkt diep naar de wiki',async()=>{
const [curriculumSource,board,settings,wiki,css]=await Promise.all([
readFile('public/js/curriculum.js','utf8'),
readFile('public/js/board.js','utf8'),
readFile('public/js/settings.js','utf8'),
readFile('public/js/wiki.js','utf8'),
readFile('public/css/teach.css','utf8')
]);
const context={};
runInNewContext(curriculumSource+';globalThis.__curriculum=CURRICULUM_PO_2026',context);
const data=JSON.parse(JSON.stringify(context.__curriculum));
const registered=new Set([...board.matchAll(/\{\s*id:"([^"]+)"\s*,\s*cat:/g)].map(match=>match[1]));
const linked=new Set(data.areas.flatMap(area=>area.goals.flatMap(goal=>goal.widgets)));
for(const widget of linked)assert.ok(registered.has(widget),widget+' is gekoppeld maar niet geregistreerd');
for(const widget of ['letters','sentence','madd','fractions','dice','timer','schedule','trees','topography','noise','birthday','avatar']){
assert.ok(linked.has(widget),widget+' mist een inhoudelijke kerndoelkoppeling');
}
assert.match(board,/function curriculumGoalsForWidget/);
assert.match(board,/link\.href="#wiki-goal-"\+goal\.id/);
assert.match(board,/openSettings\("curriculum",\{area:area\.id,goal:goal\.id\}\)/);
assert.match(settings,/window\.openSettings = function\(section, payload\)/);
assert.match(wiki,/card\.id="wiki-goal-"\+goal\.id/);
assert.match(wiki,/target\.scrollIntoView\(\{block:"center"\}\)/);
assert.match(css,/\.winfo\[hidden\]\{display:none\}/);
assert.match(css,/\.widget-curriculum-modal/);
});
test('curriculumwiki en widgetinformatie zijn alleen zichtbaar voor volwassen rollen',async()=>{
assert.deepEqual(PERMISSIONS['curriculum.view'],['super','admin','teacher','parent']);
assert.ok(!PERMISSIONS['curriculum.view'].includes('pupil'));
const [client,wiki,board,html]=await Promise.all([
readFile('public/js/permissions.js','utf8'),
readFile('public/js/wiki.js','utf8'),
readFile('public/js/board.js','utf8'),
readFile('public/index.html','utf8')
]);
assert.match(client,/'curriculum\.view':\s*\['super', 'admin', 'teacher', 'parent'\]/);
assert.match(wiki,/visible:\(\)=>!!currentUser&&can\("curriculum\.view"\)/);
assert.match(board,/infoBtn\.hidden=!\(currentUser&&can\("curriculum\.view"\)\)/);
assert.match(board,/if\(!currentUser\|\|!can\("curriculum\.view"\)\)return/);
assert.doesNotMatch(html,/id="btnWiki"/);
assert.doesNotMatch(wiki,/wikiButton/);
assert.doesNotMatch(wiki,/innerHTML\s*=/);
});
test('curriculumwiki is geladen, doorzoekbaar, responsief en tweetalig bediend',async()=>{
const [html,wiki,core,css,version]=await Promise.all([
readFile('public/index.html','utf8'),
readFile('public/js/wiki.js','utf8'),
readFile('public/js/core.js','utf8'),
readFile('public/css/teach.css','utf8'),
readFile('VERSION','utf8')
]);
assert.ok(html.indexOf('js/settings.js')<html.indexOf('js/curriculum.js'));
assert.ok(html.indexOf('js/curriculum.js')<html.indexOf('js/wiki.js'));
assert.ok(html.indexOf('js/wiki.js')<html.indexOf('js/app.js'));
assert.doesNotMatch(html,/id="btnWiki"/);
assert.match(html,/data-section="curriculum"/);
assert.match(wiki,/input\.type="search"/);
assert.match(wiki,/dataset\.area/);
for(const key of ['wikiTitle','wikiSub','wikiSearchPlaceholder','wikiCoveragePartial','wikiCoverageSupport','wikiCoverageOpen','wikiCarefulText']){
assert.equal((core.match(new RegExp(key+':','g'))||[]).length,2,key);
}
assert.match(css,/\.wiki-grid\{[^}]*grid-template-columns:repeat\(2/);
assert.match(css,/@media \(max-width:720px\)[\s\S]*?\.wiki-grid\{grid-template-columns:1fr\}/);
assert.doesNotMatch(core,/btnWiki/);
assert.ok(core.includes('const VERSION = "'+version.trim()+'"'));
});