42 lines
2.8 KiB
JavaScript
42 lines
2.8 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { ART_DIRECTIONS, directionTheme, artDirection, appearanceTile } from '../src/art-directions.js';
|
|
import { contrast } from '../src/design-tokens.js';
|
|
import { drawScene, drawTile, drawExit } from '../src/renderer.js';
|
|
import { createStudyLevel } from '../src/study-levels.js';
|
|
import { available, trace } from '../src/core.js';
|
|
import { layout } from '../src/geometry.js';
|
|
test('each of four art directions has five readable themes and independent token colors',()=>{
|
|
assert.equal(ART_DIRECTIONS.length,4);assert.equal(new Set(ART_DIRECTIONS.map(d=>d.id)).size,4);
|
|
for(const d of ART_DIRECTIONS){
|
|
assert.deepEqual(d.themes.map(t=>t.label),['轻松','进阶','烧脑','挑战','每周挑战']);
|
|
for(const t of d.themes){assert.ok(contrast(t.background,t.ink)>=4.5);assert.equal(directionTheme(d,t.id).artStyle,d.style);}
|
|
for(const p of d.pigments)assert.ok(contrast(p.color,p.arrow)>=3);
|
|
}
|
|
assert.equal(artDirection('invalid').id,'calm');
|
|
});
|
|
test('art styles change actual geometry without changing level state, including moving tokens',()=>{
|
|
const level=createStudyLevel(3),copy=JSON.stringify(level),view=layout(level.cells,520,600),tile=available(level,level.tiles)[0],route=trace(level,tile,level.tiles);
|
|
const signatures=[];
|
|
for(const d of ART_DIRECTIONS){
|
|
const commands=[],p={polygon:(points,color)=>{assert.ok(color);assert.ok(points.every(p=>Number.isFinite(p.x)&&Number.isFinite(p.y)));commands.push(['polygon',points.length,color]);},circle:(x,y,r,color)=>{assert.ok(Number.isFinite(r)&&r>=0);commands.push(['circle',r,color]);},line:(points,color,width)=>{assert.ok(width>0);commands.push(['line',points.length,color]);}};
|
|
const theme=directionTheme(d,'lagoon'),t=appearanceTile({color:0,dir:1},theme);
|
|
drawTile(p,50,50,40,t);signatures.push(JSON.stringify(commands));
|
|
drawScene(p,level,level.tiles,view,{theme});drawExit(p,route,view,.4,t);drawExit(p,route,view,.99,t);
|
|
}
|
|
assert.equal(new Set(signatures).size,4);assert.equal(JSON.stringify(level),copy);
|
|
});
|
|
test('vivid worlds retain strong chroma and each new theme has its own seven-color mix',()=>{
|
|
const vivid=artDirection('vivid');
|
|
assert.equal(vivid.themes[0].background,'#B8F34A');
|
|
for(const t of vivid.themes){
|
|
const rgb=t.background.slice(1).match(/../g).map(v=>parseInt(v,16)/255),hi=Math.max(...rgb),lo=Math.min(...rgb),l=(hi+lo)/2,s=(hi-lo)/(1-Math.abs(2*l-1));
|
|
assert.ok(s>=.65&&l<=.65,`${t.name} should keep the saturated poster treatment`);
|
|
}
|
|
for(const d of ART_DIRECTIONS.slice(1)){
|
|
assert.equal(new Set(d.themes.map(t=>directionTheme(d,t.id).palette.slice().sort((a,b)=>a-b).join(','))).size,5);
|
|
assert.equal(new Set(d.themes.map(t=>t.materials.board)).size,5);
|
|
for(const t of d.themes)assert.ok(contrast(t.materials.track,t.materials.board)>=3);
|
|
}
|
|
});
|