Skip to content

Commit e6b98cf

Browse files
authored
Merge pull request #126 from woocommerce/issue/58-order-unit-test
Order List: Breaking on null `date_created_gmt`
2 parents 6f20e78 + f1d73ae commit e6b98cf

File tree

4 files changed

+192
-3
lines changed

4 files changed

+192
-3
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
B5C6FCCF20A3592900A4F8E4 /* OrderItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C6FCCE20A3592900A4F8E4 /* OrderItem.swift */; };
4949
B5C6FCD420A373BB00A4F8E4 /* OrderMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C6FCD320A373BA00A4F8E4 /* OrderMapper.swift */; };
5050
B5C6FCD620A3768900A4F8E4 /* order.json in Resources */ = {isa = PBXBuildFile; fileRef = B5C6FCD520A3768900A4F8E4 /* order.json */; };
51+
CE20179320E3EFA7005B4C18 /* broken-order.json in Resources */ = {isa = PBXBuildFile; fileRef = CE20179220E3EFA7005B4C18 /* broken-order.json */; };
5152
/* End PBXBuildFile section */
5253

5354
/* Begin PBXContainerItemProxy section */
@@ -107,6 +108,7 @@
107108
B5C6FCD520A3768900A4F8E4 /* order.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = order.json; sourceTree = "<group>"; };
108109
BD9439D9B8F2C1ED2EADAA51 /* Pods-NetworkingTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkingTests.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-NetworkingTests/Pods-NetworkingTests.debug.xcconfig"; sourceTree = "<group>"; };
109110
C8F9A8CC6F90A8C9B5EF2EE2 /* Pods-Networking.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Networking.release.xcconfig"; path = "../Pods/Target Support Files/Pods-Networking/Pods-Networking.release.xcconfig"; sourceTree = "<group>"; };
111+
CE20179220E3EFA7005B4C18 /* broken-order.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "broken-order.json"; sourceTree = "<group>"; };
110112
F3F25DC15EC1D7C631169CB5 /* Pods_Networking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Networking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
111113
F6CEE1CA2AD376C0C28AE9F6 /* Pods-NetworkingTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkingTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-NetworkingTests/Pods-NetworkingTests.release.xcconfig"; sourceTree = "<group>"; };
112114
/* End PBXFileReference section */
@@ -289,6 +291,7 @@
289291
B505F6D420BEE4E600BB1B69 /* me.json */,
290292
B559EBA920A0B5CD00836CD4 /* orders-load-all.json */,
291293
B5C6FCD520A3768900A4F8E4 /* order.json */,
294+
CE20179220E3EFA7005B4C18 /* broken-order.json */,
292295
);
293296
path = Responses;
294297
sourceTree = "<group>";
@@ -452,6 +455,7 @@
452455
B505F6D520BEE4E700BB1B69 /* me.json in Resources */,
453456
B5C6FCD620A3768900A4F8E4 /* order.json in Resources */,
454457
B559EBAA20A0B5CD00836CD4 /* orders-load-all.json in Resources */,
458+
CE20179320E3EFA7005B4C18 /* broken-order.json in Resources */,
455459
);
456460
runOnlyForDeploymentPostprocessing = 0;
457461
};

Networking/Networking/Model/Order.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,66 @@ public struct Order: Decodable {
2727
public let items: [OrderItem]
2828
public let billingAddress: Address
2929
public let shippingAddress: Address
30+
31+
/// Order struct initializer.
32+
///
33+
init(orderID: Int, parentID: Int, customerID: Int, number: String, status: OrderStatus, currency: String, customerNote: String?, dateCreated: Date, dateModified: Date, datePaid: Date?, discountTotal: String, discountTax: String, shippingTotal: String, shippingTax: String, total: String, totalTax: String, items: [OrderItem], billingAddress: Address, shippingAddress: Address) {
34+
self.orderID = orderID
35+
self.parentID = parentID
36+
self.customerID = customerID
37+
38+
self.number = number
39+
self.status = status
40+
self.currency = currency
41+
self.customerNote = customerNote
42+
43+
self.dateCreated = dateCreated
44+
self.dateModified = dateModified
45+
self.datePaid = datePaid
46+
47+
self.discountTotal = discountTotal
48+
self.discountTax = discountTax
49+
self.shippingTotal = shippingTotal
50+
self.shippingTax = shippingTax
51+
self.total = total
52+
self.totalTax = totalTax
53+
54+
self.items = items
55+
self.billingAddress = billingAddress
56+
self.shippingAddress = shippingAddress
57+
}
58+
59+
60+
/// The public initializer for Order.
61+
///
62+
public init(from decoder: Decoder) throws {
63+
let container = try decoder.container(keyedBy: CodingKeys.self)
64+
let orderID = try container.decode(Int.self, forKey: .orderID)
65+
let parentID = try container.decode(Int.self, forKey: .parentID)
66+
let customerID = try container.decode(Int.self, forKey: .customerID)
67+
68+
let number = try container.decode(String.self, forKey: .number)
69+
let status = try container.decode(OrderStatus.self, forKey: .status)
70+
let currency = try container.decode(String.self, forKey: .currency)
71+
let customerNote = try container.decode(String.self, forKey: .customerNote)
72+
73+
let dateCreated = try container.decodeIfPresent(Date.self, forKey: .dateCreated) ?? Date()
74+
let dateModified = try container.decodeIfPresent(Date.self, forKey: .dateModified) ?? Date()
75+
let datePaid = try container.decodeIfPresent(Date.self, forKey: .datePaid)
76+
77+
let discountTotal = try container.decode(String.self, forKey: .discountTotal)
78+
let discountTax = try container.decode(String.self, forKey: .discountTax)
79+
let shippingTax = try container.decode(String.self, forKey: .shippingTax)
80+
let shippingTotal = try container.decode(String.self, forKey: .shippingTotal)
81+
let total = try container.decode(String.self, forKey: .total)
82+
let totalTax = try container.decode(String.self, forKey: .totalTax)
83+
84+
let items = try container.decode([OrderItem].self, forKey: .items)
85+
let shippingAddress = try container.decode(Address.self, forKey: .shippingAddress)
86+
let billingAddress = try container.decode(Address.self, forKey: .billingAddress)
87+
88+
self.init(orderID: orderID, parentID: parentID, customerID: customerID, number: number, status: status, currency: currency, customerNote: customerNote, dateCreated: dateCreated, dateModified: dateModified, datePaid: datePaid, discountTotal: discountTotal, discountTax: discountTax, shippingTotal: shippingTotal, shippingTax: shippingTax, total: total, totalTax: totalTax, items: items, billingAddress: billingAddress, shippingAddress: shippingAddress) // initialize the struct
89+
}
3090
}
3191

3292

Networking/NetworkingTests/Mapper/OrderListMapperTests.swift

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,50 @@ class OrderListMapperTests: XCTestCase {
7676
XCTAssertEqual(firstItem.totalTax, "1.20")
7777
XCTAssertEqual(firstItem.variationID, 0)
7878
}
79+
80+
/// Verifies that an Order in a broken state does [gets default values] | [gets skipped while parsing]
81+
///
82+
func testOrderHasDefaultDateCreatedWhenNullDateReceived() {
83+
let orders = mapLoadBrokenOrderResponse()
84+
XCTAssert(orders.count == 1)
85+
86+
let brokenOrder = orders[0]
87+
let format = DateFormatter()
88+
format.dateStyle = .short
89+
90+
let orderCreatedString = format.string(from: brokenOrder.dateCreated)
91+
let todayCreatedString = format.string(from: Date())
92+
XCTAssertEqual(orderCreatedString, todayCreatedString)
93+
94+
let orderModifiedString = format.string(from: brokenOrder.dateModified)
95+
XCTAssertEqual(orderModifiedString, todayCreatedString)
96+
}
7997
}
8098

8199

82100
/// Private Methods.
83101
///
84102
private extension OrderListMapperTests {
85103

86-
/// Returns the OrderListMapper output upon receiving `orders-load-all` (Data Encoded)
104+
/// Returns the OrderListMapper output upon receiving `filename` (Data Encoded)
87105
///
88-
func mapLoadAllOrdersResponse() -> [Order] {
89-
guard let response = Loader.contentsOf("orders-load-all") else {
106+
func mapOrders(from filename: String) -> [Order] {
107+
guard let response = Loader.contentsOf(filename) else {
90108
return []
91109
}
92110

93111
return try! OrderListMapper().map(response: response)
94112
}
113+
114+
/// Returns the OrderListMapper output upon receiving `orders-load-all`
115+
///
116+
func mapLoadAllOrdersResponse() -> [Order] {
117+
return mapOrders(from: "orders-load-all")
118+
}
119+
120+
/// Returns the OrderlistMapper output upon receiving `broken-order`
121+
///
122+
func mapLoadBrokenOrderResponse() -> [Order] {
123+
return mapOrders(from: "broken-order")
124+
}
95125
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"data": [{
3+
"id": 85,
4+
"parent_id": 0,
5+
"number": "85",
6+
"order_key": false,
7+
"created_via": "",
8+
"version": "",
9+
"status": "draft",
10+
"currency": "GBP",
11+
"date_created": null,
12+
"date_created_gmt": null,
13+
"date_modified": null,
14+
"date_modified_gmt": null,
15+
"discount_total": "0.00",
16+
"discount_tax": "0.00",
17+
"shipping_total": "0.00",
18+
"shipping_tax": "0.00",
19+
"cart_tax": "0.00",
20+
"total": "0.00",
21+
"total_tax": "0.00",
22+
"prices_include_tax": false,
23+
"customer_id": 0,
24+
"customer_ip_address": "",
25+
"customer_user_agent": "",
26+
"customer_note": "",
27+
"billing": {
28+
"first_name": "",
29+
"last_name": "",
30+
"company": "",
31+
"address_1": "",
32+
"address_2": "",
33+
"city": "",
34+
"state": "",
35+
"postcode": "",
36+
"country": "",
37+
"email": "",
38+
"phone": ""
39+
},
40+
"shipping": {
41+
"first_name": "",
42+
"last_name": "",
43+
"company": "",
44+
"address_1": "",
45+
"address_2": "",
46+
"city": "",
47+
"state": "",
48+
"postcode": "",
49+
"country": ""
50+
},
51+
"payment_method": "",
52+
"payment_method_title": "",
53+
"transaction_id": "",
54+
"date_paid": null,
55+
"date_paid_gmt": null,
56+
"date_completed": null,
57+
"date_completed_gmt": null,
58+
"cart_hash": "",
59+
"meta_data": [],
60+
"line_items": [],
61+
"tax_lines": [],
62+
"shipping_lines": [{
63+
"id": 1,
64+
"method_title": "Shipping",
65+
"method_id": "",
66+
"total": "0.00",
67+
"total_tax": "0.00",
68+
"taxes": [],
69+
"meta_data": []
70+
}, {
71+
"id": 2,
72+
"method_title": "Shipping",
73+
"method_id": "",
74+
"total": "0.00",
75+
"total_tax": "0.00",
76+
"taxes": [],
77+
"meta_data": []
78+
}, {
79+
"id": 3,
80+
"method_title": "Shipping",
81+
"method_id": "",
82+
"total": "0.00",
83+
"total_tax": "0.00",
84+
"taxes": [],
85+
"meta_data": []
86+
}],
87+
"fee_lines": [],
88+
"coupon_lines": [],
89+
"refunds": [],
90+
"_links": {
91+
"self": [],
92+
"collection": []
93+
}
94+
}]
95+
}

0 commit comments

Comments
 (0)