@@ -9,6 +9,8 @@ import struct Yosemite.OrderCouponLine
99import enum Yosemite. OrderAction
1010import class WooFoundation. CurrencySettings
1111import protocol WooFoundation. Analytics
12+ import enum Networking. DotcomError
13+ import enum Networking. NetworkError
1214
1315struct PointOfSaleOrderControllerTests {
1416 let mockOrderService = MockPOSOrderService ( )
@@ -435,6 +437,93 @@ struct PointOfSaleOrderControllerTests {
435437 #expect( mockOrderService. syncOrderWasCalled == true )
436438 }
437439
440+ @available ( iOS 17 . 0 , * )
441+ @Test func syncOrder_when_orderService_fails_with_couponsError_then_sets_invalidCoupon_error( ) async throws {
442+ // Given
443+ let sut = PointOfSaleOrderController ( orderService: mockOrderService,
444+ receiptService: mockReceiptService)
445+ let errorMessage = " Invalid coupon code "
446+ mockOrderService. errorToReturn = DotcomError . unknown ( code: " woocommerce_rest_invalid_coupon " , message: errorMessage)
447+
448+ var orderStates : [ PointOfSaleInternalOrderState ] = [ sut. orderState]
449+ var orderStateAppendTask : Task < Void , Never > ? = nil
450+ await confirmation ( expectedCount: 2 ) { confirmation in
451+ @Sendable func observeOrderState( ) {
452+ withObservationTracking {
453+ _ = sut. orderState
454+ } onChange: {
455+ orderStateAppendTask = Task { @MainActor in
456+ orderStates. append ( sut. orderState)
457+ }
458+ confirmation ( )
459+ observeOrderState ( )
460+ }
461+ }
462+ observeOrderState ( )
463+
464+ // When
465+ await sut. syncOrder ( for: . init( items: [ makeItem ( ) ] ,
466+ coupons: [ . init( id: UUID ( ) , code: " INVALID " ) ] ) ,
467+ retryHandler: { } )
468+ }
469+
470+ await orderStateAppendTask? . value
471+
472+ // Then
473+ #expect( orderStates == [
474+ . idle,
475+ . syncing,
476+ . error( . invalidCoupon( errorMessage) , { } )
477+ ] )
478+ }
479+
480+ @available ( iOS 17 . 0 , * )
481+ @Test func syncOrder_when_orderService_fails_with_networkError_containing_couponsError_then_sets_invalidCoupon_error( ) async throws {
482+ // Given
483+ let sut = PointOfSaleOrderController ( orderService: mockOrderService,
484+ receiptService: mockReceiptService)
485+ let errorMessage = " Coupon INVALID does not exist "
486+ let errorJSON = """
487+ {
488+ " code " : " woocommerce_rest_invalid_coupon " ,
489+ " message " : " \( errorMessage) "
490+ }
491+ """
492+ let errorData = errorJSON. data ( using: . utf8) !
493+ mockOrderService. errorToReturn = NetworkError . unacceptableStatusCode ( statusCode: 400 , response: errorData)
494+
495+ var orderStates : [ PointOfSaleInternalOrderState ] = [ sut. orderState]
496+ var orderStateAppendTask : Task < Void , Never > ? = nil
497+ await confirmation ( expectedCount: 2 ) { confirmation in
498+ @Sendable func observeOrderState( ) {
499+ withObservationTracking {
500+ _ = sut. orderState
501+ } onChange: {
502+ orderStateAppendTask = Task { @MainActor in
503+ orderStates. append ( sut. orderState)
504+ }
505+ confirmation ( )
506+ observeOrderState ( )
507+ }
508+ }
509+ observeOrderState ( )
510+
511+ // When
512+ await sut. syncOrder ( for: . init( items: [ makeItem ( ) ] ,
513+ coupons: [ . init( id: UUID ( ) , code: " INVALID " ) ] ) ,
514+ retryHandler: { } )
515+ }
516+
517+ await orderStateAppendTask? . value
518+
519+ // Then
520+ #expect( orderStates == [
521+ . idle,
522+ . syncing,
523+ . error( . invalidCoupon( errorMessage) , { } )
524+ ] )
525+ }
526+
438527 struct AnalyticsTests {
439528 private let analytics : WooAnalytics
440529 private let analyticsProvider = MockAnalyticsProvider ( )
0 commit comments