58 lines
4.2 KiB
TypeScript
58 lines
4.2 KiB
TypeScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { randomBytes, randomUUID } from 'node:crypto';
|
|
import { MongoClient } from 'mongodb';
|
|
import { io } from 'socket.io-client';
|
|
import { createGameServer } from '../src/server/create-server.js';
|
|
import { ManualClock } from './helpers.js';
|
|
const uri = process.env.TEST_MONGODB_URI;
|
|
|
|
test('HTTP game registration survives server restart without game timers and old gameplay sockets are rejected', { skip: !uri }, async () => {
|
|
const databaseName = 'dragon_ball_test_server_' + randomUUID().replaceAll('-', ''), clock = new ManualClock();
|
|
const options = { mongoUri: uri!, databaseName, clientDirectory: 'dist/client', clock };
|
|
let app = await createGameServer(options);
|
|
const client = await new MongoClient(uri!).connect();
|
|
let socket: ReturnType<typeof io> | undefined;
|
|
try {
|
|
const url = await app.listen({ host: '127.0.0.1', port: 0 });
|
|
assert.equal((await app.inject('/health')).statusCode, 200);
|
|
assert.equal((await app.inject('/ready')).statusCode, 200);
|
|
const session = (await app.inject({ method: 'POST', url: '/api/game-sessions', payload: { createRequestId: randomBytes(32).toString('base64url') } })).json().data;
|
|
const headers = { authorization: 'Bearer ' + session.token, 'x-game-session': session.gameSessionId };
|
|
const input = { requestId: 'register', matchId: 'bot-match', mode: 'bot', expectedPreviousSeq: 0 };
|
|
const match = (await app.inject({ method: 'POST', url: '/api/game-session/matches', headers, payload: input })).json().data;
|
|
assert.equal(match.seq, 1);
|
|
await clock.advance(12000);
|
|
assert.equal((await app.inject({ url: '/api/game-session', headers })).json().data.activeMatch.matchId, 'bot-match');
|
|
assert.equal(await client.db(databaseName).collection('matches').countDocuments(), 0);
|
|
socket = io(url, { autoConnect: false, reconnection: false, transports: ['websocket'] });
|
|
const status = new Promise<string>(resolve => { socket!.once('connect_error', () => resolve('rejected')); socket!.once('connect', () => resolve('accepted')); });
|
|
socket.connect(); assert.equal(await status, 'rejected'); socket.disconnect();
|
|
await app.close(); app = await createGameServer(options);
|
|
assert.equal((await app.inject({ url: '/api/game-session', headers })).json().data.activeMatch.matchId, 'bot-match');
|
|
const payload = { ...match, outcome: 'loss', reason: 'timeout' };
|
|
assert.equal((await app.inject({ method: 'POST', url: '/api/game-session/results', headers, payload })).json().data.stats.bot.losses, 1);
|
|
assert.equal((await app.inject({ method: 'POST', url: '/api/game-session/results', headers, payload })).json().data.status, 'duplicate');
|
|
assert.equal((await app.inject({ method: 'POST', url: '/api/game-session/results', payload })).statusCode, 401);
|
|
const state = (await app.inject({ url: '/api/game-session', headers })).json().data;
|
|
assert.equal(state.activeMatch, undefined); assert.equal(state.stats.bot.losses, 1);
|
|
} finally { socket?.disconnect(); await app.close(); try { await client.db(databaseName).dropDatabase(); } finally { await client.close(); } }
|
|
});
|
|
|
|
test('production server enforces session limits before database creation', { skip: !uri }, async () => {
|
|
const databaseName = 'dragon_ball_test_limits_' + randomUUID().replaceAll('-', '');
|
|
const app = await createGameServer({ mongoUri: uri!, databaseName, clientDirectory: 'dist/client', environment: 'test' });
|
|
const client = await new MongoClient(uri!).connect();
|
|
try {
|
|
for (let i = 0; i < 30; i++) {
|
|
assert.equal((await app.inject({ method: 'POST', url: '/api/game-sessions', payload: {} })).statusCode, 400);
|
|
}
|
|
const response = await app.inject({ method: 'POST', url: '/api/game-sessions',
|
|
payload: { createRequestId: randomBytes(32).toString('base64url') } });
|
|
assert.equal(response.statusCode, 429);
|
|
assert.ok(Number(response.headers['retry-after']) > 0);
|
|
assert.equal(await client.db(databaseName).collection('players').countDocuments(), 0);
|
|
assert.equal(await client.db(databaseName).collection('game_sessions').countDocuments(), 0);
|
|
} finally { await app.close(); try { await client.db(databaseName).dropDatabase(); } finally { await client.close(); } }
|
|
});
|