Skip to content

Commit 8c832a1

Browse files
committed
Add unit tests for PaymentStore.
1 parent ac2850c commit 8c832a1

File tree

4 files changed

+176
-3
lines changed

4 files changed

+176
-3
lines changed

Yosemite/Yosemite.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@
8484
02E7FFD92562234F00C53030 /* MockShippingLabelRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E7FFD82562234F00C53030 /* MockShippingLabelRemote.swift */; };
8585
02EF1666292DB65000D90AD6 /* PaymentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EF1665292DB65000D90AD6 /* PaymentStore.swift */; };
8686
02EF1668292DB68C00D90AD6 /* PaymentAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EF1667292DB68C00D90AD6 /* PaymentAction.swift */; };
87+
02F2722D292F18BF00C36419 /* PaymentStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F2722C292F18BF00C36419 /* PaymentStoreTests.swift */; };
88+
02F2722F292F18FD00C36419 /* MockPaymentRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F2722E292F18FD00C36419 /* MockPaymentRemote.swift */; };
8789
02F6AAAC270556A4002425D0 /* Models+Copiable.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F6AAAB270556A4002425D0 /* Models+Copiable.generated.swift */; };
8890
02FF054D23D983F30058E6E7 /* MediaFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FF054523D983F30058E6E7 /* MediaFileManager.swift */; };
8991
02FF054E23D983F30058E6E7 /* MediaImageExporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FF054623D983F30058E6E7 /* MediaImageExporter.swift */; };
@@ -511,6 +513,8 @@
511513
02E7FFD82562234F00C53030 /* MockShippingLabelRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockShippingLabelRemote.swift; sourceTree = "<group>"; };
512514
02EF1665292DB65000D90AD6 /* PaymentStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentStore.swift; sourceTree = "<group>"; };
513515
02EF1667292DB68C00D90AD6 /* PaymentAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentAction.swift; sourceTree = "<group>"; };
516+
02F2722C292F18BF00C36419 /* PaymentStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentStoreTests.swift; sourceTree = "<group>"; };
517+
02F2722E292F18FD00C36419 /* MockPaymentRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPaymentRemote.swift; sourceTree = "<group>"; };
514518
02F6AAAB270556A4002425D0 /* Models+Copiable.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Models+Copiable.generated.swift"; sourceTree = "<group>"; };
515519
02FF054523D983F30058E6E7 /* MediaFileManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaFileManager.swift; sourceTree = "<group>"; };
516520
02FF054623D983F30058E6E7 /* MediaImageExporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaImageExporter.swift; sourceTree = "<group>"; };
@@ -1210,6 +1214,7 @@
12101214
021BA0C328576940006E9886 /* MockDotcomAccountRemote.swift */,
12111215
02DAE7F9291A9F36009342B7 /* MockDomainRemote.swift */,
12121216
02616F932921E1CD0095BC00 /* MockSiteRemote.swift */,
1217+
02F2722E292F18FD00C36419 /* MockPaymentRemote.swift */,
12131218
);
12141219
path = Remote;
12151220
sourceTree = "<group>";
@@ -1485,6 +1490,7 @@
14851490
02E3B629290622DE007E0F13 /* AccountCreationStoreTests.swift */,
14861491
02DAE7F7291A9F11009342B7 /* DomainStoreTests.swift */,
14871492
02616F912921E1530095BC00 /* SiteStoreTests.swift */,
1493+
02F2722C292F18BF00C36419 /* PaymentStoreTests.swift */,
14881494
);
14891495
path = Stores;
14901496
sourceTree = "<group>";
@@ -2287,6 +2293,7 @@
22872293
02FF055B23D9846A0058E6E7 /* MediaDirectoryTests.swift in Sources */,
22882294
265BCA0024301ACD004E53EE /* ProductCategoryStoreTests.swift in Sources */,
22892295
02FF056D23DEDCB90058E6E7 /* MockImageSourceWriter.swift in Sources */,
2296+
02F2722F292F18FD00C36419 /* MockPaymentRemote.swift in Sources */,
22902297
FE28F6F2268462A6004465C7 /* UserStoreTests.swift in Sources */,
22912298
02DAE7FA291A9F36009342B7 /* MockDomainRemote.swift in Sources */,
22922299
741F34842195F752005F5BD9 /* CommentStoreTests.swift in Sources */,
@@ -2303,6 +2310,7 @@
23032310
031FD8A026FC970400B315C7 /* RosettaTestingHelper.swift in Sources */,
23042311
077F39E526A5C98200ABEADC /* SystemStatusStoreTests.swift in Sources */,
23052312
022F931D257F27B40011CD94 /* MockShippingLabelAddress.swift in Sources */,
2313+
02F2722D292F18BF00C36419 /* PaymentStoreTests.swift in Sources */,
23062314
02FF056923DECD5B0058E6E7 /* MediaImageExporterTests.swift in Sources */,
23072315
0202B6972387AFBF00F3EBE0 /* MockInMemoryStorage.swift in Sources */,
23082316
028BCE2422DE22BB00056966 /* SiteVisitStatsStoreErrorTests.swift in Sources */,

Yosemite/Yosemite/Actions/PaymentAction.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@ import Foundation
33
/// PaymentAction: Defines all of the Actions supported by the PaymentStore.
44
///
55
public enum PaymentAction: Action {
6+
/// Loads a specific WPCOM plan.
7+
/// - Parameters:
8+
/// - productID: The ID of the WPCOM product to return.
9+
/// - completion: Invoked when the WPCOM plan that matches the given ID is loaded.
610
case loadPlan(productID: Int64,
711
completion: (Result<WPComPlan, Error>) -> Void)
812

9-
/// Creates a cart with a WPCOM product.
13+
/// Creates a cart with a WPCOM plan.
1014
/// - Parameters:
11-
/// - productID: The ID of the WPCOM product.
12-
/// - siteID: The site ID for the WPCOM product to be attached to.
15+
/// - productID: The ID of the WPCOM plan product.
16+
/// - siteID: The site ID for the WPCOM plan to be attached to.
1317
/// - completion: The result of cart creation.
1418
case createCart(productID: String,
1519
siteID: Int64,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import Networking
2+
import XCTest
3+
4+
/// Mock for `PaymentRemote`.
5+
///
6+
final class MockPaymentRemote {
7+
/// The results to return in `loadPlan`.
8+
private var loadPlanResult: Result<WPComPlan, Error>?
9+
10+
/// The results to return in `createCart`.
11+
private var createCartResult: Result<Void, Error>?
12+
13+
/// Returns the value when `loadPlan` is called.
14+
func whenLoadingPlan(thenReturn result: Result<WPComPlan, Error>) {
15+
loadPlanResult = result
16+
}
17+
18+
/// Returns the value when `createCart` is called.
19+
func whenCreatingCart(thenReturn result: Result<Void, Error>) {
20+
createCartResult = result
21+
}
22+
}
23+
24+
extension MockPaymentRemote: PaymentRemoteProtocol {
25+
func loadPlan(thatMatchesID productID: Int64) async throws -> Networking.WPComPlan {
26+
guard let result = loadPlanResult else {
27+
XCTFail("Could not find result for loading a plan.")
28+
throw NetworkError.notFound
29+
}
30+
return try result.get()
31+
}
32+
33+
func createCart(siteID: Int64, productID: Int64) async throws {
34+
guard let result = createCartResult else {
35+
XCTFail("Could not find result for creating a cart.")
36+
throw NetworkError.notFound
37+
}
38+
return try result.get()
39+
}
40+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import TestKit
2+
import XCTest
3+
@testable import Networking
4+
@testable import Yosemite
5+
6+
final class PaymentStoreTests: XCTestCase {
7+
/// Mock Dispatcher.
8+
private var dispatcher: Dispatcher!
9+
10+
/// Mock Storage: InMemory.
11+
private var storageManager: MockStorageManager!
12+
13+
/// Mock Network: Allows us to inject predefined responses.
14+
private var network: MockNetwork!
15+
16+
private var remote: MockPaymentRemote!
17+
private var store: PaymentStore!
18+
19+
override func setUp() {
20+
super.setUp()
21+
dispatcher = Dispatcher()
22+
storageManager = MockStorageManager()
23+
network = MockNetwork()
24+
remote = MockPaymentRemote()
25+
store = PaymentStore(remote: remote, dispatcher: dispatcher, storageManager: storageManager, network: network)
26+
}
27+
28+
override func tearDown() {
29+
store = nil
30+
remote = nil
31+
network = nil
32+
storageManager = nil
33+
dispatcher = nil
34+
super.tearDown()
35+
}
36+
37+
// MARK: - `loadPlan`
38+
39+
func test_loadPlan_returns_plan_on_success() throws {
40+
// Given
41+
remote.whenLoadingPlan(thenReturn: .success(.init(productID: 12, name: "woo", formattedPrice: "$16.8")))
42+
43+
// When
44+
let result = waitFor { promise in
45+
self.store.onAction(PaymentAction.loadPlan(productID: 12) { result in
46+
promise(result)
47+
})
48+
}
49+
50+
// Then
51+
XCTAssertTrue(result.isSuccess)
52+
let plan = try XCTUnwrap(result.get())
53+
XCTAssertEqual(plan, .init(productID: 12, name: "woo", formattedPrice: "$16.8"))
54+
}
55+
56+
func test_loadPlan_returns_failure_on_error() throws {
57+
// Given
58+
remote.whenLoadingPlan(thenReturn: .failure(NetworkError.timeout))
59+
60+
// When
61+
let result = waitFor { promise in
62+
self.store.onAction(PaymentAction.loadPlan(productID: 12) { result in
63+
promise(result)
64+
})
65+
}
66+
67+
// Then
68+
XCTAssertTrue(result.isFailure)
69+
let error = try XCTUnwrap(result.failure)
70+
XCTAssertEqual(error as? NetworkError, .timeout)
71+
}
72+
73+
// MARK: - `createCart`
74+
75+
func test_createCart_returns_on_success() throws {
76+
// Given
77+
remote.whenCreatingCart(thenReturn: .success(()))
78+
79+
// When
80+
let result = waitFor { promise in
81+
self.store.onAction(PaymentAction.createCart(productID: "12", siteID: 62) { result in
82+
promise(result)
83+
})
84+
}
85+
86+
// Then
87+
XCTAssertTrue(result.isSuccess)
88+
}
89+
90+
func test_createCart_returns_invalidProductID_error_when_productID_is_not_integer() throws {
91+
// Given
92+
remote.whenCreatingCart(thenReturn: .failure(NetworkError.timeout))
93+
94+
// When
95+
let result = waitFor { promise in
96+
self.store.onAction(PaymentAction.createCart(productID: "wo0", siteID: 62) { result in
97+
promise(result)
98+
})
99+
}
100+
101+
// Then
102+
XCTAssertTrue(result.isFailure)
103+
let error = try XCTUnwrap(result.failure)
104+
XCTAssertEqual(error as? Yosemite.CreateCartError, .invalidProductID)
105+
}
106+
107+
func test_createCart_returns_failure_on_error() throws {
108+
// Given
109+
remote.whenCreatingCart(thenReturn: .failure(NetworkError.timeout))
110+
111+
// When
112+
let result = waitFor { promise in
113+
self.store.onAction(PaymentAction.createCart(productID: "12", siteID: 62) { result in
114+
promise(result)
115+
})
116+
}
117+
118+
// Then
119+
XCTAssertTrue(result.isFailure)
120+
}
121+
}

0 commit comments

Comments
 (0)