// ── The read path's logic ───────────────────────────────────────────────── // // The model decides what a caller gets. Two properties are worth more than the // rest, and both are about a caller who did something slightly wrong: // // • a route that forgets to say who is asking gets the PUBLIC view; // • a caller asking for a million rows gets two hundred. const test = require('node:test') const assert = require('node:assert') const { fakeCtx } = require('./_fakes') function withCore() { require('../core')._reset() require('../core').init(fakeCtx()) } test('the limit is bounded, whatever was asked for', () => { withCore() const model = require('../model/events/events.model') assert.equal(model.boundedLimit(10), 10) assert.equal(model.boundedLimit(undefined), 50) assert.equal(model.boundedLimit('nonsense'), 50) assert.equal(model.boundedLimit(-5), 50) assert.equal(model.boundedLimit(0), 50) assert.equal(model.boundedLimit(1e9), model.MAX_LIMIT) assert.equal(model.boundedLimit(12.9), 12) }) test('kinds parse from one name or a list, and nothing means "not specified"', () => { withCore() const model = require('../model/events/events.model') assert.deepEqual(model.parseKinds('player.death'), ['player.death']) assert.deepEqual(model.parseKinds('player.death, player.chat'), ['player.death', 'player.chat']) // Null rather than an empty list: "I did not ask" and "I asked for nothing" // are different, and only the first means "whatever I am allowed". assert.equal(model.parseKinds(''), null) assert.equal(model.parseKinds(undefined), null) assert.equal(model.parseKinds(' , , '), null) }) test('a reader who does not say who they are gets the public view', async () => { withCore() const db = require('../model/events/events.db') const model = require('../model/events/events.model') const original = db.recentEvents let asked = null db.recentEvents = async (args) => { asked = args return [] } try { await model.recent({ serverId: 'main' }) assert.ok(!asked.kinds.includes('player.banned'), 'no IP-carrying kind by default') assert.ok(asked.kinds.includes('player.death')) await model.recent({ serverId: 'main', admin: true }) assert.ok(asked.kinds.includes('player.banned'), 'an admin who says so gets them') } finally { db.recentEvents = original } }) test('asking only for kinds you may not see answers with nothing, and queries nothing', async () => { withCore() const db = require('../model/events/events.db') const model = require('../model/events/events.model') const original = db.recentEvents let called = false db.recentEvents = async () => { called = true return [] } try { const rows = await model.recent({ serverId: 'main', kind: 'player.banned,player.approved' }) assert.deepEqual(rows, []) assert.equal(called, false, 'a query with no permitted kinds must not reach the database') } finally { db.recentEvents = original } }) test('a row whose stored frame will not parse still answers with its envelope', async () => { withCore() const db = require('../model/events/events.db') const model = require('../model/events/events.model') const original = db.recentEvents db.recentEvents = async () => [ { id: 7, kind: 'player.death', t: 12, wipeId: 'w-1', steamId: 'p1', raw: '{not json' }, ] try { const [row] = await model.recent({ serverId: 'main' }) // One unreadable row must not fail a whole page. What is known is still // reported; the body is empty rather than absent. assert.equal(row.id, 7) assert.equal(row.kind, 'player.death') assert.deepEqual(row.frame, {}) } finally { db.recentEvents = original } }) test('the leaderboard answers numbers, never nulls', async () => { withCore() const db = require('../model/events/events.db') const model = require('../model/events/events.model') const original = db.leaderboard // SUM() over no rows is NULL in SQL, and a JOIN with no player row gives a // null name. A page that has to defend against both is a page with the // defence in three places. db.leaderboard = async () => [ { steamId: 'p1', name: null, kills: null, deaths: '3', npcKills: null, playtimeSec: null }, ] try { const [row] = await model.leaderboard({ serverId: 'main' }) assert.equal(row.kills, 0) assert.equal(row.deaths, 3) assert.equal(row.npcKills, 0) assert.equal(row.playtimeSec, 0) assert.equal(row.name, null) } finally { db.leaderboard = original } })