Skip to content

Commit 3a8e00c

Browse files
committed
Add the Create and Update PaymentGateway actions
1 parent 44ff5a4 commit 3a8e00c

File tree

3 files changed

+118
-6
lines changed

3 files changed

+118
-6
lines changed

Yosemite/Yosemite/Actions/PaymentGatewayAction.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@ public enum PaymentGatewayAction: Action {
66
/// Retrieves and stores all payment gateways for the provided `siteID`
77
///
88
case synchronizePaymentGateways(siteID: Int64, onCompletion: (Result<Void, Error>) -> Void)
9+
10+
/// Updates a Payment Gateway for a site given its ID and returns the updated Payment Gateway if the request succeeds.
11+
///
12+
/// - `paymentGateway`: the Payment Gateway to be updated.
13+
/// - `onCompletion`: invoked when the update finishes.
14+
///
15+
case updatePaymentGateway(_ paymentGateway: PaymentGateway,
16+
onCompletion: (Result<PaymentGateway, Error>) -> Void)
917
}

Yosemite/Yosemite/Stores/PaymentGatewayStore.swift

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@ public final class PaymentGatewayStore: Store {
3636
switch action {
3737
case let .synchronizePaymentGateways(siteID, onCompletion):
3838
synchronizePaymentGateways(siteID: siteID, onCompletion: onCompletion)
39+
case let .updatePaymentGateway(paymentGateway, onCompletion):
40+
updatePaymentGateway(paymentGateway, onCompletion: onCompletion)
3941
}
4042
}
4143
}
4244

43-
// MARK: Storage Methods
45+
// MARK: Payment Gateway store services
4446
private extension PaymentGatewayStore {
45-
4647
/// Loads and stores all payment gateways for the provided `siteID`
4748
func synchronizePaymentGateways(siteID: Int64, onCompletion: @escaping (Result<Void, Error>) -> Void) {
4849
remote.loadAllPaymentGateways(siteID: siteID) { [weak self] result in
@@ -59,6 +60,31 @@ private extension PaymentGatewayStore {
5960
}
6061
}
6162

63+
/// Updates a paymentGateway given its details.
64+
/// After the API request succeeds, the stored paymentGateway should be updated accordingly.
65+
/// - Parameters:
66+
/// - paymentGateway: The paymentGateway to be updated
67+
/// - onCompletion: Closure to call after update is complete. Called on the main thread.
68+
///
69+
func updatePaymentGateway(_ paymentGateway: PaymentGateway,
70+
siteTimezone: TimeZone? = nil,
71+
onCompletion: @escaping (Result<PaymentGateway, Error>) -> Void) {
72+
remote.updatePaymentGateway(paymentGateway) { [weak self] result in
73+
guard let self = self else { return }
74+
switch result {
75+
case .failure(let error):
76+
onCompletion(.failure(error))
77+
case .success(let paymentGateway):
78+
self.upsertPaymentGatewaysInBackground(siteID: paymentGateway.siteID, paymentGateways: [paymentGateway]) {
79+
onCompletion(.success(paymentGateway))
80+
}
81+
}
82+
}
83+
}
84+
}
85+
86+
// MARK: Storage Methods
87+
private extension PaymentGatewayStore {
6288
/// Updates (OR Inserts) the specified ReadOnly Payment Gateways Entities
6389
/// *in a background thread*. `onCompletion` will be called on the main thread!
6490
///

Yosemite/YosemiteTests/Stores/PaymentGatewayStoreTests.swift

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,38 @@ final class PaymentGatewayStoreTests: XCTestCase {
2727
return storageManager.viewStorage
2828
}
2929

30+
/// Convenience: returns the number of stored payment gateways
31+
///
32+
private var storedPaymentGatewaysCount: Int {
33+
return viewStorage.countObjects(ofType: StoragePaymentGateway.self)
34+
}
35+
3036
/// Dummy Site ID
3137
///
3238
private let sampleSiteID: Int64 = 123
3339

40+
/// Store
41+
///
42+
private var store: PaymentGatewayStore!
43+
3444
override func setUp() {
3545
super.setUp()
3646
dispatcher = Dispatcher()
3747
storageManager = MockStorageManager()
3848
network = MockNetwork(useResponseQueue: true)
49+
store = PaymentGatewayStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
3950
}
4051

4152
func test_synchronize_gateways_correctly_persists_payment_gateways() throws {
4253
// Given
43-
let store = PaymentGatewayStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
4454
network.simulateResponse(requestUrlSuffix: "payment_gateways", filename: "payment-gateway-list")
4555

4656
// When
4757
let result: Result<Void, Error> = waitFor { promise in
4858
let action = PaymentGatewayAction.synchronizePaymentGateways(siteID: self.sampleSiteID) { result in
4959
promise(result)
5060
}
51-
store.onAction(action)
61+
self.store.onAction(action)
5262
}
5363

5464
// Then
@@ -61,7 +71,6 @@ final class PaymentGatewayStoreTests: XCTestCase {
6171

6272
func test_synchronize_gateways_correctly_deletes_stale_payment_gateways() throws {
6373
// Given
64-
let store = PaymentGatewayStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
6574
network.simulateResponse(requestUrlSuffix: "payment_gateways", filename: "payment-gateway-list")
6675
network.simulateResponse(requestUrlSuffix: "payment_gateways", filename: "payment-gateway-list-half")
6776

@@ -73,7 +82,7 @@ final class PaymentGatewayStoreTests: XCTestCase {
7382
let secondSync = PaymentGatewayAction.synchronizePaymentGateways(siteID: self.sampleSiteID) { result in
7483
promise(result)
7584
}
76-
store.onAction(secondSync)
85+
self.store.onAction(secondSync)
7786
}
7887

7988
// Then
@@ -83,4 +92,73 @@ final class PaymentGatewayStoreTests: XCTestCase {
8392
XCTAssertNil(viewStorage.loadPaymentGateway(siteID: sampleSiteID, gatewayID: "paypal"))
8493
XCTAssertNil(viewStorage.loadPaymentGateway(siteID: sampleSiteID, gatewayID: "cod"))
8594
}
95+
96+
func test_updatePaymentGateway_returns_network_error_on_failure() {
97+
// Given
98+
let samplePaymentGatewayID = "cod"
99+
let samplePaymentGateway = PaymentGateway.fake().copy(siteID: sampleSiteID,
100+
gatewayID: samplePaymentGatewayID,
101+
title: "Failing gateway",
102+
enabled: false)
103+
storePaymentGateway(samplePaymentGateway, for: sampleSiteID)
104+
assertEqual(1, storedPaymentGatewaysCount)
105+
106+
let expectedError = NetworkError.unacceptableStatusCode(statusCode: 500)
107+
network.simulateError(requestUrlSuffix: "payment_gateways/\(samplePaymentGatewayID)", error: expectedError)
108+
109+
// When
110+
let updatedPaymentGateway = samplePaymentGateway.copy(title: "Cash on delivery")
111+
let result: Result<Networking.PaymentGateway, Error> = waitFor { promise in
112+
let action = PaymentGatewayAction.updatePaymentGateway(updatedPaymentGateway) { result in
113+
promise(result)
114+
}
115+
self.store.onAction(action)
116+
}
117+
118+
// Then
119+
XCTAssertEqual(result.failure as? NetworkError, expectedError)
120+
assertEqual(1, storedPaymentGatewaysCount)
121+
assertEqual("Failing gateway", viewStorage.loadPaymentGateway(siteID: sampleSiteID, gatewayID: samplePaymentGatewayID)?.title)
122+
}
123+
124+
func test_updatePaymentGateway_updates_stored_paymentGateway_upon_success() throws {
125+
// Given
126+
let samplePaymentGatewayID = "cod"
127+
let samplePaymentGateway = PaymentGateway.fake().copy(siteID: sampleSiteID,
128+
gatewayID: samplePaymentGatewayID,
129+
title: "Old title",
130+
enabled: false)
131+
132+
storePaymentGateway(samplePaymentGateway, for: sampleSiteID)
133+
assertEqual(1, storedPaymentGatewaysCount)
134+
135+
network.simulateResponse(requestUrlSuffix: "payment_gateways/\(samplePaymentGatewayID)", filename: "payment-gateway-cod")
136+
137+
// When
138+
let updatedPaymentGateway = samplePaymentGateway.copy(enabled: true)
139+
let result: Result<Networking.PaymentGateway, Error> = waitFor { promise in
140+
let action: PaymentGatewayAction
141+
action = .updatePaymentGateway(updatedPaymentGateway) { result in
142+
promise(result)
143+
}
144+
self.store.onAction(action)
145+
}
146+
147+
// Then
148+
XCTAssertTrue(result.isSuccess)
149+
150+
let storedPaymentGateway = try XCTUnwrap(viewStorage.loadPaymentGateway(siteID: sampleSiteID, gatewayID: samplePaymentGatewayID))
151+
assertEqual("Cash on delivery", storedPaymentGateway.title)
152+
XCTAssertTrue(storedPaymentGateway.enabled)
153+
}
154+
}
155+
156+
private extension PaymentGatewayStoreTests {
157+
@discardableResult
158+
func storePaymentGateway(_ paymentGateway: Networking.PaymentGateway, for siteID: Int64) -> Storage.PaymentGateway {
159+
let storedPaymentGateway = viewStorage.insertNewObject(ofType: PaymentGateway.self)
160+
storedPaymentGateway.update(with: paymentGateway)
161+
storedPaymentGateway.siteID = siteID
162+
return storedPaymentGateway
163+
}
86164
}

0 commit comments

Comments
 (0)