zelda-dungeon/test-full-node.js
2026-07-03 01:08:48 +00:00

110 lines
5.8 KiB
JavaScript

// Full browser simulation test
const fs = require('fs');
const vm = require('vm');
// Create browser context
const context = {
window: null,
document: {
currentScript: { src: '', getAttribute: function(a) { return null; } },
getElementsByTagName: function() { return []; },
},
location: { origin: 'http://localhost:3000' },
console: console,
Math: Math, JSON: JSON, Array: Array, Object: Object,
String: String, Number: Number, Function: Function,
Error: Error, RegExp: RegExp, Set: Set, Map: Map,
Promise: Promise, setTimeout: setTimeout,
localStorage: { getItem: () => null, setItem: () => {}, removeItem: () => {} },
};
context.window = context;
vm.createContext(context);
var results = [];
function assert(name, cond) { results.push((cond ? 'PASS' : 'FAIL') + ': ' + name); }
function setScript(src) { context.document.currentScript = { src: 'http://localhost:3000' + src, getAttribute: () => null }; }
function load(name, code) {
setScript(name);
try {
vm.runInContext(code, context);
console.log(' Loaded:', name);
} catch(e) {
console.error(' ERROR in', name + ':', e.message);
}
}
// Load all scripts in order
load('/src/browser-polyfill.js', fs.readFileSync('src/browser-polyfill.js', 'utf8'));
load('/src/core/constants.js', fs.readFileSync('src/core/constants.js', 'utf8'));
load('/src/core/rng.js', fs.readFileSync('src/core/rng.js', 'utf8'));
load('/src/core/utils.js', fs.readFileSync('src/core/utils.js', 'utf8'));
load('/src/data/themes.js', fs.readFileSync('src/data/themes.js', 'utf8'));
load('/src/data/dungeons.js', fs.readFileSync('src/data/dungeons.js', 'utf8'));
load('/src/data/enemies.js', fs.readFileSync('src/data/enemies.js', 'utf8'));
load('/src/data/weapons.js', fs.readFileSync('src/data/weapons.js', 'utf8'));
load('/src/data/bosses.js', fs.readFileSync('src/data/bosses.js', 'utf8'));
load('/src/data/items.js', fs.readFileSync('src/data/items.js', 'utf8'));
load('/src/generator/rooms.js', fs.readFileSync('src/generator/rooms.js', 'utf8'));
load('/src/generator/puzzles.js', fs.readFileSync('src/generator/puzzles.js', 'utf8'));
load('/src/generator/placement.js', fs.readFileSync('src/generator/placement.js', 'utf8'));
load('/src/generator/dungeon.js', fs.readFileSync('src/generator/dungeon.js', 'utf8'));
// Core tests
assert('module exists', typeof context.module !== 'undefined');
assert('require is function', typeof context.require === 'function');
assert('TILE=32', context.window.TILE === 32);
assert('COLS=32', context.window.COLS === 32);
assert('ROWS=24', context.window.ROWS === 24);
assert('TILE_TYPES object', context.window.TILE_TYPES && typeof context.window.TILE_TYPES === 'object');
assert('COLORS object', context.window.COLORS && typeof context.window.COLORS === 'object');
assert('createRNG function', typeof context.createRNG === 'function');
assert('createEmptyLayout function', typeof context.createEmptyLayout === 'function');
assert('createBorderLayout function', typeof context.createBorderLayout === 'function');
assert('isPassable function', typeof context.isPassable === 'function');
// Data tests
assert('THEMES object', context.window.THEMES && typeof context.window.THEMES === 'object');
assert('DUNGEONS array', Array.isArray(context.window.DUNGEONS));
assert('DUNGEONS count=100', context.window.DUNGEONS && context.window.DUNGEONS.length === 100);
assert('ENEMY_TYPES array', Array.isArray(context.window.ENEMY_TYPES));
assert('ENEMY_TYPES count=22', context.window.ENEMY_TYPES && context.window.ENEMY_TYPES.length === 22);
assert('WEAPONS array', Array.isArray(context.window.WEAPONS));
assert('WEAPONS count=12', context.window.WEAPONS && context.window.WEAPONS.length === 12);
assert('BOSS_TYPES array', Array.isArray(context.window.BOSS_TYPES));
assert('BOSS_TYPES count=100', context.window.BOSS_TYPES && context.window.BOSS_TYPES.length === 100);
assert('ITEMS array', Array.isArray(context.window.ITEMS));
assert('getItem function', typeof context.getItem === 'function');
assert('getEnemyType function', typeof context.getEnemyType === 'function');
assert('getBossType function', typeof context.getBossType === 'function');
assert('getWeapon function', typeof context.getWeapon === 'function');
// Generator tests
assert('generateDungeon function', typeof context.generateDungeon === 'function');
assert('generateRoomLayout function', typeof context.generateRoomLayout === 'function');
assert('generatePuzzles function', typeof context.generatePuzzles === 'function');
assert('generatePlacement function', typeof context.generatePlacement === 'function');
// Require resolution tests
context.document.currentScript = { src: 'http://localhost:3000/src/generator/placement.js', getAttribute: () => null };
var roomsMod = context.require('./rooms');
assert('require ./rooms generateRoomLayout', roomsMod.generateRoomLayout !== undefined);
var enemiesMod = context.require('../data/enemies');
assert('require ../data/enemies ENEMY_TYPES', Array.isArray(enemiesMod.ENEMY_TYPES));
// Dungeon generation test
var dungeon0 = context.window.DUNGEONS[0];
var rooms = context.generateDungeon(dungeon0);
assert('generateDungeon returns rooms', Array.isArray(rooms) && rooms.length > 0);
assert('dungeon #0 rooms ~20', rooms.length >= 17 && rooms.length <= 25);
assert('entrance assigned', rooms[0].type === 'entrance');
assert('boss assigned', rooms[rooms.length - 1].type === 'boss');
assert('all rooms connected', rooms.every(function(r) { return r.connections && r.connections.length >= 1; }));
assert('rooms have tiles', rooms.every(function(r) { return Array.isArray(r.tiles); }));
console.log('\n=== Results ===');
results.forEach(r => console.log(r));
var passed = results.filter(r => r.startsWith('PASS')).length;
var failed = results.filter(r => r.startsWith('FAIL')).length;
console.log('\n' + passed + ' passed, ' + failed + ' failed');
process.exit(failed > 0 ? 1 : 0);