From 88e5faabca40b07bf0504dc1cceca3a331c00222 Mon Sep 17 00:00:00 2001 From: RafaelKayumov Date: Thu, 27 Nov 2025 13:26:11 +0300 Subject: [PATCH 1/7] Add default site fallback and non-fatal logging --- ...erCardPresentPaymentEligibilityStore.swift | 59 ++++++++++++++++++- .../Classes/Yosemite/AuthenticatedState.swift | 1 + 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift b/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift index 72b3c4ec90d..c26dde3691e 100644 --- a/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift +++ b/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift @@ -1,11 +1,14 @@ import Foundation import protocol Storage.StorageManagerType import protocol NetworkingCore.Network +import protocol WooFoundation.CrashLogger +import enum WooFoundation.SeverityLevel /// Determines whether an order is eligible for card present payment or not /// public final class OrderCardPresentPaymentEligibilityStore: Store { private let currentSite: () -> Site? + private let crashLogger: CrashLogger private lazy var siteCIABEligibilityChecker: CIABEligibilityCheckerProtocol = CIABEligibilityChecker( currentSite: currentSite ) @@ -14,9 +17,11 @@ public final class OrderCardPresentPaymentEligibilityStore: Store { dispatcher: Dispatcher, storageManager: StorageManagerType, network: Network, + crashLogger: CrashLogger, currentSite: @escaping () -> Site? ) { self.currentSite = currentSite + self.crashLogger = crashLogger super.init( dispatcher: dispatcher, storageManager: storageManager, @@ -55,11 +60,27 @@ private extension OrderCardPresentPaymentEligibilityStore { cardPresentPaymentsConfiguration: CardPresentPaymentsConfiguration, onCompletion: (Result) -> Void) { let storage = storageManager.viewStorage + let storageSite = storage.loadSite(siteID: siteID)?.toReadOnly() + + let site: Site? + if let storageSite { + site = storageSite + } else { + /// Non - fatal fallback to `currentSite` when a storage site is missing + site = currentSite() + + logFailedStorageSiteRead( + siteID: siteID, + currentSiteFallbackValue: site + ) + } + + guard let site else { + logFailedDefaultSiteRead(siteID: siteID) - guard let site = storage.loadSite(siteID: siteID)?.toReadOnly() else { return onCompletion( .failure( - OrderIsEligibleForCardPresentPaymentError.siteNotFoundInStorage + OrderIsEligibleForCardPresentPaymentError.failedToObtainSite ) ) } @@ -83,10 +104,42 @@ private extension OrderCardPresentPaymentEligibilityStore { } } +/// Error logging +private extension OrderCardPresentPaymentEligibilityStore { + func logFailedStorageSiteRead(siteID: Int64, currentSiteFallbackValue: Site?) { + let message = "OrderCardPresentPaymentEligibilityStore: Storage site missing, falling back to currentSite." + + DDLogError(message) + + crashLogger.logMessage( + message, + properties: [ + "siteID": siteID, + "currentSiteID": currentSiteFallbackValue?.siteID ?? "empty", + ], + level: .error + ) + } + + func logFailedDefaultSiteRead(siteID: Int64) { + let message = "OrderCardPresentPaymentEligibilityStore: Current default site missing." + + DDLogError(message) + + crashLogger.logMessage( + "OrderCardPresentPaymentEligibilityStore: Current default site missing.", + properties: [ + "requestedSiteID": siteID + ], + level: .error + ) + } +} + extension OrderCardPresentPaymentEligibilityStore { enum OrderIsEligibleForCardPresentPaymentError: Error { case orderNotFoundInStorage - case siteNotFoundInStorage + case failedToObtainSite case cardReaderPaymentOptionIsNotSupportedForCIABSites } } diff --git a/WooCommerce/Classes/Yosemite/AuthenticatedState.swift b/WooCommerce/Classes/Yosemite/AuthenticatedState.swift index 612dfa85653..9bcdb854f57 100644 --- a/WooCommerce/Classes/Yosemite/AuthenticatedState.swift +++ b/WooCommerce/Classes/Yosemite/AuthenticatedState.swift @@ -86,6 +86,7 @@ class AuthenticatedState: StoresManagerState { dispatcher: dispatcher, storageManager: storageManager, network: network, + crashLogger: ServiceLocator.crashLogging, currentSite: { ServiceLocator.stores.sessionManager.defaultSite } From 9c5685263a607367347a4894542208535aeec824 Mon Sep 17 00:00:00 2001 From: RafaelKayumov Date: Thu, 27 Nov 2025 13:43:57 +0300 Subject: [PATCH 2/7] Update tests --- .../Stores/OrderCardPresentPaymentEligibilityStoreTests.swift | 2 ++ .../Orders/Payment Methods/PaymentMethodsViewModelTests.swift | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift index 444a60e7512..88babcc012f 100644 --- a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift +++ b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift @@ -4,6 +4,7 @@ import XCTest @testable import Yosemite @testable import Networking +@testable import WooFoundation final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { @@ -38,6 +39,7 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { dispatcher: dispatcher, storageManager: storageManager, network: network, + crashLogger: MockCrashLogger(), currentSite: { [weak self] in return self?.currentSite } diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift index a2430966297..93ac75de8d5 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift @@ -2,11 +2,11 @@ import Foundation import XCTest import Combine import Fakes -import WooFoundation @testable import WooCommerce @testable import Yosemite @testable import Networking +@testable import WooFoundation private typealias Dependencies = PaymentMethodsViewModel.Dependencies @@ -807,6 +807,7 @@ final class PaymentMethodsViewModelTests: XCTestCase { dispatcher: Dispatcher(), storageManager: storage, network: MockNetwork(), + crashLogger: MockCrashLogger(), currentSite: { ciabSite } ) From 96f2d3d824231e802982bd9ccf9160586b0305d9 Mon Sep 17 00:00:00 2001 From: RafaelKayumov Date: Thu, 27 Nov 2025 14:21:52 +0300 Subject: [PATCH 3/7] Add tests --- ...dPresentPaymentEligibilityStoreTests.swift | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift index 88babcc012f..31abf8edb5c 100644 --- a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift +++ b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift @@ -100,6 +100,53 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { XCTAssertTrue(eligibility) } + func test_orderIsEligibleForCardPresentPayment_returns_true_for_eligible_order_and_none_stored_site() throws { + // Given + let orderItem = OrderItem.fake().copy(itemID: 1234, + name: "Chocolate cake", + productID: 678, + quantity: 1.0) + let cppEligibleOrder = Order.fake().copy(siteID: sampleSiteID, + orderID: 111, + status: .pending, + currency: "USD", + datePaid: nil, + total: "5.00", + paymentMethodID: "woocommerce_payments", + items: [orderItem]) + let nonSubscriptionProduct = Product.fake().copy(siteID: sampleSiteID, + productID: 678, + name: "Chocolate cake", + productTypeKey: "simple") + + let regularSite = Site.fake().copy( + siteID: sampleSiteID, + isGarden: false, + gardenName: nil + ) + self.currentSite = regularSite + + storageManager.insertSampleProduct(readOnlyProduct: nonSubscriptionProduct) + storageManager.insertSampleOrder(readOnlyOrder: cppEligibleOrder) + + let configuration = CardPresentPaymentsConfiguration(country: .US) + + // When + let result = waitFor { promise in + let action = OrderCardPresentPaymentEligibilityAction + .orderIsEligibleForCardPresentPayment(orderID: 111, + siteID: self.sampleSiteID, + cardPresentPaymentsConfiguration: configuration) { result in + promise(result) + } + self.store.onAction(action) + } + + // Then + let eligibility = try XCTUnwrap(result.get()) + XCTAssertTrue(eligibility) + } + func test_orderIsEligibleForCardPresentPayment_returns_failure_for_CIAB_sites() throws { // Given let orderItem = OrderItem.fake().copy(itemID: 1234, From dbb2a63c570cdb0c06bc9c3491f832749c22d567 Mon Sep 17 00:00:00 2001 From: RafaelKayumov Date: Thu, 27 Nov 2025 15:26:55 +0300 Subject: [PATCH 4/7] Wrap site assessment behind `ciab` FF --- .../DefaultFeatureFlagService.swift | 2 + Modules/Sources/Experiments/FeatureFlag.swift | 5 ++ ...erCardPresentPaymentEligibilityStore.swift | 59 +++++++++++-------- .../Classes/Yosemite/AuthenticatedState.swift | 3 + 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift index 95f7d3abef0..146aaa286c2 100644 --- a/Modules/Sources/Experiments/DefaultFeatureFlagService.swift +++ b/Modules/Sources/Experiments/DefaultFeatureFlagService.swift @@ -98,6 +98,8 @@ public struct DefaultFeatureFlagService: FeatureFlagService { return buildConfig == .localDeveloper || buildConfig == .alpha case .ciabBookings: return buildConfig == .localDeveloper || buildConfig == .alpha + case .ciab: + return buildConfig == .localDeveloper || buildConfig == .alpha case .pointOfSaleSurveys: return buildConfig == .localDeveloper || buildConfig == .alpha case .pointOfSaleSettingsCardReaderFlow: diff --git a/Modules/Sources/Experiments/FeatureFlag.swift b/Modules/Sources/Experiments/FeatureFlag.swift index 620a0a55855..7a885e49992 100644 --- a/Modules/Sources/Experiments/FeatureFlag.swift +++ b/Modules/Sources/Experiments/FeatureFlag.swift @@ -204,6 +204,11 @@ public enum FeatureFlag: Int { /// case ciabBookings + /// Represents CIAB environment availability overall + /// Has same underlying logic as `ciabBookings` flag. + /// + case ciab + /// Enables surveys for potential and current POS merchants /// case pointOfSaleSurveys diff --git a/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift b/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift index c26dde3691e..0e9ed868cf1 100644 --- a/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift +++ b/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift @@ -8,6 +8,7 @@ import enum WooFoundation.SeverityLevel /// public final class OrderCardPresentPaymentEligibilityStore: Store { private let currentSite: () -> Site? + private let isCIABEnvironmentSupported: () -> Bool private let crashLogger: CrashLogger private lazy var siteCIABEligibilityChecker: CIABEligibilityCheckerProtocol = CIABEligibilityChecker( currentSite: currentSite @@ -18,9 +19,11 @@ public final class OrderCardPresentPaymentEligibilityStore: Store { storageManager: StorageManagerType, network: Network, crashLogger: CrashLogger, + isCIABEnvironmentSupported: @escaping () -> Bool, currentSite: @escaping () -> Site? ) { self.currentSite = currentSite + self.isCIABEnvironmentSupported = isCIABEnvironmentSupported self.crashLogger = crashLogger super.init( dispatcher: dispatcher, @@ -60,37 +63,41 @@ private extension OrderCardPresentPaymentEligibilityStore { cardPresentPaymentsConfiguration: CardPresentPaymentsConfiguration, onCompletion: (Result) -> Void) { let storage = storageManager.viewStorage - let storageSite = storage.loadSite(siteID: siteID)?.toReadOnly() - - let site: Site? - if let storageSite { - site = storageSite - } else { - /// Non - fatal fallback to `currentSite` when a storage site is missing - site = currentSite() - - logFailedStorageSiteRead( - siteID: siteID, - currentSiteFallbackValue: site - ) - } - guard let site else { - logFailedDefaultSiteRead(siteID: siteID) + /// The following checks are only relevant if CIAB is rolled out. + if isCIABEnvironmentSupported() { + let storageSite = storage.loadSite(siteID: siteID)?.toReadOnly() + + let site: Site? + if let storageSite { + site = storageSite + } else { + /// Non - fatal fallback to `currentSite` when a storage site is missing + site = currentSite() - return onCompletion( - .failure( - OrderIsEligibleForCardPresentPaymentError.failedToObtainSite + logFailedStorageSiteRead( + siteID: siteID, + currentSiteFallbackValue: site ) - ) - } + } + + guard let site else { + logFailedDefaultSiteRead(siteID: siteID) + + return onCompletion( + .failure( + OrderIsEligibleForCardPresentPaymentError.failedToObtainSite + ) + ) + } - guard siteCIABEligibilityChecker.isFeatureSupported(.cardReader, for: site) else { - return onCompletion( - .failure( - OrderIsEligibleForCardPresentPaymentError.cardReaderPaymentOptionIsNotSupportedForCIABSites + guard siteCIABEligibilityChecker.isFeatureSupported(.cardReader, for: site) else { + return onCompletion( + .failure( + OrderIsEligibleForCardPresentPaymentError.cardReaderPaymentOptionIsNotSupportedForCIABSites + ) ) - ) + } } guard let order = storage.loadOrder(siteID: siteID, orderID: orderID)?.toReadOnly() else { diff --git a/WooCommerce/Classes/Yosemite/AuthenticatedState.swift b/WooCommerce/Classes/Yosemite/AuthenticatedState.swift index 9bcdb854f57..45c8496c30d 100644 --- a/WooCommerce/Classes/Yosemite/AuthenticatedState.swift +++ b/WooCommerce/Classes/Yosemite/AuthenticatedState.swift @@ -87,6 +87,9 @@ class AuthenticatedState: StoresManagerState { storageManager: storageManager, network: network, crashLogger: ServiceLocator.crashLogging, + isCIABEnvironmentSupported: { + ServiceLocator.featureFlagService.isFeatureFlagEnabled(.ciab) + }, currentSite: { ServiceLocator.stores.sessionManager.defaultSite } From ed43a74b9905688515e8dded3318546a515c3d22 Mon Sep 17 00:00:00 2001 From: RafaelKayumov Date: Thu, 27 Nov 2025 15:48:54 +0300 Subject: [PATCH 5/7] Add test for site assessment skip when CIAB is not supported --- .../Mocks/MockFeatureFlagService.swift | 7 ++- ...dPresentPaymentEligibilityStoreTests.swift | 57 +++++++++++++++++++ .../PaymentMethodsViewModelTests.swift | 1 + 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Modules/Tests/PointOfSaleTests/Mocks/MockFeatureFlagService.swift b/Modules/Tests/PointOfSaleTests/Mocks/MockFeatureFlagService.swift index f76817d0f81..e974037853d 100644 --- a/Modules/Tests/PointOfSaleTests/Mocks/MockFeatureFlagService.swift +++ b/Modules/Tests/PointOfSaleTests/Mocks/MockFeatureFlagService.swift @@ -25,6 +25,7 @@ final class MockFeatureFlagService: POSFeatureFlagProviding { var isProductImageOptimizedHandlingEnabled: Bool var isFeatureFlagEnabledReturnValue: [FeatureFlag: Bool] = [:] var isCIABBookingsEnabled: Bool + var isCIABEnabled: Bool init(isInboxOn: Bool = false, isShowInboxCTAEnabled: Bool = false, @@ -47,7 +48,8 @@ final class MockFeatureFlagService: POSFeatureFlagProviding { notificationSettings: Bool = false, allowMerchantAIAPIKey: Bool = false, isProductImageOptimizedHandlingEnabled: Bool = false, - isCIABBookingsEnabled: Bool = false) { + isCIABBookingsEnabled: Bool = false, + isCIABEnabled: Bool = false) { self.isInboxOn = isInboxOn self.isShowInboxCTAEnabled = isShowInboxCTAEnabled self.isUpdateOrderOptimisticallyOn = isUpdateOrderOptimisticallyOn @@ -70,6 +72,7 @@ final class MockFeatureFlagService: POSFeatureFlagProviding { self.allowMerchantAIAPIKey = allowMerchantAIAPIKey self.isProductImageOptimizedHandlingEnabled = isProductImageOptimizedHandlingEnabled self.isCIABBookingsEnabled = isCIABBookingsEnabled + self.isCIABEnabled = isCIABEnabled } func isFeatureFlagEnabled(_ featureFlag: FeatureFlag) -> Bool { @@ -124,6 +127,8 @@ final class MockFeatureFlagService: POSFeatureFlagProviding { return isProductImageOptimizedHandlingEnabled case .ciabBookings: return isCIABBookingsEnabled + case .ciab: + return isCIABEnabled default: return false } diff --git a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift index 31abf8edb5c..e4a17a5b55f 100644 --- a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift +++ b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift @@ -29,6 +29,7 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { private var store: OrderCardPresentPaymentEligibilityStore! private var currentSite: Site? + private var isCIABSupported = true override func setUp() { super.setUp() @@ -40,6 +41,9 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { storageManager: storageManager, network: network, crashLogger: MockCrashLogger(), + isCIABEnvironmentSupported: { [weak self] in + return self?.isCIABSupported ?? false + }, currentSite: { [weak self] in return self?.currentSite } @@ -48,6 +52,7 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { override func tearDown() { currentSite = nil + isCIABSupported = true super.tearDown() } @@ -196,4 +201,56 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { .cardReaderPaymentOptionIsNotSupportedForCIABSites) } } + + func test_orderIsEligibleForCardPresentPayment_returns_success_when_site_is_CIAB_and_CIAB_not_supported() throws { + // Given + + /// Simulate that the CIAB environment support is not yet rolled out + isCIABSupported = false + + let orderItem = OrderItem.fake().copy(itemID: 1234, + name: "Chocolate cake", + productID: 678, + quantity: 1.0) + let cppEligibleOrder = Order.fake().copy(siteID: sampleSiteID, + orderID: 111, + status: .pending, + currency: "USD", + datePaid: nil, + total: "5.00", + paymentMethodID: "woocommerce_payments", + items: [orderItem]) + let nonSubscriptionProduct = Product.fake().copy(siteID: sampleSiteID, + productID: 678, + name: "Chocolate cake", + productTypeKey: "simple") + + let ciabSite = Site.fake().copy( + siteID: sampleSiteID, + isGarden: true, + gardenName: "commerce" + ) + self.currentSite = ciabSite + + storageManager.insertSampleSite(readOnlySite: ciabSite) + storageManager.insertSampleProduct(readOnlyProduct: nonSubscriptionProduct) + storageManager.insertSampleOrder(readOnlyOrder: cppEligibleOrder) + + let configuration = CardPresentPaymentsConfiguration(country: .US) + + // When + let result = waitFor { promise in + let action = OrderCardPresentPaymentEligibilityAction + .orderIsEligibleForCardPresentPayment(orderID: 111, + siteID: self.sampleSiteID, + cardPresentPaymentsConfiguration: configuration) { result in + promise(result) + } + self.store.onAction(action) + } + + // Then + let eligibility = try XCTUnwrap(result.get()) + XCTAssertTrue(eligibility) + } } diff --git a/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift index 93ac75de8d5..ef567c429b5 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/Orders/Payment Methods/PaymentMethodsViewModelTests.swift @@ -808,6 +808,7 @@ final class PaymentMethodsViewModelTests: XCTestCase { storageManager: storage, network: MockNetwork(), crashLogger: MockCrashLogger(), + isCIABEnvironmentSupported: { true }, currentSite: { ciabSite } ) From 83c536afec2f980d72d46ba6c2bf9c136b6a074e Mon Sep 17 00:00:00 2001 From: RafaelKayumov Date: Thu, 27 Nov 2025 16:08:36 +0300 Subject: [PATCH 6/7] Refer to injected sessionManager instead of ServiceLocator --- WooCommerce/Classes/Yosemite/AuthenticatedState.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/Classes/Yosemite/AuthenticatedState.swift b/WooCommerce/Classes/Yosemite/AuthenticatedState.swift index 45c8496c30d..44c5ce1370e 100644 --- a/WooCommerce/Classes/Yosemite/AuthenticatedState.swift +++ b/WooCommerce/Classes/Yosemite/AuthenticatedState.swift @@ -91,7 +91,7 @@ class AuthenticatedState: StoresManagerState { ServiceLocator.featureFlagService.isFeatureFlagEnabled(.ciab) }, currentSite: { - ServiceLocator.stores.sessionManager.defaultSite + sessionManager.defaultSite } ), OrderNoteStore(dispatcher: dispatcher, storageManager: storageManager, network: network), From 8ebbd2ebeeca1630fa4d41798e713ae534a3d9a2 Mon Sep 17 00:00:00 2001 From: RafaelKayumov Date: Thu, 27 Nov 2025 18:05:35 +0300 Subject: [PATCH 7/7] Skip CIAB checks if CIAB is supported but site is not found --- ...erCardPresentPaymentEligibilityStore.swift | 29 ++++++-------- ...dPresentPaymentEligibilityStoreTests.swift | 40 +++++++++++++++++++ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift b/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift index 0e9ed868cf1..4befbbfec02 100644 --- a/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift +++ b/Modules/Sources/Yosemite/Stores/OrderCardPresentPaymentEligibilityStore.swift @@ -81,22 +81,20 @@ private extension OrderCardPresentPaymentEligibilityStore { ) } - guard let site else { - logFailedDefaultSiteRead(siteID: siteID) - - return onCompletion( - .failure( - OrderIsEligibleForCardPresentPaymentError.failedToObtainSite + if let site { + guard siteCIABEligibilityChecker.isFeatureSupported(.cardReader, for: site) else { + return onCompletion( + .failure( + OrderIsEligibleForCardPresentPaymentError.cardReaderPaymentOptionIsNotSupportedForCIABSites + ) ) - ) - } - - guard siteCIABEligibilityChecker.isFeatureSupported(.cardReader, for: site) else { - return onCompletion( - .failure( - OrderIsEligibleForCardPresentPaymentError.cardReaderPaymentOptionIsNotSupportedForCIABSites - ) - ) + } + } else { + /// Don't interrupt the flow if the `site` is not found + /// Making the assumption that it's not a CIAB site and skipping those checks + /// + /// Log an error + logFailedDefaultSiteRead(siteID: siteID) } } @@ -146,7 +144,6 @@ private extension OrderCardPresentPaymentEligibilityStore { extension OrderCardPresentPaymentEligibilityStore { enum OrderIsEligibleForCardPresentPaymentError: Error { case orderNotFoundInStorage - case failedToObtainSite case cardReaderPaymentOptionIsNotSupportedForCIABSites } } diff --git a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift index e4a17a5b55f..8deca363074 100644 --- a/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift +++ b/Modules/Tests/YosemiteTests/Stores/OrderCardPresentPaymentEligibilityStoreTests.swift @@ -253,4 +253,44 @@ final class OrderCardPresentPaymentEligibilityStoreTests: XCTestCase { let eligibility = try XCTUnwrap(result.get()) XCTAssertTrue(eligibility) } + + func test_orderIsEligibleForCardPresentPayment_returns_success_when_site_is_not_obtained_and_CIAB_supported() throws { + // Given + let orderItem = OrderItem.fake().copy(itemID: 1234, + name: "Chocolate cake", + productID: 678, + quantity: 1.0) + let cppEligibleOrder = Order.fake().copy(siteID: sampleSiteID, + orderID: 111, + status: .pending, + currency: "USD", + datePaid: nil, + total: "5.00", + paymentMethodID: "woocommerce_payments", + items: [orderItem]) + let nonSubscriptionProduct = Product.fake().copy(siteID: sampleSiteID, + productID: 678, + name: "Chocolate cake", + productTypeKey: "simple") + + storageManager.insertSampleProduct(readOnlyProduct: nonSubscriptionProduct) + storageManager.insertSampleOrder(readOnlyOrder: cppEligibleOrder) + + let configuration = CardPresentPaymentsConfiguration(country: .US) + + // When + let result = waitFor { promise in + let action = OrderCardPresentPaymentEligibilityAction + .orderIsEligibleForCardPresentPayment(orderID: 111, + siteID: self.sampleSiteID, + cardPresentPaymentsConfiguration: configuration) { result in + promise(result) + } + self.store.onAction(action) + } + + // Then + let eligibility = try XCTUnwrap(result.get()) + XCTAssertTrue(eligibility) + } }