Skip to content

Commit fe4d98a

Browse files
Merge pull request #8739 from woocommerce/feat/8715-product-shipping-class-migration
[REST API] Migrate product shipping class endpoints
2 parents dbeeca7 + fb9c275 commit fe4d98a

8 files changed

+248
-4
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,10 @@
809809
EE57C13C297FBECB00BC31E7 /* product-tags-all-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C13B297FBECB00BC31E7 /* product-tags-all-without-data.json */; };
810810
EE57C13E297FBEE200BC31E7 /* product-tags-created-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C13D297FBEE200BC31E7 /* product-tags-created-without-data.json */; };
811811
EE57C140297FBEFB00BC31E7 /* product-tags-deleted-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C13F297FBEFB00BC31E7 /* product-tags-deleted-without-data.json */; };
812+
EE57C143297FCCA700BC31E7 /* product-shipping-classes-load-all-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C141297FCCA700BC31E7 /* product-shipping-classes-load-all-without-data.json */; };
813+
EE57C144297FCCA700BC31E7 /* product-shipping-classes-load-one-without-data.json in Resources */ = {isa = PBXBuildFile; fileRef = EE57C142297FCCA700BC31E7 /* product-shipping-classes-load-one-without-data.json */; };
814+
EE57C146297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE57C145297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift */; };
815+
EE57C148297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE57C147297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift */; };
812816
EE62EE61295ACF8D009C965B /* RequestConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE62EE60295ACF8D009C965B /* RequestConverterTests.swift */; };
813817
EE62EE63295AD45E009C965B /* String+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE62EE62295AD45E009C965B /* String+URL.swift */; };
814818
EE62EE65295AD46D009C965B /* String+URLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE62EE64295AD46D009C965B /* String+URLTests.swift */; };
@@ -1676,6 +1680,10 @@
16761680
EE57C13B297FBECB00BC31E7 /* product-tags-all-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-tags-all-without-data.json"; sourceTree = "<group>"; };
16771681
EE57C13D297FBEE200BC31E7 /* product-tags-created-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-tags-created-without-data.json"; sourceTree = "<group>"; };
16781682
EE57C13F297FBEFB00BC31E7 /* product-tags-deleted-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-tags-deleted-without-data.json"; sourceTree = "<group>"; };
1683+
EE57C141297FCCA700BC31E7 /* product-shipping-classes-load-all-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-shipping-classes-load-all-without-data.json"; sourceTree = "<group>"; };
1684+
EE57C142297FCCA700BC31E7 /* product-shipping-classes-load-one-without-data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-shipping-classes-load-one-without-data.json"; sourceTree = "<group>"; };
1685+
EE57C145297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductShippingClassListMapperTests.swift; sourceTree = "<group>"; };
1686+
EE57C147297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductShippingClassMapperTests.swift; sourceTree = "<group>"; };
16791687
EE62EE60295ACF8D009C965B /* RequestConverterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestConverterTests.swift; sourceTree = "<group>"; };
16801688
EE62EE62295AD45E009C965B /* String+URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+URL.swift"; sourceTree = "<group>"; };
16811689
EE62EE64295AD46D009C965B /* String+URLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+URLTests.swift"; sourceTree = "<group>"; };
@@ -2408,6 +2416,8 @@
24082416
4524CD9B242CEFAB00B2F20A /* product-on-sale-with-empty-sale-price.json */,
24092417
025CA2C7238F4FF400B05C81 /* product-shipping-classes-load-all.json */,
24102418
020220E123966CD900290165 /* product-shipping-classes-load-one.json */,
2419+
EE57C141297FCCA700BC31E7 /* product-shipping-classes-load-all-without-data.json */,
2420+
EE57C142297FCCA700BC31E7 /* product-shipping-classes-load-one-without-data.json */,
24112421
457FC68B2382B2FD00B41B02 /* product-update.json */,
24122422
AEA056E3296DBA6E00948D52 /* products-batch-update.json */,
24132423
45152818257A84A60076B03C /* product-attributes-all.json */,
@@ -2770,6 +2780,8 @@
27702780
45D685FB23D0C739005F87D0 /* ProductSkuMapperTests.swift */,
27712781
4599FC5924A626B70056157A /* ProductTagListMapperTests.swift */,
27722782
CEC4BF94234E7F34008D9195 /* RefundListMapperTests.swift */,
2783+
EE57C145297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift */,
2784+
EE57C147297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift */,
27732785
CEC4BF8E234E382F008D9195 /* RefundMapperTests.swift */,
27742786
7412A8ED21B6E335005D182A /* ReportOrderMapperTests.swift */,
27752787
743E84F722172E1F00FAC9D7 /* ShipmentTrackingListMapperTests.swift */,
@@ -3130,6 +3142,7 @@
31303142
DE66C55F2977C67D00DAA978 /* shipping-label-account-settings-without-data.json in Resources */,
31313143
E137619929151C7400FD098F /* error-wp-rest-forbidden.json in Resources */,
31323144
31A451CE27863A2E00FE81AA /* stripe-account-wrong-json.json in Resources */,
3145+
EE57C143297FCCA700BC31E7 /* product-shipping-classes-load-all-without-data.json in Resources */,
31333146
26BD9FCD2965EC3C004E0D15 /* product-variations-bulk-create.json in Resources */,
31343147
EE57C13C297FBECB00BC31E7 /* product-tags-all-without-data.json in Resources */,
31353148
028CB718290223CB00331C09 /* account-username-suggestions.json in Resources */,
@@ -3228,6 +3241,7 @@
32283241
B5C6FCD620A3768900A4F8E4 /* order.json in Resources */,
32293242
3158FE7426129D9F00E566B9 /* wcpay-account-rejected-other.json in Resources */,
32303243
CC0786C7267BB10700BA9AC1 /* shipping-label-status-success.json in Resources */,
3244+
EE57C144297FCCA700BC31E7 /* product-shipping-classes-load-one-without-data.json in Resources */,
32313245
028CB71B290224D700331C09 /* create-account-error-username.json in Resources */,
32323246
EEA6583E2966B41E00112DF0 /* products-load-all-without-data.json in Resources */,
32333247
68F48B1328E3E5750045C15B /* wc-analytics-customers.json in Resources */,
@@ -3898,6 +3912,7 @@
38983912
03DCB7442624AD9B00C8953D /* CouponListMapperTests.swift in Sources */,
38993913
AE2D6623272A8F6E004A2C3A /* TelemetryRemoteTests.swift in Sources */,
39003914
B5C151C0217EE3FB00C7BDC1 /* NoteListMapperTests.swift in Sources */,
3915+
EE57C146297FCCD200BC31E7 /* ProductShippingClassListMapperTests.swift in Sources */,
39013916
026CF622237D7E61009563D4 /* ProductVariationsRemoteTests.swift in Sources */,
39023917
DEC51A99274DDDC9009F3DF4 /* SitePluginMapperTests.swift in Sources */,
39033918
EEFAA581295D78E9003583BE /* AuthenticatedRESTRequestTests.swift in Sources */,
@@ -3967,6 +3982,7 @@
39673982
CC07866526790B1100BA9AC1 /* ShippingLabelPurchaseMapperTests.swift in Sources */,
39683983
74002D6A2118B26100A63C19 /* SiteVisitStatsMapperTests.swift in Sources */,
39693984
743E84FA221742E300FAC9D7 /* ShipmentsRemoteTests.swift in Sources */,
3985+
EE57C148297FCCE000BC31E7 /* ProductShippingClassMapperTests.swift in Sources */,
39703986
03DCB7822627394500C8953D /* CouponMapperTests.swift in Sources */,
39713987
03DCB76C262591C400C8953D /* CouponsRemoteTests.swift in Sources */,
39723988
31A451BD2786344B00FE81AA /* StripeRemoteTests.swift in Sources */,

Networking/Networking/Mapper/ProductShippingClassListMapper.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ struct ProductShippingClassListMapper: Mapper {
1717
.siteID: siteID
1818
]
1919

20-
return try decoder.decode(ProductShippingClassListEnvelope.self, from: response).data
20+
do {
21+
return try decoder.decode(ProductShippingClassListEnvelope.self, from: response).data
22+
} catch {
23+
return try decoder.decode([ProductShippingClass].self, from: response)
24+
}
2125
}
2226
}
2327

Networking/Networking/Mapper/ProductShippingClassMapper.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ struct ProductShippingClassMapper: Mapper {
1717
.siteID: siteID
1818
]
1919

20-
return try decoder.decode(ProductShippingClassEnvelope.self, from: response).productShippingClass
20+
do {
21+
return try decoder.decode(ProductShippingClassEnvelope.self, from: response).productShippingClass
22+
} catch {
23+
return try decoder.decode(ProductShippingClass.self, from: response)
24+
}
2125
}
2226
}
2327

Networking/Networking/Remote/ProductShippingClassRemote.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ public class ProductShippingClassRemote: Remote {
2626
]
2727

2828
let path = "\(Path.models)"
29-
let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: parameters)
29+
let request = JetpackRequest(wooApiVersion: .mark3,
30+
method: .get,
31+
siteID: siteID,
32+
path: path,
33+
parameters: parameters,
34+
availableAsRESTRequest: true)
3035
let mapper = ProductShippingClassListMapper(siteID: siteID)
3136
enqueue(request, mapper: mapper, completion: completion)
3237
}
@@ -41,7 +46,12 @@ public class ProductShippingClassRemote: Remote {
4146
///
4247
public func loadOne(for siteID: Int64, remoteID: Int64, completion: @escaping (ProductShippingClass?, Error?) -> Void) {
4348
let path = "\(Path.models)/\(remoteID)"
44-
let request = JetpackRequest(wooApiVersion: .mark3, method: .get, siteID: siteID, path: path, parameters: nil)
49+
let request = JetpackRequest(wooApiVersion: .mark3,
50+
method: .get,
51+
siteID: siteID,
52+
path: path,
53+
parameters: nil,
54+
availableAsRESTRequest: true)
4555
let mapper = ProductShippingClassMapper(siteID: siteID)
4656

4757
enqueue(request, mapper: mapper, completion: completion)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import XCTest
2+
@testable import Networking
3+
4+
/// Unit Tests for `ProductShippingClassListMapper`
5+
///
6+
final class ProductShippingClassListMapperTests: XCTestCase {
7+
/// Dummy Site ID.
8+
///
9+
private let dummySiteID: Int64 = 33334444
10+
11+
/// Verifies that all of the ProductShippingClass Fields are parsed correctly.
12+
///
13+
func test_ProductShippingClass_fields_are_properly_parsed() throws {
14+
let productVariation = try XCTUnwrap(mapLoadAllProductShippingClassResponse()?.first)
15+
16+
let expected = ProductShippingClass(count: 3,
17+
descriptionHTML: "Limited offer!",
18+
name: "Free Shipping",
19+
shippingClassID: 94,
20+
siteID: dummySiteID,
21+
slug: "free-shipping")
22+
23+
XCTAssertEqual(productVariation, expected)
24+
}
25+
26+
/// Verifies that all of the ProductShippingClass Fields are parsed correctly when response has no data envelope.
27+
///
28+
func test_ProductShippingClass_fields_are_properly_parsed_when_response_has_no_data_envelope() throws {
29+
let productVariation = try XCTUnwrap(mapLoadAllProductShippingClassResponseWithoutDataEnvelope()?.first)
30+
31+
let expected = ProductShippingClass(count: 3,
32+
descriptionHTML: "Limited offer!",
33+
name: "Free Shipping",
34+
shippingClassID: 94,
35+
siteID: dummySiteID,
36+
slug: "free-shipping")
37+
38+
XCTAssertEqual(productVariation, expected)
39+
}
40+
}
41+
42+
/// Private Helpers
43+
///
44+
private extension ProductShippingClassListMapperTests {
45+
/// Returns the ProductShippingClassListMapper output upon receiving `filename` (Data Encoded)
46+
///
47+
func mapProductShippingClass(from filename: String) -> [ProductShippingClass]? {
48+
guard let response = Loader.contentsOf(filename) else {
49+
return nil
50+
}
51+
52+
return try? ProductShippingClassListMapper(siteID: dummySiteID).map(response: response)
53+
}
54+
55+
/// Returns the ProductShippingClassListMapper output upon receiving `product-shipping-classes-load-all`
56+
///
57+
func mapLoadAllProductShippingClassResponse() -> [ProductShippingClass]? {
58+
return mapProductShippingClass(from: "product-shipping-classes-load-all")
59+
}
60+
61+
/// Returns the ProductShippingClassListMapper output upon receiving `product-shipping-classes-load-all-without-data`
62+
///
63+
func mapLoadAllProductShippingClassResponseWithoutDataEnvelope() -> [ProductShippingClass]? {
64+
return mapProductShippingClass(from: "product-shipping-classes-load-all-without-data")
65+
}
66+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import XCTest
2+
@testable import Networking
3+
4+
/// Unit Tests for `ProductShippingClassMapper`
5+
///
6+
final class ProductShippingClassMapperTests: XCTestCase {
7+
/// Dummy Site ID.
8+
///
9+
private let dummySiteID: Int64 = 33334444
10+
11+
/// Verifies that all of the ProductShippingClass Fields are parsed correctly.
12+
///
13+
func test_ProductShippingClass_fields_are_properly_parsed() throws {
14+
let productVariation = try XCTUnwrap(mapLoadProductShippingClassResponse())
15+
16+
let expected = ProductShippingClass(count: 3,
17+
descriptionHTML: "Limited offer!",
18+
name: "Free Shipping",
19+
shippingClassID: 94,
20+
siteID: dummySiteID,
21+
slug: "free-shipping")
22+
23+
XCTAssertEqual(productVariation, expected)
24+
}
25+
26+
/// Verifies that all of the ProductShippingClass Fields are parsed correctly when response has no data envelope.
27+
///
28+
func test_ProductShippingClass_fields_are_properly_parsed_when_response_has_no_data_envelope() throws {
29+
let productVariation = try XCTUnwrap(mapLoadProductShippingClassResponseWithoutDataEnvelope())
30+
31+
let expected = ProductShippingClass(count: 3,
32+
descriptionHTML: "Limited offer!",
33+
name: "Free Shipping",
34+
shippingClassID: 94,
35+
siteID: dummySiteID,
36+
slug: "free-shipping")
37+
38+
XCTAssertEqual(productVariation, expected)
39+
}
40+
}
41+
42+
/// Private Helpers
43+
///
44+
private extension ProductShippingClassMapperTests {
45+
/// Returns the ProductShippingClassMapper output upon receiving `filename` (Data Encoded)
46+
///
47+
func mapProductShippingClass(from filename: String) -> ProductShippingClass? {
48+
guard let response = Loader.contentsOf(filename) else {
49+
return nil
50+
}
51+
52+
return try? ProductShippingClassMapper(siteID: dummySiteID).map(response: response)
53+
}
54+
55+
/// Returns the ProductShippingClassMapper output upon receiving `product-shipping-classes-load-one`
56+
///
57+
func mapLoadProductShippingClassResponse() -> ProductShippingClass? {
58+
return mapProductShippingClass(from: "product-shipping-classes-load-one")
59+
}
60+
61+
/// Returns the ProductShippingClassMapper output upon receiving `product-shipping-classes-load-one-without-data`
62+
///
63+
func mapLoadProductShippingClassResponseWithoutDataEnvelope() -> ProductShippingClass? {
64+
return mapProductShippingClass(from: "product-shipping-classes-load-one-without-data")
65+
}
66+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
[
2+
{
3+
"id": 94,
4+
"name": "Free Shipping",
5+
"slug": "free-shipping",
6+
"description": "Limited offer!",
7+
"count": 3,
8+
"_links": {
9+
"self": [
10+
{
11+
"href": "https://shop.com/shipping_classes/94"
12+
}
13+
],
14+
"collection": [
15+
{
16+
"href": "https://shop.com/wp-json/wc/v3/products/shipping_classes"
17+
}
18+
]
19+
}
20+
},
21+
{
22+
"id": 66,
23+
"name": "Full Product Size",
24+
"slug": "full-product-size",
25+
"description": "",
26+
"count": 1,
27+
"_links": {
28+
"self": [
29+
{
30+
"href": "https://shop.com/wp-json/wc/v3/products/shipping_classes/66"
31+
}
32+
],
33+
"collection": [
34+
{
35+
"href": "https://shop.com/wp-json/wc/v3/products/shipping_classes"
36+
}
37+
]
38+
}
39+
},
40+
{
41+
"id": 95,
42+
"name": "Machine Shipping",
43+
"slug": "machine-shipping",
44+
"description": "",
45+
"count": 0,
46+
"_links": {
47+
"self": [
48+
{
49+
"href": "https://shop.com/wp-json/wc/v3/products/shipping_classes/95"
50+
}
51+
],
52+
"collection": [
53+
{
54+
"href": "https://shop.com/wp-json/wc/v3/products/shipping_classes"
55+
}
56+
]
57+
}
58+
}
59+
]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"id": 94,
3+
"name": "Free Shipping",
4+
"slug": "free-shipping",
5+
"description": "Limited offer!",
6+
"count": 3,
7+
"_links": {
8+
"self": [
9+
{
10+
"href": "https://shop.com/shipping_classes/94"
11+
}
12+
],
13+
"collection": [
14+
{
15+
"href": "https://shop.com/wp-json/wc/v3/products/shipping_classes"
16+
}
17+
]
18+
}
19+
}

0 commit comments

Comments
 (0)