migration
This commit is contained in:
151
PediFoodsTests/ApiOrderTrackingModelsTests.swift
Normal file
151
PediFoodsTests/ApiOrderTrackingModelsTests.swift
Normal file
@@ -0,0 +1,151 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import PediFoods
|
||||
|
||||
private func decode<T: Decodable>(_ type: T.Type, _ json: String) throws -> T {
|
||||
try JSONDecoder().decode(T.self, from: Data(json.utf8))
|
||||
}
|
||||
|
||||
private func makeOrder(
|
||||
status: String? = nil,
|
||||
paymentStatus: String? = nil,
|
||||
paymentConfirmed: Bool? = nil,
|
||||
customerOtp: String? = nil,
|
||||
otp: String? = nil,
|
||||
confirmOtp: String? = nil,
|
||||
timeline: [PublicOrderTimelineEvent] = []
|
||||
) -> PublicOrderResult {
|
||||
PublicOrderResult(
|
||||
id: "order-1",
|
||||
status: status,
|
||||
paymentStatus: paymentStatus,
|
||||
paymentConfirmed: paymentConfirmed,
|
||||
otp: otp,
|
||||
customerOtp: customerOtp,
|
||||
confirmOtp: confirmOtp,
|
||||
timeline: timeline
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - displayOtpCode
|
||||
|
||||
@Test("PublicOrderResult.displayOtpCode prefers customerOtp, then otp, then confirmOtp")
|
||||
func displayOtpCodePriorityOrder() {
|
||||
let allThree = makeOrder(customerOtp: "1111", otp: "2222", confirmOtp: "3333")
|
||||
#expect(allThree.displayOtpCode == "1111")
|
||||
|
||||
let otpAndConfirm = makeOrder(otp: "2222", confirmOtp: "3333")
|
||||
#expect(otpAndConfirm.displayOtpCode == "2222")
|
||||
|
||||
let confirmOnly = makeOrder(confirmOtp: "3333")
|
||||
#expect(confirmOnly.displayOtpCode == "3333")
|
||||
}
|
||||
|
||||
@Test("PublicOrderResult.displayOtpCode skips blank/whitespace-only values")
|
||||
func displayOtpCodeSkipsBlankValues() {
|
||||
let order = makeOrder(customerOtp: " ", otp: "2222")
|
||||
#expect(order.displayOtpCode == "2222")
|
||||
}
|
||||
|
||||
@Test("PublicOrderResult.displayOtpCode is nil when no OTP field is set")
|
||||
func displayOtpCodeNilWhenAbsent() {
|
||||
#expect(makeOrder().displayOtpCode == nil)
|
||||
}
|
||||
|
||||
// MARK: - isInDeliveryRoute / isFinalStatus
|
||||
|
||||
@Test("PublicOrderResult.isInDeliveryRoute recognizes OUT_FOR_DELIVERY and Portuguese equivalents")
|
||||
func isInDeliveryRouteRecognizesKnownStatuses() {
|
||||
#expect(makeOrder(status: "OUT_FOR_DELIVERY").isInDeliveryRoute)
|
||||
#expect(makeOrder(status: "em_rota").isInDeliveryRoute)
|
||||
#expect(makeOrder(status: "ON_ROUTE").isInDeliveryRoute)
|
||||
#expect(makeOrder(status: "PREPARING").isInDeliveryRoute == false)
|
||||
}
|
||||
|
||||
@Test("PublicOrderResult.isFinalStatus matches COMPLETED, CANCELED, and REFUNDED exactly")
|
||||
func isFinalStatusMatchesTerminalStatuses() {
|
||||
#expect(makeOrder(status: "COMPLETED").isFinalStatus)
|
||||
#expect(makeOrder(status: "CANCELED").isFinalStatus)
|
||||
#expect(makeOrder(status: "REFUNDED").isFinalStatus)
|
||||
#expect(makeOrder(status: "PREPARING").isFinalStatus == false)
|
||||
}
|
||||
|
||||
// MARK: - isPaymentConfirmed
|
||||
|
||||
@Test("PublicOrderResult.isPaymentConfirmed trusts the explicit paymentConfirmed flag first")
|
||||
func isPaymentConfirmedTrustsExplicitFlag() {
|
||||
#expect(makeOrder(paymentStatus: "PENDING", paymentConfirmed: true).isPaymentConfirmed)
|
||||
#expect(makeOrder(paymentStatus: "PAID", paymentConfirmed: false).isPaymentConfirmed == false)
|
||||
}
|
||||
|
||||
@Test("PublicOrderResult.isPaymentConfirmed infers from a paymentStatus that looks confirmed")
|
||||
func isPaymentConfirmedInfersFromPaymentStatus() {
|
||||
#expect(makeOrder(paymentStatus: "CONFIRMED").isPaymentConfirmed)
|
||||
#expect(makeOrder(paymentStatus: "approved").isPaymentConfirmed)
|
||||
#expect(makeOrder(paymentStatus: "PENDING").isPaymentConfirmed == false)
|
||||
#expect(makeOrder(paymentStatus: "PAYMENT_FAILED").isPaymentConfirmed == false)
|
||||
}
|
||||
|
||||
@Test("PublicOrderResult.isPaymentConfirmed falls back to the timeline when status fields don't confirm")
|
||||
func isPaymentConfirmedFallsBackToTimeline() {
|
||||
let confirmingEvent = PublicOrderTimelineEvent(status: "PAYMENT_APPROVED", message: nil, time: nil)
|
||||
let order = makeOrder(status: "PROCESSING", timeline: [confirmingEvent])
|
||||
#expect(order.isPaymentConfirmed)
|
||||
}
|
||||
|
||||
@Test("PublicOrderResult.isPaymentConfirmed is false with no confirming signal anywhere")
|
||||
func isPaymentConfirmedFalseWithNoSignal() {
|
||||
#expect(makeOrder(status: "PROCESSING").isPaymentConfirmed == false)
|
||||
}
|
||||
|
||||
// MARK: - CreateOrderResult -> PublicOrderResult mapping
|
||||
|
||||
@Test("CreateOrderResult.asPublicOrderResult maps every carried-over field")
|
||||
func createOrderResultMapsToPublicOrderResult() throws {
|
||||
let created = try decode(CreateOrderResult.self, #"{"id":"o1","shortId":"S1","status":"PENDING","paymentMethod":"PIX"}"#)
|
||||
let mapped = created.asPublicOrderResult()
|
||||
#expect(mapped.id == "o1")
|
||||
#expect(mapped.shortId == "S1")
|
||||
#expect(mapped.status == "PENDING")
|
||||
#expect(mapped.paymentMethod == "PIX")
|
||||
}
|
||||
|
||||
// MARK: - Nested decode fallbacks
|
||||
|
||||
@Test("PublicOrderDeliveryAddress falls back through street/address and zip/zipCode/zipcode key names")
|
||||
func publicOrderDeliveryAddressKeyFallback() throws {
|
||||
let viaAddress = try decode(PublicOrderDeliveryAddress.self, #"{"address":"Rua A","zipcode":"01000-000"}"#)
|
||||
#expect(viaAddress.street == "Rua A")
|
||||
#expect(viaAddress.zip == "01000-000")
|
||||
}
|
||||
|
||||
@Test("PublicOrderItem falls back from qty to the legacy quantity key")
|
||||
func publicOrderItemQuantityKeyFallback() throws {
|
||||
let item = try decode(PublicOrderItem.self, #"{"quantity":3,"price":9.9}"#)
|
||||
#expect(item.qty == 3)
|
||||
}
|
||||
|
||||
@Test("PublicOrderTimelineEvent falls back from message to event, and from time to createdAt/updatedAt")
|
||||
func publicOrderTimelineEventKeyFallback() throws {
|
||||
let viaEvent = try decode(PublicOrderTimelineEvent.self, #"{"status":"S","event":"Order placed"}"#)
|
||||
#expect(viaEvent.message == "Order placed")
|
||||
|
||||
let viaCreatedAt = try decode(PublicOrderTimelineEvent.self, #"{"status":"S","createdAt":"2026-01-01T00:00:00Z"}"#)
|
||||
#expect(viaCreatedAt.time == "2026-01-01T00:00:00Z")
|
||||
}
|
||||
|
||||
@Test("AppOrderSummary falls back through orderId/realId/id for its own id, and through many keys for storeLogoURL")
|
||||
func appOrderSummaryIdAndLogoFallback() throws {
|
||||
let viaRealId = try decode(AppOrderSummary.self, #"{"realId":"real-1"}"#)
|
||||
#expect(viaRealId.id == "real-1")
|
||||
|
||||
let viaLogo = try decode(AppOrderSummary.self, #"{"orderId":"o1","store_logo":"logo.png"}"#)
|
||||
#expect(viaLogo.storeLogoURL == "logo.png")
|
||||
}
|
||||
|
||||
@Test("AppOrderSummary falls back to the shared date key when createdAt/updatedAt are absent")
|
||||
func appOrderSummaryDateFallback() throws {
|
||||
let summary = try decode(AppOrderSummary.self, #"{"orderId":"o1","date":"2026-01-01"}"#)
|
||||
#expect(summary.createdAt == "2026-01-01")
|
||||
#expect(summary.updatedAt == "2026-01-01")
|
||||
}
|
||||
Reference in New Issue
Block a user