diff --git a/Networking/Networking.xcodeproj/project.pbxproj b/Networking/Networking.xcodeproj/project.pbxproj index e78359326c9..572d8c77247 100644 --- a/Networking/Networking.xcodeproj/project.pbxproj +++ b/Networking/Networking.xcodeproj/project.pbxproj @@ -696,6 +696,7 @@ DE42F9632967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE42F9622967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift */; }; DE42F9652967F34400D514C2 /* refund-single-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F9642967F34400D514C2 /* refund-single-without-data.json */; }; DE42F9672967F61D00D514C2 /* refunds-all-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F9662967F61D00D514C2 /* refunds-all-without-data.json */; }; + DE42F96F296BC9A700D514C2 /* countries-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = DE42F96E296BC9A700D514C2 /* countries-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 */; }; DE50295D28C6068B00551736 /* JetpackUserMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE50295C28C6068B00551736 /* JetpackUserMapper.swift */; }; @@ -1507,6 +1508,7 @@ DE42F9622967C8B900D514C2 /* ReportOrderTotalsMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportOrderTotalsMapperTests.swift; sourceTree = ""; }; DE42F9642967F34400D514C2 /* refund-single-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "refund-single-without-data.json"; sourceTree = ""; }; DE42F9662967F61D00D514C2 /* refunds-all-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "refunds-all-without-data.json"; sourceTree = ""; }; + DE42F96E296BC9A700D514C2 /* countries-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "countries-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 = ""; }; DE50295C28C6068B00551736 /* JetpackUserMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackUserMapper.swift; sourceTree = ""; }; @@ -2127,6 +2129,7 @@ B559EBA820A0B5B100836CD4 /* Responses */ = { isa = PBXGroup; children = ( + DE42F96E296BC9A700D514C2 /* countries-without-data.json */, DE42F9662967F61D00D514C2 /* refunds-all-without-data.json */, DE42F9642967F34400D514C2 /* refund-single-without-data.json */, EE80A24B29556F1D003591E4 /* Coupon */, @@ -2947,6 +2950,7 @@ DEC51A9B274E3206009F3DF4 /* plugin-inactive.json in Resources */, CCF48B382628AEAE0034EA83 /* shipping-label-account-settings-no-payment-methods.json in Resources */, 31A451D327863A2E00FE81AA /* stripe-account-complete.json in Resources */, + DE42F96F296BC9A700D514C2 /* countries-without-data.json in Resources */, EECB7EE8286555180028C888 /* media-update-product-id.json in Resources */, D88D5A43230BC668007B6E01 /* reviews-single.json in Resources */, DE5CA111288A3E080077BEF9 /* product-malformed-variations-and-image-alt.json in Resources */, diff --git a/Networking/Networking/Mapper/CountryListMapper.swift b/Networking/Networking/Mapper/CountryListMapper.swift index f4242f7c266..990efe991dc 100644 --- a/Networking/Networking/Mapper/CountryListMapper.swift +++ b/Networking/Networking/Mapper/CountryListMapper.swift @@ -8,7 +8,11 @@ struct CountryListMapper: Mapper { /// (Attempts) to convert an instance of Data into an array of Country Entities. /// func map(response: Data) throws -> [Country] { - return try JSONDecoder().decode(CountryListEnvelope.self, from: response).data + do { + return try JSONDecoder().decode(CountryListEnvelope.self, from: response).data + } catch { + return try JSONDecoder().decode([Country].self, from: response) + } } } diff --git a/Networking/Networking/Remote/DataRemote.swift b/Networking/Networking/Remote/DataRemote.swift index e4ed52cc70b..395af0fb7e5 100644 --- a/Networking/Networking/Remote/DataRemote.swift +++ b/Networking/Networking/Remote/DataRemote.swift @@ -8,7 +8,11 @@ public final class DataRemote: Remote { /// - siteID: Remote ID of the site that owns the countries. /// - completion: Closure to be executed upon completion. public func loadCountries(siteID: Int64, completion: @escaping (Result<[Country], Error>) -> Void) { - let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: Path.countries) + let request = JetpackRequest(wooApiVersion: .mark3, + method: .get, + siteID: siteID, + path: Path.countries, + availableAsRESTRequest: true) let mapper = CountryListMapper() enqueue(request, mapper: mapper, completion: completion) } diff --git a/Networking/NetworkingTests/Mapper/CountryListMapperTests.swift b/Networking/NetworkingTests/Mapper/CountryListMapperTests.swift index a0c9d68b7d4..18f6b49680b 100644 --- a/Networking/NetworkingTests/Mapper/CountryListMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/CountryListMapperTests.swift @@ -21,6 +21,20 @@ class CountryListMapperTests: XCTestCase { XCTAssertEqual(countries[1].states.count, 18) XCTAssertEqual(countries[1].states.first, StateOfACountry(code: "PY-ASU", name: "Asunción")) } + + func test_countries_are_properly_parsed_if_the_response_has_no_data_envelope() { + guard let countries = mapCountriesResponseWithoutDataEnvelope() else { + XCTFail() + return + } + + XCTAssertEqual(countries.count, 3) + XCTAssertEqual(countries.first?.states.isEmpty, true) + XCTAssertEqual(countries[1].code, "PY") + XCTAssertEqual(countries[1].name, "Paraguay") + XCTAssertEqual(countries[1].states.count, 18) + XCTAssertEqual(countries[1].states.first, StateOfACountry(code: "PY-ASU", name: "Asunción")) + } } /// Private Helpers @@ -37,9 +51,15 @@ private extension CountryListMapperTests { return try! CountryListMapper().map(response: response) } - /// Returns the CountryListMapper output upon receiving `countries` + /// Returns the [Country] output upon receiving `countries` /// func mapCountriesResponse() -> [Country]? { return mapCountries(from: "countries") } + + /// Returns the [Country] output upon receiving `countries-without-data` + /// + func mapCountriesResponseWithoutDataEnvelope() -> [Country]? { + return mapCountries(from: "countries-without-data") + } } diff --git a/Networking/NetworkingTests/Responses/countries-without-data.json b/Networking/NetworkingTests/Responses/countries-without-data.json new file mode 100644 index 00000000000..bc36b18f5bf --- /dev/null +++ b/Networking/NetworkingTests/Responses/countries-without-data.json @@ -0,0 +1,343 @@ +[ + { + "code": "AT", + "name": "Austria", + "states": [], + "_links": { + "self": [ + { + "href": "https://test.com/wp-json/wc/v3/data/countries/at" + } + ], + "collection": [ + { + "href": "https://test.com/wp-json/wc/v3/data/countries" + } + ] + } + }, + { + "code": "PY", + "name": "Paraguay", + "states": [ + { + "code": "PY-ASU", + "name": "Asunción" + }, + { + "code": "PY-1", + "name": "Concepción" + }, + { + "code": "PY-2", + "name": "San Pedro" + }, + { + "code": "PY-3", + "name": "Cordillera" + }, + { + "code": "PY-4", + "name": "Guairá" + }, + { + "code": "PY-5", + "name": "Caaguazú" + }, + { + "code": "PY-6", + "name": "Caazapá" + }, + { + "code": "PY-7", + "name": "Itapúa" + }, + { + "code": "PY-8", + "name": "Misiones" + }, + { + "code": "PY-9", + "name": "Paraguarí" + }, + { + "code": "PY-10", + "name": "Alto Paraná" + }, + { + "code": "PY-11", + "name": "Central" + }, + { + "code": "PY-12", + "name": "Ñeembucú" + }, + { + "code": "PY-13", + "name": "Amambay" + }, + { + "code": "PY-14", + "name": "Canindeyú" + }, + { + "code": "PY-15", + "name": "Presidente Hayes" + }, + { + "code": "PY-16", + "name": "Alto Paraguay" + }, + { + "code": "PY-17", + "name": "Boquerón" + } + ], + "_links": { + "self": [ + { + "href": "https://test.com/wp-json/wc/v3/data/countries/py" + } + ], + "collection": [ + { + "href": "https://test.com/wp-json/wc/v3/data/countries" + } + ] + } + }, + { + "code": "US", + "name": "United States (US)", + "states": [ + { + "code": "AL", + "name": "Alabama" + }, + { + "code": "AK", + "name": "Alaska" + }, + { + "code": "AZ", + "name": "Arizona" + }, + { + "code": "AR", + "name": "Arkansas" + }, + { + "code": "CA", + "name": "California" + }, + { + "code": "CO", + "name": "Colorado" + }, + { + "code": "CT", + "name": "Connecticut" + }, + { + "code": "DE", + "name": "Delaware" + }, + { + "code": "DC", + "name": "District Of Columbia" + }, + { + "code": "FL", + "name": "Florida" + }, + { + "code": "GA", + "name": "Georgia" + }, + { + "code": "HI", + "name": "Hawaii" + }, + { + "code": "ID", + "name": "Idaho" + }, + { + "code": "IL", + "name": "Illinois" + }, + { + "code": "IN", + "name": "Indiana" + }, + { + "code": "IA", + "name": "Iowa" + }, + { + "code": "KS", + "name": "Kansas" + }, + { + "code": "KY", + "name": "Kentucky" + }, + { + "code": "LA", + "name": "Louisiana" + }, + { + "code": "ME", + "name": "Maine" + }, + { + "code": "MD", + "name": "Maryland" + }, + { + "code": "MA", + "name": "Massachusetts" + }, + { + "code": "MI", + "name": "Michigan" + }, + { + "code": "MN", + "name": "Minnesota" + }, + { + "code": "MS", + "name": "Mississippi" + }, + { + "code": "MO", + "name": "Missouri" + }, + { + "code": "MT", + "name": "Montana" + }, + { + "code": "NE", + "name": "Nebraska" + }, + { + "code": "NV", + "name": "Nevada" + }, + { + "code": "NH", + "name": "New Hampshire" + }, + { + "code": "NJ", + "name": "New Jersey" + }, + { + "code": "NM", + "name": "New Mexico" + }, + { + "code": "NY", + "name": "New York" + }, + { + "code": "NC", + "name": "North Carolina" + }, + { + "code": "ND", + "name": "North Dakota" + }, + { + "code": "OH", + "name": "Ohio" + }, + { + "code": "OK", + "name": "Oklahoma" + }, + { + "code": "OR", + "name": "Oregon" + }, + { + "code": "PA", + "name": "Pennsylvania" + }, + { + "code": "RI", + "name": "Rhode Island" + }, + { + "code": "SC", + "name": "South Carolina" + }, + { + "code": "SD", + "name": "South Dakota" + }, + { + "code": "TN", + "name": "Tennessee" + }, + { + "code": "TX", + "name": "Texas" + }, + { + "code": "UT", + "name": "Utah" + }, + { + "code": "VT", + "name": "Vermont" + }, + { + "code": "VA", + "name": "Virginia" + }, + { + "code": "WA", + "name": "Washington" + }, + { + "code": "WV", + "name": "West Virginia" + }, + { + "code": "WI", + "name": "Wisconsin" + }, + { + "code": "WY", + "name": "Wyoming" + }, + { + "code": "AA", + "name": "Armed Forces (AA)" + }, + { + "code": "AE", + "name": "Armed Forces (AE)" + }, + { + "code": "AP", + "name": "Armed Forces (AP)" + } + ], + "_links": { + "self": [ + { + "href": "https://test.com/wp-json/wc/v3/data/countries/us" + } + ], + "collection": [ + { + "href": "https://test.com/wp-json/wc/v3/data/countries" + } + ] + } + } +]