76 lines
3.7 KiB
JavaScript
Executable File
76 lines
3.7 KiB
JavaScript
Executable File
const test = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
const data = require("../assets/scripts/pages/princess-lima-data.js");
|
|
const state = require("../assets/scripts/pages/princess-lima-state.js");
|
|
const systems = require("../assets/scripts/pages/princess-lima-systems.js");
|
|
const intro = require("../assets/scripts/pages/princess-lima-intro.js");
|
|
|
|
const root = path.resolve(__dirname, "..");
|
|
const rpgSource = fs.readFileSync(path.join(root, "play/rpg.org"), "utf8");
|
|
const sceneSource = fs.readFileSync(path.join(root, "assets/scripts/pages/princess-lima-scenes.js"), "utf8");
|
|
|
|
test("all nine regions use the exact atlas artwork and valid collision-safe transitions", () => {
|
|
const mapsSource = fs.readFileSync(path.join(root, "assets/scripts/pages/princess-lima-maps.js"), "utf8");
|
|
data.MAP_IDS.forEach((region) => {
|
|
assert.match(mapsSource, new RegExp(`${region}:\\s*\\d`));
|
|
Object.values(data.MAPS[region].spawns).forEach((spawn) => {
|
|
assert.ok(spawn.x > 0 && spawn.x < data.WIDTH);
|
|
assert.ok(spawn.y > 0 && spawn.y < data.HEIGHT);
|
|
});
|
|
data.MAPS[region].exits.forEach((exit) => {
|
|
assert.ok(data.MAPS[exit.target]);
|
|
assert.ok(data.MAPS[exit.target].spawns[exit.spawn]);
|
|
});
|
|
});
|
|
assert.equal(data.WIDTH, data.HEIGHT);
|
|
assert.match(mapsSource, /\.setAlpha\(1\)/);
|
|
assert.doesNotMatch(mapsSource, /tilemap|tileSprite|add\.circle|add\.ellipse|drawDecor|drawObstacle/);
|
|
assert.doesNotMatch(sceneSource, /lima-world-tiles|world-tiles\.png/);
|
|
});
|
|
|
|
test("all authored actors and interaction points sit outside visible terrain collision", () => {
|
|
const auditState = state.fresh("Collision audit", "azure");
|
|
auditState.unlockedRoutes = ["bridge_repaired"];
|
|
data.MAP_IDS.forEach((region) => {
|
|
const map = data.MAPS[region];
|
|
const points = [
|
|
...Object.entries(map.spawns).map(([name, point]) => [`spawn:${name}`, point.x, point.y]),
|
|
...(map.npcs || []).map(([name, x, y]) => [`npc:${name}`, x, y]),
|
|
...(map.enemies || []).map((enemy, index) => [`enemy:${enemy.type}:${index}`, enemy.x, enemy.y]),
|
|
...(map.pickups || []).map(([name, x, y], index) => [`pickup:${name}:${index}`, x, y]),
|
|
...(map.puzzle ? map.puzzle.objects.map(([name, x, y]) => [`puzzle:${name}`, x, y]) : [])
|
|
];
|
|
points.forEach(([name, x, y]) => {
|
|
assert.equal(systems.isSafePosition(auditState, region, x, y), true, `${region} ${name} must be collision-safe`);
|
|
});
|
|
});
|
|
});
|
|
|
|
test("every region exposes named Tiled-compatible collision and object layers", () => {
|
|
const expected = ["Collision", "Dynamic Collision", "Exits", "NPCs", "Enemies", "Puzzles", "Items"];
|
|
data.MAP_IDS.forEach((region) => {
|
|
const layers = data.MAP_LAYERS[region];
|
|
assert.deepEqual(layers.map((layer) => layer.name), expected);
|
|
assert.ok(layers.every((layer) => layer.type === "objectgroup"));
|
|
assert.equal(layers.find((layer) => layer.name === "Collision").objects, data.MAPS[region].obstacles);
|
|
});
|
|
});
|
|
|
|
test("keyboard-only page contains one left HUD and no touch controls", () => {
|
|
assert.match(rpgSource, /class="lima-hud"/);
|
|
assert.match(rpgSource, /Inventory <kbd>I<\/kbd>/);
|
|
assert.match(rpgSource, /Menu <kbd>M<\/kbd>/);
|
|
assert.doesNotMatch(rpgSource, /data-lima-touch|data-lima-move|Touch controls|data-lima-attack/);
|
|
});
|
|
|
|
test("opening cinematic is complete, replayable and accessible", () => {
|
|
assert.equal(intro.BEATS.length, 5);
|
|
assert.ok(intro.BEATS.reduce((total, beat) => total + beat.duration, 0) >= 60000);
|
|
assert.ok(intro.BEATS.every((beat) => beat.subtitle.length > 20));
|
|
assert.match(rpgSource, /data-lima-replay-intro/);
|
|
assert.match(rpgSource, /data-lima-intro-pause/);
|
|
assert.match(rpgSource, /Hold Escape to skip/);
|
|
});
|