+
@@ -214,6 +260,60 @@ export default function TournamentSeedsPage() {
);
}
+function SeedingDraggable({
+ id,
+ disabled,
+ children,
+ testId,
+ isActive,
+}: {
+ id: number;
+ disabled: boolean;
+ children: React.ReactNode;
+ testId?: string;
+ isActive: boolean;
+}) {
+ const {
+ attributes,
+ listeners,
+ setNodeRef,
+ transform,
+ transition,
+ isDragging,
+ } = useSortable({ id, disabled });
+
+ const style = {
+ transform: CSS.Transform.toString(transform),
+ transition,
+ };
+
+ return (
+
+
+
+
+ {children}
+
+ );
+}
+
function StartingBracketDialog() {
const fetcher = useFetcher();
const tournament = useTournament();
@@ -338,7 +438,7 @@ function SeedAlert({ teamOrder }: { teamOrder: number[] }) {
const teamOrderChanged = teamOrder.some((id, i) => id !== teamOrderInDb[i]);
return (
-
+
@@ -366,6 +466,10 @@ function RowContents({
team,
seed,
teamSeedingSkill,
+ isNewTeam,
+ newPlayerIds,
+ removedPlayers,
+ onSeedChange,
}: {
team: TournamentDataTeam;
seed?: number;
@@ -373,37 +477,176 @@ function RowContents({
sp: number | null;
outOfOrder: boolean;
};
+ isNewTeam?: boolean;
+ newPlayerIds?: Set;
+ removedPlayers?: Array<{ userId: number; username: string }>;
+ onSeedChange?: (newSeed: number) => void;
}) {
const tournament = useTournament();
+ const [inputValue, setInputValue] = React.useState(String(seed ?? ""));
+
+ React.useEffect(() => {
+ setInputValue(String(seed ?? ""));
+ }, [seed]);
+
+ const handleInputBlur = () => {
+ const newSeed = Number.parseInt(inputValue, 10);
+ if (!Number.isNaN(newSeed) && onSeedChange) {
+ onSeedChange(newSeed);
+ } else {
+ setInputValue(String(seed ?? ""));
+ }
+ };
const logoUrl = tournament.tournamentTeamLogoSrc(team);
return (
<>
- {seed}
-
-
- {team.checkIns.length > 0 ? "✅ " : "❌ "} {team.name}
+
+ {seed !== undefined && onSeedChange ? (
+
setInputValue(e.target.value)}
+ onBlur={handleInputBlur}
+ onKeyDown={(e) => {
+ if (e.key === "Enter") {
+ e.currentTarget.blur();
+ }
+ }}
+ />
+ ) : (
+
{seed}
+ )}
-
- {teamSeedingSkill.sp}
+
-
- {team.members.map((member) => {
- return (
-
-
- {member.username}
-
+
+
+
+ {team.checkIns.length > 0 ? "✅ " : "❌ "} {team.name}
+
+ {isNewTeam ? NEW : null}
+
+
+
+
+ {teamSeedingSkill.sp}
+
+
+
+
+ {removedPlayers?.map((player) => (
+
+ {player.username}
- );
- })}
+ ))}
+ {team.members.map((member) => {
+ const isNew = newPlayerIds?.has(member.userId);
+ return (
+
+
+ {member.username}
+
+ {member.plusTier ? (
+
+
+ {member.plusTier}
+
+ ) : null}
+ {isNew ? (
+ NEW
+ ) : null}
+
+ );
+ })}
+
>
);
}
+function computeNewTeamIds(
+ teams: TournamentDataTeam[],
+ snapshot: SeedingSnapshot | null,
+): Set
{
+ if (!snapshot) return new Set();
+ const savedTeamIds = new Set(snapshot.teams.map((t) => t.teamId));
+ return new Set(teams.filter((t) => !savedTeamIds.has(t.id)).map((t) => t.id));
+}
+
+function computeNewPlayers(
+ teams: TournamentDataTeam[],
+ snapshot: SeedingSnapshot | null,
+): Map> {
+ const result = new Map>();
+ if (!snapshot) return result;
+
+ const savedTeamMap = new Map(
+ snapshot.teams.map((t) => [
+ t.teamId,
+ new Set(t.members.map((m) => m.userId)),
+ ]),
+ );
+
+ for (const team of teams) {
+ const savedMembers = savedTeamMap.get(team.id);
+ if (!savedMembers) continue;
+
+ const newPlayerIds = new Set(
+ team.members
+ .filter((m) => !savedMembers.has(m.userId))
+ .map((m) => m.userId),
+ );
+ if (newPlayerIds.size > 0) {
+ result.set(team.id, newPlayerIds);
+ }
+ }
+ return result;
+}
+
+function computeRemovedPlayers(
+ teams: TournamentDataTeam[],
+ snapshot: SeedingSnapshot | null,
+): Map> {
+ const result = new Map>();
+ if (!snapshot) return result;
+
+ const currentTeamMap = new Map(
+ teams.map((t) => [t.id, new Set(t.members.map((m) => m.userId))]),
+ );
+
+ for (const savedTeam of snapshot.teams) {
+ const currentMembers = currentTeamMap.get(savedTeam.teamId);
+ if (!currentMembers) continue;
+
+ const removedMembers = savedTeam.members.filter(
+ (member) => !currentMembers.has(member.userId),
+ );
+ if (removedMembers.length > 0) {
+ result.set(savedTeam.teamId, removedMembers);
+ }
+ }
+ return result;
+}
+
export const ErrorBoundary = Catcher;
diff --git a/app/features/tournament/tournament-utils.test.ts b/app/features/tournament/tournament-utils.test.ts
index f933ba7e6..1d8a1f591 100644
--- a/app/features/tournament/tournament-utils.test.ts
+++ b/app/features/tournament/tournament-utils.test.ts
@@ -1,6 +1,330 @@
import { describe, expect, it } from "vitest";
import type { ParsedBracket } from "../tournament-bracket/core/Progression";
-import { getBracketProgressionLabel } from "./tournament-utils";
+import {
+ compareTeamsForOrdering,
+ findTeamInsertPosition,
+ getBracketProgressionLabel,
+ sortTeamsBySeeding,
+ type TeamForOrdering,
+} from "./tournament-utils";
+
+const createTeam = (
+ id: number,
+ options: {
+ seed?: number | null;
+ members?: number;
+ avgSeedingSkillOrdinal?: number | null;
+ createdAt?: number;
+ startingBracketIdx?: number | null;
+ } = {},
+): TeamForOrdering => ({
+ id,
+ seed: options.seed ?? null,
+ members: { length: options.members ?? 4 },
+ avgSeedingSkillOrdinal: options.avgSeedingSkillOrdinal ?? 100,
+ createdAt: options.createdAt ?? id,
+ startingBracketIdx: options.startingBracketIdx ?? null,
+});
+
+const MIN_MEMBERS = 4;
+
+describe("compareTeamsForOrdering", () => {
+ describe("full teams priority", () => {
+ it("places full teams before not-full teams", () => {
+ const fullTeam = createTeam(1, { members: 4 });
+ const notFullTeam = createTeam(2, { members: 3 });
+
+ const result = compareTeamsForOrdering(
+ fullTeam,
+ notFullTeam,
+ MIN_MEMBERS,
+ );
+
+ expect(result).toBeLessThan(0);
+ });
+
+ it("places not-full teams after full teams", () => {
+ const notFullTeam = createTeam(1, { members: 3 });
+ const fullTeam = createTeam(2, { members: 4 });
+
+ const result = compareTeamsForOrdering(
+ notFullTeam,
+ fullTeam,
+ MIN_MEMBERS,
+ );
+
+ expect(result).toBeGreaterThan(0);
+ });
+ });
+
+ describe("seed priority", () => {
+ it("orders by seed when both have seeds", () => {
+ const team1 = createTeam(1, { seed: 1 });
+ const team2 = createTeam(2, { seed: 2 });
+
+ const result = compareTeamsForOrdering(team1, team2, MIN_MEMBERS);
+
+ expect(result).toBeLessThan(0);
+ });
+
+ it("places seeded team before unseeded team when unseeded has no skill", () => {
+ const seededTeam = createTeam(1, { seed: 5 });
+ const unseededTeam = createTeam(2);
+
+ const result = compareTeamsForOrdering(
+ seededTeam,
+ unseededTeam,
+ MIN_MEMBERS,
+ );
+
+ expect(result).toBeLessThan(0);
+ });
+
+ it("compares by skill ordinal when both full teams have skill but only one has seed", () => {
+ const seededLowSkill = createTeam(1, {
+ seed: 5,
+ avgSeedingSkillOrdinal: 100,
+ });
+ const unseededHighSkill = createTeam(2, { avgSeedingSkillOrdinal: 300 });
+
+ const result = compareTeamsForOrdering(
+ seededLowSkill,
+ unseededHighSkill,
+ MIN_MEMBERS,
+ );
+
+ expect(result).toBeGreaterThan(0);
+ });
+
+ it("places seeded team first when only seeded team has skill ordinal", () => {
+ const seededWithSkill = createTeam(1, {
+ seed: 5,
+ avgSeedingSkillOrdinal: 100,
+ });
+ const unseededNoSkill = createTeam(2);
+
+ const result = compareTeamsForOrdering(
+ seededWithSkill,
+ unseededNoSkill,
+ MIN_MEMBERS,
+ );
+
+ expect(result).toBeLessThan(0);
+ });
+
+ it("places seeded team first when not-full team has higher skill", () => {
+ const seededFull = createTeam(1, {
+ seed: 5,
+ avgSeedingSkillOrdinal: 100,
+ });
+ const unseededNotFull = createTeam(2, {
+ members: 3,
+ avgSeedingSkillOrdinal: 500,
+ });
+
+ const result = compareTeamsForOrdering(
+ seededFull,
+ unseededNotFull,
+ MIN_MEMBERS,
+ );
+
+ expect(result).toBeLessThan(0);
+ });
+ });
+
+ describe("skill ordinal priority", () => {
+ it("orders by skill ordinal when no seeds (higher skill first)", () => {
+ const highSkill = createTeam(1, { avgSeedingSkillOrdinal: 300 });
+ const lowSkill = createTeam(2, { avgSeedingSkillOrdinal: 100 });
+
+ const result = compareTeamsForOrdering(highSkill, lowSkill, MIN_MEMBERS);
+
+ expect(result).toBeLessThan(0);
+ });
+
+ it("places team with skill before team without skill", () => {
+ const withSkill = createTeam(1, { avgSeedingSkillOrdinal: 100 });
+ const withoutSkill = createTeam(2);
+
+ const result = compareTeamsForOrdering(
+ withSkill,
+ withoutSkill,
+ MIN_MEMBERS,
+ );
+
+ expect(result).toBeLessThan(0);
+ });
+ });
+
+ describe("createdAt tiebreaker", () => {
+ it("orders by createdAt when all else is equal", () => {
+ const olderTeam = createTeam(1, { createdAt: 100 });
+ const newerTeam = createTeam(2, { createdAt: 200 });
+
+ const result = compareTeamsForOrdering(olderTeam, newerTeam, MIN_MEMBERS);
+
+ expect(result).toBeLessThan(0);
+ });
+ });
+});
+
+describe("sortTeamsBySeeding", () => {
+ it("sorts teams correctly with mixed properties", () => {
+ const teams = [
+ createTeam(1, { members: 3, avgSeedingSkillOrdinal: 500 }),
+ createTeam(2, { seed: 2 }),
+ createTeam(3, { avgSeedingSkillOrdinal: 300 }),
+ createTeam(4, { seed: 1 }),
+ createTeam(5, { avgSeedingSkillOrdinal: 400 }),
+ createTeam(6, { members: 3 }),
+ ];
+
+ const sorted = sortTeamsBySeeding(teams, MIN_MEMBERS);
+
+ expect(sorted.map((t) => t.id)).toEqual([5, 3, 4, 2, 1, 6]);
+ });
+
+ it("does not mutate original array", () => {
+ const teams = [
+ createTeam(2, { avgSeedingSkillOrdinal: 100 }),
+ createTeam(1, { avgSeedingSkillOrdinal: 200 }),
+ ];
+
+ sortTeamsBySeeding(teams, MIN_MEMBERS);
+
+ expect(teams[0].id).toBe(2);
+ });
+});
+
+describe("findTeamInsertPosition", () => {
+ it("inserts at beginning when new team should be first", () => {
+ const team1 = createTeam(1, { avgSeedingSkillOrdinal: 100 });
+ const team2 = createTeam(2, { avgSeedingSkillOrdinal: 200 });
+ const teamMap = new Map([
+ [1, team1],
+ [2, team2],
+ ]);
+ const existingOrder = [2, 1];
+ const newTeam = createTeam(3, { avgSeedingSkillOrdinal: 300 });
+
+ const position = findTeamInsertPosition(
+ existingOrder,
+ newTeam,
+ teamMap,
+ MIN_MEMBERS,
+ );
+
+ expect(position).toBe(0);
+ });
+
+ it("inserts at end when new team should be last", () => {
+ const team1 = createTeam(1, { avgSeedingSkillOrdinal: 100 });
+ const team2 = createTeam(2, { avgSeedingSkillOrdinal: 200 });
+ const teamMap = new Map([
+ [1, team1],
+ [2, team2],
+ ]);
+ const existingOrder = [2, 1];
+ const newTeam = createTeam(3, { avgSeedingSkillOrdinal: 50 });
+
+ const position = findTeamInsertPosition(
+ existingOrder,
+ newTeam,
+ teamMap,
+ MIN_MEMBERS,
+ );
+
+ expect(position).toBe(2);
+ });
+
+ it("inserts in middle based on comparison", () => {
+ const team1 = createTeam(1, { avgSeedingSkillOrdinal: 100 });
+ const team2 = createTeam(2, { avgSeedingSkillOrdinal: 300 });
+ const team3 = createTeam(3, { avgSeedingSkillOrdinal: 200 });
+ const teamMap = new Map([
+ [1, team1],
+ [2, team2],
+ [3, team3],
+ ]);
+ const existingOrder = [2, 3, 1];
+ const newTeam = createTeam(4, { avgSeedingSkillOrdinal: 150 });
+
+ const position = findTeamInsertPosition(
+ existingOrder,
+ newTeam,
+ teamMap,
+ MIN_MEMBERS,
+ );
+
+ expect(position).toBe(2);
+ });
+
+ it("handles empty existing order", () => {
+ const teamMap = new Map();
+ const existingOrder: number[] = [];
+ const newTeam = createTeam(1, { avgSeedingSkillOrdinal: 100 });
+
+ const position = findTeamInsertPosition(
+ existingOrder,
+ newTeam,
+ teamMap,
+ MIN_MEMBERS,
+ );
+
+ expect(position).toBe(0);
+ });
+
+ it("skips missing teams in map", () => {
+ const team1 = createTeam(1, { avgSeedingSkillOrdinal: 100 });
+ const teamMap = new Map([[1, team1]]);
+ const existingOrder = [2, 1];
+ const newTeam = createTeam(3, { avgSeedingSkillOrdinal: 150 });
+
+ const position = findTeamInsertPosition(
+ existingOrder,
+ newTeam,
+ teamMap,
+ MIN_MEMBERS,
+ );
+
+ expect(position).toBe(1);
+ });
+});
+
+describe("sortTeamsBySeeding with startingBracketIdx", () => {
+ it("orders by startingBracketIdx first", () => {
+ const teams = [
+ createTeam(1, {
+ startingBracketIdx: 1,
+ avgSeedingSkillOrdinal: 500,
+ }),
+ createTeam(2, {
+ startingBracketIdx: 0,
+ avgSeedingSkillOrdinal: 100,
+ }),
+ createTeam(3, {
+ startingBracketIdx: 0,
+ avgSeedingSkillOrdinal: 200,
+ }),
+ ];
+
+ const sorted = sortTeamsBySeeding(teams, MIN_MEMBERS);
+
+ expect(sorted.map((t) => t.id)).toEqual([3, 2, 1]);
+ });
+
+ it("uses seeds within same bracket", () => {
+ const teams = [
+ createTeam(1, { seed: 2 }),
+ createTeam(2, { seed: 1 }),
+ createTeam(3, { avgSeedingSkillOrdinal: 500 }),
+ ];
+
+ const sorted = sortTeamsBySeeding(teams, MIN_MEMBERS);
+
+ expect(sorted.map((t) => t.id)).toEqual([3, 2, 1]);
+ });
+});
const createBracket = (name: string): ParsedBracket => ({
name,
diff --git a/app/features/tournament/tournament-utils.ts b/app/features/tournament/tournament-utils.ts
index b381ebc80..49f0b730f 100644
--- a/app/features/tournament/tournament-utils.ts
+++ b/app/features/tournament/tournament-utils.ts
@@ -262,6 +262,75 @@ export function normalizedTeamCount({
return teamsCount * minMembersPerTeam;
}
+export type TeamForOrdering = {
+ id: number;
+ seed: number | null;
+ members: { length: number };
+ avgSeedingSkillOrdinal: number | null;
+ createdAt: number;
+ startingBracketIdx: number | null;
+};
+
+export function compareTeamsForOrdering(
+ a: TeamForOrdering,
+ b: TeamForOrdering,
+ minMembersPerTeam: number,
+): number {
+ if (a.startingBracketIdx !== b.startingBracketIdx) {
+ return (a.startingBracketIdx ?? 0) - (b.startingBracketIdx ?? 0);
+ }
+
+ const aIsFull = a.members.length >= minMembersPerTeam;
+ const bIsFull = b.members.length >= minMembersPerTeam;
+
+ if (aIsFull && !bIsFull) {
+ return -1;
+ }
+ if (!aIsFull && bIsFull) {
+ return 1;
+ }
+
+ if (a.seed !== null && b.seed !== null) {
+ return a.seed - b.seed;
+ }
+
+ if (
+ a.avgSeedingSkillOrdinal !== b.avgSeedingSkillOrdinal &&
+ a.avgSeedingSkillOrdinal !== null &&
+ b.avgSeedingSkillOrdinal !== null
+ ) {
+ return b.avgSeedingSkillOrdinal - a.avgSeedingSkillOrdinal;
+ }
+
+ return a.createdAt - b.createdAt;
+}
+
+export function sortTeamsBySeeding(
+ teams: T[],
+ minMembersPerTeam: number,
+): T[] {
+ return [...teams].sort((a, b) =>
+ compareTeamsForOrdering(a, b, minMembersPerTeam),
+ );
+}
+
+export function findTeamInsertPosition(
+ existingOrder: number[],
+ newTeam: T,
+ teamMap: Map,
+ minMembersPerTeam: number,
+): number {
+ for (let i = 0; i < existingOrder.length; i++) {
+ const existingTeam = teamMap.get(existingOrder[i]);
+ if (!existingTeam) continue;
+
+ if (compareTeamsForOrdering(newTeam, existingTeam, minMembersPerTeam) < 0) {
+ return i;
+ }
+ }
+ return existingOrder.length;
+}
+
export function getBracketProgressionLabel(
startingBracketIdx: number,
progression: ParsedBracket[],
diff --git a/db-test.sqlite3 b/db-test.sqlite3
index c5305ecce..4218d7744 100644
Binary files a/db-test.sqlite3 and b/db-test.sqlite3 differ
diff --git a/e2e/seeds/db-seed-DEFAULT.sqlite3 b/e2e/seeds/db-seed-DEFAULT.sqlite3
index 0367d9bd9..25a2acba7 100644
Binary files a/e2e/seeds/db-seed-DEFAULT.sqlite3 and b/e2e/seeds/db-seed-DEFAULT.sqlite3 differ
diff --git a/e2e/seeds/db-seed-NO_SCRIMS.sqlite3 b/e2e/seeds/db-seed-NO_SCRIMS.sqlite3
index 2c0111c4a..31b15d581 100644
Binary files a/e2e/seeds/db-seed-NO_SCRIMS.sqlite3 and b/e2e/seeds/db-seed-NO_SCRIMS.sqlite3 differ
diff --git a/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3 b/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3
index ef6f731c8..72a9bb566 100644
Binary files a/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3 and b/e2e/seeds/db-seed-NO_SQ_GROUPS.sqlite3 differ
diff --git a/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3 b/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3
index fb153a53e..28210be3e 100644
Binary files a/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3 and b/e2e/seeds/db-seed-NO_TOURNAMENT_TEAMS.sqlite3 differ
diff --git a/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3 b/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3
index d2f61d7b0..6252d2928 100644
Binary files a/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3 and b/e2e/seeds/db-seed-NZAP_IN_TEAM.sqlite3 differ
diff --git a/e2e/seeds/db-seed-REG_OPEN.sqlite3 b/e2e/seeds/db-seed-REG_OPEN.sqlite3
index e80c78b4c..760a39904 100644
Binary files a/e2e/seeds/db-seed-REG_OPEN.sqlite3 and b/e2e/seeds/db-seed-REG_OPEN.sqlite3 differ
diff --git a/e2e/seeds/db-seed-SMALL_SOS.sqlite3 b/e2e/seeds/db-seed-SMALL_SOS.sqlite3
index aa251a60d..b8c2fce4d 100644
Binary files a/e2e/seeds/db-seed-SMALL_SOS.sqlite3 and b/e2e/seeds/db-seed-SMALL_SOS.sqlite3 differ
diff --git a/e2e/tournament-bracket.spec.ts b/e2e/tournament-bracket.spec.ts
index bbb51f123..33a042588 100644
--- a/e2e/tournament-bracket.spec.ts
+++ b/e2e/tournament-bracket.spec.ts
@@ -33,13 +33,11 @@ const navigateToMatch = async (page: Page, matchId: number) => {
const reportResult = async ({
page,
amountOfMapsToReport,
- sidesWithMoreThanFourPlayers = ["last"],
winner = 1,
points,
}: {
page: Page;
amountOfMapsToReport: 1 | 2 | 3 | 4;
- sidesWithMoreThanFourPlayers?: ("first" | "last")[];
winner?: 1 | 2;
points?: [number, number];
}) => {
@@ -53,9 +51,12 @@ const reportResult = async ({
await page.getByTestId("actions-tab").click();
+ // Auto-detect and set rosters for teams with 5+ players
+ // Check if first team needs roster selection (checkbox exists and is not disabled)
+ const firstTeamCheckbox = page.getByTestId("player-checkbox-0").first();
if (
- sidesWithMoreThanFourPlayers.includes("first") &&
- !(await page.getByTestId("player-checkbox-0").first().isDisabled())
+ (await firstTeamCheckbox.count()) > 0 &&
+ !(await firstTeamCheckbox.isDisabled())
) {
await page.getByTestId("player-checkbox-0").first().click();
await page.getByTestId("player-checkbox-1").first().click();
@@ -67,9 +68,12 @@ const reportResult = async ({
// update went through
await expect(page.getByTestId("player-checkbox-0").first()).toBeDisabled();
}
+
+ // Check if second team needs roster selection
+ const lastTeamCheckbox = page.getByTestId("player-checkbox-0").last();
if (
- sidesWithMoreThanFourPlayers.includes("last") &&
- !(await page.getByTestId("player-checkbox-0").last().isDisabled())
+ (await lastTeamCheckbox.count()) > 0 &&
+ !(await lastTeamCheckbox.isDisabled())
) {
await page.getByTestId("player-checkbox-0").last().click();
await page.getByTestId("player-checkbox-1").last().click();
@@ -139,6 +143,8 @@ const expectScore = (page: Page, score: [number, number]) =>
test.describe("Tournament bracket", () => {
test("sets active roster as regular member", async ({ page }) => {
const tournamentId = 1;
+ // User 37 is owner of team 10 (seed 10) which has 5 players
+ // Team 10 vs Team 9 (seed 9) is match 2 in WB Round 1
const matchId = 2;
await startBracket(page, tournamentId);
@@ -147,10 +153,13 @@ test.describe("Tournament bracket", () => {
page,
url: tournamentMatchPage({ tournamentId, matchId }),
});
+
await expect(page.getByTestId("active-roster-needed-text")).toBeVisible();
await page.getByTestId("actions-tab").click();
+ // Team 10 has 5 players; select first 4 for active roster
+ // Team 10 is team 2 (second team in the match), so use last()
await page.getByTestId("player-checkbox-0").last().click();
await page.getByTestId("player-checkbox-1").last().click();
await page.getByTestId("player-checkbox-2").last().click();
@@ -163,6 +172,7 @@ test.describe("Tournament bracket", () => {
page,
url: tournamentMatchPage({ tournamentId, matchId }),
});
+ // Only team 10 needed to set roster (team 9 has 4 players)
await isNotVisible(page.getByTestId("active-roster-needed-text"));
await page.getByTestId("actions-tab").click();
@@ -214,7 +224,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 1,
- sidesWithMoreThanFourPlayers: ["first", "last"],
});
await backToBracket(page);
@@ -246,7 +255,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
winner: 2,
});
await backToBracket(page);
@@ -323,7 +331,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: [],
});
await backToBracket(page);
@@ -394,7 +401,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["first", "last"],
points: [100, 0],
});
await backToBracket(page);
@@ -434,7 +440,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 3,
- sidesWithMoreThanFourPlayers: ["first", "last"],
});
await navigate({
@@ -448,7 +453,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 3,
- sidesWithMoreThanFourPlayers: ["first", "last"],
});
await backToBracket(page);
@@ -511,7 +515,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: [],
points: [100, 0],
});
await backToBracket(page);
@@ -635,7 +638,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["first"],
points: [100, 0],
});
@@ -699,7 +701,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
points: [100, 0],
});
await backToBracket(page);
@@ -710,7 +711,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["first"],
points: [100, 0],
});
await backToBracket(page);
@@ -719,7 +719,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
points: [100, 0],
});
await backToBracket(page);
@@ -728,7 +727,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
points: [100, 0],
});
await backToBracket(page);
@@ -739,7 +737,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["first"],
points: [0, 100],
winner: 2,
});
@@ -770,7 +767,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
points: [100, 0],
});
await backToBracket(page);
@@ -779,7 +775,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["first", "last"],
points: [100, 0],
});
await backToBracket(page);
@@ -790,7 +785,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 1,
- sidesWithMoreThanFourPlayers: ["last"],
points: [100, 0],
});
await backToBracket(page);
@@ -843,7 +837,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
});
await backToBracket(page);
@@ -855,7 +848,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
});
await backToBracket(page);
@@ -890,7 +882,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: ["last"],
});
await page.getByTestId("admin-tab").click();
@@ -962,7 +953,6 @@ test.describe("Tournament bracket", () => {
page,
amountOfMapsToReport: 3,
points: [100, 0],
- sidesWithMoreThanFourPlayers: ["last"],
winner: 1,
});
});
@@ -989,7 +979,6 @@ test.describe("Tournament bracket", () => {
await reportResult({
page,
amountOfMapsToReport: 2,
- sidesWithMoreThanFourPlayers: id === 1 ? [] : ["last"],
});
await backToBracket(page);
}
diff --git a/e2e/tournament.spec.ts b/e2e/tournament.spec.ts
index 47939062d..1494c346e 100644
--- a/e2e/tournament.spec.ts
+++ b/e2e/tournament.spec.ts
@@ -255,7 +255,7 @@ test.describe("Tournament", () => {
url: `${tournamentPage(1)}/seeds`,
});
- await page.getByTestId("seed-team-1").hover();
+ await page.getByTestId("seed-team-1-handle").hover();
await page.mouse.down();
// i think the drag & drop library might actually be a bit buggy
// so we have to do it in steps like this to allow for testing
diff --git a/migrations/111-seeding-snapshot.js b/migrations/111-seeding-snapshot.js
new file mode 100644
index 000000000..020ff1b11
--- /dev/null
+++ b/migrations/111-seeding-snapshot.js
@@ -0,0 +1,7 @@
+export function up(db) {
+ db.transaction(() => {
+ db.prepare(
+ /* sql */ `alter table "Tournament" add "seedingSnapshot" text default null`,
+ ).run();
+ })();
+}