Clean up abandoned matches and fix analytics validation
This commit is contained in:
@@ -6,6 +6,40 @@ 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('server cleanup releases a closed browser while an authenticated presence connection protects another tab', { skip: !uri }, async () => {
|
||||
const databaseName = 'dragon_ball_test_cleanup_' + randomUUID().replaceAll('-', ''), clock = new ManualClock();
|
||||
const app = await createGameServer({ mongoUri: uri!, databaseName, clientDirectory: 'dist/client', clock });
|
||||
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 });
|
||||
const create = async (guestToken?: string) => (await app.inject({ method: 'POST', url: '/api/game-sessions',
|
||||
payload: { createRequestId: randomBytes(32).toString('base64url'), guestToken } })).json().data;
|
||||
const old = await create(), live = await create(old.guestToken), otherBrowser = await create();
|
||||
assert.equal(old.playerId, live.playerId);
|
||||
assert.notEqual(old.playerId, otherBrowser.playerId);
|
||||
const headers = (s: typeof old) => ({ authorization: 'Bearer ' + s.token, 'x-game-session': s.gameSessionId });
|
||||
for (const session of [old, live]) {
|
||||
assert.equal((await app.inject({ method: 'POST', url: '/api/game-session/matches', headers: headers(session),
|
||||
payload: { requestId: 'bot', matchId: session.gameSessionId, mode: 'bot', expectedPreviousSeq: 0 } })).statusCode, 200);
|
||||
}
|
||||
assert.equal((await app.inject({ method: 'POST', url: '/api/ranked/queue', headers: headers(otherBrowser), payload: {} })).statusCode, 200);
|
||||
await clock.advance(90000);
|
||||
socket = io(url + '/presence', { autoConnect: false, reconnection: false, auth: { gameSessionId: live.gameSessionId, token: live.token } });
|
||||
const connected = new Promise<void>((resolve, reject) => { socket!.once('connect', resolve); socket!.once('connect_error', reject); });
|
||||
socket.connect(); await connected;
|
||||
await clock.advance(60000);
|
||||
const get = async (s: typeof old) => (await app.inject({ url: '/api/game-session', headers: headers(s) })).json().data;
|
||||
assert.equal((await get(old)).activeMatch, undefined);
|
||||
assert.equal((await get(old)).stats.bot.losses, 0);
|
||||
assert.equal((await get(live)).activeMatch.matchId, live.gameSessionId);
|
||||
assert.equal((await app.inject({ method: 'POST', url: '/api/ranked/queue', headers: headers(old), payload: {} })).json().code, 'MATCH_PENDING');
|
||||
socket.disconnect();
|
||||
await clock.advance(90000);
|
||||
assert.equal((await get(live)).activeMatch, undefined);
|
||||
assert.equal((await app.inject({ method: 'POST', url: '/api/ranked/queue', headers: headers(old), payload: {} })).statusCode, 200);
|
||||
} finally { socket?.disconnect(); await app.close(); await client.db(databaseName).dropDatabase(); await client.close(); }
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user