refactor(itinerary): extract reordering logic into pure functions
Extract all itinerary reordering logic from ItineraryTableViewController into ItineraryReorderingLogic.swift for testability. Key changes: - Add flattenDays, dayNumber, travelRow, simulateMove pure functions - Add calculateSortOrder with proper region classification (before/after games) - Add computeValidDestinationRowsProposed with simulation+validation pattern - Add coordinate space conversion helpers (proposedToOriginal, originalToProposed) - Fix DragZones coordinate space mismatch (was mixing proposed/original indices) - Add comprehensive documentation of coordinate space conventions Test coverage includes: - Row flattening order and semantic travel model - Sort order calculation for before/after games regions - Travel constraints validation - DragZones coordinate space correctness - Coordinate conversion helpers - Edge cases (empty days, multi-day trips) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
67
SportsTimeTests/Features/Trip/ItineraryEdgeCaseTests.swift
Normal file
67
SportsTimeTests/Features/Trip/ItineraryEdgeCaseTests.swift
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// ItineraryEdgeCaseTests.swift
|
||||
// SportsTimeTests
|
||||
//
|
||||
// Tests for edge cases in itinerary display and manipulation.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import SportsTime
|
||||
|
||||
private typealias H = ItineraryTestHelpers
|
||||
|
||||
final class ItineraryEdgeCaseTests: XCTestCase {
|
||||
|
||||
private let testDate = H.testDate
|
||||
|
||||
// MARK: - Empty/Minimal Day Tests
|
||||
|
||||
func test_emptyDay_onlyShowsHeader() {
|
||||
// Given: A day with no games and no items
|
||||
let dayData = ItineraryDayData(id: 1, dayNumber: 1, date: testDate, games: [], items: [], travelBefore: nil)
|
||||
|
||||
let controller = ItineraryTableViewController(style: .plain)
|
||||
controller.reloadData(days: [dayData], travelValidRanges: [:])
|
||||
|
||||
let rowCount = controller.tableView(controller.tableView, numberOfRowsInSection: 0)
|
||||
XCTAssertEqual(rowCount, 1, "Empty day should only have header row")
|
||||
}
|
||||
|
||||
func test_restDay_withTravelBefore_onlyShowsHeader() {
|
||||
// Given: A rest day with travelBefore set (legacy field)
|
||||
// Semantic model: travelBefore is IGNORED - travel must be in items to appear
|
||||
let travel = H.makeTravelSegment(from: "Chicago", to: "Detroit")
|
||||
let dayData = ItineraryDayData(id: 1, dayNumber: 1, date: testDate, games: [], items: [], travelBefore: travel)
|
||||
|
||||
let controller = ItineraryTableViewController(style: .plain)
|
||||
controller.reloadData(days: [dayData], travelValidRanges: [:])
|
||||
|
||||
let rowCount = controller.tableView(controller.tableView, numberOfRowsInSection: 0)
|
||||
XCTAssertEqual(rowCount, 1, "travelBefore is ignored - only header should appear")
|
||||
}
|
||||
|
||||
func test_singleGameDay_showsHeaderAndGame() {
|
||||
// Given: A day with one game
|
||||
let games = [H.makeRichGame(city: "Detroit", hour: 19)]
|
||||
let dayData = ItineraryDayData(id: 1, dayNumber: 1, date: testDate, games: games, items: [], travelBefore: nil)
|
||||
|
||||
let controller = ItineraryTableViewController(style: .plain)
|
||||
controller.reloadData(days: [dayData], travelValidRanges: [:])
|
||||
|
||||
let rowCount = controller.tableView(controller.tableView, numberOfRowsInSection: 0)
|
||||
XCTAssertEqual(rowCount, 2, "Day with one game should have 2 rows: header + games")
|
||||
}
|
||||
|
||||
// MARK: - Multi-Day Trip Tests
|
||||
|
||||
func test_multiDayTrip_allDaysRepresented() {
|
||||
// Given: A 5-day trip
|
||||
let days = H.makeDays(count: 5)
|
||||
|
||||
let controller = ItineraryTableViewController(style: .plain)
|
||||
controller.reloadData(days: days, travelValidRanges: [:])
|
||||
|
||||
let rowCount = controller.tableView(controller.tableView, numberOfRowsInSection: 0)
|
||||
XCTAssertEqual(rowCount, 5, "5-day trip with empty days should have 5 header rows")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user