diff --git a/Networking/Networking.xcodeproj/project.pbxproj b/Networking/Networking.xcodeproj/project.pbxproj index 449b2759930..492224b5fab 100644 --- a/Networking/Networking.xcodeproj/project.pbxproj +++ b/Networking/Networking.xcodeproj/project.pbxproj @@ -699,6 +699,8 @@ DE42F96B296BC23800D514C2 /* customer-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F96A296BC23800D514C2 /* customer-without-data.json */; }; DE42F96D296BC67E00D514C2 /* wc-analytics-customers-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F96C296BC67E00D514C2 /* wc-analytics-customers-without-data.json */; }; DE42F96F296BC9A700D514C2 /* countries-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F96E296BC9A700D514C2 /* countries-without-data.json */; }; + DE4F2A3F29750EF400B0701C /* inbox-note-list-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE4F2A3D29750EF400B0701C /* inbox-note-list-without-data.json */; }; + DE4F2A4029750EF400B0701C /* inbox-note-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE4F2A3E29750EF400B0701C /* inbox-note-without-data.json */; }; DE4F2A4229751EAE00B0701C /* setting-coupon-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE4F2A4129751EAE00B0701C /* setting-coupon-without-data.json */; }; DE50295928C5BD0200551736 /* JetpackUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE50295828C5BD0200551736 /* JetpackUser.swift */; }; DE50295B28C5F99700551736 /* DotcomUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE50295A28C5F99700551736 /* DotcomUser.swift */; }; @@ -1519,6 +1521,8 @@ DE42F96A296BC23800D514C2 /* customer-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "customer-without-data.json"; sourceTree = ""; }; DE42F96C296BC67E00D514C2 /* wc-analytics-customers-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "wc-analytics-customers-without-data.json"; sourceTree = ""; }; DE42F96E296BC9A700D514C2 /* countries-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "countries-without-data.json"; sourceTree = ""; }; + DE4F2A3D29750EF400B0701C /* inbox-note-list-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "inbox-note-list-without-data.json"; sourceTree = ""; }; + DE4F2A3E29750EF400B0701C /* inbox-note-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "inbox-note-without-data.json"; sourceTree = ""; }; DE4F2A4129751EAE00B0701C /* setting-coupon-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "setting-coupon-without-data.json"; 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 = ""; }; @@ -2145,6 +2149,8 @@ B559EBA820A0B5B100836CD4 /* Responses */ = { isa = PBXGroup; children = ( + DE4F2A3D29750EF400B0701C /* inbox-note-list-without-data.json */, + DE4F2A3E29750EF400B0701C /* inbox-note-without-data.json */, DE4F2A4129751EAE00B0701C /* setting-coupon-without-data.json */, DEEDA4432975003800F845AB /* settings-general-without-data.json */, DEA6B1C8296D0E8A005AA5E9 /* systemStatus-without-data.json */, @@ -2939,6 +2945,7 @@ 09885C8027C3FFD200910A62 /* product-variations-bulk-update.json in Resources */, 31054734262E36AB00C5C02B /* wcpay-payment-intent-error.json in Resources */, 02AF07EE27493AE700B2D81E /* media-upload-to-wordpress-site.json in Resources */, + DE4F2A4029750EF400B0701C /* inbox-note-without-data.json in Resources */, 45ED4F12239E8C57004F1BE3 /* taxes-classes.json in Resources */, B5A2417B217F98FC00595DEF /* broken-notifications.json in Resources */, 3158A4A32729F42500C3CFA8 /* wcpay-account-dev-test.json in Resources */, @@ -3153,6 +3160,7 @@ 02698CFA24C188E9005337C4 /* product-variations-load-all-alternative-types.json in Resources */, 02616F902921336C0095BC00 /* site-creation-success.json in Resources */, CC0786632678F79500BA9AC1 /* shipping-label-purchase-success.json in Resources */, + DE4F2A3F29750EF400B0701C /* inbox-note-list-without-data.json in Resources */, 7497376A2141F2BE0008C490 /* top-performers-week-alt.json in Resources */, DEEDA4442975003800F845AB /* settings-general-without-data.json in Resources */, D865CE61278CA1AE002C8520 /* stripe-payment-intent-processing.json in Resources */, diff --git a/Networking/Networking/Mapper/InboxNoteListMapper.swift b/Networking/Networking/Mapper/InboxNoteListMapper.swift index 67e581056a5..13696f06d43 100644 --- a/Networking/Networking/Mapper/InboxNoteListMapper.swift +++ b/Networking/Networking/Mapper/InboxNoteListMapper.swift @@ -17,7 +17,11 @@ struct InboxNoteListMapper: Mapper { decoder.userInfo = [ .siteID: siteID ] - return try decoder.decode(InboxNoteListEnvelope.self, from: response).data + do { + return try decoder.decode(InboxNoteListEnvelope.self, from: response).data + } catch { + return try decoder.decode([InboxNote].self, from: response) + } } } diff --git a/Networking/Networking/Mapper/InboxNoteMapper.swift b/Networking/Networking/Mapper/InboxNoteMapper.swift index 34393f05cee..f208d06f20d 100644 --- a/Networking/Networking/Mapper/InboxNoteMapper.swift +++ b/Networking/Networking/Mapper/InboxNoteMapper.swift @@ -17,7 +17,11 @@ struct InboxNoteMapper: Mapper { decoder.userInfo = [ .siteID: siteID ] - return try decoder.decode(InboxNoteEnvelope.self, from: response).data + do { + return try decoder.decode(InboxNoteEnvelope.self, from: response).data + } catch { + return try decoder.decode(InboxNote.self, from: response) + } } } diff --git a/Networking/Networking/Remote/InboxNotesRemote.swift b/Networking/Networking/Remote/InboxNotesRemote.swift index c93b8754efe..fef97851b58 100644 --- a/Networking/Networking/Remote/InboxNotesRemote.swift +++ b/Networking/Networking/Remote/InboxNotesRemote.swift @@ -76,7 +76,8 @@ public final class InboxNotesRemote: Remote, InboxNotesRemoteProtocol { method: .get, siteID: siteID, path: Path.notes, - parameters: parameters) + parameters: parameters, + availableAsRESTRequest: true) let mapper = InboxNoteListMapper(siteID: siteID) @@ -100,7 +101,8 @@ public final class InboxNotesRemote: Remote, InboxNotesRemoteProtocol { method: .delete, siteID: siteID, path: Path.notes + "/delete/\(noteID)", - parameters: [ParameterKey.fields: ParameterValue.noteFields]) + parameters: [ParameterKey.fields: ParameterValue.noteFields], + availableAsRESTRequest: true) let mapper = InboxNoteMapper(siteID: siteID) @@ -148,7 +150,8 @@ public final class InboxNotesRemote: Remote, InboxNotesRemoteProtocol { method: .delete, siteID: siteID, path: Path.notes + "/delete/all", - parameters: parameters) + parameters: parameters, + availableAsRESTRequest: true) let mapper = InboxNoteListMapper(siteID: siteID) @@ -175,7 +178,8 @@ public final class InboxNotesRemote: Remote, InboxNotesRemoteProtocol { method: .post, siteID: siteID, path: Path.notes + "/\(noteID)/action/\(actionID)", - parameters: [ParameterKey.fields: ParameterValue.noteFields]) + parameters: [ParameterKey.fields: ParameterValue.noteFields], + availableAsRESTRequest: true) let mapper = InboxNoteMapper(siteID: siteID) diff --git a/Networking/NetworkingTests/Mapper/InboxNoteListMapperTests.swift b/Networking/NetworkingTests/Mapper/InboxNoteListMapperTests.swift index 2bea675087a..14772b858bf 100644 --- a/Networking/NetworkingTests/Mapper/InboxNoteListMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/InboxNoteListMapperTests.swift @@ -14,6 +14,13 @@ final class InboxNoteListMapperTests: XCTestCase { XCTAssertEqual(inboxNotes.count, 24) } + /// Verifies that the whole list is parsed when response has no data envelope. + /// + func test_InboxNoteListMapper_parses_all_InboxNotes_in_response_without_data_envelope() throws { + let inboxNotes = try mapLoadInboxNoteListResponseWithoutDataEnvelope() + XCTAssertEqual(inboxNotes.count, 2) + } + /// Verifies that the `siteID` is added in the mapper, to all results, because it's not provided by the API endpoint. /// func test_InboxNoteListMapper_includes_siteID_in_parsed_results() throws { @@ -77,4 +84,10 @@ private extension InboxNoteListMapperTests { func mapLoadInboxNoteListResponse() throws -> [InboxNote] { return try mapInboxNoteList(from: "inbox-note-list") } + + /// Returns the InboxNoteListMapper output from `inbox-note-list-without-data.json` + /// + func mapLoadInboxNoteListResponseWithoutDataEnvelope() throws -> [InboxNote] { + return try mapInboxNoteList(from: "inbox-note-list-without-data") + } } diff --git a/Networking/NetworkingTests/Mapper/InboxNoteMapperTests.swift b/Networking/NetworkingTests/Mapper/InboxNoteMapperTests.swift index 80216d0541b..19bcd8074ed 100644 --- a/Networking/NetworkingTests/Mapper/InboxNoteMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/InboxNoteMapperTests.swift @@ -7,13 +7,20 @@ final class InboxNoteMapperTests: XCTestCase { /// private let dummySiteID: Int64 = 12983476 - /// Verifies that the whole list is parsed. + /// Verifies that the inbox note is parsed. /// func test_InboxNoteMapper_parses_the_InboxNote_in_response() throws { let inboxNote = try mapLoadInboxNoteResponse() XCTAssertNotNil(inboxNote) } + /// Verifies that the inbox note is parsed when response has no data envelope. + /// + func test_InboxNoteMapper_parses_the_InboxNote_in_response_without_data_envelope() throws { + let inboxNote = try mapLoadInboxNoteResponseWithoutDataEnvelope() + XCTAssertNotNil(inboxNote) + } + /// Verifies that the `siteID` is added in the mapper, because it's not provided by the API endpoint. /// func test_InboxNoteMapper_includes_siteID_in_parsed_result() throws { @@ -83,6 +90,12 @@ private extension InboxNoteMapperTests { return try mapInboxNote(from: "inbox-note") } + /// Returns the InboxNoteMapper output from `inbox-note-without-data.json` + /// + func mapLoadInboxNoteResponseWithoutDataEnvelope() throws -> InboxNote? { + return try mapInboxNote(from: "inbox-note-without-data") + } + /// Returns the InboxNoteMapper output from `inbox-note-without-isRead.json` /// func mapLoadInboxNoteWithoutIsReadResponse() throws -> InboxNote? { diff --git a/Networking/NetworkingTests/Responses/inbox-note-list-without-data.json b/Networking/NetworkingTests/Responses/inbox-note-list-without-data.json new file mode 100644 index 00000000000..f5cd2628b53 --- /dev/null +++ b/Networking/NetworkingTests/Responses/inbox-note-list-without-data.json @@ -0,0 +1,55 @@ +[ + { + "id": 291, + "name": "wc-admin-launch-checklist", + "type": "info", + "locale": "en_US", + "title": "Ready to launch your store?", + "content": "To make sure you never get that sinking \"what did I forget\" feeling, we've put together the essential pre-launch checklist.", + "status": "unactioned", + "date_created": "2022-01-26T09:02:08", + "actions": [{ + "id": 13225, + "name": "learn-more", + "label": "Learn more", + "query": "https:\/\/woocommerce.com\/posts\/pre-launch-checklist-the-essentials\/?utm_source=inbox&utm_medium=product", + "status": "actioned", + "primary": false, + "actioned_text": "", + "nonce_action": null, + "nonce_name": null, + "url": "https:\/\/woocommerce.com\/posts\/pre-launch-checklist-the-essentials\/?utm_source=inbox&utm_medium=product" + }], + "layout": "plain", + "image": "", + "is_deleted": false, + "is_read": false, + "date_created_gmt": "2022-01-26T14:32:08" + }, { + "id": 97, + "name": "wc-admin-optimizing-the-checkout-flow", + "type": "info", + "locale": "en_US", + "title": "Optimizing the checkout flow", + "content": "It's crucial to get your store's checkout as smooth as possible to avoid losing sales. Let's take a look at how you can optimize the checkout experience for your shoppers.", + "status": "unactioned", + "date_created": "2022-01-26T09:02:08", + "actions": [{ + "id": 13271, + "name": "optimizing-the-checkout-flow", + "label": "Learn more", + "query": "https:\/\/woocommerce.com\/posts\/optimizing-woocommerce-checkout?utm_source=inbox", + "status": "actioned", + "primary": true, + "actioned_text": "", + "nonce_action": null, + "nonce_name": null, + "url": "https:\/\/woocommerce.com\/posts\/optimizing-woocommerce-checkout?utm_source=inbox" + }], + "layout": "plain", + "image": "", + "is_deleted": false, + "is_read": false, + "date_created_gmt": "2022-01-26T14:32:08" + } +] diff --git a/Networking/NetworkingTests/Responses/inbox-note-without-data.json b/Networking/NetworkingTests/Responses/inbox-note-without-data.json new file mode 100644 index 00000000000..65c3aa8c7ae --- /dev/null +++ b/Networking/NetworkingTests/Responses/inbox-note-without-data.json @@ -0,0 +1,52 @@ +{ + "id": 296, + "name": "wc-admin-wc-helper-subscription", + "type": "warning", + "locale": "en_US", + "title": "WooCommerce Bookings subscription expired", + "content": "Your subscription expired on October 22nd. Get a new subscription to continue receiving updates and access to support.", + "content_data": { + "product_id": 390890, + "product_name": "WooCommerce Bookings", + "expired": true, + "expires": 1634860800, + "expires_date": "October 22nd" + }, + "status": "unactioned", + "source": "woocommerce-admin", + "date_created": "2022-01-31T08:55:32", + "date_reminder": null, + "is_snoozable": false, + "actions": [ + { + "id": 13329, + "name": "renew-subscription", + "label": "Renew Subscription", + "query": "https://woocommerce.com/products/woocommerce-bookings/", + "status": "actioned", + "primary": false, + "actioned_text": "", + "nonce_action": null, + "nonce_name": null, + "url": "https://woocommerce.com/products/woocommerce-bookings/" + } + ], + "layout": "plain", + "image": "", + "is_deleted": true, + "is_read": false, + "date_created_gmt": "2022-01-31T14:25:32", + "date_reminder_gmt": null, + "_links": { + "self": [ + { + "href": "https://mywootesting.mystagingwebsite.com/wp-json/wc-analytics/admin/notes/296" + } + ], + "collection": [ + { + "href": "https://mywootesting.mystagingwebsite.com/wp-json/wc-analytics/admin/notes" + } + ] + } +}