- Add PlanningTips data model with 105 tips across 7 categories - Wire random tips into HomeView (3 tips per session) - Add TripOptionsGrouper for grouping by city/game count and mileage - Update TripOptionsView with sectioned display when sorting - Recommended and Best Efficiency remain flat lists Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
96 lines
3.2 KiB
Swift
96 lines
3.2 KiB
Swift
//
|
|
// TripOptionsGroupingTests.swift
|
|
// SportsTimeTests
|
|
//
|
|
|
|
import Testing
|
|
@testable import SportsTime
|
|
|
|
struct TripOptionsGroupingTests {
|
|
|
|
// Helper to create mock ItineraryOption
|
|
private func makeOption(stops: [(city: String, games: [String])], totalMiles: Double = 500) -> ItineraryOption {
|
|
let tripStops = stops.map { stopData in
|
|
TripStop(
|
|
city: stopData.city,
|
|
state: "XX",
|
|
coordinate: .init(latitude: 0, longitude: 0),
|
|
games: stopData.games,
|
|
arrivalDate: Date(),
|
|
departureDate: Date(),
|
|
travelFromPrevious: nil
|
|
)
|
|
}
|
|
return ItineraryOption(
|
|
id: UUID().uuidString,
|
|
stops: tripStops,
|
|
totalDistanceMiles: totalMiles,
|
|
totalDrivingHours: totalMiles / 60,
|
|
score: 1.0
|
|
)
|
|
}
|
|
|
|
@Test func groupByCityCountDescending() {
|
|
let options = [
|
|
makeOption(stops: [("NYC", []), ("Boston", [])]), // 2 cities
|
|
makeOption(stops: [("LA", []), ("SF", []), ("Seattle", [])]), // 3 cities
|
|
makeOption(stops: [("Chicago", [])]), // 1 city
|
|
]
|
|
|
|
let grouped = TripOptionsGrouper.groupByCityCount(options, ascending: false)
|
|
|
|
#expect(grouped.count == 3)
|
|
#expect(grouped[0].header == "3 cities")
|
|
#expect(grouped[1].header == "2 cities")
|
|
#expect(grouped[2].header == "1 city")
|
|
}
|
|
|
|
@Test func groupByGameCountAscending() {
|
|
let options = [
|
|
makeOption(stops: [("NYC", ["g1", "g2", "g3"])]), // 3 games
|
|
makeOption(stops: [("LA", ["g1"])]), // 1 game
|
|
makeOption(stops: [("Chicago", ["g1", "g2"])]), // 2 games
|
|
]
|
|
|
|
let grouped = TripOptionsGrouper.groupByGameCount(options, ascending: true)
|
|
|
|
#expect(grouped.count == 3)
|
|
#expect(grouped[0].header == "1 game")
|
|
#expect(grouped[1].header == "2 games")
|
|
#expect(grouped[2].header == "3 games")
|
|
}
|
|
|
|
@Test func groupByMileageRangeDescending() {
|
|
let options = [
|
|
makeOption(stops: [("NYC", [])], totalMiles: 300), // 0-500
|
|
makeOption(stops: [("LA", [])], totalMiles: 1200), // 1000-1500
|
|
makeOption(stops: [("Chicago", [])], totalMiles: 2500), // 2000+
|
|
]
|
|
|
|
let grouped = TripOptionsGrouper.groupByMileageRange(options, ascending: false)
|
|
|
|
#expect(grouped[0].header == "2000+ mi")
|
|
#expect(grouped[1].header == "1000-1500 mi")
|
|
#expect(grouped[2].header == "0-500 mi")
|
|
}
|
|
|
|
@Test func groupByMileageRangeAscending() {
|
|
let options = [
|
|
makeOption(stops: [("NYC", [])], totalMiles: 300),
|
|
makeOption(stops: [("LA", [])], totalMiles: 1200),
|
|
makeOption(stops: [("Chicago", [])], totalMiles: 2500),
|
|
]
|
|
|
|
let grouped = TripOptionsGrouper.groupByMileageRange(options, ascending: true)
|
|
|
|
#expect(grouped[0].header == "0-500 mi")
|
|
#expect(grouped[1].header == "1000-1500 mi")
|
|
#expect(grouped[2].header == "2000+ mi")
|
|
}
|
|
|
|
@Test func emptyOptionsReturnsEmptyGroups() {
|
|
let grouped = TripOptionsGrouper.groupByCityCount([], ascending: false)
|
|
#expect(grouped.isEmpty)
|
|
}
|
|
}
|