import Foundation import Testing @testable import PediFoods private func decode(_ type: T.Type, _ json: String) throws -> T { try JSONDecoder().decode(T.self, from: Data(json.utf8)) } @Test("SubmitOrderReviewResult accepts orderPositiveTags as either an array or a single string") func submitOrderReviewResultTagsArrayOrSingleString() throws { let asArray = try decode(SubmitOrderReviewResult.self, #"{"orderPositiveTags":["fast","tasty"]}"#) #expect(asArray.orderPositiveTags == ["fast", "tasty"]) let asSingleString = try decode(SubmitOrderReviewResult.self, #"{"orderPositiveTags":"fast"}"#) #expect(asSingleString.orderPositiveTags == ["fast"]) } @Test("SubmitOrderReviewResult falls back from orderPositiveTags to the legacy itemFeedback key") func submitOrderReviewResultTagsLegacyKeyFallback() throws { let result = try decode(SubmitOrderReviewResult.self, #"{"itemFeedback":["fresh"]}"#) #expect(result.orderPositiveTags == ["fresh"]) } @Test("SubmitOrderReviewResult coerces appNps from Int, Double, or comma-decimal String") func submitOrderReviewResultAppNpsCoercion() throws { let asInt = try decode(SubmitOrderReviewResult.self, #"{"appNps":9}"#) #expect(asInt.appNps == 9) let asDouble = try decode(SubmitOrderReviewResult.self, #"{"appNps":8.6}"#) #expect(asDouble.appNps == 9) let asString = try decode(SubmitOrderReviewResult.self, #"{"appNps":"7,4"}"#) #expect(asString.appNps == 7) } @Test("SubmitOrderReviewResult reads appNps from the legacy app_nps key") func submitOrderReviewResultAppNpsLegacyKey() throws { let result = try decode(SubmitOrderReviewResult.self, #"{"app_nps":10}"#) #expect(result.appNps == 10) } @Test("SubmitOrderReviewResult prefers the flat storeReplyMessage field over nested reply objects") func submitOrderReviewResultStoreReplyMessagePrefersFlatField() throws { let json = #"{"storeReplyMessage":"Obrigado!","storeReply":{"message":"ignored"}}"# let result = try decode(SubmitOrderReviewResult.self, json) #expect(result.storeReplyMessage == "Obrigado!") } @Test("SubmitOrderReviewResult extracts a reply message from a nested object's candidate keys") func submitOrderReviewResultStoreReplyMessageFromNestedObject() throws { let viaMessage = try decode(SubmitOrderReviewResult.self, #"{"storeReply":{"message":"Obrigado!"}}"#) #expect(viaMessage.storeReplyMessage == "Obrigado!") let viaText = try decode(SubmitOrderReviewResult.self, #"{"reply":{"text":"Valeu!"}}"#) #expect(viaText.storeReplyMessage == "Valeu!") let viaStoreResponse = try decode(SubmitOrderReviewResult.self, #"{"store_response":{"content":"Obrigado pela visita!"}}"#) #expect(viaStoreResponse.storeReplyMessage == "Obrigado pela visita!") } @Test("SubmitOrderReviewResult extracts a reply date from a nested object's candidate keys") func submitOrderReviewResultStoreReplyDateFromNestedObject() throws { let result = try decode(SubmitOrderReviewResult.self, #"{"storeReply":{"repliedAt":"2026-01-05"}}"#) #expect(result.storeReplyAt == "2026-01-05") } @Test("SubmitOrderReviewResult leaves storeReplyMessage nil when there's no reply at all") func submitOrderReviewResultNoReply() throws { let result = try decode(SubmitOrderReviewResult.self, "{}") #expect(result.storeReplyMessage == nil) #expect(result.storeReplyAt == nil) } @Test("PublicStoreReviewsResult decodes a bare top-level array of reviews") func publicStoreReviewsResultBareArray() throws { let json = #"[{"id":"1"},{"id":"2"}]"# let result = try decode(PublicStoreReviewsResult.self, json) #expect(result.reviews.count == 2) } @Test("PublicStoreReviewsResult falls back through reviews, data, and items wrapper keys") func publicStoreReviewsResultWrapperKeyFallback() throws { let viaReviews = try decode(PublicStoreReviewsResult.self, #"{"reviews":[{"id":"1"}]}"#) #expect(viaReviews.reviews.count == 1) let viaData = try decode(PublicStoreReviewsResult.self, #"{"data":[{"id":"1"},{"id":"2"}]}"#) #expect(viaData.reviews.count == 2) let viaItems = try decode(PublicStoreReviewsResult.self, #"{"items":[{"id":"1"}]}"#) #expect(viaItems.reviews.count == 1) } @Test("PublicStoreReviewsResult defaults to an empty array when nothing matches") func publicStoreReviewsResultDefaultsToEmpty() throws { let result = try decode(PublicStoreReviewsResult.self, "{}") #expect(result.reviews.isEmpty) } @Test("ReviewPlatform.current is iOS on this platform") func reviewPlatformCurrentIsIOS() { #expect(ReviewPlatform.current == .ios) }