Files
Emberfall/tests/helpers.js
T
bepis f1ae7b3119 feat: complete Phase 4 combat/hunting system
- Add content migration (003_content.sql): zones, monsters, items, loot tables
- Add inventory migration (004_inventory.sql) and logs migration (006_logs.sql)
- Add Mulberry32 PRNG (src/utils/rng.js) for deterministic combat
- Add combat system (src/game/combat.js) with turn order, crit, mage bonus, 20-round cap
- Add rewards/loot system (src/game/rewards.js) and leveling (src/game/leveling.js)
- Add hunt endpoint (POST /api/hunt) with full combat flow in DB transaction
- Add hunt integration tests and unit tests for rewards/leveling/combat
- Fix session middleware to use memory store in tests (avoids cleanup hang)
- Fix huntService transaction (db.transaction() returns wrapper, must call separately)
- Add huntService to helpers.js cache invalidation for test isolation
2026-10-20 17:46:18 +11:00

86 lines
2.1 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const os = require('os');
let tmpDir;
let dbPath;
let server;
let dbRef;
function createFreshApp() {
process.env.DB_PATH = dbPath;
const cached = [
require.resolve('../src/db'),
require.resolve('../src/config'),
require.resolve('../src/middleware/session'),
require.resolve('../src/services/authService'),
require.resolve('../src/services/huntService'),
require.resolve('../src/app'),
require.resolve('../scripts/migrate'),
];
for (const id of cached) {
if (require.cache[id]) delete require.cache[id];
}
const { runMigrations } = require('../scripts/migrate');
runMigrations();
// Capture the DB instance before creating the app (session store uses it)
const dbModule = require('../src/db');
dbRef = dbModule.getDb();
const { createApp } = require('../src/app');
return createApp();
}
async function setup() {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'emberfall-test-'));
dbPath = path.join(tmpDir, 'test.db');
const app = createFreshApp();
return new Promise((resolve, reject) => {
server = app.listen(0, () => {
const port = server.address().port;
resolve(`http://localhost:${port}`);
});
server.on('error', reject);
});
}
function teardown() {
return new Promise((resolve) => {
if (server) {
// Close server first to stop accepting connections
try { server.closeAllConnections(); } catch (_) {}
server.close(() => {
server = null;
// Then close DB to stop session store's cleanup interval
if (dbRef) {
try { dbRef.close(); } catch (_) {}
dbRef = null;
}
resolve();
});
} else {
// No server, just close DB
if (dbRef) {
try { dbRef.close(); } catch (_) {}
dbRef = null;
}
resolve();
}
});
}
function cleanup() {
if (tmpDir && fs.existsSync(tmpDir)) {
try { fs.rmSync(tmpDir, { recursive: true }); } catch (_) {}
}
tmpDir = undefined;
dbPath = undefined;
}
module.exports = { setup, teardown, cleanup };