Skip to content

Commit c06d9fe

Browse files
committed
Merge branch 'trunk' into issue/9839-bool-decoding-fallbacks
2 parents 2a90dee + a5285cc commit c06d9fe

14 files changed

+319
-14
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@
641641
CE19CB11222486A600E8AF7A /* order-statuses.json in Resources */ = {isa = PBXBuildFile; fileRef = CE19CB10222486A500E8AF7A /* order-statuses.json */; };
642642
CE20179320E3EFA7005B4C18 /* broken-orders.json in Resources */ = {isa = PBXBuildFile; fileRef = CE20179220E3EFA7005B4C18 /* broken-orders.json */; };
643643
CE227093228DD44C00C0626C /* ProductStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE227092228DD44C00C0626C /* ProductStatus.swift */; };
644+
CE2678432A26102A00FD9AEB /* order-alternative-types.json in Resources */ = {isa = PBXBuildFile; fileRef = CE2678422A26102A00FD9AEB /* order-alternative-types.json */; };
644645
CE43066A23465F340073CBFF /* Refund.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE43066923465F340073CBFF /* Refund.swift */; };
645646
CE43066C2347C5F90073CBFF /* OrderItemRefund.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE43066B2347C5F90073CBFF /* OrderItemRefund.swift */; };
646647
CE43066E2347CBA70073CBFF /* OrderItemTaxRefund.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE43066D2347CBA70073CBFF /* OrderItemTaxRefund.swift */; };
@@ -1579,6 +1580,7 @@
15791580
CE19CB10222486A500E8AF7A /* order-statuses.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-statuses.json"; sourceTree = "<group>"; };
15801581
CE20179220E3EFA7005B4C18 /* broken-orders.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "broken-orders.json"; sourceTree = "<group>"; };
15811582
CE227092228DD44C00C0626C /* ProductStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductStatus.swift; sourceTree = "<group>"; };
1583+
CE2678422A26102A00FD9AEB /* order-alternative-types.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "order-alternative-types.json"; sourceTree = "<group>"; };
15821584
CE43066923465F340073CBFF /* Refund.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Refund.swift; sourceTree = "<group>"; };
15831585
CE43066B2347C5F90073CBFF /* OrderItemRefund.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderItemRefund.swift; sourceTree = "<group>"; };
15841586
CE43066D2347CBA70073CBFF /* OrderItemTaxRefund.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderItemTaxRefund.swift; sourceTree = "<group>"; };
@@ -2541,6 +2543,7 @@
25412543
B554FA8C2180B59700C54DFF /* notifications-load-hashes.json */,
25422544
AE2D6624272A941C004A2C3A /* null-data.json */,
25432545
B5C6FCD520A3768900A4F8E4 /* order.json */,
2546+
CE2678422A26102A00FD9AEB /* order-alternative-types.json */,
25442547
DEF13C5F29668C420024A02B /* order-without-data.json */,
25452548
034480C227A42F9100DFACD2 /* order-with-charge.json */,
25462549
02C254D62563999200A04423 /* order-shipping-labels.json */,
@@ -3620,6 +3623,7 @@
36203623
74ABA1C9213F19FE00FFAD30 /* top-performers-month.json in Resources */,
36213624
3158FE7026129D7500E566B9 /* wcpay-account-rejected-listed.json in Resources */,
36223625
743E84F622172D3E00FAC9D7 /* shipment_tracking_single.json in Resources */,
3626+
CE2678432A26102A00FD9AEB /* order-alternative-types.json in Resources */,
36233627
D865CE5B278CA10B002C8520 /* stripe-payment-intent-requires-payment-method.json in Resources */,
36243628
CC9A254626442CA7005DE56E /* shipping-label-eligibility-failure.json in Resources */,
36253629
4524CD9C242CEFAB00B2F20A /* product-on-sale-with-empty-sale-price.json in Resources */,

Networking/Networking/Model/OrderItem.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ public struct OrderItem: Codable, Equatable, Hashable, GeneratedFakeable, Genera
8888
let decimalPrice = try container.decodeIfPresent(Decimal.self, forKey: .price) ?? Decimal(0)
8989
let price = NSDecimalNumber(decimal: decimalPrice)
9090

91-
let sku = try container.decodeIfPresent(String.self, forKey: .sku)
91+
// Even though a plain install of WooCommerce Core provides String values,
92+
// some plugins alter the field value from String to Int or Decimal.
93+
let sku = container.failsafeDecodeIfPresent(targetType: String.self,
94+
forKey: .sku,
95+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })])
9296
let subtotal = try container.decode(String.self, forKey: .subtotal)
9397
let subtotalTax = try container.decode(String.self, forKey: .subtotalTax)
9498
let taxClass = try container.decode(String.self, forKey: .taxClass)

Networking/Networking/Model/Product/Product.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,12 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
357357

358358
let fullDescription = try container.decodeIfPresent(String.self, forKey: .fullDescription)
359359
let shortDescription = try container.decodeIfPresent(String.self, forKey: .shortDescription)
360-
let sku = try container.decodeIfPresent(String.self, forKey: .sku)
360+
361+
// Even though a plain install of WooCommerce Core provides String values,
362+
// some plugins alter the field value from String to Int or Decimal.
363+
let sku = container.failsafeDecodeIfPresent(targetType: String.self,
364+
forKey: .sku,
365+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })])
361366

362367
// Even though a plain install of WooCommerce Core provides string values,
363368
// some plugins alter the field value from String to Int or Decimal.
@@ -434,7 +439,12 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
434439
let backordered = try container.decode(Bool.self, forKey: .backordered)
435440

436441
let soldIndividually = try container.decodeIfPresent(Bool.self, forKey: .soldIndividually) ?? false
437-
let weight = try container.decodeIfPresent(String.self, forKey: .weight)
442+
443+
// Even though a plain install of WooCommerce Core provides String values,
444+
// some plugins alter the field value from String to Int or Decimal.
445+
let weight = container.failsafeDecodeIfPresent(targetType: String.self,
446+
forKey: .weight,
447+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })])
438448
let dimensions = try container.decode(ProductDimensions.self, forKey: .dimensions)
439449

440450
let shippingRequired = try container.decode(Bool.self, forKey: .shippingRequired)

Networking/Networking/Model/Product/ProductDimensions.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@ public struct ProductDimensions: Codable, Equatable, GeneratedFakeable {
1717
self.width = width
1818
self.height = height
1919
}
20+
21+
public init(from decoder: Decoder) throws {
22+
let container = try decoder.container(keyedBy: CodingKeys.self)
23+
24+
// Even though a plain install of WooCommerce Core provides String dimension values,
25+
// some plugins may alter the field values from String to Int or Decimal.
26+
let length = container.failsafeDecodeIfPresent(targetType: String.self,
27+
forKey: .length,
28+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })]) ?? ""
29+
let width = container.failsafeDecodeIfPresent(targetType: String.self,
30+
forKey: .width,
31+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })]) ?? ""
32+
let height = container.failsafeDecodeIfPresent(targetType: String.self,
33+
forKey: .height,
34+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })]) ?? ""
35+
36+
self.init(length: length, width: width, height: height)
37+
}
2038
}
2139

2240
/// Defines all of the Dimensions CodingKeys

Networking/Networking/Model/Product/ProductDownload.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ public struct ProductDownload: Codable, Equatable, GeneratedFakeable {
2323
public init(from decoder: Decoder) throws {
2424
let container = try decoder.container(keyedBy: CodingKeys.self)
2525

26-
let downloadID = try container.decode(String.self, forKey: .downloadID)
26+
// Even though a plain install of WooCommerce Core provides String values,
27+
// some plugins alter the field value from String to Int or Decimal.
28+
let downloadID = container.failsafeDecodeIfPresent(targetType: String.self,
29+
forKey: .downloadID,
30+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })]) ?? "0"
2731
let name = try container.decodeIfPresent(String.self, forKey: .name)
2832
let fileURL = try container.decodeIfPresent(String.self, forKey: .fileURL)
2933

Networking/Networking/Model/Product/ProductVariation.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,12 @@ public struct ProductVariation: Codable, GeneratedCopiable, Equatable, Generated
206206
let statusKey = try container.decode(String.self, forKey: .statusKey)
207207
let status = ProductStatus(rawValue: statusKey)
208208
let description = try container.decodeIfPresent(String.self, forKey: .description)
209-
let sku = try container.decodeIfPresent(String.self, forKey: .sku)
209+
210+
// Even though a plain install of WooCommerce Core provides String values,
211+
// some plugins alter the field value from String to Int or Decimal.
212+
let sku = container.failsafeDecodeIfPresent(targetType: String.self,
213+
forKey: .sku,
214+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })])
210215

211216
// Even though a plain install of WooCommerce Core provides string values,
212217
// some plugins alter the field value from String to Int or Decimal.
@@ -281,7 +286,12 @@ public struct ProductVariation: Codable, GeneratedCopiable, Equatable, Generated
281286
alternativeTypes: [ .string(transform: { NSString(string: $0).boolValue })]) ?? false
282287

283288
let backordered = try container.decode(Bool.self, forKey: .backordered)
284-
let weight = try container.decodeIfPresent(String.self, forKey: .weight)
289+
290+
// Even though a plain install of WooCommerce Core provides String values,
291+
// some plugins alter the field value from String to Int or Decimal.
292+
let weight = container.failsafeDecodeIfPresent(targetType: String.self,
293+
forKey: .weight,
294+
alternativeTypes: [.decimal(transform: { NSDecimalNumber(decimal: $0).stringValue })])
285295
let dimensions = try container.decode(ProductDimensions.self, forKey: .dimensions)
286296
let shippingClass = try container.decodeIfPresent(String.self, forKey: .shippingClass)
287297
let shippingClassID = try container.decode(Int64.self, forKey: .shippingClassID)

Networking/Networking/Model/ShippingLineTax.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ public struct ShippingLineTax: Decodable, Hashable, GeneratedFakeable {
2424
self.subtotal = subtotal
2525
self.total = total
2626
}
27+
28+
/// The public initializer for ShippingLineTax.
29+
///
30+
public init(from decoder: Decoder) throws {
31+
let container = try decoder.container(keyedBy: CodingKeys.self)
32+
33+
// Even though a plain install of WooCommerce Core provides Int values,
34+
// some plugins alter the field value from Int to String.
35+
let taxID = container.failsafeDecodeIfPresent(targetType: Int64.self,
36+
forKey: .taxID,
37+
alternativeTypes: [.string(transform: { Int64($0) ?? 0 })]) ?? 0
38+
let subtotal = try container.decode(String.self, forKey: .subtotal)
39+
let total = try container.decode(String.self, forKey: .total)
40+
41+
self.init(taxID: taxID, subtotal: subtotal, total: total)
42+
}
2743
}
2844

2945
/// Defines all of the ShippingLineTax CodingKeys.

Networking/NetworkingTests/Mapper/OrderMapperTests.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,15 @@ final class OrderMapperTests: XCTestCase {
429429
XCTAssertNil(compositeProduct.parent)
430430
XCTAssertEqual(component.parent, 830)
431431
}
432+
433+
func test_that_order_alternative_types_are_properly_parsed() throws {
434+
// Given
435+
let order = try XCTUnwrap(mapLoadOrderResponseWithAlternativeTypes())
436+
437+
// Then
438+
XCTAssertEqual(order.shippingLines.first?.taxes.first?.taxID, 1)
439+
XCTAssertEqual(order.items.first?.sku, "123")
440+
}
432441
}
433442

434443

@@ -531,4 +540,10 @@ private extension OrderMapperTests {
531540
return mapOrder(from: "order-with-composite-product")
532541
}
533542

543+
/// Returns the Order output upon receiving `order-alternative-types`
544+
///
545+
func mapLoadOrderResponseWithAlternativeTypes() -> Order? {
546+
return mapOrder(from: "order-alternative-types")
547+
}
548+
534549
}

Networking/NetworkingTests/Mapper/ProductMapperTests.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ final class ProductMapperTests: XCTestCase {
117117
XCTAssertFalse(product.soldIndividually)
118118
XCTAssertTrue(product.purchasable)
119119
XCTAssertEqual(product.permalink, "")
120+
XCTAssertEqual(product.sku, "123")
121+
XCTAssertEqual(product.weight, "213")
122+
XCTAssertEqual(product.dimensions.length, "12")
123+
XCTAssertEqual(product.dimensions.width, "33")
124+
XCTAssertEqual(product.dimensions.height, "54")
125+
XCTAssertEqual(product.downloads.first?.downloadID, "12345")
120126
XCTAssertEqual(product.backordersAllowed, true)
121127
XCTAssertEqual(product.onSale, false)
122128
}

Networking/NetworkingTests/Mapper/ProductVariationMapperTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ final class ProductVariationMapperTests: XCTestCase {
4040
XCTAssertFalse(productVariation.manageStock)
4141
XCTAssertTrue(productVariation.purchasable)
4242
XCTAssertEqual(productVariation.permalink, "")
43+
XCTAssertEqual(productVariation.sku, "12345")
44+
XCTAssertEqual(productVariation.weight, "2.5")
4345
XCTAssertEqual(productVariation.backordersAllowed, true)
4446
XCTAssertEqual(productVariation.onSale, false)
4547
}

0 commit comments

Comments
 (0)