Skip to content

Commit 5e66974

Browse files
committed
Improve POSCart with PointOfSaleOrderController to match coupons when checking order changes
1 parent 0f2caac commit 5e66974

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ protocol PointOfSaleOrderControllerProtocol {
6969
retryHandler: @escaping () async -> Void) async -> Result<SyncOrderState, Error> {
7070
let posCart = POSCart(cart: cart)
7171

72-
guard !orderState.isSyncing, !posCart.items.matches(order: order) else {
72+
guard !orderState.isSyncing, !posCart.matches(order: order) else {
7373
return .success(.orderNotChanged)
7474
}
7575

WooCommerce/WooCommerceTests/POS/Controllers/PointOfSaleOrderControllerTests.swift

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Foundation
55
@testable import WooCommerce
66
import struct Yosemite.Order
77
import struct Yosemite.OrderItem
8+
import struct Yosemite.OrderCouponLine
89
import enum Yosemite.OrderAction
910
import class WooFoundation.CurrencySettings
1011
import protocol WooFoundation.Analytics
@@ -364,6 +365,72 @@ struct PointOfSaleOrderControllerTests {
364365
}
365366
}
366367

368+
@available(iOS 17.0, *)
369+
@Test func syncOrder_with_cart_matching_order_and_coupons_doesnt_call_orderService() async throws {
370+
// Given
371+
let sut = PointOfSaleOrderController(orderService: mockOrderService,
372+
receiptService: mockReceiptService)
373+
let orderItem = OrderItem.fake().copy(quantity: 1)
374+
let couponCode = "SAVE10"
375+
let coupon = OrderCouponLine.fake().copy(code: couponCode)
376+
let fakeOrder = Order.fake().copy(items: [orderItem], coupons: [coupon])
377+
let cartItem = makeItem(orderItemsToMatch: [orderItem])
378+
mockOrderService.orderToReturn = fakeOrder
379+
380+
// Initial sync to set up the order
381+
await sut.syncOrder(for: .init(items: [cartItem], coupons: [.init(id: UUID(), code: couponCode)]), retryHandler: {})
382+
383+
// When - sync with same items and coupons
384+
await sut.syncOrder(for: .init(items: [cartItem], coupons: [.init(id: UUID(), code: couponCode)]), retryHandler: {})
385+
386+
// Then
387+
#expect(mockOrderService.syncOrderWasCalled == false)
388+
}
389+
390+
@available(iOS 17.0, *)
391+
@Test func syncOrder_with_matching_items_but_different_coupons_calls_orderService() async throws {
392+
// Given
393+
let sut = PointOfSaleOrderController(orderService: mockOrderService,
394+
receiptService: mockReceiptService)
395+
let orderItem = OrderItem.fake().copy(quantity: 1)
396+
let initialCouponCode = "SAVE10"
397+
let initialCoupon = OrderCouponLine.fake().copy(code: initialCouponCode)
398+
let fakeOrder = Order.fake().copy(items: [orderItem], coupons: [initialCoupon])
399+
let cartItem = makeItem(orderItemsToMatch: [orderItem])
400+
mockOrderService.orderToReturn = fakeOrder
401+
402+
// Initial sync
403+
await sut.syncOrder(for: .init(items: [cartItem], coupons: [.init(id: UUID(), code: initialCouponCode)]), retryHandler: {})
404+
405+
// When - sync with same items but different coupon
406+
await sut.syncOrder(for: .init(items: [cartItem], coupons: [.init(id: UUID(), code: "DIFFERENT20")]), retryHandler: {})
407+
408+
// Then
409+
#expect(mockOrderService.syncOrderWasCalled == true)
410+
}
411+
412+
@available(iOS 17.0, *)
413+
@Test func syncOrder_with_matching_items_but_removed_coupon_calls_orderService() async throws {
414+
// Given
415+
let sut = PointOfSaleOrderController(orderService: mockOrderService,
416+
receiptService: mockReceiptService)
417+
let orderItem = OrderItem.fake().copy(quantity: 1)
418+
let couponCode = "SAVE10"
419+
let coupon = OrderCouponLine.fake().copy(code: couponCode)
420+
let fakeOrder = Order.fake().copy(items: [orderItem], coupons: [coupon])
421+
let cartItem = makeItem(orderItemsToMatch: [orderItem])
422+
mockOrderService.orderToReturn = fakeOrder
423+
424+
// Initial sync with coupon
425+
await sut.syncOrder(for: .init(items: [cartItem], coupons: [.init(id: UUID(), code: couponCode)]), retryHandler: {})
426+
427+
// When - sync with same items but no coupons
428+
await sut.syncOrder(for: .init(items: [cartItem], coupons: []), retryHandler: {})
429+
430+
// Then
431+
#expect(mockOrderService.syncOrderWasCalled == true)
432+
}
433+
367434
struct AnalyticsTests {
368435
private let analytics: WooAnalytics
369436
private let analyticsProvider = MockAnalyticsProvider()

Yosemite/Yosemite/Tools/POS/POSCart.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,14 @@ public struct POSCartCouponItem {
3131
}
3232
}
3333

34+
public extension POSCart {
35+
func matches(order: Order?) -> Bool {
36+
return items.matches(order: order) && coupons.matches(order: order)
37+
}
38+
}
39+
3440
extension [POSCartItem] {
35-
public func matches(order: Order?) -> Bool {
41+
func matches(order: Order?) -> Bool {
3642
guard let order else {
3743
return self.isEmpty
3844
}
@@ -94,3 +100,15 @@ extension [POSCartItem] {
94100
return output
95101
}
96102
}
103+
104+
extension [POSCartCouponItem] {
105+
func matches(order: Order?) -> Bool {
106+
guard let order else {
107+
return self.isEmpty
108+
}
109+
110+
let orderCoupons = Set(order.coupons.map(\.code))
111+
let cartCoupons = Set(self.map(\.code))
112+
return orderCoupons == cartCoupons
113+
}
114+
}

0 commit comments

Comments
 (0)