Skip to content

Commit fa5da3a

Browse files
authored
Merge pull request #6194 from woocommerce/try/cpp-configuration-loader
[Mobile Payments] Configuration loader
2 parents 7e38109 + 1e5281a commit fa5da3a

File tree

8 files changed

+208
-45
lines changed

8 files changed

+208
-45
lines changed

WooCommerce/Classes/ServiceLocator/ServiceLocator.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,14 @@ extension ServiceLocator {
260260
_shippingSettingsService = mock
261261
}
262262

263+
static func setSelectedSiteSettings(_ mock: SelectedSiteSettings) {
264+
guard isRunningTests() else {
265+
return
266+
}
267+
268+
_selectedSiteSettings = mock
269+
}
270+
263271
static func setCurrencySettings(_ mock: CurrencySettings) {
264272
guard isRunningTests() else {
265273
return
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import Foundation
2+
import Yosemite
3+
4+
final class CardPresentConfigurationLoader {
5+
private var stripeGatewayIPPEnabled: Bool = false
6+
private var canadaIPPEnabled: Bool = false
7+
8+
init(stores: StoresManager = ServiceLocator.stores) {
9+
let stripeAction = AppSettingsAction.loadStripeInPersonPaymentsSwitchState(onCompletion: { [weak self] result in
10+
if case .success(let stripeGatewayIPPEnabled) = result {
11+
self?.stripeGatewayIPPEnabled = stripeGatewayIPPEnabled
12+
}
13+
})
14+
stores.dispatch(stripeAction)
15+
16+
let canadaAction = AppSettingsAction.loadCanadaInPersonPaymentsSwitchState(onCompletion: { [weak self] result in
17+
if case .success(let canadaIPPEnabled) = result {
18+
self?.canadaIPPEnabled = canadaIPPEnabled
19+
}
20+
})
21+
stores.dispatch(canadaAction)
22+
}
23+
24+
var configuration: CardPresentPaymentsConfiguration {
25+
.init(
26+
country: SiteAddress().countryCode,
27+
stripeEnabled: stripeGatewayIPPEnabled,
28+
canadaEnabled: canadaIPPEnabled
29+
)
30+
}
31+
}

WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/CardPresentPaymentsOnboardingUseCase.swift

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ protocol CardPresentPaymentsOnboardingUseCaseProtocol {
3030
final class CardPresentPaymentsOnboardingUseCase: CardPresentPaymentsOnboardingUseCaseProtocol, ObservableObject {
3131
let storageManager: StorageManagerType
3232
let stores: StoresManager
33-
private var stripeGatewayIPPEnabled: Bool = false
34-
private var canadaIPPEnabled: Bool = false
33+
let configurationLoader: CardPresentConfigurationLoader
3534

3635
@Published var state: CardPresentPaymentOnboardingState = .loading
3736

@@ -45,26 +44,7 @@ final class CardPresentPaymentsOnboardingUseCase: CardPresentPaymentsOnboardingU
4544
) {
4645
self.storageManager = storageManager
4746
self.stores = stores
48-
49-
let stripeAction = AppSettingsAction.loadStripeInPersonPaymentsSwitchState(onCompletion: { [weak self] result in
50-
switch result {
51-
case .success(let stripeGatewayIPPEnabled):
52-
self?.stripeGatewayIPPEnabled = stripeGatewayIPPEnabled
53-
default:
54-
break
55-
}
56-
})
57-
stores.dispatch(stripeAction)
58-
59-
let canadaAction = AppSettingsAction.loadCanadaInPersonPaymentsSwitchState(onCompletion: { [weak self] result in
60-
switch result {
61-
case .success(let canadaIPPEnabled):
62-
self?.canadaIPPEnabled = canadaIPPEnabled
63-
default:
64-
break
65-
}
66-
})
67-
stores.dispatch(canadaAction)
47+
self.configurationLoader = .init(stores: stores)
6848

6949
// At the time of writing, actions are dispatched and processed synchronously, so the completion blocks for
7050
// loadStripeInPersonPaymentsSwitchState and loadCanadaInPersonPaymentsSwitchState should have been called already.
@@ -161,18 +141,9 @@ private extension CardPresentPaymentsOnboardingUseCase {
161141
return .genericError
162142
}
163143

164-
let configuration: CardPresentPaymentsConfiguration
165-
do {
166-
configuration = try CardPresentPaymentsConfiguration(
167-
country: countryCode,
168-
stripeEnabled: stripeGatewayIPPEnabled,
169-
canadaEnabled: canadaIPPEnabled
170-
)
171-
} catch is CardPresentPaymentsConfigurationMissingError {
144+
let configuration = configurationLoader.configuration
145+
guard configuration.isSupportedCountry else {
172146
return .countryNotSupported(countryCode: countryCode)
173-
} catch {
174-
DDLogError("[CardPresentPaymentsOnboarding] Unexpected error loading configuration: \(error)")
175-
return .genericError
176147
}
177148

178149
let wcPay = getWCPayPlugin()

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,7 @@
15331533
DEF3300C270444070073AE29 /* ShippingLabelSelectedRate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF3300B270444060073AE29 /* ShippingLabelSelectedRate.swift */; };
15341534
DEFD6E61264990FB00E51E0D /* SitePluginListViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEFD6E60264990FB00E51E0D /* SitePluginListViewModelTests.swift */; };
15351535
DEFD6E86264ABFB700E51E0D /* PluginListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DEFD6E85264ABFB700E51E0D /* PluginListViewController.xib */; };
1536+
E10459C627BBC22E00C1DCBA /* CardPresentConfigurationLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10459C527BBC22E00C1DCBA /* CardPresentConfigurationLoader.swift */; };
15361537
E107FCE126C12B2700BAF51B /* InPersonPaymentsCountryNotSupported.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107FCE026C12B2700BAF51B /* InPersonPaymentsCountryNotSupported.swift */; };
15371538
E107FCE326C13A0D00BAF51B /* InPersonPaymentsSupportLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = E107FCE226C13A0D00BAF51B /* InPersonPaymentsSupportLink.swift */; };
15381539
E10BC15E26CC06970064F5E2 /* ScrollableVStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10BC15D26CC06970064F5E2 /* ScrollableVStack.swift */; };
@@ -1560,6 +1561,7 @@
15601561
E1BE703A265E6F47006CA4D9 /* CardPresentModalScanningFailed.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BE7039265E6F47006CA4D9 /* CardPresentModalScanningFailed.swift */; };
15611562
E1C47209267A1ECC00D06DA1 /* CrashLoggingStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C47208267A1ECC00D06DA1 /* CrashLoggingStack.swift */; };
15621563
E1C5E78226C2A971008D4C47 /* InPersonPaymentsPluginNotSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C5E78126C2A971008D4C47 /* InPersonPaymentsPluginNotSetup.swift */; };
1564+
E1C6535C27BD1D0A003E87D4 /* CardPresentConfigurationLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C6535B27BD1D0A003E87D4 /* CardPresentConfigurationLoaderTests.swift */; };
15631565
E1D4E84426776A6B00256B83 /* HeadlineTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4E84326776A6A00256B83 /* HeadlineTableViewCell.swift */; };
15641566
E1D4E84526776AD900256B83 /* HeadlineTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E1D4E84226776A6A00256B83 /* HeadlineTableViewCell.xib */; };
15651567
E1E125AA26EB42530068A9B0 /* CardPresentModalUpdateProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E125A926EB42530068A9B0 /* CardPresentModalUpdateProgress.swift */; };
@@ -3179,6 +3181,7 @@
31793181
DEF3300B270444060073AE29 /* ShippingLabelSelectedRate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelSelectedRate.swift; sourceTree = "<group>"; };
31803182
DEFD6E60264990FB00E51E0D /* SitePluginListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SitePluginListViewModelTests.swift; sourceTree = "<group>"; };
31813183
DEFD6E85264ABFB700E51E0D /* PluginListViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PluginListViewController.xib; sourceTree = "<group>"; };
3184+
E10459C527BBC22E00C1DCBA /* CardPresentConfigurationLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentConfigurationLoader.swift; sourceTree = "<group>"; };
31823185
E107FCE026C12B2700BAF51B /* InPersonPaymentsCountryNotSupported.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InPersonPaymentsCountryNotSupported.swift; sourceTree = "<group>"; };
31833186
E107FCE226C13A0D00BAF51B /* InPersonPaymentsSupportLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InPersonPaymentsSupportLink.swift; sourceTree = "<group>"; };
31843187
E10BC15D26CC06970064F5E2 /* ScrollableVStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollableVStack.swift; sourceTree = "<group>"; };
@@ -3206,6 +3209,7 @@
32063209
E1BE7039265E6F47006CA4D9 /* CardPresentModalScanningFailed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentModalScanningFailed.swift; sourceTree = "<group>"; };
32073210
E1C47208267A1ECC00D06DA1 /* CrashLoggingStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashLoggingStack.swift; sourceTree = "<group>"; };
32083211
E1C5E78126C2A971008D4C47 /* InPersonPaymentsPluginNotSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InPersonPaymentsPluginNotSetup.swift; sourceTree = "<group>"; };
3212+
E1C6535B27BD1D0A003E87D4 /* CardPresentConfigurationLoaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentConfigurationLoaderTests.swift; sourceTree = "<group>"; };
32093213
E1D4E84226776A6A00256B83 /* HeadlineTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HeadlineTableViewCell.xib; sourceTree = "<group>"; };
32103214
E1D4E84326776A6A00256B83 /* HeadlineTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineTableViewCell.swift; sourceTree = "<group>"; };
32113215
E1E125A926EB42530068A9B0 /* CardPresentModalUpdateProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentModalUpdateProgress.swift; sourceTree = "<group>"; };
@@ -5704,6 +5708,7 @@
57045708
B53A569521123D27000776C9 /* Tools */ = {
57055709
isa = PBXGroup;
57065710
children = (
5711+
E1C6535A27BD1CFC003E87D4 /* In-Person Payments */,
57075712
029700ED24FE38DE00D242F8 /* InfiniteScroll */,
57085713
028AFFB42484ED7F00693C09 /* Logging */,
57095714
D8A8C4F22268288F001C72BF /* AddManualCustomTrackingViewModelTests.swift */,
@@ -5824,6 +5829,7 @@
58245829
024A543222BA6DD500F4F38E /* Developer */,
58255830
02C0CD2823B5BAFB00F880B1 /* ImageService */,
58265831
029700EA24FE389C00D242F8 /* InfiniteScroll */,
5832+
E10459C427BBC20C00C1DCBA /* In-Person Payments */,
58275833
B5A03699214C0E7000774E2C /* Logging */,
58285834
B58B4ABC2108F7F800076FDD /* Notices */,
58295835
45C11B7D2508E99A006C2089 /* Shared Site Settings */,
@@ -7440,6 +7446,14 @@
74407446
path = Plugins;
74417447
sourceTree = "<group>";
74427448
};
7449+
E10459C427BBC20C00C1DCBA /* In-Person Payments */ = {
7450+
isa = PBXGroup;
7451+
children = (
7452+
E10459C527BBC22E00C1DCBA /* CardPresentConfigurationLoader.swift */,
7453+
);
7454+
path = "In-Person Payments";
7455+
sourceTree = "<group>";
7456+
};
74437457
E107FCDD26C1295600BAF51B /* Onboarding Errors */ = {
74447458
isa = PBXGroup;
74457459
children = (
@@ -7487,6 +7501,14 @@
74877501
path = "In-Person Payments";
74887502
sourceTree = "<group>";
74897503
};
7504+
E1C6535A27BD1CFC003E87D4 /* In-Person Payments */ = {
7505+
isa = PBXGroup;
7506+
children = (
7507+
E1C6535B27BD1D0A003E87D4 /* CardPresentConfigurationLoaderTests.swift */,
7508+
);
7509+
path = "In-Person Payments";
7510+
sourceTree = "<group>";
7511+
};
74907512
F4B77A83B2A3D94EA331691B /* Pods */ = {
74917513
isa = PBXGroup;
74927514
children = (
@@ -8616,6 +8638,7 @@
86168638
B541B2172189EED4008FE7C1 /* NSMutableAttributedString+Helpers.swift in Sources */,
86178639
26F94E2E267A96A000DB6CCF /* ProductAddOnViewModel.swift in Sources */,
86188640
02A9BCD42737DE0D00159C79 /* JetpackBenefitsView.swift in Sources */,
8641+
E10459C627BBC22E00C1DCBA /* CardPresentConfigurationLoader.swift in Sources */,
86198642
B586906621A5F4B1001F1EFC /* UINavigationController+Woo.swift in Sources */,
86208643
45FBDF3A238D3F8B00127F77 /* ExtendedAddProductImageCollectionViewCell.swift in Sources */,
86218644
02A410F52583A84C005E2925 /* SpacerTableViewCell.swift in Sources */,
@@ -9422,6 +9445,7 @@
94229445
02524A5D252ED5C60033E7BD /* ProductVariationLoadUseCaseTests.swift in Sources */,
94239446
028AFFB62484EDA000693C09 /* Dictionary+LoggingTests.swift in Sources */,
94249447
02BC5AA824D2802B00C43326 /* MockProductVariationStoresManager.swift in Sources */,
9448+
E1C6535C27BD1D0A003E87D4 /* CardPresentConfigurationLoaderTests.swift in Sources */,
94259449
2688644325D471C700821BA5 /* EditAttributesViewModelTests.swift in Sources */,
94269450
DE001323279A793A00EB0350 /* CouponWooTests.swift in Sources */,
94279451
45B98E1F25DECC1C00A1232B /* ShippingLabelAddressFormViewModelTests.swift in Sources */,
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import XCTest
2+
import Yosemite
3+
@testable import WooCommerce
4+
5+
final class CardPresentConfigurationLoaderTests: XCTestCase {
6+
/// Mock Storage: InMemory
7+
///
8+
private var storageManager: MockStorageManager!
9+
10+
/// Mock Stores
11+
///
12+
private var stores: MockStoresManager!
13+
14+
/// Dummy Site ID
15+
///
16+
private let sampleSiteID: Int64 = 1234
17+
18+
override func setUpWithError() throws {
19+
try super.setUpWithError()
20+
storageManager = MockStorageManager()
21+
stores = MockStoresManager(sessionManager: .makeForTesting(authenticated: true))
22+
stores.whenReceivingAction(ofType: AppSettingsAction.self) { action in
23+
switch action {
24+
case .loadStripeInPersonPaymentsSwitchState(let completion):
25+
completion(.success(true))
26+
case .loadCanadaInPersonPaymentsSwitchState(let completion):
27+
completion(.success(true))
28+
default:
29+
break
30+
}
31+
}
32+
stores.sessionManager.setStoreId(sampleSiteID)
33+
ServiceLocator.setSelectedSiteSettings(SelectedSiteSettings(stores: stores, storageManager: storageManager))
34+
}
35+
36+
override func tearDownWithError() throws {
37+
ServiceLocator.setSelectedSiteSettings(SelectedSiteSettings())
38+
storageManager.reset()
39+
storageManager = nil
40+
stores = nil
41+
try super.tearDownWithError()
42+
}
43+
44+
func test_configuration_for_US_with_stripe_enabled_and_canada_enabled() {
45+
// Given
46+
setupFeatures(stripe: true, canada: true)
47+
setupCountry(country: .us)
48+
49+
// When
50+
let loader = CardPresentConfigurationLoader(stores: stores)
51+
let configuration = loader.configuration
52+
53+
// Then
54+
XCTAssertTrue(configuration.isSupportedCountry)
55+
}
56+
57+
func test_configuration_for_Canada_with_stripe_enabled_and_canada_enabled() {
58+
// Given
59+
setupFeatures(stripe: true, canada: true)
60+
setupCountry(country: .ca)
61+
62+
// When
63+
let loader = CardPresentConfigurationLoader(stores: stores)
64+
let configuration = loader.configuration
65+
66+
// Then
67+
XCTAssertTrue(configuration.isSupportedCountry)
68+
}
69+
70+
func test_configuration_for_Spain_with_stripe_enabled_and_canada_enabled() {
71+
// Given
72+
setupFeatures(stripe: true, canada: true)
73+
setupCountry(country: .es)
74+
75+
// When
76+
let loader = CardPresentConfigurationLoader(stores: stores)
77+
let configuration = loader.configuration
78+
79+
// Then
80+
XCTAssertFalse(configuration.isSupportedCountry)
81+
}
82+
}
83+
84+
private extension CardPresentConfigurationLoaderTests {
85+
func setupCountry(country: Country) {
86+
let setting = SiteSetting.fake()
87+
.copy(
88+
siteID: sampleSiteID,
89+
settingID: "woocommerce_default_country",
90+
value: country.rawValue,
91+
settingGroupKey: SiteSettingGroup.general.rawValue
92+
)
93+
storageManager.insertSampleSiteSetting(readOnlySiteSetting: setting)
94+
ServiceLocator.selectedSiteSettings.refresh()
95+
}
96+
97+
enum Country: String {
98+
case us = "US:CA"
99+
case ca = "CA:NS"
100+
case es = "ES"
101+
}
102+
103+
func setupFeatures(stripe: Bool, canada: Bool) {
104+
stores.whenReceivingAction(ofType: AppSettingsAction.self) { action in
105+
switch action {
106+
case .loadStripeInPersonPaymentsSwitchState(onCompletion: let completion):
107+
completion(.success(stripe))
108+
case .loadCanadaInPersonPaymentsSwitchState(onCompletion: let completion):
109+
completion(.success(canada))
110+
default:
111+
break
112+
}
113+
}
114+
}
115+
}

WooCommerce/WooCommerceTests/ViewRelated/CardPresentPayments/CardPresentPaymentsOnboardingUseCaseTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ class CardPresentPaymentsOnboardingUseCaseTests: XCTestCase {
3131
}
3232
}
3333
stores.sessionManager.setStoreId(sampleSiteID)
34+
ServiceLocator.setSelectedSiteSettings(SelectedSiteSettings(stores: stores, storageManager: storageManager))
3435
}
3536

3637
override func tearDownWithError() throws {
38+
ServiceLocator.setSelectedSiteSettings(SelectedSiteSettings())
39+
storageManager.reset()
3740
storageManager = nil
3841
stores = nil
3942
try super.tearDownWithError()
@@ -609,6 +612,7 @@ private extension CardPresentPaymentsOnboardingUseCaseTests {
609612
settingGroupKey: SiteSettingGroup.general.rawValue
610613
)
611614
storageManager.insertSampleSiteSetting(readOnlySiteSetting: setting)
615+
ServiceLocator.selectedSiteSettings.refresh()
612616
}
613617

614618
enum Country: String {

Yosemite/Yosemite/Model/Payments/CardPresentPaymentsConfiguration.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public struct CardPresentPaymentsConfiguration {
1111
self.paymentGateways = paymentGateways
1212
}
1313

14-
public init(country: String, stripeEnabled: Bool, canadaEnabled: Bool) throws {
14+
public init(country: String, stripeEnabled: Bool, canadaEnabled: Bool) {
1515
switch country {
1616
case "US" where stripeEnabled == true:
1717
self.init(
@@ -32,9 +32,11 @@ public struct CardPresentPaymentsConfiguration {
3232
paymentGateways: [WCPayAccount.gatewayID]
3333
)
3434
default:
35-
throw CardPresentPaymentsConfigurationMissingError()
35+
self.init(paymentMethods: [], currencies: [], paymentGateways: [])
3636
}
3737
}
38-
}
3938

40-
public struct CardPresentPaymentsConfigurationMissingError: Error {}
39+
public var isSupportedCountry: Bool {
40+
paymentMethods.isEmpty == false && currencies.isEmpty == false && paymentGateways.isEmpty == false
41+
}
42+
}

0 commit comments

Comments
 (0)