Skip to content

Commit 103da58

Browse files
committed
Update and add tests
1 parent a085ba4 commit 103da58

File tree

5 files changed

+190
-18
lines changed

5 files changed

+190
-18
lines changed

Modules/Sources/NetworkingCore/Remote/OrdersRemote.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import Foundation
22

3+
public protocol OrdersRemoteProtocol {
4+
func loadOrders(
5+
for siteID: Int64,
6+
orderIDs: [Int64]
7+
) async throws -> [Order]
8+
}
9+
310
/// Order: Remote Endpoints
411
///
5-
public class OrdersRemote: Remote {
12+
public class OrdersRemote: Remote, OrdersRemoteProtocol {
613
/// The source of the order creation.
714
public enum OrderCreationSource {
815
case storeManagement

Modules/Sources/Yosemite/Stores/BookingStore.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Storage
66
//
77
public class BookingStore: Store {
88
private let remote: BookingsRemoteProtocol
9-
private let ordersRemote: OrdersRemote
9+
private let ordersRemote: OrdersRemoteProtocol
1010

1111
public override convenience init(dispatcher: Dispatcher, storageManager: StorageManagerType, network: Network) {
1212
let remote = BookingsRemote(network: network)
@@ -18,7 +18,7 @@ public class BookingStore: Store {
1818
storageManager: StorageManagerType,
1919
network: Network,
2020
remote: BookingsRemoteProtocol,
21-
ordersRemote: OrdersRemote) {
21+
ordersRemote: OrdersRemoteProtocol) {
2222
self.remote = remote
2323
self.ordersRemote = ordersRemote
2424
super.init(dispatcher: dispatcher, storageManager: storageManager, network: network)

Modules/Tests/NetworkingTests/Remote/OrdersRemoteTests.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,55 @@ final class OrdersRemoteTests: XCTestCase {
146146
XCTAssertTrue(queryParameters.contains(expectedParam), "Expected to have param: \(expectedParam)")
147147
}
148148

149+
// MARK: - Load Orders by IDs Tests
150+
151+
func test_loadOrders_by_ids_when_request_succeeds_returns_parsed_orders() async throws {
152+
// Given
153+
let remote = OrdersRemote(network: network)
154+
let orderIDs: [Int64] = [1, 2, 3]
155+
network.simulateResponse(requestUrlSuffix: "orders", filename: "orders-load-all")
156+
157+
// When
158+
let orders = try await remote.loadOrders(for: sampleSiteID, orderIDs: orderIDs)
159+
160+
// Then
161+
XCTAssertEqual(orders.count, 4) // The sample file has 4 orders
162+
}
163+
164+
func test_loadOrders_by_ids_when_invoked_sends_correct_parameters() async throws {
165+
// Given
166+
let remote = OrdersRemote(network: network)
167+
let orderIDs: [Int64] = [1, 2, 3, 2] // with duplicate
168+
network.simulateResponse(requestUrlSuffix: "orders", filename: "orders-load-all")
169+
170+
// When
171+
_ = try await remote.loadOrders(for: sampleSiteID, orderIDs: orderIDs)
172+
173+
// Then
174+
let request = try XCTUnwrap(network.requestsForResponseData.last as? JetpackRequest)
175+
let parameters = request.parameters
176+
177+
let includeValue = parameters["include"] as? String
178+
let includedIDs = includeValue?.split(separator: ",").map { String($0) }
179+
XCTAssertNotNil(includeValue)
180+
XCTAssertEqual(Set(includedIDs ?? []), Set(["1", "2", "3"])) // check for unique ids
181+
182+
XCTAssertNotNil(parameters["_fields"])
183+
XCTAssertNil(parameters["per_page"]) // verify per_page is not sent
184+
}
185+
186+
func test_loadOrders_by_ids_with_empty_ids_returns_empty_array_and_makes_no_request() async throws {
187+
// Given
188+
let remote = OrdersRemote(network: network)
189+
190+
// When
191+
let orders = try await remote.loadOrders(for: sampleSiteID, orderIDs: [])
192+
193+
// Then
194+
XCTAssertTrue(orders.isEmpty)
195+
XCTAssertTrue(network.requestsForResponseData.isEmpty) // No network request should be made
196+
}
197+
149198
// MARK: - Load Order Tests
150199

151200
/// Verifies that loadOrder properly parses the `order` sample response.

Modules/Tests/YosemiteTests/Mocks/MockBookingsRemote.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ import Foundation
55
///
66
final class MockBookingsRemote: BookingsRemoteProtocol {
77
private var loadAllBookingsResult: Result<[Booking], Error>?
8+
private var loadBookingResult: Result<Booking?, Error>?
89

910
func whenLoadingAllBookings(thenReturn result: Result<[Booking], Error>) {
1011
loadAllBookingsResult = result
1112
}
1213

14+
func whenLoadingBooking(thenReturn result: Result<Booking?, Error>) {
15+
loadBookingResult = result
16+
}
17+
1318
func loadAllBookings(for siteID: Int64,
1419
pageNumber: Int,
1520
pageSize: Int,
@@ -21,4 +26,11 @@ final class MockBookingsRemote: BookingsRemoteProtocol {
2126
}
2227
return try result.get()
2328
}
29+
30+
func loadBooking(bookingID: Int64, siteID: Int64) async throws -> Networking.Booking? {
31+
guard let result = loadBookingResult else {
32+
throw NetworkError.timeout()
33+
}
34+
return try result.get()
35+
}
2436
}

Modules/Tests/YosemiteTests/Stores/BookingStoreTests.swift

Lines changed: 119 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct BookingStoreTests {
1212
/// Spy remote to check request parameter use
1313
///
1414
private var remote: MockBookingsRemote
15+
private var ordersRemote: MockOrdersRemote
1516

1617
/// Mock Storage: InMemory
1718
///
@@ -51,6 +52,7 @@ struct BookingStoreTests {
5152
network = MockNetwork()
5253
storageManager = MockStorageManager()
5354
remote = MockBookingsRemote()
55+
ordersRemote = MockOrdersRemote()
5456
}
5557

5658
// MARK: - synchronizeBookings
@@ -61,7 +63,8 @@ struct BookingStoreTests {
6163
let store = BookingStore(dispatcher: Dispatcher(),
6264
storageManager: storageManager,
6365
network: network,
64-
remote: remote)
66+
remote: remote,
67+
ordersRemote: ordersRemote)
6568

6669
// When
6770
let result = await withCheckedContinuation { continuation in
@@ -85,7 +88,8 @@ struct BookingStoreTests {
8588
let store = BookingStore(dispatcher: Dispatcher(),
8689
storageManager: storageManager,
8790
network: network,
88-
remote: remote)
91+
remote: remote,
92+
ordersRemote: ordersRemote)
8993

9094
// When
9195
let result = await withCheckedContinuation { continuation in
@@ -108,7 +112,8 @@ struct BookingStoreTests {
108112
let store = BookingStore(dispatcher: Dispatcher(),
109113
storageManager: storageManager,
110114
network: network,
111-
remote: remote)
115+
remote: remote,
116+
ordersRemote: ordersRemote)
112117

113118
// When
114119
let result = await withCheckedContinuation { continuation in
@@ -126,14 +131,77 @@ struct BookingStoreTests {
126131
#expect(error == .timeout())
127132
}
128133

134+
@Test func test_synchronizeBookings_when_invoked_fetches_orders_for_bookings() async throws {
135+
// Given
136+
let booking1 = Booking.fake().copy(orderID: 1)
137+
let booking2 = Booking.fake().copy(orderID: 2)
138+
remote.whenLoadingAllBookings(thenReturn: .success([booking1, booking2]))
139+
140+
let order1 = Order.fake().copy(orderID: 1)
141+
let order2 = Order.fake().copy(orderID: 2)
142+
ordersRemote.whenLoadingOrders(thenReturn: .success([order1, order2]))
143+
144+
let store = BookingStore(dispatcher: Dispatcher(),
145+
storageManager: storageManager,
146+
network: network,
147+
remote: remote,
148+
ordersRemote: ordersRemote)
149+
150+
// When
151+
let result = await withCheckedContinuation { continuation in
152+
store.onAction(BookingAction.synchronizeBookings(siteID: sampleSiteID,
153+
pageNumber: defaultPageNumber,
154+
pageSize: defaultPageSize,
155+
onCompletion: { result in
156+
continuation.resume(returning: result)
157+
}))
158+
}
159+
160+
// Then
161+
#expect(result.isSuccess)
162+
#expect(ordersRemote.invokedLoadOrders)
163+
#expect(ordersRemote.invokedLoadOrdersParameters?.orderIDs == [1, 2])
164+
}
165+
166+
@Test func test_synchronizeBooking_when_invoked_fetches_order_for_booking() async throws {
167+
// Given
168+
let booking = Booking.fake().copy(bookingID: 1, orderID: 10)
169+
remote.whenLoadingBooking(thenReturn: .success(booking))
170+
ordersRemote.whenLoadingOrders(thenReturn: .success([]))
171+
172+
let store = BookingStore(dispatcher: Dispatcher(),
173+
storageManager: storageManager,
174+
network: network,
175+
remote: remote,
176+
ordersRemote: ordersRemote)
177+
178+
// When
179+
let result = await withCheckedContinuation { continuation in
180+
store.onAction(
181+
BookingAction.synchronizeBooking(
182+
siteID: sampleSiteID,
183+
bookingID: 1
184+
) { result in
185+
continuation.resume(returning: result)
186+
}
187+
)
188+
}
189+
190+
// Then
191+
#expect(result.isSuccess)
192+
#expect(ordersRemote.invokedLoadOrders)
193+
#expect(ordersRemote.invokedLoadOrdersParameters?.orderIDs == [10])
194+
}
195+
129196
@Test func synchronizeBookings_stores_bookings_upon_success() async throws {
130197
// Given
131198
let booking = Booking.fake().copy(siteID: sampleSiteID, bookingID: 123)
132199
remote.whenLoadingAllBookings(thenReturn: .success([booking]))
133200
let store = BookingStore(dispatcher: Dispatcher(),
134201
storageManager: storageManager,
135202
network: network,
136-
remote: remote)
203+
remote: remote,
204+
ordersRemote: ordersRemote)
137205
#expect(storedBookingCount == 0)
138206

139207
// When
@@ -162,7 +230,8 @@ struct BookingStoreTests {
162230
let store = BookingStore(dispatcher: Dispatcher(),
163231
storageManager: storageManager,
164232
network: network,
165-
remote: remote)
233+
remote: remote,
234+
ordersRemote: ordersRemote)
166235

167236
// When
168237
let result = await withCheckedContinuation { continuation in
@@ -189,7 +258,8 @@ struct BookingStoreTests {
189258
let store = BookingStore(dispatcher: Dispatcher(),
190259
storageManager: storageManager,
191260
network: network,
192-
remote: remote)
261+
remote: remote,
262+
ordersRemote: ordersRemote)
193263
#expect(storedBookingCount == 0)
194264

195265
// When
@@ -218,7 +288,8 @@ struct BookingStoreTests {
218288
let store = BookingStore(dispatcher: Dispatcher(),
219289
storageManager: storageManager,
220290
network: network,
221-
remote: remote)
291+
remote: remote,
292+
ordersRemote: ordersRemote)
222293

223294
// When
224295
let result = await withCheckedContinuation { continuation in
@@ -253,7 +324,8 @@ struct BookingStoreTests {
253324
let store = BookingStore(dispatcher: Dispatcher(),
254325
storageManager: storageManager,
255326
network: network,
256-
remote: remote)
327+
remote: remote,
328+
ordersRemote: ordersRemote)
257329

258330
// When
259331
let result = await withCheckedContinuation { continuation in
@@ -289,7 +361,8 @@ struct BookingStoreTests {
289361
let store = BookingStore(dispatcher: Dispatcher(),
290362
storageManager: storageManager,
291363
network: network,
292-
remote: remote)
364+
remote: remote,
365+
ordersRemote: ordersRemote)
293366

294367
// When
295368
let result = await withCheckedContinuation { continuation in
@@ -313,7 +386,8 @@ struct BookingStoreTests {
313386
let store = BookingStore(dispatcher: Dispatcher(),
314387
storageManager: storageManager,
315388
network: network,
316-
remote: remote)
389+
remote: remote,
390+
ordersRemote: ordersRemote)
317391

318392
// When
319393
let result = await withCheckedContinuation { continuation in
@@ -336,7 +410,8 @@ struct BookingStoreTests {
336410
let store = BookingStore(dispatcher: Dispatcher(),
337411
storageManager: storageManager,
338412
network: network,
339-
remote: remote)
413+
remote: remote,
414+
ordersRemote: ordersRemote)
340415

341416
// When
342417
let result = await withCheckedContinuation { continuation in
@@ -359,7 +434,8 @@ struct BookingStoreTests {
359434
let store = BookingStore(dispatcher: Dispatcher(),
360435
storageManager: storageManager,
361436
network: network,
362-
remote: remote)
437+
remote: remote,
438+
ordersRemote: ordersRemote)
363439

364440
// When
365441
let result = await withCheckedContinuation { continuation in
@@ -385,7 +461,8 @@ struct BookingStoreTests {
385461
let store = BookingStore(dispatcher: Dispatcher(),
386462
storageManager: storageManager,
387463
network: network,
388-
remote: remote)
464+
remote: remote,
465+
ordersRemote: ordersRemote)
389466

390467
// When
391468
let result = await withCheckedContinuation { continuation in
@@ -411,7 +488,8 @@ struct BookingStoreTests {
411488
let store = BookingStore(dispatcher: Dispatcher(),
412489
storageManager: storageManager,
413490
network: network,
414-
remote: remote)
491+
remote: remote,
492+
ordersRemote: ordersRemote)
415493

416494
// When
417495
let result = await withCheckedContinuation { continuation in
@@ -437,7 +515,8 @@ struct BookingStoreTests {
437515
let store = BookingStore(dispatcher: Dispatcher(),
438516
storageManager: storageManager,
439517
network: network,
440-
remote: remote)
518+
remote: remote,
519+
ordersRemote: ordersRemote)
441520
#expect(storedBookingCount == 0)
442521

443522
// When
@@ -465,3 +544,28 @@ private extension BookingStoreTests {
465544
return storedBooking
466545
}
467546
}
547+
548+
private class MockOrdersRemote: OrdersRemoteProtocol {
549+
var invokedLoadOrders = false
550+
var invokedLoadOrdersParameters: (siteID: Int64, orderIDs: [Int64])?
551+
private var loadOrdersResult: Result<[Yosemite.Order], Error> = .success([])
552+
553+
func whenLoadingOrders(thenReturn result: Result<[Yosemite.Order], Error>) {
554+
loadOrdersResult = result
555+
}
556+
557+
func loadOrders(for siteID: Int64, orderIDs: [Int64]) async throws -> [Yosemite.Order] {
558+
invokedLoadOrders = true
559+
invokedLoadOrdersParameters = (siteID, orderIDs)
560+
switch loadOrdersResult {
561+
case .success(let orders):
562+
return orders
563+
case .failure(let error):
564+
throw error
565+
}
566+
}
567+
568+
func loadOrder(for siteID: Int64, orderID: Int64, completion: @escaping (NetworkingCore.Order?, (any Error)?) -> Void) {
569+
return
570+
}
571+
}

0 commit comments

Comments
 (0)