Skip to content

Commit 70072d7

Browse files
committed
Added some OrderStatusStore and ReportRemote unit tests
1 parent ad7455c commit 70072d7

File tree

4 files changed

+186
-5
lines changed

4 files changed

+186
-5
lines changed

Networking/NetworkingTests/Remote/ReportRemoteTests.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class ReportRemoteTests: XCTestCase {
2121
network.removeAllSimulatedResponses()
2222
}
2323

24+
// MARK: - loadOrderTotals
25+
2426
/// Verifies that 'loadOrderTotals' properly parses the successful response
2527
///
2628
func testOrderTotalsReturnsSuccess() {
@@ -65,4 +67,43 @@ class ReportRemoteTests: XCTestCase {
6567
}
6668
wait(for: [expectation], timeout: Constants.expectationTimeout)
6769
}
70+
71+
// MARK: - loadOrderStatuses
72+
73+
/// Verifies that 'loadOrderStatuses' properly parses the successful response
74+
///
75+
func testLoadOrderStatusesReturnsSuccess() {
76+
let expectation = self.expectation(description: "Load order statuses")
77+
let remote = ReportRemote(network: network)
78+
79+
network.simulateResponse(requestUrlSuffix: "reports/orders/totals", filename: "report-orders")
80+
remote.loadOrderStatuses(for: sampleSiteID) { (orderStatuses, error) in
81+
XCTAssertNil(error)
82+
XCTAssertNotNil(orderStatuses)
83+
XCTAssertEqual(orderStatuses?.count, 9)
84+
expectation.fulfill()
85+
}
86+
wait(for: [expectation], timeout: Constants.expectationTimeout)
87+
}
88+
89+
/// Verifies that `loadOrderStatuses` correctly returns a Dotcom Error, whenever the request failed.
90+
///
91+
func testLoadOrderStatusesProperlyParsesErrorResponses() {
92+
let expectation = self.expectation(description: "Error Handling")
93+
let remote = ReportRemote(network: network)
94+
95+
network.simulateResponse(requestUrlSuffix: "reports/orders/totals", filename: "generic_error")
96+
remote.loadOrderTotals(for: sampleSiteID) { (reportTotals, error) in
97+
guard let error = error as? DotcomError else {
98+
XCTFail()
99+
return
100+
}
101+
102+
XCTAssert(error == .unauthorized)
103+
XCTAssertEqual(reportTotals?.isEmpty, true)
104+
105+
expectation.fulfill()
106+
}
107+
wait(for: [expectation], timeout: Constants.expectationTimeout)
108+
}
68109
}

Yosemite/Yosemite.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
744A3218216D55F80051439B /* SiteVisitStats+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 744A3216216D55F80051439B /* SiteVisitStats+ReadOnlyConvertible.swift */; };
1717
744A3219216D55F80051439B /* SiteVisitStatsItem+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 744A3217216D55F80051439B /* SiteVisitStatsItem+ReadOnlyConvertible.swift */; };
1818
744A321B216D57D40051439B /* SiteVisitStats+ReadOnlyType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 744A321A216D57D30051439B /* SiteVisitStats+ReadOnlyType.swift */; };
19+
7455263022305F88003F8932 /* OrderStatusStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7455262F22305F88003F8932 /* OrderStatusStoreTests.swift */; };
1920
7455D4672141B57600FA8C1F /* TopEarnerStats+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7455D4662141B57600FA8C1F /* TopEarnerStats+ReadOnlyConvertible.swift */; };
2021
7455D4692141B59E00FA8C1F /* TopEarnerStatsItem+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7455D4682141B59E00FA8C1F /* TopEarnerStatsItem+ReadOnlyConvertible.swift */; };
2122
74643EE1221F567E00EDC51A /* ShipmentAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74643EE0221F567E00EDC51A /* ShipmentAction.swift */; };
@@ -110,6 +111,7 @@
110111
744A3216216D55F80051439B /* SiteVisitStats+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SiteVisitStats+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
111112
744A3217216D55F80051439B /* SiteVisitStatsItem+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SiteVisitStatsItem+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
112113
744A321A216D57D30051439B /* SiteVisitStats+ReadOnlyType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SiteVisitStats+ReadOnlyType.swift"; sourceTree = "<group>"; };
114+
7455262F22305F88003F8932 /* OrderStatusStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderStatusStoreTests.swift; sourceTree = "<group>"; };
113115
7455D4662141B57600FA8C1F /* TopEarnerStats+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TopEarnerStats+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
114116
7455D4682141B59E00FA8C1F /* TopEarnerStatsItem+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TopEarnerStatsItem+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
115117
74643EE0221F567E00EDC51A /* ShipmentAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShipmentAction.swift; sourceTree = "<group>"; };
@@ -314,6 +316,7 @@
314316
748525AB218A45360036DF75 /* NotificationStoreTests.swift */,
315317
74A7688D20D45ED400F9D437 /* OrderStoreTests.swift */,
316318
7499936720EFC0ED00CF01CD /* OrderNoteStoreTests.swift */,
319+
7455262F22305F88003F8932 /* OrderStatusStoreTests.swift */,
317320
7492FAE0217FB87100ED2C69 /* SettingStoreTests.swift */,
318321
7499A9EC2220527500D8FDFA /* ShipmentStoreTests.swift */,
319322
7495C5282114979D00CDD33B /* StatsStoreTests.swift */,
@@ -712,6 +715,7 @@
712715
B5C9DE222087FF20006B910A /* DispatcherTests.swift in Sources */,
713716
B53A56A0211245E0000776C9 /* MockupStorage+Sample.swift in Sources */,
714717
B5A01CA120D19C4700E3207E /* MockupStorage.swift in Sources */,
718+
7455263022305F88003F8932 /* OrderStatusStoreTests.swift in Sources */,
715719
B5C9DE242087FF20006B910A /* StoreTests.swift in Sources */,
716720
B5C9DE252087FF20006B910A /* MockupProcessor.swift in Sources */,
717721
B54EAF2121188C470029C35E /* EntityListenerTests.swift in Sources */,

Yosemite/Yosemite/Stores/OrderStatusStore.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private extension OrderStatusStore {
5252
return
5353
}
5454

55-
self?.upsertStoredOrdersInBackground(siteID: siteID,
55+
self?.upsertStoredStatusesInBackground(siteID: siteID,
5656
readOnlyOrderStatuses: orderStatuses,
5757
onCompletion: {
5858
onCompletion(orderStatuses, nil)
@@ -75,21 +75,30 @@ private extension OrderStatusStore {
7575

7676
// MARK: - Persistence
7777
//
78-
private extension OrderStatusStore {
78+
extension OrderStatusStore {
7979

8080
/// Updates (OR Inserts) the specified ReadOnly Order Status Entities
8181
/// *in a background thread*. onCompletion will be called on the main thread!
8282
///
83-
private func upsertStoredOrdersInBackground(siteID: Int,
84-
readOnlyOrderStatuses: [Networking.OrderStatus],
85-
onCompletion: @escaping () -> Void) {
83+
func upsertStoredStatusesInBackground(siteID: Int,
84+
readOnlyOrderStatuses: [Networking.OrderStatus],
85+
onCompletion: @escaping () -> Void) {
8686
let derivedStorage = sharedDerivedStorage
8787
derivedStorage.perform {
8888
for readOnlyItem in readOnlyOrderStatuses {
8989
let storageStatusItem = derivedStorage.loadOrderStatus(siteID: readOnlyItem.siteID, slug: readOnlyItem.slug) ??
9090
derivedStorage.insertNewObject(ofType: Storage.OrderStatus.self)
9191
storageStatusItem.update(with: readOnlyItem)
9292
}
93+
94+
// Now, remove any objects that exist in storage but not in readOnlyOrderStatuses
95+
if let storageStatuses = derivedStorage.loadOrderStatuses(siteID: siteID) {
96+
storageStatuses.forEach({ storageStatus in
97+
if readOnlyOrderStatuses.first(where: { $0.slug == storageStatus.slug } ) == nil {
98+
derivedStorage.deleteObject(storageStatus)
99+
}
100+
})
101+
}
93102
}
94103

95104
storageManager.saveDerivedType(derivedStorage: derivedStorage) {
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import XCTest
2+
@testable import Yosemite
3+
@testable import Networking
4+
@testable import Storage
5+
6+
7+
/// OrderStatusStore Unit Tests
8+
///
9+
class OrderStatusStoreTests: XCTestCase {
10+
11+
/// Mockup Dispatcher!
12+
///
13+
private var dispatcher: Dispatcher!
14+
15+
/// Mockup Storage: InMemory
16+
///
17+
private var storageManager: MockupStorageManager!
18+
19+
/// Mockup Network: Allows us to inject predefined responses!
20+
///
21+
private var network: MockupNetwork!
22+
23+
/// Convenience Property: Returns the StorageType associated with the main thread.
24+
///
25+
private var viewStorage: StorageType {
26+
return storageManager.viewStorage
27+
}
28+
29+
/// Dummy Site ID
30+
///
31+
private let sampleSiteID = 123
32+
33+
// MARK: - Overridden Methods
34+
35+
override func setUp() {
36+
super.setUp()
37+
dispatcher = Dispatcher()
38+
storageManager = MockupStorageManager()
39+
network = MockupNetwork()
40+
}
41+
42+
// MARK: - OrderStatusAction.retrieveOrderStatuses
43+
44+
/// Verifies that OrderStatusAction.retrieveOrderStatuses returns the expected statuses.
45+
///
46+
func testRetrieveOrderStatusesReturnsExpectedStatuses() {
47+
let expectation = self.expectation(description: "Retrieve order statuses")
48+
let orderStatusStore = OrderStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
49+
50+
network.simulateResponse(requestUrlSuffix: "reports/orders/totals", filename: "report-orders")
51+
let action = OrderStatusAction.retrieveOrderStatuses(siteID: sampleSiteID) { (statuses, error) in
52+
XCTAssertNil(error)
53+
XCTAssertNotNil(statuses)
54+
XCTAssertEqual(statuses?.count, 9)
55+
XCTAssertEqual(statuses, self.sampleOrderStatuses())
56+
expectation.fulfill()
57+
}
58+
59+
orderStatusStore.onAction(action)
60+
wait(for: [expectation], timeout: Constants.expectationTimeout)
61+
}
62+
63+
/// Verifies that OrderStatusAction.retrieveOrderStatuses returns an error, whenever there is an error response.
64+
///
65+
func testRetrieveOrderStatusesReturnsErrorUponReponseError() {
66+
let expectation = self.expectation(description: "Retrieve order statuses error response")
67+
let orderStatusStore = OrderStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
68+
69+
network.simulateResponse(requestUrlSuffix: "reports/orders/totals", filename: "generic_error")
70+
let action = OrderStatusAction.retrieveOrderStatuses(siteID: sampleSiteID) { (statuses, error) in
71+
XCTAssertNotNil(error)
72+
XCTAssertNil(statuses)
73+
expectation.fulfill()
74+
}
75+
76+
orderStatusStore.onAction(action)
77+
wait(for: [expectation], timeout: Constants.expectationTimeout)
78+
}
79+
80+
/// Verifies that OrderStatusAction.retrieveOrderStatuses returns an error, whenever there is not backend response.
81+
///
82+
func testRetrieveOrderStatusesReturnsErrorUponEmptyResponse() {
83+
let expectation = self.expectation(description: "Retrieve order statuses empty response error")
84+
let orderStatusStore = OrderStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
85+
86+
let action = OrderStatusAction.retrieveOrderStatuses(siteID: sampleSiteID) { (statuses, error) in
87+
XCTAssertNotNil(error)
88+
XCTAssertNil(statuses)
89+
expectation.fulfill()
90+
}
91+
92+
orderStatusStore.onAction(action)
93+
wait(for: [expectation], timeout: Constants.expectationTimeout)
94+
}
95+
}
96+
97+
98+
// MARK: - OrderStatus Samples
99+
//
100+
private extension OrderStatusStoreTests {
101+
102+
func sampleOrderStatuses() -> [Networking.OrderStatus] {
103+
return [
104+
OrderStatus(name: "Pending payment", siteID: sampleSiteID, slug: "pending", total: 123),
105+
OrderStatus(name: "Processing", siteID: sampleSiteID, slug: "processing", total: 4),
106+
OrderStatus(name: "On hold", siteID: sampleSiteID, slug: "on-hold", total: 5),
107+
OrderStatus(name: "Completed", siteID: sampleSiteID, slug: "completed", total: 6),
108+
OrderStatus(name: "Cancelled", siteID: sampleSiteID, slug: "cancelled", total: 7),
109+
OrderStatus(name: "Refunded", siteID: sampleSiteID, slug: "refunded", total: 8),
110+
OrderStatus(name: "Failed", siteID: sampleSiteID, slug: "failed", total: 9),
111+
OrderStatus(name: "CIA Investigation", siteID: sampleSiteID, slug: "cia-investigation", total: 10),
112+
OrderStatus(name: "Pre ordered", siteID: sampleSiteID, slug: "pre-ordered", total: 1)
113+
]
114+
}
115+
116+
func sampleOrderStatusesMutated() -> [Networking.OrderStatus] {
117+
return [
118+
OrderStatus(name: "Pending payment", siteID: sampleSiteID, slug: "pending", total: 1123),
119+
OrderStatus(name: "Processing", siteID: sampleSiteID, slug: "processing", total: 14),
120+
OrderStatus(name: "On hold", siteID: sampleSiteID, slug: "on-hold", total: 15),
121+
OrderStatus(name: "Completed", siteID: sampleSiteID, slug: "completed", total: 16),
122+
OrderStatus(name: "Refunded", siteID: sampleSiteID, slug: "refunded", total: 18),
123+
OrderStatus(name: "Failed", siteID: sampleSiteID, slug: "failed", total: 19),
124+
OrderStatus(name: "Pre ordered", siteID: sampleSiteID, slug: "pre-ordered", total: 11)
125+
]
126+
}
127+
}

0 commit comments

Comments
 (0)