diff --git a/Networking/Networking.xcodeproj/project.pbxproj b/Networking/Networking.xcodeproj/project.pbxproj index ddd75bd02db..9dd79e1c3a9 100644 --- a/Networking/Networking.xcodeproj/project.pbxproj +++ b/Networking/Networking.xcodeproj/project.pbxproj @@ -690,6 +690,10 @@ DE34051B28BDF12C00CF0D97 /* jetpack-connection-url.json in Resources */ = {isa = PBXBuildFile; fileRef = DE34051A28BDF12C00CF0D97 /* jetpack-connection-url.json */; }; DE34051D28BDF1C900CF0D97 /* JetpackConnectionURLMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE34051C28BDF1C900CF0D97 /* JetpackConnectionURLMapperTests.swift */; }; DE34051F28BDFB0B00CF0D97 /* JetpackConnectionRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE34051E28BDFB0B00CF0D97 /* JetpackConnectionRemoteTests.swift */; }; + DE42F95D2966CB6A00D514C2 /* order-notes-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F95C2966CB6A00D514C2 /* order-notes-without-data.json */; }; + DE42F9602967C88400D514C2 /* report-orders-total-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F95E2967C88400D514C2 /* report-orders-total-without-data.json */; }; + DE42F9612967C88400D514C2 /* report-orders-total.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F95F2967C88400D514C2 /* report-orders-total.json */; }; + DE42F9632967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE42F9622967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift */; }; DE50295928C5BD0200551736 /* JetpackUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE50295828C5BD0200551736 /* JetpackUser.swift */; }; DE50295B28C5F99700551736 /* DotcomUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE50295A28C5F99700551736 /* DotcomUser.swift */; }; DE50295D28C6068B00551736 /* JetpackUserMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE50295C28C6068B00551736 /* JetpackUserMapper.swift */; }; @@ -725,6 +729,8 @@ DEF13C562965689F0024A02B /* LeaderboardListMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF13C552965689F0024A02B /* LeaderboardListMapperTests.swift */; }; DEF13C5A296571150024A02B /* leaderboards-year-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DEF13C59296571150024A02B /* leaderboards-year-without-data.json */; }; DEF13C5C2965812D0024A02B /* order-stats-v4-year-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DEF13C5B2965812D0024A02B /* order-stats-v4-year-without-data.json */; }; + DEF13C5E296686AB0024A02B /* orders-load-all-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DEF13C5D296686AB0024A02B /* orders-load-all-without-data.json */; }; + DEF13C6029668C420024A02B /* order-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DEF13C5F29668C420024A02B /* order-without-data.json */; }; DEFBA74E29485A7600C35BA9 /* RESTRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEFBA74D29485A7600C35BA9 /* RESTRequest.swift */; }; DEFBA7542949CE6600C35BA9 /* RequestProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEFBA7532949CE6600C35BA9 /* RequestProcessor.swift */; }; DEFBA7562949D17400C35BA9 /* DefaultRequestAuthenticatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEFBA7552949D17300C35BA9 /* DefaultRequestAuthenticatorTests.swift */; }; @@ -1493,6 +1499,10 @@ DE34051A28BDF12C00CF0D97 /* jetpack-connection-url.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "jetpack-connection-url.json"; sourceTree = ""; }; DE34051C28BDF1C900CF0D97 /* JetpackConnectionURLMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackConnectionURLMapperTests.swift; sourceTree = ""; }; DE34051E28BDFB0B00CF0D97 /* JetpackConnectionRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackConnectionRemoteTests.swift; sourceTree = ""; }; + DE42F95C2966CB6A00D514C2 /* order-notes-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-notes-without-data.json"; sourceTree = ""; }; + DE42F95E2967C88400D514C2 /* report-orders-total-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "report-orders-total-without-data.json"; path = "NetworkingTests/Responses/report-orders-total-without-data.json"; sourceTree = SOURCE_ROOT; }; + DE42F95F2967C88400D514C2 /* report-orders-total.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "report-orders-total.json"; path = "NetworkingTests/Responses/report-orders-total.json"; sourceTree = SOURCE_ROOT; }; + DE42F9622967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportOrderTotalsMapperTests.swift; sourceTree = ""; }; DE50295828C5BD0200551736 /* JetpackUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackUser.swift; sourceTree = ""; }; DE50295A28C5F99700551736 /* DotcomUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotcomUser.swift; sourceTree = ""; }; DE50295C28C6068B00551736 /* JetpackUserMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackUserMapper.swift; sourceTree = ""; }; @@ -1528,6 +1538,8 @@ DEF13C552965689F0024A02B /* LeaderboardListMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeaderboardListMapperTests.swift; sourceTree = ""; }; DEF13C59296571150024A02B /* leaderboards-year-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "leaderboards-year-without-data.json"; sourceTree = ""; }; DEF13C5B2965812D0024A02B /* order-stats-v4-year-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-stats-v4-year-without-data.json"; sourceTree = ""; }; + DEF13C5D296686AB0024A02B /* orders-load-all-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "orders-load-all-without-data.json"; sourceTree = ""; }; + DEF13C5F29668C420024A02B /* order-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-without-data.json"; sourceTree = ""; }; DEFBA74D29485A7600C35BA9 /* RESTRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RESTRequest.swift; sourceTree = ""; }; DEFBA7532949CE6600C35BA9 /* RequestProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestProcessor.swift; sourceTree = ""; }; DEFBA7552949D17300C35BA9 /* DefaultRequestAuthenticatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultRequestAuthenticatorTests.swift; sourceTree = ""; }; @@ -2114,6 +2126,8 @@ EE80A24B29556F1D003591E4 /* Coupon */, EE338A0A294AF92A00183934 /* AppliicationPassword */, DE9DEEF4291CF1B40070AD7C /* site-plugin-without-envelope.json */, + DE42F95E2967C88400D514C2 /* report-orders-total-without-data.json */, + DE42F95F2967C88400D514C2 /* report-orders-total.json */, DE2E8EA8295416C9002E4B14 /* wordpress-site-info.json */, 028CB714290223CB00331C09 /* account-username-suggestions.json */, 028CB71C2902589E00331C09 /* create-account-error-email-exists.json */, @@ -2200,10 +2214,13 @@ B554FA8C2180B59700C54DFF /* notifications-load-hashes.json */, AE2D6624272A941C004A2C3A /* null-data.json */, B5C6FCD520A3768900A4F8E4 /* order.json */, + DEF13C5F29668C420024A02B /* order-without-data.json */, 034480C227A42F9100DFACD2 /* order-with-charge.json */, 02C254D62563999200A04423 /* order-shipping-labels.json */, B559EBA920A0B5CD00836CD4 /* orders-load-all.json */, + DEF13C5D296686AB0024A02B /* orders-load-all-without-data.json */, 74C8F06520EEB76400B6EDC9 /* order-notes.json */, + DE42F95C2966CB6A00D514C2 /* order-notes-without-data.json */, CEF88DAA233E911A00BED485 /* order-fully-refunded.json */, CEF88DAE233E9F7D00BED485 /* order-details-partially-refunded.json */, D8FBFF2322D52815006E3336 /* order-stats-v4-daily.json */, @@ -2615,6 +2632,7 @@ 68CB801328D8A05200E169F8 /* CustomerMapperTests.swift */, 68F48B1028E3BBC60045C15B /* WCAnalyticsCustomerMapperTests.swift */, EE338A0D294AF9BD00183934 /* ApplicationPasswordMapperTests.swift */, + DE42F9622967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift */, EEA658412966C41A00112DF0 /* ProductIDMapperTests.swift */, EEA658472966CBAD00112DF0 /* EntityIDMapperTests.swift */, ); @@ -2881,6 +2899,7 @@ D865CE5F278CA183002C8520 /* stripe-payment-intent-requires-action.json in Resources */, CCF48B2C2628AE160034EA83 /* shipping-label-account-settings.json in Resources */, 31A451D927863A2E00FE81AA /* stripe-account-live-test.json in Resources */, + DE42F9602967C88400D514C2 /* report-orders-total-without-data.json in Resources */, DE9DEEF5291CF1B40070AD7C /* site-plugin-without-envelope.json in Resources */, 0261F5A928D4641500B7AC72 /* products-sku-search.json in Resources */, EE80A24829547F8B003591E4 /* coupon-without-data.json in Resources */, @@ -2938,6 +2957,7 @@ 3158FE6C26129D2E00E566B9 /* wcpay-account-rejected-terms-of-service.json in Resources */, E16C59B928F927CA007D55BB /* iap-order-create.json in Resources */, 31054728262E2FEE00C5C02B /* wcpay-payment-intent-canceled.json in Resources */, + DE42F9612967C88400D514C2 /* report-orders-total.json in Resources */, 31A451CC27863A2E00FE81AA /* stripe-account-rejected-fraud.json in Resources */, 31A451D827863A2E00FE81AA /* stripe-account-restricted-overdue.json in Resources */, D865CE69278CA245002C8520 /* stripe-payment-intent-unknown-status.json in Resources */, @@ -3007,6 +3027,7 @@ EE80A24729547F8B003591E4 /* coupons-all-without-data.json in Resources */, 7412A8F021B6E416005D182A /* report-orders.json in Resources */, CCF4346A2906C9C300B4475A /* products-ids-only-empty.json in Resources */, + DEF13C5E296686AB0024A02B /* orders-load-all-without-data.json in Resources */, 4515282B257A8C010076B03C /* product-attribute-delete.json in Resources */, 020C907B24C6E108001E2BEB /* product-variation-update.json in Resources */, D8FBFF1822D4DDB9006E3336 /* order-stats-v4-hour.json in Resources */, @@ -3018,6 +3039,7 @@ 261CF2CB255C50010090D8D3 /* payment-gateway-list-half.json in Resources */, 02C254D72563999300A04423 /* order-shipping-labels.json in Resources */, 45B204BC24890B1200FE6526 /* category.json in Resources */, + DEF13C6029668C420024A02B /* order-without-data.json in Resources */, 022902D422E2436400059692 /* stats_module_disabled_error.json in Resources */, 4513382827A96DE700AE5E78 /* inbox-note.json in Resources */, 31A451D227863A2E00FE81AA /* stripe-account-restricted-pending.json in Resources */, @@ -3062,6 +3084,7 @@ D8FBFF1522D3BE09006E3336 /* order-stats-v4-defaults.json in Resources */, 7495AACF225D366D00801A89 /* variation-as-product.json in Resources */, 0272E3FB254AABB800436277 /* order-with-line-item-attributes-before-API-support.json in Resources */, + DE42F95D2966CB6A00D514C2 /* order-notes-without-data.json in Resources */, 31723C892787A299007F1405 /* stripe-connection-token.json in Resources */, 74A1D266211898F000931DFA /* site-visits-year.json in Resources */, 743BF8BE21191B63008A9D87 /* site-visits.json in Resources */, @@ -3642,6 +3665,7 @@ 74CF0A8C22414D7800DB993F /* ProductMapperTests.swift in Sources */, 45152815257A83DD0076B03C /* ProductAttributesRemoteTests.swift in Sources */, B505F6D720BEE58800BB1B69 /* AccountRemoteTests.swift in Sources */, + DE42F9632967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift in Sources */, 453305EB2459E01A00264E50 /* PostMapperTests.swift in Sources */, CE0A0F1D22398D520075ED8D /* ProductListMapperTests.swift in Sources */, 2670C3FC270F4E06002FE931 /* SiteListMapperTests.swift in Sources */, diff --git a/Networking/Networking/Mapper/OrderListMapper.swift b/Networking/Networking/Mapper/OrderListMapper.swift index a781b21782b..753c31a3648 100644 --- a/Networking/Networking/Mapper/OrderListMapper.swift +++ b/Networking/Networking/Mapper/OrderListMapper.swift @@ -21,7 +21,11 @@ struct OrderListMapper: Mapper { .siteID: siteID ] - return try decoder.decode(OrderListEnvelope.self, from: response).orders + do { + return try decoder.decode(OrderListEnvelope.self, from: response).orders + } catch { + return try decoder.decode([Order].self, from: response) + } } } diff --git a/Networking/Networking/Mapper/OrderMapper.swift b/Networking/Networking/Mapper/OrderMapper.swift index 99b093509b0..bcbecb6a9cc 100644 --- a/Networking/Networking/Mapper/OrderMapper.swift +++ b/Networking/Networking/Mapper/OrderMapper.swift @@ -20,8 +20,11 @@ struct OrderMapper: Mapper { decoder.userInfo = [ .siteID: siteID ] - - return try decoder.decode(OrderEnvelope.self, from: response).order + do { + return try decoder.decode(OrderEnvelope.self, from: response).order + } catch { + return try decoder.decode(Order.self, from: response) + } } } diff --git a/Networking/Networking/Mapper/OrderNoteMapper.swift b/Networking/Networking/Mapper/OrderNoteMapper.swift index c6735c265c7..e709823b736 100644 --- a/Networking/Networking/Mapper/OrderNoteMapper.swift +++ b/Networking/Networking/Mapper/OrderNoteMapper.swift @@ -11,7 +11,11 @@ class OrderNoteMapper: Mapper { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(DateFormatter.Defaults.dateTimeFormatter) - return try decoder.decode(OrderNoteEnvelope.self, from: response).orderNote + do { + return try decoder.decode(OrderNoteEnvelope.self, from: response).orderNote + } catch { + return try decoder.decode(OrderNote.self, from: response) + } } } diff --git a/Networking/Networking/Mapper/OrderNotesMapper.swift b/Networking/Networking/Mapper/OrderNotesMapper.swift index 8fc00ef0396..9151c710a47 100644 --- a/Networking/Networking/Mapper/OrderNotesMapper.swift +++ b/Networking/Networking/Mapper/OrderNotesMapper.swift @@ -11,7 +11,11 @@ class OrderNotesMapper: Mapper { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(DateFormatter.Defaults.dateTimeFormatter) - return try decoder.decode(OrderNotesEnvelope.self, from: response).orderNotes + do { + return try decoder.decode(OrderNotesEnvelope.self, from: response).orderNotes + } catch { + return try decoder.decode([OrderNote].self, from: response) + } } } diff --git a/Networking/Networking/Mapper/ReportOrderTotalsMapper.swift b/Networking/Networking/Mapper/ReportOrderTotalsMapper.swift index 6acda756b40..c2462e5b1fe 100644 --- a/Networking/Networking/Mapper/ReportOrderTotalsMapper.swift +++ b/Networking/Networking/Mapper/ReportOrderTotalsMapper.swift @@ -19,7 +19,11 @@ struct ReportOrderTotalsMapper: Mapper { decoder.userInfo = [ .siteID: siteID ] - return try decoder.decode(ReportOrderTotalsEnvelope.self, from: response).data + do { + return try decoder.decode(ReportOrderTotalsEnvelope.self, from: response).data + } catch { + return try decoder.decode([OrderStatus].self, from: response) + } } } diff --git a/Networking/Networking/Remote/OrdersRemote.swift b/Networking/Networking/Remote/OrdersRemote.swift index df2b274cbb9..bd8f10412cd 100644 --- a/Networking/Networking/Remote/OrdersRemote.swift +++ b/Networking/Networking/Remote/OrdersRemote.swift @@ -46,7 +46,12 @@ public class OrdersRemote: Remote { }() let path = Constants.ordersPath - let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .get, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) let mapper = OrderListMapper(siteID: siteID) enqueue(request, mapper: mapper, completion: completion) @@ -65,7 +70,12 @@ public class OrdersRemote: Remote { ] let path = "\(Constants.ordersPath)/\(orderID)" - let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .get, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) let mapper = OrderMapper(siteID: siteID) enqueue(request, mapper: mapper, completion: completion) @@ -80,7 +90,12 @@ public class OrdersRemote: Remote { /// public func loadOrderNotes(for siteID: Int64, orderID: Int64, completion: @escaping ([OrderNote]?, Error?) -> Void) { let path = "\(Constants.ordersPath)/\(orderID)/\(Constants.notesPath)/" - let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: nil) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .get, + siteID: siteID, + path: path, + parameters: nil, + availableAsRESTRequest: true) let mapper = OrderNotesMapper() enqueue(request, mapper: mapper, completion: completion) @@ -109,7 +124,12 @@ public class OrdersRemote: Remote { ] let path = Constants.ordersPath - let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .get, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) let mapper = OrderListMapper(siteID: siteID) enqueue(request, mapper: mapper, completion: completion) @@ -152,7 +172,12 @@ public class OrdersRemote: Remote { } }() - let request = JetpackRequest(wooApiVersion: .mark3, method: .post, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .post, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) enqueue(request, mapper: mapper, completion: completion) } catch { completion(.failure(error)) @@ -172,7 +197,12 @@ public class OrdersRemote: Remote { let parameters = [ParameterKeys.statusKey: statusKey.rawValue] let mapper = OrderMapper(siteID: siteID) - let request = JetpackRequest(wooApiVersion: .mark3, method: .post, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .post, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) enqueue(request, mapper: mapper, completion: completion) } @@ -213,7 +243,12 @@ public class OrdersRemote: Remote { } }() - let request = JetpackRequest(wooApiVersion: .mark3, method: .post, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .post, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) enqueue(request, mapper: mapper, completion: completion) } catch { completion(.failure(error)) @@ -237,7 +272,12 @@ public class OrdersRemote: Remote { ParameterKeys.addedByUser: String(true)] // This will always be true when creating notes in-app let mapper = OrderNoteMapper() - let request = JetpackRequest(wooApiVersion: .mark3, method: .post, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .post, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) enqueue(request, mapper: mapper, completion: completion) } @@ -252,7 +292,12 @@ public class OrdersRemote: Remote { public func deleteOrder(for siteID: Int64, orderID: Int64, force: Bool, completion: @escaping (Result) -> Void) { let path = "\(Constants.ordersPath)/\(orderID)" let parameters = [ParameterKeys.force: String(force)] - let request = JetpackRequest(wooApiVersion: .mark3, method: .delete, siteID: siteID, path: path, parameters: parameters) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .delete, + siteID: siteID, + path: path, + parameters: parameters, + availableAsRESTRequest: true) let mapper = OrderMapper(siteID: siteID) enqueue(request, mapper: mapper, completion: completion) } diff --git a/Networking/Networking/Remote/ReportRemote.swift b/Networking/Networking/Remote/ReportRemote.swift index 45a210a06a7..e56d8474e24 100644 --- a/Networking/Networking/Remote/ReportRemote.swift +++ b/Networking/Networking/Remote/ReportRemote.swift @@ -9,7 +9,7 @@ public class ReportRemote: Remote { /// public func loadOrdersTotals(for siteID: Int64, completion: @escaping (Result<[OrderStatus], Error>) -> Void) { let path = Constants.orderTotalsPath - let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: nil) + let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: nil, availableAsRESTRequest: true) let mapper = ReportOrderTotalsMapper(siteID: siteID) enqueue(request, mapper: mapper, completion: completion) diff --git a/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift b/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift index bc0d1c3f5be..75e196c9d28 100644 --- a/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift @@ -40,6 +40,35 @@ class OrderListMapperTests: XCTestCase { XCTAssertEqual(firstOrder.totalTax, "1.20") } + /// Verifies that all of the Order Fields are parsed correctly when the response has no data envelope. + /// + func test_order_fields_are_properly_parsed_when_the_response_has_no_data_envelope() { + let orders = mapLoadAllOrdersResponseWithoutDataEnvelope() + XCTAssert(orders.count == 1) + + let firstOrder = orders[0] + let dateCreated = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-04-03T23:05:12") + let dateModified = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-04-03T23:05:14") + let datePaid = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-04-03T23:05:14") + + XCTAssertEqual(firstOrder.orderID, 963) + XCTAssertEqual(firstOrder.parentID, 0) + XCTAssertEqual(firstOrder.customerID, 11) + XCTAssertEqual(firstOrder.number, "963") + XCTAssertEqual(firstOrder.status, .processing) + XCTAssertEqual(firstOrder.currency, "USD") + XCTAssertEqual(firstOrder.customerNote, "") + XCTAssertEqual(firstOrder.dateCreated, dateCreated) + XCTAssertEqual(firstOrder.dateModified, dateModified) + XCTAssertEqual(firstOrder.datePaid, datePaid) + XCTAssertEqual(firstOrder.discountTotal, "30.00") + XCTAssertEqual(firstOrder.discountTax, "1.20") + XCTAssertEqual(firstOrder.shippingTotal, "0.00") + XCTAssertEqual(firstOrder.shippingTax, "0.00") + XCTAssertEqual(firstOrder.total, "31.20") + XCTAssertEqual(firstOrder.totalTax, "1.20") + } + /// Verifies that the siteID field is properly set. /// func test_site_identifier_is_properly_injected_into_every_order() { @@ -140,7 +169,7 @@ class OrderListMapperTests: XCTestCase { /// private extension OrderListMapperTests { - /// Returns the OrderListMapper output upon receiving `filename` (Data Encoded) + /// Returns the [Order] output upon receiving `filename` (Data Encoded) /// func mapOrders(from filename: String) -> [Order] { guard let response = Loader.contentsOf(filename) else { @@ -150,19 +179,25 @@ private extension OrderListMapperTests { return try! OrderListMapper(siteID: dummySiteID).map(response: response) } - /// Returns the OrderListMapper output upon receiving `orders-load-all` + /// Returns the [Order] output upon receiving `orders-load-all` /// func mapLoadAllOrdersResponse() -> [Order] { return mapOrders(from: "orders-load-all") } - /// Returns the OrderListMapper output upon receiving `broken-order` + /// Returns the [Order] output upon receiving `orders-load-all-without-data` + /// + func mapLoadAllOrdersResponseWithoutDataEnvelope() -> [Order] { + return mapOrders(from: "orders-load-all-without-data") + } + + /// Returns the [Order] output upon receiving `broken-order` /// func mapLoadBrokenOrderResponse() -> [Order] { return mapOrders(from: "broken-orders") } - /// Returns the OrderListMapper output upon receiving `broken-orders-mark-2` + /// Returns the [Order] output upon receiving `broken-orders-mark-2` /// func mapLoadBrokenOrdersResponseMarkII() -> [Order] { return mapOrders(from: "broken-orders-mark-2") diff --git a/Networking/NetworkingTests/Mapper/OrderMapperTests.swift b/Networking/NetworkingTests/Mapper/OrderMapperTests.swift index faf2b7b58ac..6660f8c19f3 100644 --- a/Networking/NetworkingTests/Mapper/OrderMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/OrderMapperTests.swift @@ -43,6 +43,38 @@ final class OrderMapperTests: XCTestCase { XCTAssertEqual(order.paymentURL, URL(string: "http://www.automattic.com")) } + /// Verifies that all of the Order Fields are parsed correctly when response has no data envelope. + /// + func test_Order_fields_are_properly_parsed_when_response_has_no_data_envelope() { + guard let order = mapLoadOrderResponseWithoutDataEnvelope() else { + XCTFail() + return + } + + let dateCreated = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-04-03T23:05:12") + let dateModified = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-04-03T23:05:14") + let datePaid = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-04-03T23:05:14") + + XCTAssertEqual(order.siteID, dummySiteID) + XCTAssertEqual(order.orderID, 963) + XCTAssertEqual(order.parentID, 0) + XCTAssertEqual(order.customerID, 11) + XCTAssertEqual(order.number, "963") + XCTAssertEqual(order.status, .processing) + XCTAssertEqual(order.currency, "USD") + XCTAssertEqual(order.customerNote, "") + XCTAssertEqual(order.dateCreated, dateCreated) + XCTAssertEqual(order.dateModified, dateModified) + XCTAssertEqual(order.datePaid, datePaid) + XCTAssertEqual(order.discountTotal, "30.00") + XCTAssertEqual(order.discountTax, "1.20") + XCTAssertEqual(order.shippingTotal, "0.00") + XCTAssertEqual(order.shippingTax, "0.00") + XCTAssertEqual(order.total, "31.20") + XCTAssertEqual(order.totalTax, "1.20") + XCTAssertEqual(order.paymentURL, URL(string: "http://www.automattic.com")) + } + /// Verifies that all of the Order Address fields are parsed correctly. /// func test_Order_addresses_are_correctly_parsed() { @@ -354,7 +386,7 @@ final class OrderMapperTests: XCTestCase { /// private extension OrderMapperTests { - /// Returns the OrderMapper output upon receiving `filename` (Data Encoded) + /// Returns the Order output upon receiving `filename` (Data Encoded) /// func mapOrder(from filename: String) -> Order? { guard let response = Loader.contentsOf(filename) else { @@ -364,56 +396,62 @@ private extension OrderMapperTests { return try! OrderMapper(siteID: dummySiteID).map(response: response) } - /// Returns the OrderMapper output upon receiving `order` + /// Returns the Order output upon receiving `order` /// func mapLoadOrderResponse() -> Order? { return mapOrder(from: "order") } - /// Returns the OrderMapper output upon receiving `broken-order` + /// Returns the Order output upon receiving `order-without-data` + /// + func mapLoadOrderResponseWithoutDataEnvelope() -> Order? { + return mapOrder(from: "order-without-data") + } + + /// Returns the Order output upon receiving `broken-order` /// func mapLoadBrokenOrderResponse() -> Order? { return mapOrder(from: "broken-order") } - /// Returns the OrderMapper output upon receiving `order-fully-refunded` + /// Returns the Order output upon receiving `order-fully-refunded` /// func mapLoadFullyRefundedOrderResponse() -> Order? { return mapOrder(from: "order-fully-refunded") } - /// Returns the OrderMapper output upon receiving `order-details-partially-refunded` + /// Returns the Order output upon receiving `order-details-partially-refunded` /// func mapLoadPartiallRefundedOrderResponse() -> Order? { return mapOrder(from: "order-details-partially-refunded") } - /// Returns the OrderMapper output upon receiving `order-with-line-item-attributes` + /// Returns the Order output upon receiving `order-with-line-item-attributes` /// func mapLoadOrderWithLineItemAttributesResponse() -> Order? { return mapOrder(from: "order-with-line-item-attributes") } - /// Returns the OrderMapper output upon receiving `order-with-faulty-attributes` + /// Returns the Order output upon receiving `order-with-faulty-attributes` /// Where the `value` to `_measurement_data` is not a `string` but a `JSON object` /// func mapLoadOrderWithFaultyAttributesResponse() -> Order? { return mapOrder(from: "order-with-faulty-attributes") } - /// Returns the OrderMapper output upon receiving `order-with-line-item-attributes-before-API-support` + /// Returns the Order output upon receiving `order-with-line-item-attributes-before-API-support` /// func mapLoadOrderWithLineItemAttributesBeforeAPISupportResponse() -> Order? { return mapOrder(from: "order-with-line-item-attributes-before-API-support") } - /// Returns the OrderMapper output upon receiving `order-with-deleted-refunds` + /// Returns the Order output upon receiving `order-with-deleted-refunds` /// func mapLoadOrderWithDeletedRefundsResponse() -> Order? { return mapOrder(from: "order-with-deleted-refunds") } - /// Returns the OrderMapper output upon receiving `order-with-charge` + /// Returns the Order output upon receiving `order-with-charge` /// func mapLoadOrderWithChargeResponse() -> Order? { return mapOrder(from: "order-with-charge") diff --git a/Networking/NetworkingTests/Mapper/OrderNotesMapperTests.swift b/Networking/NetworkingTests/Mapper/OrderNotesMapperTests.swift index 3a13fd8cbdf..fe69c45bb93 100644 --- a/Networking/NetworkingTests/Mapper/OrderNotesMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/OrderNotesMapperTests.swift @@ -31,6 +31,31 @@ class OrderNotesMapperTests: XCTestCase { XCTAssertEqual(secondNote.author, "someuser") } + /// Verifies that all of the OrderNote Fields are parsed correctly. + /// + func test_Note_fields_are_properly_parsed_when_response_has_no_data_envelope() { + let notes = mapLoadAllOrderNotesResponseWithoutDataEnvelope() + XCTAssertEqual(notes.count, 2) + + let firstNote = notes[0] + let firstNoteCreated = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-06-23T16:05:55") + + XCTAssertEqual(firstNote.noteID, 2260) + XCTAssertEqual(firstNote.dateCreated, firstNoteCreated) + XCTAssertEqual(firstNote.note, "This order is going to be a problem.") + XCTAssertEqual(firstNote.isCustomerNote, false) + XCTAssertEqual(firstNote.author, "someadmin") + + let secondNote = notes[1] + let secondNoteCreated = DateFormatter.Defaults.dateTimeFormatter.date(from: "2018-06-23T17:06:55") + + XCTAssertEqual(secondNote.noteID, 2261) + XCTAssertEqual(secondNote.dateCreated, secondNoteCreated) + XCTAssertEqual(secondNote.note, "I love your products!") + XCTAssertEqual(secondNote.isCustomerNote, true) + XCTAssertEqual(secondNote.author, "someuser") + } + /// Verifies that an Note in a broken state does [gets default values] | [gets skipped while parsing] /// func test_Note_has_default_dateCreated_when_null_date_received() { @@ -52,7 +77,7 @@ class OrderNotesMapperTests: XCTestCase { /// private extension OrderNotesMapperTests { - /// Returns the OrderNotesMapper output upon receiving `filename` (Data Encoded) + /// Returns the [OrderNote] output upon receiving `filename` (Data Encoded) /// func mapNotes(from filename: String) -> [OrderNote] { guard let response = Loader.contentsOf(filename) else { @@ -62,13 +87,19 @@ private extension OrderNotesMapperTests { return try! OrderNotesMapper().map(response: response) } - /// Returns the OrderNotesMapper output upon receiving `orders-load-all` + /// Returns the [OrderNote] output upon receiving `order-notes` /// func mapLoadAllOrderNotesResponse() -> [OrderNote] { return mapNotes(from: "order-notes") } - /// Returns the OrderNotesMapper output upon receiving `broken-order` + /// Returns the [OrderNote] output upon receiving `order-notes-without-data` + /// + func mapLoadAllOrderNotesResponseWithoutDataEnvelope() -> [OrderNote] { + return mapNotes(from: "order-notes-without-data") + } + + /// Returns the [OrderNote] output upon receiving `broken-order` /// func mapLoadBrokenOrderNotesResponse() -> [OrderNote] { return mapNotes(from: "broken-notes") diff --git a/Networking/NetworkingTests/Mapper/ReportOrderTotalsMapperTests.swift b/Networking/NetworkingTests/Mapper/ReportOrderTotalsMapperTests.swift new file mode 100644 index 00000000000..8f8e06767d3 --- /dev/null +++ b/Networking/NetworkingTests/Mapper/ReportOrderTotalsMapperTests.swift @@ -0,0 +1,42 @@ +import XCTest +@testable import Networking + +final class ReportOrderTotalsMapperTests: XCTestCase { + + /// Dummy Site ID. + /// + private let dummySiteID: Int64 = 123 + + private let fileNameWithDataEnvelope = "report-orders-total" + private let fileNameWithoutDataEnvelope = "report-orders-total-without-data" + + func test_order_statuses_is_mapped_from_response_with_data_envelope() throws { + // Given + let mapper = ReportOrderTotalsMapper(siteID: dummySiteID) + guard let data = Loader.contentsOf(fileNameWithDataEnvelope) else { + XCTFail(fileNameWithDataEnvelope + ".json not found") + return + } + + // When + let statuses = try mapper.map(response: data) + + // Then + XCTAssertEqual(statuses.count, 8) + } + + func test_order_statuses_is_mapped_from_response_without_data_envelope() throws { + // Given + let mapper = ReportOrderTotalsMapper(siteID: dummySiteID) + guard let data = Loader.contentsOf(fileNameWithoutDataEnvelope) else { + XCTFail(fileNameWithoutDataEnvelope + ".json not found") + return + } + + // When + let statuses = try mapper.map(response: data) + + // Then + XCTAssertEqual(statuses.count, 8) + } +} diff --git a/Networking/NetworkingTests/Responses/order-notes-without-data.json b/Networking/NetworkingTests/Responses/order-notes-without-data.json new file mode 100644 index 00000000000..5f1a7148d7f --- /dev/null +++ b/Networking/NetworkingTests/Responses/order-notes-without-data.json @@ -0,0 +1,52 @@ +[ + { + "id": 2260, + "date_created": "2018-06-23T12:05:55", + "date_created_gmt": "2018-06-23T16:05:55", + "note": "This order is going to be a problem.", + "customer_note": false, + "author": "someadmin", + "_links": { + "self": [ + { + "href": "https:\/\/jamosova3.mystagingwebsite.com\/wp-json\/wc\/v2\/orders\/1044\/notes\/2260" + } + ], + "collection": [ + { + "href": "https:\/\/jamosova3.mystagingwebsite.com\/wp-json\/wc\/v2\/orders\/1044\/notes" + } + ], + "up": [ + { + "href": "https:\/\/jamosova3.mystagingwebsite.com\/wp-json\/wc\/v2\/orders\/1044" + } + ] + } + }, + { + "id": 2261, + "date_created": "2018-06-23T13:06:55", + "date_created_gmt": "2018-06-23T17:06:55", + "note": "I love your products!", + "customer_note": true, + "author": "someuser", + "_links": { + "self": [ + { + "href": "https:\/\/jamosova3.mystagingwebsite.com\/wp-json\/wc\/v2\/orders\/1044\/notes\/2261" + } + ], + "collection": [ + { + "href": "https:\/\/jamosova3.mystagingwebsite.com\/wp-json\/wc\/v2\/orders\/1044\/notes" + } + ], + "up": [ + { + "href": "https:\/\/jamosova3.mystagingwebsite.com\/wp-json\/wc\/v2\/orders\/1044" + } + ] + } + } +] diff --git a/Networking/NetworkingTests/Responses/order-without-data.json b/Networking/NetworkingTests/Responses/order-without-data.json new file mode 100644 index 00000000000..5dac9430f86 --- /dev/null +++ b/Networking/NetworkingTests/Responses/order-without-data.json @@ -0,0 +1,81 @@ +{ + "id": 963, + "parent_id": 0, + "is_editable": true, + "needs_payment": true, + "needs_processing": true, + "number": "963", + "status": "processing", + "order_key": "abc123", + "currency": "USD", + "date_created_gmt": "2018-04-03T23:05:12", + "date_modified_gmt": "2018-04-03T23:05:14", + "discount_total": "30.00", + "discount_tax": "1.20", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "1.20", + "total": "31.20", + "total_tax": "1.20", + "customer_id": 11, + "customer_note": "", + "billing": { + "first_name": "Johnny", + "last_name": "Appleseed", + "company": "", + "address_1": "234 70th Street", + "address_2": "", + "city": "Niagara Falls", + "state": "NY", + "postcode": "14304", + "country": "US", + "email": "scrambled@scrambled.com", + "phone": "333-333-3333" + }, + "shipping": { + "first_name": "Johnny", + "last_name": "Appleseed", + "company": "", + "address_1": "234 70th Street", + "address_2": "", + "city": "Niagara Falls", + "state": "NY", + "postcode": "14304", + "country": "US", + "email": "scrambled@scrambled.com", + "phone": "333-333-3333" + }, + "shipping_lines": [], + "fee_lines": [], + "tax_lines": [], + "payment_method": "stripe", + "payment_method_title": "Credit Card (Stripe)", + "payment_url": "http://www.automattic.com", + "date_paid_gmt": "2018-04-03T23:05:14", + "date_completed_gmt": null, + "line_items": [ + { + "id": 890, + "name": "Fruits Basket (Mix & Match Product)", + "product_id": 52, + "variation_id": 0, + "quantity": 2, + "price": 30.00, + "tax_class": "", + "subtotal": "50.00", + "subtotal_tax": "2.00", + "total": "30.00", + "total_tax": "1.20", + "taxes": [ + { + "id": 1, + "total": "1.2", + "subtotal": "2" + } + ], + "meta_data": [], + "sku": "" + } + ], + "coupon_lines": [] +} diff --git a/Networking/NetworkingTests/Responses/orders-load-all-without-data.json b/Networking/NetworkingTests/Responses/orders-load-all-without-data.json new file mode 100644 index 00000000000..7f82a4d4f07 --- /dev/null +++ b/Networking/NetworkingTests/Responses/orders-load-all-without-data.json @@ -0,0 +1,83 @@ +[ + { + "id": 963, + "parent_id": 0, + "is_editable": true, + "needs_payment": true, + "needs_processing": true, + "number": "963", + "status": "processing", + "order_key": "abc123", + "currency": "USD", + "date_created_gmt": "2018-04-03T23:05:12", + "date_modified_gmt": "2018-04-03T23:05:14", + "discount_total": "30.00", + "discount_tax": "1.20", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "1.20", + "total": "31.20", + "total_tax": "1.20", + "customer_id": 11, + "customer_note": "", + "billing": { + "first_name": "Johnny", + "last_name": "Appleseed", + "company": "", + "address_1": "234 70th Street", + "address_2": "", + "city": "Niagara Falls", + "state": "NY", + "postcode": "14304", + "country": "US", + "email": "scrambled@scrambled.com", + "phone": "333-333-3333" + }, + "shipping": { + "first_name": "Johnny", + "last_name": "Appleseed", + "company": "", + "address_1": "234 70th Street", + "address_2": "", + "city": "Niagara Falls", + "state": "NY", + "postcode": "14304", + "country": "US", + "email": "scrambled@scrambled.com", + "phone": "333-333-3333" + }, + "shipping_lines": [], + "fee_lines": [], + "tax_lines": [], + "payment_method": "stripe", + "payment_method_title": "Credit Card (Stripe)", + "payment_url": "http://www.automattic.com", + "date_paid_gmt": "2018-04-03T23:05:14", + "date_completed_gmt": null, + "line_items": [ + { + "id": 890, + "name": "Fruits Basket (Mix & Match Product)", + "product_id": 52, + "variation_id": 0, + "quantity": 2, + "price": 30.00, + "tax_class": "", + "subtotal": "50.00", + "subtotal_tax": "2.00", + "total": "30.00", + "total_tax": "1.20", + "taxes": [ + { + "id": 1, + "total": "1.2", + "subtotal": "2" + } + ], + "meta_data": [], + "sku": "" + } + ], + "coupon_lines": [] + } +] diff --git a/Networking/NetworkingTests/Responses/report-orders-total-without-data.json b/Networking/NetworkingTests/Responses/report-orders-total-without-data.json new file mode 100644 index 00000000000..b1d1d55fcf1 --- /dev/null +++ b/Networking/NetworkingTests/Responses/report-orders-total-without-data.json @@ -0,0 +1,42 @@ +[ + { + "slug": "pending", + "name": "Pending payment", + "total": 61 + }, + { + "slug": "processing", + "name": "Processing", + "total": 109 + }, + { + "slug": "on-hold", + "name": "On hold", + "total": 2 + }, + { + "slug": "completed", + "name": "Completed", + "total": 77 + }, + { + "slug": "cancelled", + "name": "Cancelled", + "total": 2 + }, + { + "slug": "refunded", + "name": "Refunded", + "total": 2 + }, + { + "slug": "failed", + "name": "Failed", + "total": 0 + }, + { + "slug": "checkout-draft", + "name": "Draft", + "total": 0 + } +] diff --git a/Networking/NetworkingTests/Responses/report-orders-total.json b/Networking/NetworkingTests/Responses/report-orders-total.json new file mode 100644 index 00000000000..6ade84f2970 --- /dev/null +++ b/Networking/NetworkingTests/Responses/report-orders-total.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "slug": "pending", + "name": "Pending payment", + "total": 61 + }, + { + "slug": "processing", + "name": "Processing", + "total": 109 + }, + { + "slug": "on-hold", + "name": "On hold", + "total": 2 + }, + { + "slug": "completed", + "name": "Completed", + "total": 77 + }, + { + "slug": "cancelled", + "name": "Cancelled", + "total": 2 + }, + { + "slug": "refunded", + "name": "Refunded", + "total": 2 + }, + { + "slug": "failed", + "name": "Failed", + "total": 0 + }, + { + "slug": "checkout-draft", + "name": "Draft", + "total": 0 + } + ] +}