--- phase: 03-visual-flattening plan: 02 type: execute wave: 2 depends_on: ["03-01"] files_modified: - SportsTimeTests/ItineraryFlattenerTests.swift autonomous: true must_haves: truths: - "Same semantic state produces identical row order on repeated flattening" - "Item with sortOrder -1.0 appears before all games in that day" - "Reordering an item and re-flattening preserves the new order" artifacts: - path: "SportsTimeTests/ItineraryFlattenerTests.swift" provides: "Determinism and ordering tests" min_lines: 80 key_links: - from: "ItineraryFlattenerTests" to: "ItineraryFlattener.flatten()" via: "test assertions" pattern: "ItineraryFlattener\\.flatten" --- Add tests verifying ItineraryFlattener produces deterministic, sortOrder-based output. Purpose: Ensure the three success criteria from ROADMAP.md are verifiable through automated tests. Output: New test file `ItineraryFlattenerTests.swift` with tests covering all success criteria. @~/.claude/get-shit-done/workflows/execute-plan.md @~/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/03-visual-flattening/03-RESEARCH.md @.planning/phases/03-visual-flattening/03-01-SUMMARY.md @SportsTime/Core/Models/Domain/ItineraryFlattener.swift @SportsTime/Core/Models/Domain/SortOrderProvider.swift @SportsTimeTests/ItineraryConstraintsTests.swift Task 1: Create ItineraryFlattenerTests with determinism tests SportsTimeTests/ItineraryFlattenerTests.swift Create a new test file `ItineraryFlattenerTests.swift` using Swift Testing (`@Suite`, `@Test`). Test suite structure: ```swift import Testing @testable import SportsTime @Suite("ItineraryFlattener") struct ItineraryFlattenerTests { // Test helper to create mock ItineraryDayData // Test helper to create mock RichGame // Test helper to create mock ItineraryItem } ``` Required tests (map directly to ROADMAP success criteria): 1. **success_negativeSortOrderAppearsBeforeGames** (Success Criterion 1) - Create item with sortOrder = -1.0 - Create games with sortOrder ~820 (noon game) - Flatten and verify custom item index < games index - Assert: "Item with sortOrder -1.0 appears before all games in that day's section" 2. **success_sameStateProducesIdenticalOrder** (Success Criterion 2) - Create fixed test data (2 days, games, travel, custom items) - Flatten twice - Compare resulting row IDs - Assert: arrays are identical (not just equal length) 3. **success_reorderPreservesNewOrder** (Success Criterion 3) - Create items with sortOrder 1.0, 2.0, 3.0 - Simulate reorder: change item from 1.0 to 2.5 - Flatten - Verify new order is [2.0, 2.5, 3.0] not [1.0, 2.0, 3.0] Additional tests for comprehensive coverage: 4. **flatten_dayHeaderAlwaysFirst** - Verify first item for each day is `.dayHeader` 5. **flatten_sortsByDayThenSortOrder** - Items on day 1 appear before items on day 2 - Within each day, items sorted by sortOrder 6. **flatten_gamesGetSortOrderFromTime** - Game at 8:00 PM (sortOrder ~1180) appears after item with sortOrder 500 - Game at 1:00 PM (sortOrder ~880) appears before item with sortOrder 1000 7. **flatten_emptyDayHasOnlyHeader** - Day with no games, no items produces only `.dayHeader` row 8. **flatten_multipleGamesOnSameDay** - Day with 2 games: both included in single `.games` row - Custom items around games sort correctly Test helpers needed: - `makeGame(id:, stadium:, dateTime:)` -> RichGame - `makeItem(day:, sortOrder:, kind:)` -> ItineraryItem - `makeDayData(dayNumber:, date:, games:, items:)` -> ItineraryDayData Run tests: `xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' -only-testing:SportsTimeTests/ItineraryFlattenerTests test 2>&1 | grep -E "(Test Suite|passed|failed|error:)"` `ItineraryFlattenerTests.swift` exists with: - 3 success_* tests mapping to ROADMAP success criteria - 5+ additional tests for comprehensive coverage - All tests passing Task 2: Verify existing behavior unchanged SportsTimeTests/ItineraryFlattenerTests.swift Add integration-style tests that verify the refactored flattening produces expected behavior for realistic trip data. Additional tests: 1. **flatten_travelWithNegativeSortOrderAppearsBeforeGames** - Travel item with sortOrder = -5.0 - Should appear before games in same day 2. **flatten_travelWithPositiveSortOrderAppearsAfterGames** - Travel item with sortOrder = 1500.0 (after noon game) - Should appear after games in same day 3. **flatten_mixedItemTypes** - Day with: travel (-5), custom (-1), games (820), custom (900), travel (1500) - Verify exact order: header, travel, custom, games, custom, travel 4. **flatten_multiDayTrip** - 3-day trip with different item configurations per day - Verify each day's items are independent and sorted correctly Run full test suite to ensure no regressions: `xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' test` Full test suite passes: `xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' test 2>&1 | grep -E "(Test Suite|passed|failed)" | tail -10` - All ItineraryFlattenerTests passing (12+ tests) - Full test suite passes (no regressions) - Tests cover all three ROADMAP success criteria 1. All tests in `ItineraryFlattenerTests.swift` pass 2. Tests explicitly named `success_*` map to ROADMAP success criteria: - success_negativeSortOrderAppearsBeforeGames -> Criterion 1 - success_sameStateProducesIdenticalOrder -> Criterion 2 - success_reorderPreservesNewOrder -> Criterion 3 3. Full test suite passes (no regressions from refactoring) - FLAT-02: Flattening is deterministic and stateless (verified by success_sameStateProducesIdenticalOrder test) - All three ROADMAP success criteria have corresponding tests After completion, create `.planning/phases/03-visual-flattening/03-02-SUMMARY.md`