206 lines
7.9 KiB
TypeScript
206 lines
7.9 KiB
TypeScript
|
|
import { describe, it, expect } from "vitest";
|
|||
|
|
import { NCAA_68, getScoringRoundType } from "~/lib/bracket-templates";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* NCAA 68 Bracket Unit Tests - Phase 2.8
|
|||
|
|
*
|
|||
|
|
* Tests the NCAA 68 tournament template structure and scoring logic:
|
|||
|
|
* - 68 teams total (60 direct seeds + 8 in First Four)
|
|||
|
|
* - First Four: 4 play-in games (8 teams)
|
|||
|
|
* - Round of 64: 32 games
|
|||
|
|
* - Only Elite Eight and beyond score fantasy points
|
|||
|
|
*/
|
|||
|
|
describe("NCAA 68 Bracket Template - Phase 2.8", () => {
|
|||
|
|
describe("Template Structure", () => {
|
|||
|
|
it("has correct total teams", () => {
|
|||
|
|
expect(NCAA_68.totalTeams).toBe(68);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("has all 7 rounds", () => {
|
|||
|
|
expect(NCAA_68.rounds).toHaveLength(7);
|
|||
|
|
expect(NCAA_68.rounds[0].name).toBe("First Four");
|
|||
|
|
expect(NCAA_68.rounds[1].name).toBe("Round of 64");
|
|||
|
|
expect(NCAA_68.rounds[2].name).toBe("Round of 32");
|
|||
|
|
expect(NCAA_68.rounds[3].name).toBe("Sweet Sixteen");
|
|||
|
|
expect(NCAA_68.rounds[4].name).toBe("Elite Eight");
|
|||
|
|
expect(NCAA_68.rounds[5].name).toBe("Final Four");
|
|||
|
|
expect(NCAA_68.rounds[6].name).toBe("Championship");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("has correct match counts per round", () => {
|
|||
|
|
expect(NCAA_68.rounds[0].matchCount).toBe(4); // First Four
|
|||
|
|
expect(NCAA_68.rounds[1].matchCount).toBe(32); // Round of 64
|
|||
|
|
expect(NCAA_68.rounds[2].matchCount).toBe(16); // Round of 32
|
|||
|
|
expect(NCAA_68.rounds[3].matchCount).toBe(8); // Sweet Sixteen
|
|||
|
|
expect(NCAA_68.rounds[4].matchCount).toBe(4); // Elite Eight (Quarterfinals)
|
|||
|
|
expect(NCAA_68.rounds[5].matchCount).toBe(2); // Final Four (Semifinals)
|
|||
|
|
expect(NCAA_68.rounds[6].matchCount).toBe(1); // Championship (Finals)
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("has correct round feeding structure", () => {
|
|||
|
|
expect(NCAA_68.rounds[0].feedsInto).toBe("Round of 64");
|
|||
|
|
expect(NCAA_68.rounds[1].feedsInto).toBe("Round of 32");
|
|||
|
|
expect(NCAA_68.rounds[2].feedsInto).toBe("Sweet Sixteen");
|
|||
|
|
expect(NCAA_68.rounds[3].feedsInto).toBe("Elite Eight");
|
|||
|
|
expect(NCAA_68.rounds[4].feedsInto).toBe("Final Four");
|
|||
|
|
expect(NCAA_68.rounds[5].feedsInto).toBe("Championship");
|
|||
|
|
expect(NCAA_68.rounds[6].feedsInto).toBeNull(); // Championship has no next round
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe("Scoring Configuration", () => {
|
|||
|
|
it("marks scoring to start at Elite Eight", () => {
|
|||
|
|
expect(NCAA_68.scoringStartsAtRound).toBe("Elite Eight");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("marks First Four as non-scoring", () => {
|
|||
|
|
const firstFour = NCAA_68.rounds[0];
|
|||
|
|
expect(firstFour.name).toBe("First Four");
|
|||
|
|
expect(firstFour.isScoring).toBe(false);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("marks Round of 64 as non-scoring", () => {
|
|||
|
|
const roundOf64 = NCAA_68.rounds[1];
|
|||
|
|
expect(roundOf64.name).toBe("Round of 64");
|
|||
|
|
expect(roundOf64.isScoring).toBe(false);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("marks Round of 32 as non-scoring", () => {
|
|||
|
|
const roundOf32 = NCAA_68.rounds[2];
|
|||
|
|
expect(roundOf32.name).toBe("Round of 32");
|
|||
|
|
expect(roundOf32.isScoring).toBe(false);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("marks Sweet Sixteen as non-scoring", () => {
|
|||
|
|
const sweetSixteen = NCAA_68.rounds[3];
|
|||
|
|
expect(sweetSixteen.name).toBe("Sweet Sixteen");
|
|||
|
|
expect(sweetSixteen.isScoring).toBe(false);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("marks Elite Eight as scoring (Quarterfinals)", () => {
|
|||
|
|
const eliteEight = NCAA_68.rounds[4];
|
|||
|
|
expect(eliteEight.name).toBe("Elite Eight");
|
|||
|
|
expect(eliteEight.isScoring).toBe(true);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("marks Final Four as scoring (Semifinals)", () => {
|
|||
|
|
const finalFour = NCAA_68.rounds[5];
|
|||
|
|
expect(finalFour.name).toBe("Final Four");
|
|||
|
|
expect(finalFour.isScoring).toBe(true);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("marks Championship as scoring (Finals)", () => {
|
|||
|
|
const championship = NCAA_68.rounds[6];
|
|||
|
|
expect(championship.name).toBe("Championship");
|
|||
|
|
expect(championship.isScoring).toBe(true);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("has exactly 3 scoring rounds (Elite Eight, Final Four, Championship)", () => {
|
|||
|
|
const scoringRounds = NCAA_68.rounds.filter((r) => r.isScoring);
|
|||
|
|
expect(scoringRounds).toHaveLength(3);
|
|||
|
|
expect(scoringRounds[0].name).toBe("Elite Eight");
|
|||
|
|
expect(scoringRounds[1].name).toBe("Final Four");
|
|||
|
|
expect(scoringRounds[2].name).toBe("Championship");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("has exactly 4 non-scoring rounds (FF, R64, R32, S16)", () => {
|
|||
|
|
const nonScoringRounds = NCAA_68.rounds.filter((r) => !r.isScoring);
|
|||
|
|
expect(nonScoringRounds).toHaveLength(4);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe("Scoring Round Types", () => {
|
|||
|
|
it("identifies Elite Eight as quarterfinals", () => {
|
|||
|
|
const type = getScoringRoundType("Elite Eight", NCAA_68);
|
|||
|
|
expect(type).toBe("quarterfinals");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("identifies Final Four as semifinals", () => {
|
|||
|
|
const type = getScoringRoundType("Final Four", NCAA_68);
|
|||
|
|
expect(type).toBe("semifinals");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("identifies Championship as finals", () => {
|
|||
|
|
const type = getScoringRoundType("Championship", NCAA_68);
|
|||
|
|
expect(type).toBe("finals");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("returns null for non-scoring rounds", () => {
|
|||
|
|
expect(getScoringRoundType("First Four", NCAA_68)).toBeNull();
|
|||
|
|
expect(getScoringRoundType("Round of 64", NCAA_68)).toBeNull();
|
|||
|
|
expect(getScoringRoundType("Round of 32", NCAA_68)).toBeNull();
|
|||
|
|
expect(getScoringRoundType("Sweet Sixteen", NCAA_68)).toBeNull();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe("Tournament Math", () => {
|
|||
|
|
it("has correct number of total matches", () => {
|
|||
|
|
// 4 + 32 + 16 + 8 + 4 + 2 + 1 = 67 total matches
|
|||
|
|
const totalMatches = NCAA_68.rounds.reduce((sum, round) => sum + round.matchCount, 0);
|
|||
|
|
expect(totalMatches).toBe(67);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("eliminates 60 teams before Elite Eight (4+32+16+8)", () => {
|
|||
|
|
const nonScoringRounds = NCAA_68.rounds.filter((r) => !r.isScoring);
|
|||
|
|
const teamsEliminatedBeforeEliteEight = nonScoringRounds.reduce(
|
|||
|
|
(sum, round) => sum + round.matchCount,
|
|||
|
|
0
|
|||
|
|
);
|
|||
|
|
expect(teamsEliminatedBeforeEliteEight).toBe(60); // 4+32+16+8
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("has 8 teams in Elite Eight (top 8 scoring)", () => {
|
|||
|
|
const eliteEightRound = NCAA_68.rounds.find((r) => r.name === "Elite Eight");
|
|||
|
|
const teamsInEliteEight = eliteEightRound!.matchCount * 2;
|
|||
|
|
expect(teamsInEliteEight).toBe(8);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("verifies only 8 teams score fantasy points (Q18)", () => {
|
|||
|
|
// Elite Eight has 4 matches = 8 teams
|
|||
|
|
// These are the ONLY teams that can score fantasy points
|
|||
|
|
const scoringRounds = NCAA_68.rounds.filter((r) => r.isScoring);
|
|||
|
|
const eliteEightMatches = scoringRounds[0].matchCount;
|
|||
|
|
const scoringTeamsCount = eliteEightMatches * 2;
|
|||
|
|
expect(scoringTeamsCount).toBe(8);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
describe("Phase 2.8 Requirements", () => {
|
|||
|
|
it("meets requirement: 68 total teams", () => {
|
|||
|
|
expect(NCAA_68.totalTeams).toBe(68);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("meets requirement: 4 First Four play-in games", () => {
|
|||
|
|
const firstFour = NCAA_68.rounds[0];
|
|||
|
|
expect(firstFour.matchCount).toBe(4);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("meets requirement: Only Elite Eight and beyond score points", () => {
|
|||
|
|
const scoringRoundNames = NCAA_68.rounds
|
|||
|
|
.filter((r) => r.isScoring)
|
|||
|
|
.map((r) => r.name);
|
|||
|
|
expect(scoringRoundNames).toEqual(["Elite Eight", "Final Four", "Championship"]);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("meets requirement: Early elimination = 0 points (per Q20)", () => {
|
|||
|
|
const firstFour = NCAA_68.rounds[0];
|
|||
|
|
const roundOf64 = NCAA_68.rounds[1];
|
|||
|
|
const roundOf32 = NCAA_68.rounds[2];
|
|||
|
|
const sweetSixteen = NCAA_68.rounds[3];
|
|||
|
|
|
|||
|
|
expect(firstFour.isScoring).toBe(false); // 0 points
|
|||
|
|
expect(roundOf64.isScoring).toBe(false); // 0 points
|
|||
|
|
expect(roundOf32.isScoring).toBe(false); // 0 points
|
|||
|
|
expect(sweetSixteen.isScoring).toBe(false); // 0 points
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it("verifies total participants: 60 direct + 8 First Four", () => {
|
|||
|
|
const firstFourTeams = 4 * 2; // 4 games × 2 teams = 8 teams
|
|||
|
|
const directSeeds = 68 - firstFourTeams; // 60 teams directly seeded
|
|||
|
|
expect(directSeeds).toBe(60);
|
|||
|
|
expect(firstFourTeams).toBe(8);
|
|||
|
|
expect(directSeeds + firstFourTeams).toBe(68);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|