Replace complex anchor system (anchorType, anchorId, anchorDay) with simple (day: Int, sortOrder: Double) positioning for custom items. Changes: - CustomItineraryItem: Remove anchor fields, add day and sortOrder - CKModels: Add migration fallback from old CloudKit fields - ItineraryTableViewController: Add calculateSortOrder() for midpoint insertion - TripDetailView: Simplify callbacks, itinerarySections, and routeWaypoints - AddItemSheet: Take simple day parameter instead of anchor - SavedTrip: Update LocalCustomItem SwiftData model Benefits: - Items freely movable via drag-and-drop - Route waypoints follow exact visual order - Simpler mental model: position = (day, sortOrder) - Midpoint insertion allows unlimited reordering Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
86 lines
2.4 KiB
Swift
86 lines
2.4 KiB
Swift
//
|
|
// CustomItineraryItemTests.swift
|
|
// SportsTimeTests
|
|
//
|
|
|
|
import Testing
|
|
@testable import SportsTime
|
|
import Foundation
|
|
|
|
struct CustomItineraryItemTests {
|
|
|
|
@Test("Item initializes with default values")
|
|
func item_InitializesWithDefaults() {
|
|
let tripId = UUID()
|
|
let item = CustomItineraryItem(
|
|
tripId: tripId,
|
|
category: .restaurant,
|
|
title: "Joe's BBQ",
|
|
day: 1
|
|
)
|
|
|
|
#expect(item.tripId == tripId)
|
|
#expect(item.category == .restaurant)
|
|
#expect(item.title == "Joe's BBQ")
|
|
#expect(item.day == 1)
|
|
#expect(item.sortOrder == 0.0)
|
|
}
|
|
|
|
@Test("Item initializes with day and sortOrder")
|
|
func item_InitializesWithDayAndSortOrder() {
|
|
let tripId = UUID()
|
|
let item = CustomItineraryItem(
|
|
tripId: tripId,
|
|
category: .restaurant,
|
|
title: "Joe's BBQ",
|
|
day: 1,
|
|
sortOrder: 1.5
|
|
)
|
|
|
|
#expect(item.tripId == tripId)
|
|
#expect(item.category == .restaurant)
|
|
#expect(item.title == "Joe's BBQ")
|
|
#expect(item.day == 1)
|
|
#expect(item.sortOrder == 1.5)
|
|
}
|
|
|
|
@Test("SortOrder defaults to 0.0")
|
|
func sortOrder_DefaultsToZero() {
|
|
let item = CustomItineraryItem(
|
|
tripId: UUID(),
|
|
category: .activity,
|
|
title: "City Tour",
|
|
day: 2
|
|
)
|
|
|
|
#expect(item.sortOrder == 0.0)
|
|
}
|
|
|
|
@Test("Item category has correct icons")
|
|
func category_HasCorrectIcons() {
|
|
#expect(CustomItineraryItem.ItemCategory.restaurant.icon == "🍽️")
|
|
#expect(CustomItineraryItem.ItemCategory.hotel.icon == "🏨")
|
|
#expect(CustomItineraryItem.ItemCategory.activity.icon == "🎯")
|
|
#expect(CustomItineraryItem.ItemCategory.note.icon == "📝")
|
|
}
|
|
|
|
@Test("Item is Codable")
|
|
func item_IsCodable() throws {
|
|
let item = CustomItineraryItem(
|
|
tripId: UUID(),
|
|
category: .hotel,
|
|
title: "Hilton Downtown",
|
|
day: 2,
|
|
sortOrder: 3.5
|
|
)
|
|
|
|
let encoded = try JSONEncoder().encode(item)
|
|
let decoded = try JSONDecoder().decode(CustomItineraryItem.self, from: encoded)
|
|
|
|
#expect(decoded.id == item.id)
|
|
#expect(decoded.title == item.title)
|
|
#expect(decoded.day == 2)
|
|
#expect(decoded.sortOrder == 3.5)
|
|
}
|
|
}
|