Merge feature/messer-match-server in main

# Conflicts:
#	client/src/styles.css
This commit is contained in:
mregosar committed 2026-11-01 18:26:42 +01:00
commit 148cd99856
10 files changed
+220 -20

No files matched your search

+50
View File
@@ -713,3 +713,53 @@ test('Konsole: nur für Admins, Ausgabe kommt live, unbekannte Server 404', asyn
await close();
}
});
test('Messerrunde auf dem eigenen Match-Server: Verbindungsdaten in der Lobby, danach derselbe Server fürs Match', async () => {
const { app, call, close } = await setup();
try {
const created = await call('POST', '/matches', { body: { teamA: 'Alpha', teamB: 'Bravo', mode: 'wingman', format: 'bo1', vetoStart: 'knife' } });
const { id, organizerToken: org } = created.body;
const codes = (await call('GET', `/matches/${id}`, { token: org })).body.organizer.codes;
const tokens = {};
for (const [name, team] of [['a1', 'A'], ['a2', 'A'], ['b1', 'B'], ['b2', 'B']]) {
tokens[name] = (await call('POST', `/matches/${id}/join`, { body: { code: codes[team], nickname: name } })).body.playerToken;
}
// Vor dem Start: Aktionen gehen noch nicht
assert.equal((await call('POST', `/matches/${id}/server/knife-start`, { token: org })).status, 409);
await app.manager.poll();
await waitFor(() => app.manager.row(id).knife_phase === 'warmup', { label: 'Messerrunde eingerichtet' });
const player = (await call('GET', `/matches/${id}`, { token: tokens.b1 })).body;
assert.deepEqual(player.server.knife, { ready: true, phase: 'warmup' });
assert.equal(player.server.connect.password, app.manager.row(id).server_password, 'Spieler bekommen das Passwort des Matches');
const pub = (await call('GET', `/matches/${id}`)).body;
assert.equal(pub.server?.connect, undefined, 'öffentlich keine Verbindungsdaten');
// Nur der Organisator startet die Runde
assert.equal((await call('POST', `/matches/${id}/server/knife-start`, { token: tokens.a1 })).status, 403);
assert.equal((await call('POST', `/matches/${id}/server/knife-start`, { token: org })).status, 200);
assert.equal(app.manager.row(id).knife_phase, 'live');
assert.equal((await call('POST', `/matches/${id}/server/knife-reset`, { token: org })).status, 200);
assert.equal(app.manager.row(id).knife_phase, 'warmup');
// Nach dem Veto wird derselbe Server fürs Match eingerichtet, die Messer-Einstellungen werden zurückgenommen
const handle = app.manager.row(id).handle;
const plans = [];
const configure = app.adapter.configure.bind(app.adapter);
app.adapter.configure = async (h, plan) => { plans.push(plan); return configure(h, plan); };
for (const t of Object.values(tokens)) await call('POST', `/matches/${id}/ready`, { token: t, body: { ready: true } });
assert.equal((await call('POST', `/matches/${id}/veto/start`, { token: org, body: { firstTeam: 'A' } })).status, 200);
const snap = (await call('GET', `/matches/${id}`, { token: org })).body;
const capA = snap.teams.A.players.find((p) => p.isCaptain)?.nickname ?? 'a1';
const capB = snap.teams.B.players.find((p) => p.isCaptain)?.nickname ?? 'b1';
await playVeto(call, id, { A: tokens[capA], B: tokens[capB] });
await waitFor(() => app.manager.row(id).status === 'configured', { label: 'Match eingerichtet' });
const row = app.manager.row(id);
assert.equal(row.handle, handle, 'derselbe Server');
assert.equal(row.knife_at, null);
assert.ok(plans.at(-1).afterMapChange.includes('mp_give_player_c4 1'));
assert.equal((await call('GET', `/matches/${id}`, { token: tokens.b1 })).body.server.knife, undefined);
} finally {
await close();
}
});