105 lines
3.4 KiB
JavaScript
105 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const {
|
|
LIMITS,
|
|
sanitizeRoomName,
|
|
sanitizePlayerId,
|
|
normalizeSettings,
|
|
cleanText,
|
|
clampInt,
|
|
games,
|
|
getOrCreateGame,
|
|
removeRoomIfEmpty
|
|
} = require('../server');
|
|
|
|
test('room names are restricted to a safe charset and length', () => {
|
|
assert.equal(sanitizeRoomName('Lobby'), 'lobby');
|
|
assert.equal(sanitizeRoomName(' story-time_2 '), 'story-time_2');
|
|
assert.equal(sanitizeRoomName('../../etc'), null);
|
|
assert.equal(sanitizeRoomName('my room'), null);
|
|
assert.equal(sanitizeRoomName('a'.repeat(LIMITS.roomName + 1)), null);
|
|
assert.equal(sanitizeRoomName(''), null);
|
|
assert.equal(sanitizeRoomName(null), null);
|
|
assert.equal(sanitizeRoomName(42), null);
|
|
});
|
|
|
|
test('player ids are restricted to a safe charset and length', () => {
|
|
assert.equal(sanitizePlayerId('abc-123_XYZ'), 'abc-123_XYZ');
|
|
assert.equal(sanitizePlayerId('has space'), null);
|
|
assert.equal(sanitizePlayerId('x'.repeat(65)), null);
|
|
assert.equal(sanitizePlayerId(undefined), null);
|
|
});
|
|
|
|
test('settings are clamped and scoreLimit 0 is preserved', () => {
|
|
const defaults = {
|
|
scoreLimit: 0,
|
|
roundLimit: 15,
|
|
timeLimit: 60,
|
|
botCount: 0,
|
|
startText: 'Once upon a time...'
|
|
};
|
|
|
|
assert.deepEqual(normalizeSettings(defaults, {}), defaults);
|
|
|
|
const clamped = normalizeSettings(defaults, {
|
|
scoreLimit: '0',
|
|
roundLimit: 9999,
|
|
timeLimit: 1,
|
|
botCount: 99,
|
|
startText: ' '
|
|
});
|
|
assert.equal(clamped.scoreLimit, 0);
|
|
assert.equal(clamped.roundLimit, LIMITS.settings.roundLimit[1]);
|
|
assert.equal(clamped.timeLimit, LIMITS.settings.timeLimit[0]);
|
|
assert.equal(clamped.botCount, LIMITS.settings.botCount[1]);
|
|
assert.equal(clamped.startText, defaults.startText);
|
|
|
|
const negative = normalizeSettings(defaults, { scoreLimit: -50, timeLimit: -10 });
|
|
assert.equal(negative.scoreLimit, 0);
|
|
assert.equal(negative.timeLimit, LIMITS.settings.timeLimit[0]);
|
|
|
|
const junk = normalizeSettings(defaults, { roundLimit: 'abc', startText: 42 });
|
|
assert.equal(junk.roundLimit, 15);
|
|
assert.equal(junk.startText, defaults.startText);
|
|
});
|
|
|
|
test('text cleaning collapses whitespace, trims and caps', () => {
|
|
assert.equal(cleanText(' hello \n world ', 100), 'hello world');
|
|
assert.equal(cleanText('x'.repeat(500), 10), 'xxxxxxxxxx');
|
|
assert.equal(cleanText('', 10), null);
|
|
assert.equal(cleanText(' ', 10), null);
|
|
assert.equal(cleanText(null, 10), null);
|
|
assert.equal(cleanText({}, 10), null);
|
|
});
|
|
|
|
test('clampInt handles junk input', () => {
|
|
assert.equal(clampInt('5', 0, 10, 7), 5);
|
|
assert.equal(clampInt(50, 0, 10, 7), 10);
|
|
assert.equal(clampInt(-5, 0, 10, 7), 0);
|
|
assert.equal(clampInt('abc', 0, 10, 7), 7);
|
|
assert.equal(clampInt(undefined, 0, 10, 7), 7);
|
|
assert.equal(clampInt(1.9, 0, 10, 7), 1);
|
|
});
|
|
|
|
|
|
test('rooms are only removed once every human has left', () => {
|
|
const game = getOrCreateGame('lifecycle-room');
|
|
assert.ok(game);
|
|
game.addPlayer('p1', 'Alice', 's1');
|
|
|
|
removeRoomIfEmpty('lifecycle-room');
|
|
assert.ok(games['lifecycle-room'], 'a room with humans stays');
|
|
|
|
game.removePlayer('p1');
|
|
removeRoomIfEmpty('lifecycle-room');
|
|
assert.equal(games['lifecycle-room'], undefined, 'empty rooms are cleaned up');
|
|
});
|
|
|
|
test('getOrCreateGame rejects unsafe room names', () => {
|
|
assert.equal(getOrCreateGame('../evil'), null);
|
|
assert.equal(games['../evil'], undefined);
|
|
});
|