Skip to content

Commit 73eff71

Browse files
Merge pull request #8743 from woocommerce/feat/8742-shipments-migration
[REST API] Migrate shipment tracking provider endpoints
2 parents 6097649 + 13d9151 commit 73eff71

12 files changed

+375
-12
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,11 @@
814814
EE57C146297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE57C145297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift */; };
815815
EE57C148297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE57C147297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift */; };
816816
EE57C14A2980CE4B00BC31E7 /* taxes-classes-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C1492980CE4B00BC31E7 /* taxes-classes-without-data.json */; };
817+
EE57C14E2980E71200BC31E7 /* NewShipmentTrackingMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE57C14D2980E71200BC31E7 /* NewShipmentTrackingMapperTests.swift */; };
818+
EE57C1502980F0B700BC31E7 /* shipment_tracking_new-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C14F2980F0B700BC31E7 /* shipment_tracking_new-without-data.json */; };
819+
EE57C1542980F18500BC31E7 /* ShipmentTrackingProviderListMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE57C1532980F18500BC31E7 /* ShipmentTrackingProviderListMapperTests.swift */; };
820+
EE57C1562980F3BF00BC31E7 /* shipment_tracking_single_without_data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C1552980F3BF00BC31E7 /* shipment_tracking_single_without_data.json */; };
821+
EE57C1582980F3D400BC31E7 /* shipment_tracking_providers_without_data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C1572980F3D400BC31E7 /* shipment_tracking_providers_without_data.json */; };
817822
EE62EE61295ACF8D009C965B /* RequestConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE62EE60295ACF8D009C965B /* RequestConverterTests.swift */; };
818823
EE62EE63295AD45E009C965B /* String+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE62EE62295AD45E009C965B /* String+URL.swift */; };
819824
EE62EE65295AD46D009C965B /* String+URLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE62EE64295AD46D009C965B /* String+URLTests.swift */; };
@@ -1686,6 +1691,11 @@
16861691
EE57C145297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductShippingClassListMapperTests.swift; sourceTree = "<group>"; };
16871692
EE57C147297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductShippingClassMapperTests.swift; sourceTree = "<group>"; };
16881693
EE57C1492980CE4B00BC31E7 /* taxes-classes-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "taxes-classes-without-data.json"; sourceTree = "<group>"; };
1694+
EE57C14D2980E71200BC31E7 /* NewShipmentTrackingMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewShipmentTrackingMapperTests.swift; sourceTree = "<group>"; };
1695+
EE57C14F2980F0B700BC31E7 /* shipment_tracking_new-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "shipment_tracking_new-without-data.json"; sourceTree = "<group>"; };
1696+
EE57C1532980F18500BC31E7 /* ShipmentTrackingProviderListMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShipmentTrackingProviderListMapperTests.swift; sourceTree = "<group>"; };
1697+
EE57C1552980F3BF00BC31E7 /* shipment_tracking_single_without_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = shipment_tracking_single_without_data.json; sourceTree = "<group>"; };
1698+
EE57C1572980F3D400BC31E7 /* shipment_tracking_providers_without_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = shipment_tracking_providers_without_data.json; sourceTree = "<group>"; };
16891699
EE62EE60295ACF8D009C965B /* RequestConverterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestConverterTests.swift; sourceTree = "<group>"; };
16901700
EE62EE62295AD45E009C965B /* String+URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+URL.swift"; sourceTree = "<group>"; };
16911701
EE62EE64295AD46D009C965B /* String+URLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+URLTests.swift"; sourceTree = "<group>"; };
@@ -2473,12 +2483,15 @@
24732483
74159627224D63CE003C21CF /* settings-product-alt.json */,
24742484
743E84F022172D0900FAC9D7 /* shipment_tracking_empty.json */,
24752485
743E84F522172D3E00FAC9D7 /* shipment_tracking_single.json */,
2486+
EE57C1552980F3BF00BC31E7 /* shipment_tracking_single_without_data.json */,
24762487
743E84F122172D0900FAC9D7 /* shipment_tracking_multiple.json */,
24772488
743E84EF22172D0900FAC9D7 /* shipment_tracking_plugin_not_active.json */,
24782489
D823D9022237450A00C90817 /* shipment_tracking_new.json */,
2490+
EE57C14F2980F0B700BC31E7 /* shipment_tracking_new-without-data.json */,
24792491
D823D90622376B4800C90817 /* shipment_tracking_new_custom_provider.json */,
24802492
D823D90A22376EFE00C90817 /* shipment_tracking_delete.json */,
24812493
D823D91322377EE600C90817 /* shipment_tracking_providers.json */,
2494+
EE57C1572980F3D400BC31E7 /* shipment_tracking_providers_without_data.json */,
24822495
451A97DD260B59870059D135 /* shipping-label-packages-success.json */,
24832496
02E7FFCE25621C7900C53030 /* shipping-label-print.json */,
24842497
028FA471257E110700F88A48 /* shipping-label-refund-error.json */,
@@ -2765,6 +2778,7 @@
27652778
036563DE29069C8F00D84BFD /* JustInTimeMessageListMapperTests.swift */,
27662779
B554FA922180C17200C54DFF /* NoteHashListMapperTests.swift */,
27672780
B5C151BF217EE3FB00C7BDC1 /* NoteListMapperTests.swift */,
2781+
EE57C14D2980E71200BC31E7 /* NewShipmentTrackingMapperTests.swift */,
27682782
B5C6FCCC20A34B8300A4F8E4 /* OrderListMapperTests.swift */,
27692783
74C8F06920EEBC8C00B6EDC9 /* OrderMapperTests.swift */,
27702784
74C8F06D20EEC1E700B6EDC9 /* OrderNotesMapperTests.swift */,
@@ -2789,6 +2803,7 @@
27892803
7412A8ED21B6E335005D182A /* ReportOrderMapperTests.swift */,
27902804
743E84F722172E1F00FAC9D7 /* ShipmentTrackingListMapperTests.swift */,
27912805
74AB5B4C21AF354E00859C12 /* SiteAPIMapperTests.swift */,
2806+
EE57C1532980F18500BC31E7 /* ShipmentTrackingProviderListMapperTests.swift */,
27922807
2670C3FB270F4E06002FE931 /* SiteListMapperTests.swift */,
27932808
453305EA2459E01A00264E50 /* PostMapperTests.swift */,
27942809
311976DF2602BD4B006AC56C /* SitePluginsMapperTests.swift */,
@@ -3131,6 +3146,7 @@
31313146
DE34051B28BDF12C00CF0D97 /* jetpack-connection-url.json in Resources */,
31323147
D823D91422377EE600C90817 /* shipment_tracking_providers.json in Resources */,
31333148
4599FC5C24A6276F0056157A /* product-tags-all.json in Resources */,
3149+
EE57C1562980F3BF00BC31E7 /* shipment_tracking_single_without_data.json in Resources */,
31343150
03DCB77E262738E300C8953D /* coupon.json in Resources */,
31353151
688908AE28FF920C0081A07E /* customer-2.json in Resources */,
31363152
034480C327A42F9100DFACD2 /* order-with-charge.json in Resources */,
@@ -3237,6 +3253,7 @@
32373253
D823D90B22376EFE00C90817 /* shipment_tracking_delete.json in Resources */,
32383254
31A451D727863A2E00FE81AA /* stripe-account-dev-test.json in Resources */,
32393255
74C947832193A6C70024CB60 /* comment-moderate-trash.json in Resources */,
3256+
EE57C1582980F3D400BC31E7 /* shipment_tracking_providers_without_data.json in Resources */,
32403257
B58D10CA2114D22E00107ED4 /* new-order-note.json in Resources */,
32413258
D865CE6B278CA266002C8520 /* stripe-payment-intent-error.json in Resources */,
32423259
CCB2CAA82620ABCC00285CA0 /* shipping-label-create-package-error.json in Resources */,
@@ -3339,6 +3356,7 @@
33393356
74A1D266211898F000931DFA /* site-visits-year.json in Resources */,
33403357
743BF8BE21191B63008A9D87 /* site-visits.json in Resources */,
33413358
CE0A0F1F223998A10075ED8D /* products-load-all.json in Resources */,
3359+
EE57C1502980F0B700BC31E7 /* shipment_tracking_new-without-data.json in Resources */,
33423360
D8A284F425FBB48D0019A84B /* product-attribute-terms.json in Resources */,
33433361
74E30951216E8DCE00ABCE4C /* site-visits-alt.json in Resources */,
33443362
74ABA1C5213F17AA00FFAD30 /* top-performers-day.json in Resources */,
@@ -3951,6 +3969,7 @@
39513969
B518662A20A09C6F00037A38 /* OrdersRemoteTests.swift in Sources */,
39523970
02EF166E292F0C5800D90AD6 /* PaymentRemoteTests.swift in Sources */,
39533971
B5969E1520A47F99005E9DF1 /* RemoteTests.swift in Sources */,
3972+
EE57C14E2980E71200BC31E7 /* NewShipmentTrackingMapperTests.swift in Sources */,
39543973
74C8F06E20EEC1E800B6EDC9 /* OrderNotesMapperTests.swift in Sources */,
39553974
45ED4F10239E8A54004F1BE3 /* TaxClassListMapperTest.swift in Sources */,
39563975
FE28F6EA26842E49004465C7 /* UserMapperTests.swift in Sources */,
@@ -3985,6 +4004,7 @@
39854004
DEFBA7562949D17400C35BA9 /* DefaultRequestAuthenticatorTests.swift in Sources */,
39864005
CC07866526790B1100BA9AC1 /* ShippingLabelPurchaseMapperTests.swift in Sources */,
39874006
74002D6A2118B26100A63C19 /* SiteVisitStatsMapperTests.swift in Sources */,
4007+
EE57C1542980F18500BC31E7 /* ShipmentTrackingProviderListMapperTests.swift in Sources */,
39884008
743E84FA221742E300FAC9D7 /* ShipmentsRemoteTests.swift in Sources */,
39894009
EE57C148297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift in Sources */,
39904010
03DCB7822627394500C8953D /* CouponMapperTests.swift in Sources */,

Networking/Networking/Mapper/NewShipmentTrackingMapper.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ struct NewShipmentTrackingMapper: Mapper {
2222
.siteID: siteID,
2323
.orderID: orderID
2424
]
25-
return try decoder.decode(NewShipmentTrackingMapperEnvelope.self, from: response).shipmentTracking
25+
26+
do {
27+
return try decoder.decode(NewShipmentTrackingMapperEnvelope.self, from: response).shipmentTracking
28+
} catch {
29+
return try decoder.decode(ShipmentTracking.self, from: response)
30+
}
2631
}
2732
}
2833

Networking/Networking/Mapper/ShipmentTrackingListMapper.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ struct ShipmentTrackingListMapper: Mapper {
2727
.orderID: orderID
2828
]
2929

30-
return try decoder.decode(ShipmentTrackingListEnvelope.self, from: response).shipmentTrackings
30+
do {
31+
return try decoder.decode(ShipmentTrackingListEnvelope.self, from: response).shipmentTrackings
32+
} catch {
33+
return try decoder.decode([ShipmentTracking].self, from: response)
34+
}
3135
}
3236
}
3337

Networking/Networking/Mapper/ShipmentTrackingProviderListMapper.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ struct ShipmentTrackingProviderListMapper: Mapper {
1111

1212
func map(response: Data) throws -> [ShipmentTrackingProviderGroup] {
1313
let decoder = JSONDecoder()
14-
let rawDictionary = try? decoder.decode(ShipmentTrackingProviderListEnvelope.self, from: response).rawData
15-
return rawDictionary?.map({ ShipmentTrackingProviderGroup(name: $0.key, siteID: siteID, dictionary: $0.value) }) ?? []
14+
let rawDictionary: ShipmentTrackingProviderListEnvelope.RawData
15+
do {
16+
rawDictionary = try decoder.decode(ShipmentTrackingProviderListEnvelope.self, from: response).rawData
17+
} catch {
18+
rawDictionary = try decoder.decode(ShipmentTrackingProviderListEnvelope.RawData.self, from: response)
19+
}
20+
return rawDictionary.map({ ShipmentTrackingProviderGroup(name: $0.key, siteID: siteID, dictionary: $0.value) })
1621
}
1722
}
1823

@@ -21,7 +26,9 @@ struct ShipmentTrackingProviderListMapper: Mapper {
2126
/// the providers within a `data` key.
2227
///
2328
private struct ShipmentTrackingProviderListEnvelope: Decodable {
24-
let rawData: [String: [String: String]]
29+
typealias RawData = [String: [String: String]]
30+
31+
let rawData: RawData
2532

2633
private enum CodingKeys: String, CodingKey {
2734
case rawData = "data"

Networking/Networking/Remote/ShipmentsRemote.swift

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ public final class ShipmentsRemote: Remote {
1616
let path = "\(Constants.ordersPath)/" + String(orderID) + "/" + "\(Constants.shipmentPath)/"
1717

1818
// 2019-2-15 — We are using the v2 endpoint here because this endpoint does not support v3 yet
19-
let request = JetpackRequest(wooApiVersion: .mark2, method: .get, siteID: siteID, path: path, parameters: nil)
19+
let request = JetpackRequest(wooApiVersion: .mark2,
20+
method: .get,
21+
siteID: siteID,
22+
path: path,
23+
parameters: nil,
24+
availableAsRESTRequest: true)
2025
let mapper = ShipmentTrackingListMapper(siteID: siteID, orderID: orderID)
2126

2227
enqueue(request, mapper: mapper, completion: completion)
@@ -43,7 +48,12 @@ public final class ShipmentsRemote: Remote {
4348
ParameterKeys.trackingProvider: trackingProvider,
4449
ParameterKeys.dateShipped: dateShipped]
4550

46-
let request = JetpackRequest(wooApiVersion: .mark2, method: .post, siteID: siteID, path: path, parameters: parameters)
51+
let request = JetpackRequest(wooApiVersion: .mark2,
52+
method: .post,
53+
siteID: siteID,
54+
path: path,
55+
parameters: parameters,
56+
availableAsRESTRequest: true)
4757
let mapper = NewShipmentTrackingMapper(siteID: siteID, orderID: orderID)
4858

4959
enqueue(request, mapper: mapper, completion: completion)
@@ -73,7 +83,12 @@ public final class ShipmentsRemote: Remote {
7383
ParameterKeys.customTrackingProvider: trackingProvider,
7484
ParameterKeys.dateShipped: dateShipped]
7585

76-
let request = JetpackRequest(wooApiVersion: .mark2, method: .post, siteID: siteID, path: path, parameters: parameters)
86+
let request = JetpackRequest(wooApiVersion: .mark2,
87+
method: .post,
88+
siteID: siteID,
89+
path: path,
90+
parameters: parameters,
91+
availableAsRESTRequest: true)
7792
let mapper = NewShipmentTrackingMapper(siteID: siteID, orderID: orderID)
7893

7994
enqueue(request, mapper: mapper, completion: completion)
@@ -90,7 +105,12 @@ public final class ShipmentsRemote: Remote {
90105
public func deleteShipmentTracking(for siteID: Int64, orderID: Int64, trackingID: String, completion: @escaping (ShipmentTracking?, Error?) -> Void) {
91106
let path = "\(Constants.ordersPath)/" + String(orderID) + "/" + "\(Constants.shipmentPath)/" + trackingID
92107

93-
let request = JetpackRequest(wooApiVersion: .mark2, method: .delete, siteID: siteID, path: path, parameters: nil)
108+
let request = JetpackRequest(wooApiVersion: .mark2,
109+
method: .delete,
110+
siteID: siteID,
111+
path: path,
112+
parameters: nil,
113+
availableAsRESTRequest: true)
94114
let mapper = NewShipmentTrackingMapper(siteID: siteID, orderID: orderID)
95115

96116
enqueue(request, mapper: mapper, completion: completion)
@@ -101,7 +121,12 @@ public final class ShipmentsRemote: Remote {
101121
completion: @escaping ([ShipmentTrackingProviderGroup]?, Error?) -> Void) {
102122
let path = "\(Constants.ordersPath)/" + String(orderID) + "/" + "\(Constants.shipmentPath)/\(Constants.providersPath)"
103123

104-
let request = JetpackRequest(wooApiVersion: .mark2, method: .get, siteID: siteID, path: path, parameters: nil)
124+
let request = JetpackRequest(wooApiVersion: .mark2,
125+
method: .get,
126+
siteID: siteID,
127+
path: path,
128+
parameters: nil,
129+
availableAsRESTRequest: true)
105130
let mapper = ShipmentTrackingProviderListMapper(siteID: siteID)
106131

107132
enqueue(request, mapper: mapper, completion: completion)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import XCTest
2+
@testable import Networking
3+
4+
/// NewShipmentTrackingMapper Unit Tests
5+
///
6+
final class NewShipmentTrackingMapperTests: XCTestCase {
7+
8+
/// Dummy Site ID.
9+
///
10+
private let dummySiteID: Int64 = 424242
11+
12+
/// Dummy Order ID.
13+
///
14+
private let dummyOrderID: Int64 = 99999999
15+
16+
func test_tracking_fields_are_properly_parsed() throws {
17+
let shipmentTracking = try mapLoadShipmentTrackingResponse()
18+
let shipmentTrackingShipDate = DateFormatter.Defaults.yearMonthDayDateFormatter.date(from: "2019-03-12")
19+
XCTAssertEqual(shipmentTracking.siteID, dummySiteID)
20+
XCTAssertEqual(shipmentTracking.orderID, dummyOrderID)
21+
XCTAssertEqual(shipmentTracking.trackingID, "f2e7783b40837b9e1ec503a149dab4a1")
22+
XCTAssertEqual(shipmentTracking.trackingNumber, "123456781234567812345678")
23+
XCTAssertEqual(shipmentTracking.trackingProvider, "TNT Express (consignment)")
24+
XCTAssertEqual(shipmentTracking.trackingURL, "http://www.tnt.com/webtracker/tracking")
25+
XCTAssertEqual(shipmentTracking.dateShipped, shipmentTrackingShipDate)
26+
}
27+
28+
func test_tracking_fields_are_properly_parsed_when_response_has_no_data_envelope() throws {
29+
let shipmentTracking = try mapLoadShipmentTrackingResponseWithoutDataEnvelope()
30+
let shipmentTrackingShipDate = DateFormatter.Defaults.yearMonthDayDateFormatter.date(from: "2019-03-12")
31+
XCTAssertEqual(shipmentTracking.siteID, dummySiteID)
32+
XCTAssertEqual(shipmentTracking.orderID, dummyOrderID)
33+
XCTAssertEqual(shipmentTracking.trackingID, "f2e7783b40837b9e1ec503a149dab4a1")
34+
XCTAssertEqual(shipmentTracking.trackingNumber, "123456781234567812345678")
35+
XCTAssertEqual(shipmentTracking.trackingProvider, "TNT Express (consignment)")
36+
XCTAssertEqual(shipmentTracking.trackingURL, "http://www.tnt.com/webtracker/tracking")
37+
XCTAssertEqual(shipmentTracking.dateShipped, shipmentTrackingShipDate)
38+
}
39+
}
40+
41+
42+
/// Private Methods.
43+
///
44+
private extension NewShipmentTrackingMapperTests {
45+
46+
/// Returns the NewShipmentTrackingMapper output upon receiving `filename` (Data Encoded)
47+
///
48+
func mapShipmentTracking(from filename: String) throws -> ShipmentTracking {
49+
guard let response = Loader.contentsOf(filename) else {
50+
throw ParsingError.unableToLoadFile
51+
}
52+
53+
return try! NewShipmentTrackingMapper(siteID: dummySiteID, orderID: dummyOrderID).map(response: response)
54+
}
55+
56+
/// Returns the NewShipmentTrackingMapper output upon receiving `shipment_tracking_new`
57+
///
58+
func mapLoadShipmentTrackingResponse() throws -> ShipmentTracking {
59+
try mapShipmentTracking(from: "shipment_tracking_new")
60+
}
61+
62+
/// Returns the NewShipmentTrackingMapper output upon receiving `shipment_tracking_new-without-data`
63+
///
64+
func mapLoadShipmentTrackingResponseWithoutDataEnvelope() throws -> ShipmentTracking {
65+
try mapShipmentTracking(from: "shipment_tracking_new-without-data")
66+
}
67+
}
68+
69+
private enum ParsingError: Error {
70+
case unableToLoadFile
71+
}

0 commit comments

Comments
 (0)