diff --git a/Networking/Networking.xcodeproj/project.pbxproj b/Networking/Networking.xcodeproj/project.pbxproj index fe0496a3961..8a1418296d5 100644 --- a/Networking/Networking.xcodeproj/project.pbxproj +++ b/Networking/Networking.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ B505F6D720BEE58800BB1B69 /* AccountRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B505F6D620BEE58800BB1B69 /* AccountRemoteTests.swift */; }; B505F6EA20BEFC3700BB1B69 /* MockupNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518662620A09BCC00037A38 /* MockupNetwork.swift */; }; B505F6EC20BEFDC200BB1B69 /* Loader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518663420A0A2E800037A38 /* Loader.swift */; }; + B5147876211B9227007562E5 /* broken-orders-mark-2.json in Resources */ = {isa = PBXBuildFile; fileRef = B5147875211B9227007562E5 /* broken-orders-mark-2.json */; }; B518662220A097C200037A38 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518662120A097C200037A38 /* Network.swift */; }; B518662420A099BF00037A38 /* AlamofireNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518662320A099BF00037A38 /* AlamofireNetwork.swift */; }; B518662A20A09C6F00037A38 /* OrdersRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B518662920A09C6F00037A38 /* OrdersRemoteTests.swift */; }; @@ -146,6 +147,7 @@ B505F6D220BEE3A500BB1B69 /* AccountMapperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountMapperTests.swift; sourceTree = ""; }; B505F6D420BEE4E600BB1B69 /* me.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = me.json; sourceTree = ""; }; B505F6D620BEE58800BB1B69 /* AccountRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRemoteTests.swift; sourceTree = ""; }; + B5147875211B9227007562E5 /* broken-orders-mark-2.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "broken-orders-mark-2.json"; sourceTree = ""; }; B518662120A097C200037A38 /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; B518662320A099BF00037A38 /* AlamofireNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlamofireNetwork.swift; sourceTree = ""; }; B518662620A09BCC00037A38 /* MockupNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockupNetwork.swift; sourceTree = ""; }; @@ -398,6 +400,7 @@ 74C8F06F20EEC3A800B6EDC9 /* broken-notes.json */, 74C8F06B20EEBD5D00B6EDC9 /* broken-order.json */, CE20179220E3EFA7005B4C18 /* broken-orders.json */, + B5147875211B9227007562E5 /* broken-orders-mark-2.json */, B58D10C72114D21C00107ED4 /* generic_error.json */, B505F6D420BEE4E600BB1B69 /* me.json */, B58D10C92114D22E00107ED4 /* new-order-note.json */, @@ -582,6 +585,7 @@ B58D10CA2114D22E00107ED4 /* new-order-note.json in Resources */, 74C8F06C20EEBD5D00B6EDC9 /* broken-order.json in Resources */, B58D10C82114D21D00107ED4 /* generic_error.json in Resources */, + B5147876211B9227007562E5 /* broken-orders-mark-2.json in Resources */, 743BF8BE21191B63008A9D87 /* site-visits.json in Resources */, B505F6D520BEE4E700BB1B69 /* me.json in Resources */, B5C6FCD620A3768900A4F8E4 /* order.json in Resources */, diff --git a/Networking/Networking/Model/OrderItem.swift b/Networking/Networking/Model/OrderItem.swift index a31ef414ea3..337189ba4df 100644 --- a/Networking/Networking/Model/OrderItem.swift +++ b/Networking/Networking/Model/OrderItem.swift @@ -8,7 +8,7 @@ public struct OrderItem: Decodable { public let name: String public let productID: Int public let quantity: Int - public let sku: String + public let sku: String? public let subtotal: String public let subtotalTax: String public let taxClass: String diff --git a/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift b/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift index d5629042f4c..00336d414b6 100644 --- a/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift @@ -107,6 +107,24 @@ class OrderListMapperTests: XCTestCase { let orderModifiedString = format.string(from: brokenOrder.dateModified) XCTAssertEqual(orderModifiedString, todayCreatedString) } + + /// Verifies that `broken-orders-mark-2` gets properly parsed: 6 Orders with 2 items each, and the SKU property should + /// always be set to null. + /// + /// Ref. Issue: https://github.com/woocommerce/woocommerce-ios/issues/221 + /// + func testOrderListWithBreakingFormatIsProperlyParsed() { + let orders = mapLoadBrokenOrdersResponseMarkII() + XCTAssertEqual(orders.count, 6) + + for order in orders { + XCTAssertEqual(order.items.count, 2) + + for item in order.items { + XCTAssertNil(item.sku) + } + } + } } @@ -130,9 +148,15 @@ private extension OrderListMapperTests { return mapOrders(from: "orders-load-all") } - /// Returns the OrderlistMapper output upon receiving `broken-order` + /// Returns the OrderListMapper output upon receiving `broken-order` /// func mapLoadBrokenOrderResponse() -> [Order] { return mapOrders(from: "broken-orders") } + + /// Returns the OrderListMapper output upon receiving `broken-orders-mark-2` + /// + func mapLoadBrokenOrdersResponseMarkII() -> [Order] { + return mapOrders(from: "broken-orders-mark-2") + } } diff --git a/Networking/NetworkingTests/Responses/broken-orders-mark-2.json b/Networking/NetworkingTests/Responses/broken-orders-mark-2.json new file mode 100644 index 00000000000..f15cf37fb25 --- /dev/null +++ b/Networking/NetworkingTests/Responses/broken-orders-mark-2.json @@ -0,0 +1,689 @@ +{ + "data": [{ + "id": 263, + "parent_id": 0, + "number": "263", + "order_key": "wc_order_5b671708d1382", + "created_via": "checkout", + "version": "3.4.1", + "status": "processing", + "currency": "EUR", + "date_created": "2018-08-05T15:26:00", + "date_created_gmt": "2018-08-05T15:26:00", + "date_modified": "2018-08-05T15:26:04", + "date_modified_gmt": "2018-08-05T15:26:04", + "discount_total": "0.00", + "discount_tax": "0.00", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "0.00", + "total": "25.00", + "total_tax": "0.00", + "prices_include_tax": false, + "customer_id": 1, + "customer_ip_address": "192.0.0.0", + "customer_user_agent": "mozilla\/5.0 (macintosh; intel mac os x 10_13_6) applewebkit\/537.36 (khtml, like gecko) chrome\/67.0.3396.99 safari\/537.36", + "customer_note": "", + "billing": { + "first_name": "Woo", + "last_name": "Woo", + "company": "", + "address_1": "1223 Woo Street", + "address_2": "", + "city": "Vancouver", + "state": "CA", + "postcode": "90210", + "country": "US", + "email": "scrambled@scrambled.com", + "phone": "555 555 5555" + }, + "shipping": { + "first_name": "", + "last_name": "", + "company": "", + "address_1": "", + "address_2": "", + "city": "", + "state": "", + "postcode": "", + "country": "" + }, + "payment_method": "stripe", + "payment_method_title": "Credit Card (Stripe)", + "transaction_id": "ch_000000000000000", + "date_paid": "2018-08-05T15:26:04", + "date_paid_gmt": "2018-08-05T15:26:04", + "date_completed": null, + "date_completed_gmt": null, + "cart_hash": "ch_000000000000000", + "meta_data": [{ + "id": 7450, + "key": "_stripe_source_id", + "value": "ch_000000000000000" + }, { + "id": 7451, + "key": "_stripe_charge_captured", + "value": "yes" + }, { + "id": 7452, + "key": "_stripe_fee", + "value": "1.37" + }, { + "id": 7453, + "key": "_stripe_net", + "value": "35.54" + }, { + "id": 7454, + "key": "_stripe_currency", + "value": "CAD" + }], + "line_items": [{ + "id": 7, + "name": "Another tea", + "product_id": 224, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "25.00", + "subtotal_tax": "0.00", + "total": "25.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 25 + }, { + "id": 7, + "name": "Another tea", + "product_id": 224, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "25.00", + "subtotal_tax": "0.00", + "total": "25.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 25 + }], + "tax_lines": [], + "shipping_lines": [], + "fee_lines": [], + "coupon_lines": [], + "refunds": [], + "_links": { + "self": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders\/263" + }], + "collection": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders" + }], + "customer": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/customers\/1" + }] + } + }, { + "id": 259, + "parent_id": 0, + "number": "259", + "order_key": "wc_order_5ace602461f2b", + "created_via": "checkout", + "version": "3.3.5", + "status": "processing", + "currency": "EUR", + "date_created": "2018-04-11T19:21:08", + "date_created_gmt": "2018-04-11T19:21:08", + "date_modified": "2018-04-11T19:21:11", + "date_modified_gmt": "2018-04-11T19:21:11", + "discount_total": "0.00", + "discount_tax": "0.00", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "0.00", + "total": "25.00", + "total_tax": "0.00", + "prices_include_tax": true, + "customer_id": 1, + "customer_ip_address": "192.168.1.1", + "customer_user_agent": "mozilla\/5.0 (macintosh; intel mac os x 10_13_4) applewebkit\/537.36 (khtml, like gecko) chrome\/65.0.3325.181 safari\/537.36", + "customer_note": "", + "billing": { + "first_name": "Scrambled", + "last_name": "Woo", + "company": "", + "address_1": "1223 Woo Street", + "address_2": "", + "city": "Vancouver", + "state": "CA", + "postcode": "90210", + "country": "US", + "email": "scrambled@scrambled", + "phone": "555 555 5555" + }, + "shipping": { + "first_name": "", + "last_name": "", + "company": "", + "address_1": "", + "address_2": "", + "city": "", + "state": "", + "postcode": "", + "country": "" + }, + "payment_method": "stripe", + "payment_method_title": "Credit Card (Stripe)", + "transaction_id": "ch_1CFoVGGNTAspWcqrNITccw58", + "date_paid": "2018-04-11T19:21:10", + "date_paid_gmt": "2018-04-11T19:21:10", + "date_completed": null, + "date_completed_gmt": null, + "cart_hash": "ff2c750d9bbeabb4a072aa1df515d227", + "meta_data": [{ + "id": 7388, + "key": "_stripe_source_id", + "value": "src_1CFoVDGNTAspWcqr8tCvgigU" + }, { + "id": 7389, + "key": "_stripe_charge_captured", + "value": "yes" + }, { + "id": 7390, + "key": "_stripe_fee", + "value": "1.41" + }, { + "id": 7391, + "key": "_stripe_net", + "value": "36.87" + }, { + "id": 7392, + "key": "_stripe_currency", + "value": "CAD" + }], + "line_items": [{ + "id": 6, + "name": "Another tea", + "product_id": 224, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "25.00", + "subtotal_tax": "0.00", + "total": "25.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 25 + }, { + "id": 6, + "name": "Another tea", + "product_id": 224, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "25.00", + "subtotal_tax": "0.00", + "total": "25.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 25 + }], + "tax_lines": [], + "shipping_lines": [], + "fee_lines": [], + "coupon_lines": [], + "refunds": [], + "_links": { + "self": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders\/259" + }], + "collection": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders" + }], + "customer": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/customers\/1" + }] + } + }, { + "id": 161, + "parent_id": 0, + "number": "161", + "order_key": "wc_order_5a2c94d5252c0", + "created_via": "checkout", + "version": "3.1.2", + "status": "processing", + "currency": "GBP", + "date_created": "2017-12-10T01:58:45", + "date_created_gmt": "2017-12-10T01:58:45", + "date_modified": "2017-12-10T01:58:45", + "date_modified_gmt": "2017-12-10T01:58:45", + "discount_total": "0.00", + "discount_tax": "0.00", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "0.00", + "total": "12.00", + "total_tax": "0.00", + "prices_include_tax": false, + "customer_id": 1, + "customer_ip_address": "192.168.1.1", + "customer_user_agent": "mozilla\/5.0 (macintosh; intel mac os x 10_13_1) applewebkit\/537.36 (khtml, like gecko) chrome\/62.0.3202.94 safari\/537.36", + "customer_note": "Here are my order notes, do they show in the email?", + "billing": { + "first_name": "Scrambled", + "last_name": "Woo", + "company": "", + "address_1": "1223 Woo Street", + "address_2": "", + "city": "Vancouver", + "state": "CA", + "postcode": "90210", + "country": "US", + "email": "scrambled@scrambled", + "phone": "555 555 5555" + }, + "shipping": { + "first_name": "", + "last_name": "", + "company": "", + "address_1": "", + "address_2": "", + "city": "", + "state": "", + "postcode": "", + "country": "" + }, + "payment_method": "cod", + "payment_method_title": "Cash on delivery", + "transaction_id": "", + "date_paid": null, + "date_paid_gmt": null, + "date_completed": null, + "date_completed_gmt": null, + "cart_hash": "4c3db942a20dad7ad9ed8e218e46cb1c", + "meta_data": [{ + "id": 1406, + "key": "_shipping_method", + "value": "" + }], + "line_items": [{ + "id": 5, + "name": "Flying Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "12.00", + "subtotal_tax": "0.00", + "total": "12.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 12 + }, { + "id": 5, + "name": "Flying Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "12.00", + "subtotal_tax": "0.00", + "total": "12.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 12 + }], + "tax_lines": [], + "shipping_lines": [], + "fee_lines": [], + "coupon_lines": [], + "refunds": [], + "_links": { + "self": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders\/161" + }], + "collection": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders" + }], + "customer": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/customers\/1" + }] + } + }, { + "id": 160, + "parent_id": 0, + "number": "160", + "order_key": "wc_order_5a2c94b07f79e", + "created_via": "checkout", + "version": "3.1.2", + "status": "processing", + "currency": "GBP", + "date_created": "2017-12-10T01:58:08", + "date_created_gmt": "2017-12-10T01:58:08", + "date_modified": "2017-12-10T01:58:08", + "date_modified_gmt": "2017-12-10T01:58:08", + "discount_total": "0.00", + "discount_tax": "0.00", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "0.00", + "total": "12.00", + "total_tax": "0.00", + "prices_include_tax": false, + "customer_id": 1, + "customer_ip_address": "192.168.1.1", + "customer_user_agent": "mozilla\/5.0 (macintosh; intel mac os x 10_13_1) applewebkit\/537.36 (khtml, like gecko) chrome\/62.0.3202.94 safari\/537.36", + "customer_note": "", + "billing": { + "first_name": "Scrambled", + "last_name": "Woo", + "company": "", + "address_1": "1223 Woo Street", + "address_2": "", + "city": "Vancouver", + "state": "CA", + "postcode": "90210", + "country": "US", + "email": "scrambled@scrambled", + "phone": "555 555 5555" + }, + "shipping": { + "first_name": "", + "last_name": "", + "company": "", + "address_1": "", + "address_2": "", + "city": "", + "state": "", + "postcode": "", + "country": "" + }, + "payment_method": "cod", + "payment_method_title": "Cash on delivery", + "transaction_id": "", + "date_paid": null, + "date_paid_gmt": null, + "date_completed": null, + "date_completed_gmt": null, + "cart_hash": "4c3db942a20dad7ad9ed8e218e46cb1c", + "meta_data": [{ + "id": 1357, + "key": "_shipping_method", + "value": "" + }], + "line_items": [{ + "id": 4, + "name": "Flying Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "12.00", + "subtotal_tax": "0.00", + "total": "12.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 12 + }, { + "id": 4, + "name": "Flying Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "12.00", + "subtotal_tax": "0.00", + "total": "12.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 12 + }], + "tax_lines": [], + "shipping_lines": [], + "fee_lines": [], + "coupon_lines": [], + "refunds": [], + "_links": { + "self": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders\/160" + }], + "collection": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders" + }], + "customer": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/customers\/1" + }] + } + }, { + "id": 159, + "parent_id": 0, + "number": "159", + "order_key": "wc_order_5a2c93ef7eb03", + "created_via": "checkout", + "version": "3.1.2", + "status": "processing", + "currency": "GBP", + "date_created": "2017-12-10T01:54:55", + "date_created_gmt": "2017-12-10T01:54:55", + "date_modified": "2017-12-10T01:54:55", + "date_modified_gmt": "2017-12-10T01:54:55", + "discount_total": "0.00", + "discount_tax": "0.00", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "0.00", + "total": "15.00", + "total_tax": "0.00", + "prices_include_tax": false, + "customer_id": 1, + "customer_ip_address": "192.168.1.1", + "customer_user_agent": "mozilla\/5.0 (macintosh; intel mac os x 10_13_1) applewebkit\/537.36 (khtml, like gecko) chrome\/62.0.3202.94 safari\/537.36", + "customer_note": "Testing AT site Order Notes. Fingers crossed...", + "billing": { + "first_name": "Scrambled", + "last_name": "Woo", + "company": "", + "address_1": "1223 Woo Street", + "address_2": "", + "city": "Vancouver", + "state": "CA", + "postcode": "90210", + "country": "US", + "email": "scrambled@scrambled", + "phone": "555 555 5555" + }, + "shipping": { + "first_name": "", + "last_name": "", + "company": "", + "address_1": "", + "address_2": "", + "city": "", + "state": "", + "postcode": "", + "country": "" + }, + "payment_method": "cod", + "payment_method_title": "Cash on delivery", + "transaction_id": "", + "date_paid": null, + "date_paid_gmt": null, + "date_completed": null, + "date_completed_gmt": null, + "cart_hash": "59ef163e9f566ecee03d891868e28762", + "meta_data": [{ + "id": 1308, + "key": "_shipping_method", + "value": "" + }], + "line_items": [{ + "id": 3, + "name": "Woo Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "15.00", + "subtotal_tax": "0.00", + "total": "15.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 15 + }, { + "id": 3, + "name": "Woo Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "15.00", + "subtotal_tax": "0.00", + "total": "15.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 15 + }], + "tax_lines": [], + "shipping_lines": [], + "fee_lines": [], + "coupon_lines": [], + "refunds": [], + "_links": { + "self": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders\/159" + }], + "collection": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders" + }], + "customer": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/customers\/1" + }] + } + }, { + "id": 158, + "parent_id": 0, + "number": "158", + "order_key": "wc_order_5a00fd94b3379", + "created_via": "checkout", + "version": "3.1.2", + "status": "processing", + "currency": "GBP", + "date_created": "2017-11-07T00:25:56", + "date_created_gmt": "2017-11-07T00:25:56", + "date_modified": "2017-11-07T00:25:57", + "date_modified_gmt": "2017-11-07T00:25:57", + "discount_total": "0.00", + "discount_tax": "0.00", + "shipping_total": "0.00", + "shipping_tax": "0.00", + "cart_tax": "0.00", + "total": "30.00", + "total_tax": "0.00", + "prices_include_tax": false, + "customer_id": 1, + "customer_ip_address": "172.103.149.103", + "customer_user_agent": "mozilla\/5.0 (macintosh; intel mac os x 10_12_6) applewebkit\/537.36 (khtml, like gecko) chrome\/62.0.3202.75 safari\/537.36", + "customer_note": "", + "billing": { + "first_name": "Scrambled", + "last_name": "Woo", + "company": "", + "address_1": "1223 Woo Street", + "address_2": "", + "city": "Vancouver", + "state": "CA", + "postcode": "90210", + "country": "US", + "email": "scrambled@scrambled", + "phone": "555 555 5555" + }, + "shipping": { + "first_name": "", + "last_name": "", + "company": "", + "address_1": "", + "address_2": "", + "city": "", + "state": "", + "postcode": "", + "country": "" + }, + "payment_method": "cod", + "payment_method_title": "Cash on delivery", + "transaction_id": "", + "date_paid": null, + "date_paid_gmt": null, + "date_completed": null, + "date_completed_gmt": null, + "cart_hash": "5c5c196dbcee14723a60291b94cbc92e", + "meta_data": [{ + "id": 1249, + "key": "_shipping_method", + "value": "" + }], + "line_items": [{ + "id": 1, + "name": "Flying Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "12.00", + "subtotal_tax": "0.00", + "total": "12.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 12 + }, { + "id": 2, + "name": "Happy Ninja", + "product_id": 0, + "variation_id": 0, + "quantity": 1, + "tax_class": "", + "subtotal": "18.00", + "subtotal_tax": "0.00", + "total": "18.00", + "total_tax": "0.00", + "taxes": [], + "meta_data": [], + "sku": null, + "price": 18 + }], + "tax_lines": [], + "shipping_lines": [], + "fee_lines": [], + "coupon_lines": [], + "refunds": [], + "_links": { + "self": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders\/158" + }], + "collection": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/orders" + }], + "customer": [{ + "href": "https:\/\/scrambled.scrambled.com\/wp-json\/wc\/v2\/customers\/1" + }] + } + }] +} diff --git a/WooCommerce/Classes/ViewModels/OrderItemViewModel.swift b/WooCommerce/Classes/ViewModels/OrderItemViewModel.swift index de97daf5b6b..4b0b57ce485 100644 --- a/WooCommerce/Classes/ViewModels/OrderItemViewModel.swift +++ b/WooCommerce/Classes/ViewModels/OrderItemViewModel.swift @@ -51,11 +51,11 @@ struct OrderItemViewModel { /// Item's SKU /// var sku: String? { - guard item.sku.isEmpty == false else { + guard let sku = item.sku, sku.isEmpty == false else { return nil } let prefix = NSLocalizedString("SKU:", comment: "SKU label") - return prefix + " " + item.sku + return prefix + " " + sku } } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/ProductDetailsTableViewCell.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/ProductDetailsTableViewCell.swift index f7b036f616b..59d95e4d5a8 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/ProductDetailsTableViewCell.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/ProductDetailsTableViewCell.swift @@ -119,7 +119,8 @@ extension ProductDetailsTableViewCell { taxLabel.text = taxText let skuString = NSLocalizedString("SKU:", comment: "SKU label") - let skuText = item.sku.isEmpty ? nil : "\(skuString) \(item.sku)" + let skuRaw = item.sku ?? String() + let skuText = skuRaw.isEmpty ? nil : "\(skuString) \(skuRaw)" skuLabel.text = skuText } } diff --git a/Yosemite/YosemiteTests/Stores/OrderStoreTests.swift b/Yosemite/YosemiteTests/Stores/OrderStoreTests.swift index 425ebf7ac65..d05915d1ea5 100644 --- a/Yosemite/YosemiteTests/Stores/OrderStoreTests.swift +++ b/Yosemite/YosemiteTests/Stores/OrderStoreTests.swift @@ -111,6 +111,28 @@ class OrderStoreTests: XCTestCase { wait(for: [expectation], timeout: Constants.expectationTimeout) } + /// Verifies that `OrderAction.retrieveOrders` can properly process the document `broken-orders-mark-2`. + /// + /// Ref. Issue: https://github.com/woocommerce/woocommerce-ios/issues/221 + /// + func testRetrieveOrdersWithBreakingDocumentIsProperlyParsedAndInsertedIntoStorage() { + let expectation = self.expectation(description: "Persist order list") + let orderStore = OrderStore(dispatcher: dispatcher, storageManager: storageManager, network: network) + + network.simulateResponse(requestUrlSuffix: "orders", filename: "broken-orders-mark-2") + XCTAssertEqual(viewStorage.countObjects(ofType: Storage.Order.self), 0) + + let action = OrderAction.retrieveOrders(siteID: sampleSiteID) { error in + XCTAssertNil(error) + XCTAssertEqual(self.viewStorage.countObjects(ofType: Storage.Order.self), 6) + + expectation.fulfill() + } + + orderStore.onAction(action) + wait(for: [expectation], timeout: Constants.expectationTimeout) + } + /// Verifies that OrderAction.retrieveOrders returns an error whenever there is an error response from the backend. /// func testRetrieveOrdersReturnsErrorUponReponseError() {