# League Pages Testing Strategy

## 1. API Tests

### League Discovery (`/leagues/all-with-capacity-and-scoring`)
- **Data Returned**: List of leagues with capacity, scoring summary, and basic info.
- **Validation Rules**:
    - `totalCount` must match array length.
    - `usedSlots` must be <= `maxDrivers`.
    - `scoring` object must contain `gameId` and `scoringPresetId`.
- **Edge Cases**:
    - Empty league list.
    - Leagues with 0 capacity.
    - Leagues with missing scoring config.

### League Detail (`/leagues/{leagueId}`)
- **Data Returned**: Comprehensive league details including stats and status.
- **Validation Rules**:
    - `id` must match requested ID.
    - `rating` should be a number between 0-100 (if present).
    - `seasonStatus` must be one of the valid enum values.
- **Edge Cases**:
    - Invalid `leagueId`.
    - Private league access (should return 403/404).

### League Schedule (`/leagues/{leagueId}/schedule`)
- **Data Returned**: List of races for the current/specified season.
- **Validation Rules**:
    - Races must be sorted by `scheduledAt`.
    - Each race must have a `track` and `car`.
- **Edge Cases**:
    - Season with no races.
    - Unpublished schedule (check visibility for non-admins).

### League Standings (`/leagues/{leagueId}/standings`)
- **Data Returned**: Driver standings with points, positions, and stats.
- **Validation Rules**:
    - `position` must be sequential starting from 1.
    - `points` must be non-negative.
    - `races` count must be <= total completed races in league.
- **Edge Cases**:
    - Tie in points (check tie-breaking logic).
    - Drivers with 0 points.
    - Empty standings (new season).

### League Roster (`/leagues/{leagueId}/memberships`)
- **Data Returned**: List of members and their roles.
- **Validation Rules**:
    - At least one 'owner' must exist.
    - `joinedAt` must be a valid ISO date.
- **Edge Cases**:
    - League with only an owner.

---

## 2. E2E Tests for League Pages

### `/leagues` (Discovery)
- **Click Path**: Home -> "Leagues" in Nav.
- **Validation**:
    - Verify league cards display correct `usedSlots` vs `maxDrivers`.
    - Verify "Join" button visibility based on capacity and membership status.

### `/leagues/[id]` (Overview)
- **Click Path**: League Card -> Click Title.
- **Validation**:
    - Verify "Stats" (Members, Races, Avg SOF) match API values.
    - Verify "Next Race" widget shows the correct upcoming race.
    - Verify "Season Progress" bar reflects completed vs total races.

### `/leagues/[id]/schedule` (Schedule)
- **Click Path**: League Detail -> "Schedule" Tab.
- **Validation**:
    - Verify race list matches API `/schedule` endpoint.
    - Verify "Register" button state for upcoming races.

### `/leagues/[id]/standings` (Standings)
- **Click Path**: League Detail -> "Standings" Tab.
- **Validation**:
    - Verify table rows match API `/standings` data.
    - Verify current user is highlighted (if logged in and in standings).
    - **Critical**: Cross-check total points in UI with sum of race points (if available).

---

## 3. Unit Tests for ViewDataBuilders

### `LeagueDetailViewDataBuilder`
- **Transformations**: Aggregates league, owner, and race data into a flat view model.
- **Validation**:
    - `avgSOF` calculation logic (ignoring 0/null SOF).
    - `seasonProgress` percentage calculation.
    - Role badge assignment (Owner vs Admin vs Steward).
- **Edge Cases**:
    - Missing owner data.
    - No races scheduled.

### `LeagueStandingsViewDataBuilder`
- **Transformations**: Maps `LeagueStandingDTO` to `StandingEntryData`.
- **Validation**:
    - Correct mapping of `points` to `totalPoints`.
    - Handling of `positionChange` (up/down/stable).
    - Driver metadata mapping (name, country).
- **Edge Cases**:
    - Missing driver objects in standings DTO.
    - Empty standings array.

### `LeagueScheduleViewDataBuilder`
- **Transformations**: Groups races by status or month.
- **Validation**:
    - Date formatting for UI.
    - "Live" status detection based on current time.
- **Edge Cases**:
    - Races exactly at "now".
