Files

12 lines
3.0 KiB
JavaScript

import fs from 'node:fs';import vm from 'node:vm';import assert from 'node:assert/strict';import path from 'node:path';import {fileURLToPath} from 'node:url';
const here=path.dirname(fileURLToPath(import.meta.url));const html=fs.readFileSync(path.join(here,'index.html'),'utf8'),plan=JSON.parse(fs.readFileSync(path.join(here,'demo-design.json'),'utf8'));const checks=[];const elements=new Map();class Element{constructor(){this.value='';this.children=[];this.handlers={};this.innerHTML='';this.textContent='';}appendChild(x){this.children.push(x);}addEventListener(k,f){this.handlers[k]=f;}}const get=id=>{if(!elements.has(id))elements.set(id,new Element());return elements.get(id);};const context=vm.createContext({document:{getElementById:get,createElement:()=>new Element()},console,Blob,URL,setTimeout});const script=html.match(/<script>([\s\S]*)<\/script>/)[1];new vm.Script(script).runInContext(context);
function check(n,f){f();checks.push(n);}const count=()=>((get('tasks').innerHTML.match(/<tr /g)||[]).length);
check('默认50条任务和5章',()=>{assert.equal(count(),50);assert.equal((get('chapters').innerHTML.match(/<tr>/g)||[]).length,5);assert.equal((get('details').innerHTML.match(/<details /g)||[]).length,50);});
check('A/B峰值位置',()=>{assert.ok(get('tasks').innerHTML.includes('8<br>'));get('b').onclick();const peakPositions=[...get('tasks').innerHTML.matchAll(/<tr class="peak"><td>(\d+)/g)].map(m=>Number(m[1]));assert.deepEqual(peakPositions,[10,20,30,40,50]);get('a').onclick();const normalPeakPositions=[...get('tasks').innerHTML.matchAll(/<tr class="peak"><td>(\d+)/g)].map(m=>Number(m[1]));assert.deepEqual(normalPeakPositions,[8,18,28,38,48]);});
check('章节筛选',()=>{get('chapter').value='3';get('chapter').handlers.change();assert.equal(count(),10);get('chapter').value='';});
check('奇偶筛选',()=>{get('feature').value='parity';get('feature').handlers.change();assert.equal(count(),13);get('feature').value='';});
check('释放功能筛选',()=>{get('role').value='释放';get('role').handlers.change();assert.equal(count(),5);get('role').value='';get('role').handlers.change();});
check('单文件规划页与状态说明',()=>{assert.ok(!/<script[^>]+src=|fetch\(/.test(html));assert.ok(html.includes('尚非可玩关卡包'));assert.ok(html.includes('六道桥接样题'));assert.ok(html.includes('前置技能'));});
check('CSV数据与设计任务一致',()=>{const csv=fs.readFileSync(path.join(here,'difficulty-curve.csv'),'utf8').replace(/^\uFEFF/,'').trim().split(/\r?\n/);assert.equal(csv.length,51);for(let i=0;i<50;i++){const row=csv[i+1].split(',');assert.equal(row[0],plan.levels[i].designKey);assert.equal(row[1],plan.levels[i].levelId);assert.equal(Number(row[10]),plan.levels[i].targetDifficulty);}});
fs.writeFileSync(path.join(here,'h5-check.json'),JSON.stringify({passed:true,checks,scope:'离线规划页脚本和数据一致性检查;不代表实际浏览器像素、手机测试或可玩关卡验收'},null,2));console.log('PASS '+checks.length+' planning-page checks');