bunch of shit from claude code
This commit is contained in:
97
backend/tests/application/QueueService.test.ts
Normal file
97
backend/tests/application/QueueService.test.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { test, expect, beforeEach } from "bun:test";
|
||||
import { TestHarness } from "../../src/testing/TestHarness";
|
||||
|
||||
let harness: TestHarness;
|
||||
|
||||
beforeEach(() => {
|
||||
harness = new TestHarness();
|
||||
});
|
||||
|
||||
test("team can join queue", async () => {
|
||||
const players = harness.createPlayers(1);
|
||||
const team = harness.createTeam(players, { name: "Test Team" });
|
||||
|
||||
const entry = await harness.queueService.joinQueue(team, "ranked");
|
||||
|
||||
expect(entry.team.id).toBe(team.id);
|
||||
expect(entry.queueType).toBe("ranked");
|
||||
});
|
||||
|
||||
test("team cannot join queue twice", async () => {
|
||||
const players = harness.createPlayers(1);
|
||||
const team = harness.createTeam(players, { name: "Test Team" });
|
||||
|
||||
await harness.queueService.joinQueue(team, "ranked");
|
||||
|
||||
expect(async () => {
|
||||
await harness.queueService.joinQueue(team, "ranked");
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("team can leave queue", async () => {
|
||||
const players = harness.createPlayers(1);
|
||||
const team = harness.createTeam(players, { name: "Test Team" });
|
||||
|
||||
await harness.queueService.joinQueue(team, "ranked");
|
||||
await harness.queueService.leaveQueue(team.id);
|
||||
|
||||
const status = await harness.queueService.getQueueStatus("ranked");
|
||||
expect(status.count).toBe(0);
|
||||
});
|
||||
|
||||
test("findMatch returns null when less than 2 teams in queue", async () => {
|
||||
const players = harness.createPlayers(1);
|
||||
const team = harness.createTeam(players, { name: "Test Team" });
|
||||
|
||||
await harness.queueService.joinQueue(team, "ranked");
|
||||
|
||||
const match = await harness.queueService.findMatch("ranked");
|
||||
expect(match).toBeNull();
|
||||
});
|
||||
|
||||
test("findMatch creates match when 2 teams in queue", async () => {
|
||||
const players1 = harness.createPlayers(1, 1000);
|
||||
const players2 = harness.createPlayers(1, 1010);
|
||||
|
||||
const team1 = harness.createTeam(players1, { name: "Team 1" });
|
||||
const team2 = harness.createTeam(players2, { name: "Team 2" });
|
||||
|
||||
await harness.queueService.joinQueue(team1, "ranked");
|
||||
await harness.queueService.joinQueue(team2, "ranked");
|
||||
|
||||
const match = await harness.queueService.findMatch("ranked");
|
||||
|
||||
expect(match).not.toBeNull();
|
||||
expect(match!.teams.length).toBe(2);
|
||||
});
|
||||
|
||||
test("getQueueStatus returns correct count", async () => {
|
||||
const players1 = harness.createPlayers(1);
|
||||
const players2 = harness.createPlayers(1);
|
||||
|
||||
const team1 = harness.createTeam(players1, { name: "Team 1" });
|
||||
const team2 = harness.createTeam(players2, { name: "Team 2" });
|
||||
|
||||
await harness.queueService.joinQueue(team1, "ranked");
|
||||
await harness.queueService.joinQueue(team2, "ranked");
|
||||
|
||||
const status = await harness.queueService.getQueueStatus("ranked");
|
||||
|
||||
expect(status.count).toBe(2);
|
||||
expect(status.entries.length).toBe(2);
|
||||
});
|
||||
|
||||
test("queue events are published", async () => {
|
||||
const players = harness.createPlayers(1);
|
||||
const team = harness.createTeam(players, { name: "Test Team" });
|
||||
|
||||
await harness.queueService.joinQueue(team, "ranked");
|
||||
|
||||
const joinEvents = harness.getEventsByType("queue.team_joined");
|
||||
expect(joinEvents.length).toBe(1);
|
||||
|
||||
await harness.queueService.leaveQueue(team.id);
|
||||
|
||||
const leaveEvents = harness.getEventsByType("queue.team_left");
|
||||
expect(leaveEvents.length).toBe(1);
|
||||
});
|
||||
155
backend/tests/domain/protocols/StandardOsuProtocol.test.ts
Normal file
155
backend/tests/domain/protocols/StandardOsuProtocol.test.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
import { test, expect, beforeEach } from "bun:test";
|
||||
import { StandardOsuProtocol } from "../../../src/domain/protocols/StandardOsuProtocol";
|
||||
import { createMatch } from "../../../src/domain/models/Match";
|
||||
import { createTeam } from "../../../src/domain/models/Team";
|
||||
import { createPlayer } from "../../../src/domain/models/Player";
|
||||
import type { Score } from "../../../src/domain/models/Score";
|
||||
|
||||
let protocol: StandardOsuProtocol;
|
||||
|
||||
beforeEach(() => {
|
||||
protocol = new StandardOsuProtocol();
|
||||
});
|
||||
|
||||
test("has correct configuration", () => {
|
||||
expect(protocol.name).toBe("standard-osu");
|
||||
expect(protocol.teamSize).toBe(4);
|
||||
expect(protocol.bestOf).toBe(9);
|
||||
expect(protocol.hasPickBan).toBe(true);
|
||||
expect(protocol.hasFreemod).toBe(true);
|
||||
});
|
||||
|
||||
test("getWinsNeeded returns correct value for best of 9", () => {
|
||||
expect(protocol.getWinsNeeded()).toBe(5);
|
||||
});
|
||||
|
||||
test("calculateMapWinner returns winning team based on scores", () => {
|
||||
const players1 = [
|
||||
createPlayer({ id: "p1", discordId: "d1", osuId: 1, osuName: "Player1" }),
|
||||
createPlayer({ id: "p2", discordId: "d2", osuId: 2, osuName: "Player2" }),
|
||||
];
|
||||
const players2 = [
|
||||
createPlayer({ id: "p3", discordId: "d3", osuId: 3, osuName: "Player3" }),
|
||||
createPlayer({ id: "p4", discordId: "d4", osuId: 4, osuName: "Player4" }),
|
||||
];
|
||||
|
||||
const team1 = createTeam({ id: "team1", name: "Team 1", players: players1 });
|
||||
const team2 = createTeam({ id: "team2", name: "Team 2", players: players2 });
|
||||
|
||||
const match = createMatch({
|
||||
teams: [team1, team2],
|
||||
protocol: "standard-osu",
|
||||
});
|
||||
|
||||
const scores: Score[] = [
|
||||
{ playerId: "p1", score: 500000, accuracy: 95, maxCombo: 800, misses: 2 },
|
||||
{ playerId: "p2", score: 450000, accuracy: 94, maxCombo: 750, misses: 3 },
|
||||
{ playerId: "p3", score: 400000, accuracy: 92, maxCombo: 700, misses: 5 },
|
||||
{ playerId: "p4", score: 380000, accuracy: 91, maxCombo: 680, misses: 6 },
|
||||
];
|
||||
|
||||
const winner = protocol.calculateMapWinner(match, scores);
|
||||
expect(winner).toBe("team1");
|
||||
});
|
||||
|
||||
test("calculateMatchWinner returns null when no team has enough wins", () => {
|
||||
const players1 = [createPlayer({ id: "p1", discordId: "d1", osuId: 1, osuName: "P1" })];
|
||||
const players2 = [createPlayer({ id: "p2", discordId: "d2", osuId: 2, osuName: "P2" })];
|
||||
|
||||
const team1 = createTeam({ id: "team1", name: "Team 1", players: players1 });
|
||||
const team2 = createTeam({ id: "team2", name: "Team 2", players: players2 });
|
||||
|
||||
const match = createMatch({
|
||||
teams: [team1, team2],
|
||||
protocol: "standard-osu",
|
||||
});
|
||||
|
||||
expect(protocol.calculateMatchWinner(match)).toBeNull();
|
||||
});
|
||||
|
||||
test("isValidPick returns false when not the picking team", () => {
|
||||
const players1 = [createPlayer({ id: "p1", discordId: "d1", osuId: 1, osuName: "P1" })];
|
||||
const players2 = [createPlayer({ id: "p2", discordId: "d2", osuId: 2, osuName: "P2" })];
|
||||
|
||||
const team1 = createTeam({ id: "team1", name: "Team 1", players: players1 });
|
||||
const team2 = createTeam({ id: "team2", name: "Team 2", players: players2 });
|
||||
|
||||
const match = createMatch({
|
||||
teams: [team1, team2],
|
||||
protocol: "standard-osu",
|
||||
});
|
||||
|
||||
match.currentPicker = "team1";
|
||||
|
||||
const map = {
|
||||
id: 123,
|
||||
beatmapSetId: 456,
|
||||
title: "Test Map",
|
||||
artist: "Artist",
|
||||
difficulty: "Hard",
|
||||
starRating: 5.5,
|
||||
bpm: 180,
|
||||
length: 120,
|
||||
};
|
||||
|
||||
expect(protocol.isValidPick(match, team1, map)).toBe(true);
|
||||
expect(protocol.isValidPick(match, team2, map)).toBe(false);
|
||||
});
|
||||
|
||||
test("isValidPick returns false for banned maps", () => {
|
||||
const players1 = [createPlayer({ id: "p1", discordId: "d1", osuId: 1, osuName: "P1" })];
|
||||
const players2 = [createPlayer({ id: "p2", discordId: "d2", osuId: 2, osuName: "P2" })];
|
||||
|
||||
const team1 = createTeam({ id: "team1", name: "Team 1", players: players1 });
|
||||
const team2 = createTeam({ id: "team2", name: "Team 2", players: players2 });
|
||||
|
||||
const match = createMatch({
|
||||
teams: [team1, team2],
|
||||
protocol: "standard-osu",
|
||||
});
|
||||
|
||||
match.currentPicker = "team1";
|
||||
match.bans.set("team2", [123]);
|
||||
|
||||
const map = {
|
||||
id: 123,
|
||||
beatmapSetId: 456,
|
||||
title: "Test Map",
|
||||
artist: "Artist",
|
||||
difficulty: "Hard",
|
||||
starRating: 5.5,
|
||||
bpm: 180,
|
||||
length: 120,
|
||||
};
|
||||
|
||||
expect(protocol.isValidPick(match, team1, map)).toBe(false);
|
||||
});
|
||||
|
||||
test("isValidPick returns false for already picked maps", () => {
|
||||
const players1 = [createPlayer({ id: "p1", discordId: "d1", osuId: 1, osuName: "P1" })];
|
||||
const players2 = [createPlayer({ id: "p2", discordId: "d2", osuId: 2, osuName: "P2" })];
|
||||
|
||||
const team1 = createTeam({ id: "team1", name: "Team 1", players: players1 });
|
||||
const team2 = createTeam({ id: "team2", name: "Team 2", players: players2 });
|
||||
|
||||
const match = createMatch({
|
||||
teams: [team1, team2],
|
||||
protocol: "standard-osu",
|
||||
});
|
||||
|
||||
match.currentPicker = "team1";
|
||||
match.picks.push(123);
|
||||
|
||||
const map = {
|
||||
id: 123,
|
||||
beatmapSetId: 456,
|
||||
title: "Test Map",
|
||||
artist: "Artist",
|
||||
difficulty: "Hard",
|
||||
starRating: 5.5,
|
||||
bpm: 180,
|
||||
length: 120,
|
||||
};
|
||||
|
||||
expect(protocol.isValidPick(match, team1, map)).toBe(false);
|
||||
});
|
||||
121
backend/tests/integration/full-match-flow.test.ts
Normal file
121
backend/tests/integration/full-match-flow.test.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import { test, expect, beforeEach } from "bun:test";
|
||||
import { TestHarness } from "../../src/testing/TestHarness";
|
||||
import { MatchState } from "../../src/domain/models/MatchState";
|
||||
|
||||
let harness: TestHarness;
|
||||
|
||||
beforeEach(() => {
|
||||
harness = new TestHarness();
|
||||
});
|
||||
|
||||
test("complete match flow from queue to completion", async () => {
|
||||
const players1 = harness.createPlayers(1, 1000);
|
||||
const players2 = harness.createPlayers(1, 1020);
|
||||
|
||||
const team1 = harness.createTeam(players1, { name: "Team Alpha" });
|
||||
const team2 = harness.createTeam(players2, { name: "Team Beta" });
|
||||
|
||||
await harness.queueService.joinQueue(team1, "ranked");
|
||||
await harness.queueService.joinQueue(team2, "ranked");
|
||||
|
||||
const match = await harness.queueService.findMatch("ranked");
|
||||
|
||||
expect(match).not.toBeNull();
|
||||
expect(match!.teams.length).toBe(2);
|
||||
expect(match!.lobbyId).toBeDefined();
|
||||
|
||||
await harness.simulateAllPlayersJoin(match!);
|
||||
|
||||
let updatedMatch = await harness.matchRepo.findById(match!.id);
|
||||
expect(updatedMatch!.state).toBe(MatchState.ROLLING);
|
||||
|
||||
const rolls = new Map<string, number>();
|
||||
rolls.set(team1.id, 75);
|
||||
rolls.set(team2.id, 50);
|
||||
await harness.simulateRolls(match!, rolls);
|
||||
|
||||
updatedMatch = await harness.matchRepo.findById(match!.id);
|
||||
expect(updatedMatch!.state).toBe(MatchState.PICKING);
|
||||
|
||||
const events = harness.getEventsByType("match.created");
|
||||
expect(events.length).toBe(1);
|
||||
|
||||
const stateChanges = harness.getEventsByType("match.state_changed");
|
||||
expect(stateChanges.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("match creates lobby on start", async () => {
|
||||
const players1 = harness.createPlayers(1);
|
||||
const players2 = harness.createPlayers(1);
|
||||
|
||||
const team1 = harness.createTeam(players1, { name: "Team 1" });
|
||||
const team2 = harness.createTeam(players2, { name: "Team 2" });
|
||||
|
||||
await harness.queueService.joinQueue(team1, "ranked");
|
||||
await harness.queueService.joinQueue(team2, "ranked");
|
||||
|
||||
const match = await harness.queueService.findMatch("ranked");
|
||||
|
||||
expect(match!.lobbyId).toBeDefined();
|
||||
expect(harness.mockGameService.lobbies.has(match!.lobbyId!)).toBe(true);
|
||||
});
|
||||
|
||||
test("notifications are sent when match is created", async () => {
|
||||
const players1 = harness.createPlayers(1);
|
||||
const players2 = harness.createPlayers(1);
|
||||
|
||||
const team1 = harness.createTeam(players1, { name: "Team 1" });
|
||||
const team2 = harness.createTeam(players2, { name: "Team 2" });
|
||||
|
||||
await harness.queueService.joinQueue(team1, "ranked");
|
||||
await harness.queueService.joinQueue(team2, "ranked");
|
||||
|
||||
await harness.queueService.findMatch("ranked");
|
||||
|
||||
expect(harness.mockNotificationService.announcements.length).toBe(1);
|
||||
});
|
||||
|
||||
test("match state transitions correctly through rolling phase", async () => {
|
||||
const players1 = harness.createPlayers(1);
|
||||
const players2 = harness.createPlayers(1);
|
||||
|
||||
const team1 = harness.createTeam(players1, { name: "Team 1" });
|
||||
const team2 = harness.createTeam(players2, { name: "Team 2" });
|
||||
|
||||
await harness.queueService.joinQueue(team1, "ranked");
|
||||
await harness.queueService.joinQueue(team2, "ranked");
|
||||
|
||||
const match = await harness.queueService.findMatch("ranked");
|
||||
expect(match!.state).toBe(MatchState.WAITING_PLAYERS);
|
||||
|
||||
await harness.simulateAllPlayersJoin(match!);
|
||||
|
||||
let updatedMatch = await harness.matchRepo.findById(match!.id);
|
||||
expect(updatedMatch!.state).toBe(MatchState.ROLLING);
|
||||
|
||||
const rolls = new Map<string, number>();
|
||||
rolls.set(team1.id, 75);
|
||||
rolls.set(team2.id, 50);
|
||||
await harness.simulateRolls(match!, rolls);
|
||||
|
||||
updatedMatch = await harness.matchRepo.findById(match!.id);
|
||||
expect(updatedMatch!.state).toBe(MatchState.PICKING);
|
||||
// In head-to-head protocol, roll winner picks first
|
||||
expect(updatedMatch!.currentPicker).toBe(team1.id);
|
||||
});
|
||||
|
||||
test("queue status is empty after match found", async () => {
|
||||
const players1 = harness.createPlayers(1);
|
||||
const players2 = harness.createPlayers(1);
|
||||
|
||||
const team1 = harness.createTeam(players1, { name: "Team 1" });
|
||||
const team2 = harness.createTeam(players2, { name: "Team 2" });
|
||||
|
||||
await harness.queueService.joinQueue(team1, "ranked");
|
||||
await harness.queueService.joinQueue(team2, "ranked");
|
||||
|
||||
await harness.queueService.findMatch("ranked");
|
||||
|
||||
const status = await harness.queueService.getQueueStatus("ranked");
|
||||
expect(status.count).toBe(0);
|
||||
});
|
||||
Reference in New Issue
Block a user