Files
yarn-ng/tests/validation.test.js
T

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);
});