Skip to content

Commit 2de6170

Browse files
committed
Add new action to check if store has bookings
1 parent 94221d2 commit 2de6170

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

Modules/Sources/Yosemite/Actions/BookingAction.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@ public enum BookingAction: Action {
1414
pageNumber: Int,
1515
pageSize: Int = BookingsRemote.Default.pageSize,
1616
onCompletion: (Result<Bool, Error>) -> Void)
17+
18+
/// Checks if the store already has any bookings.
19+
/// Returns `false` if the store has no bookings.
20+
///
21+
case checkIfStoreHasBookings(siteID: Int64,
22+
onCompletion: (Result<Bool, Error>) -> Void)
1723
}

Modules/Sources/Yosemite/Stores/BookingStore.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class BookingStore: Store {
3737
switch action {
3838
case let .synchronizeBookings(siteID, pageNumber, pageSize, onCompletion):
3939
synchronizeBookings(siteID: siteID, pageNumber: pageNumber, pageSize: pageSize, onCompletion: onCompletion)
40+
case let .checkIfStoreHasBookings(siteID, onCompletion):
41+
checkIfStoreHasBookings(siteID: siteID, onCompletion: onCompletion)
4042
}
4143
}
4244
}
@@ -65,6 +67,31 @@ private extension BookingStore {
6567
}
6668
}
6769
}
70+
71+
/// Checks if the store already has any bookings.
72+
/// Returns `false` if the store has no bookings.
73+
///
74+
func checkIfStoreHasBookings(siteID: Int64, onCompletion: @escaping (Result<Bool, Error>) -> Void) {
75+
let derivedStorage = storageManager.viewStorage
76+
let hasLocalBookings = derivedStorage.countObjects(ofType: StorageBooking.self, matching: NSPredicate(format: "siteID == %lld", siteID)) > 0
77+
78+
if hasLocalBookings {
79+
onCompletion(.success(true))
80+
return
81+
}
82+
83+
Task { @MainActor in
84+
do {
85+
let bookings = try await remote.loadAllBookings(for: siteID,
86+
pageNumber: 1,
87+
pageSize: 1)
88+
let hasRemoteBookings = !bookings.isEmpty
89+
onCompletion(.success(hasRemoteBookings))
90+
} catch {
91+
onCompletion(.failure(error))
92+
}
93+
}
94+
}
6895
}
6996

7097

Modules/Tests/YosemiteTests/Stores/BookingStoreTests.swift

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,103 @@ struct BookingStoreTests {
206206
#expect(result.isSuccess)
207207
#expect(storedBookingCount == 2)
208208
}
209+
210+
// MARK: - checkIfStoreHasBookings
211+
212+
@Test func checkIfStoreHasBookings_returns_true_when_bookings_exist_locally() async throws {
213+
// Given
214+
let booking = Booking.fake().copy(siteID: sampleSiteID, bookingID: 123)
215+
storeBooking(booking)
216+
#expect(storedBookingCount == 1)
217+
218+
let store = BookingStore(dispatcher: Dispatcher(),
219+
storageManager: storageManager,
220+
network: network,
221+
remote: remote)
222+
223+
// When
224+
let result = await withCheckedContinuation { continuation in
225+
store.onAction(BookingAction.checkIfStoreHasBookings(siteID: sampleSiteID,
226+
onCompletion: { result in
227+
continuation.resume(returning: result)
228+
}))
229+
}
230+
231+
// Then
232+
let hasBookings = try result.get()
233+
#expect(hasBookings == true)
234+
}
235+
236+
@Test func checkIfStoreHasBookings_returns_true_when_no_local_bookings_but_remote_has_bookings() async throws {
237+
// Given
238+
#expect(storedBookingCount == 0)
239+
let remoteBooking = Booking.fake()
240+
remote.whenLoadingAllBookings(thenReturn: .success([remoteBooking]))
241+
242+
let store = BookingStore(dispatcher: Dispatcher(),
243+
storageManager: storageManager,
244+
network: network,
245+
remote: remote)
246+
247+
// When
248+
let result = await withCheckedContinuation { continuation in
249+
store.onAction(BookingAction.checkIfStoreHasBookings(siteID: sampleSiteID,
250+
onCompletion: { result in
251+
continuation.resume(returning: result)
252+
}))
253+
}
254+
255+
// Then
256+
let hasBookings = try result.get()
257+
#expect(hasBookings == true)
258+
}
259+
260+
@Test func checkIfStoreHasBookings_returns_false_when_no_bookings_exist_locally_or_remotely() async throws {
261+
// Given
262+
#expect(storedBookingCount == 0)
263+
remote.whenLoadingAllBookings(thenReturn: .success([]))
264+
265+
let store = BookingStore(dispatcher: Dispatcher(),
266+
storageManager: storageManager,
267+
network: network,
268+
remote: remote)
269+
270+
// When
271+
let result = await withCheckedContinuation { continuation in
272+
store.onAction(BookingAction.checkIfStoreHasBookings(siteID: sampleSiteID,
273+
onCompletion: { result in
274+
continuation.resume(returning: result)
275+
}))
276+
}
277+
278+
// Then
279+
let hasBookings = try result.get()
280+
#expect(hasBookings == false)
281+
}
282+
283+
@Test func checkIfStoreHasBookings_returns_error_on_remote_failure() async throws {
284+
// Given
285+
#expect(storedBookingCount == 0)
286+
remote.whenLoadingAllBookings(thenReturn: .failure(NetworkError.timeout()))
287+
288+
let store = BookingStore(dispatcher: Dispatcher(),
289+
storageManager: storageManager,
290+
network: network,
291+
remote: remote)
292+
293+
// When
294+
let result = await withCheckedContinuation { continuation in
295+
store.onAction(BookingAction.checkIfStoreHasBookings(siteID: sampleSiteID,
296+
onCompletion: { result in
297+
continuation.resume(returning: result)
298+
}))
299+
}
300+
301+
// Then
302+
#expect(result.isFailure)
303+
let error = result.failure as? NetworkError
304+
#expect(error == .timeout())
305+
}
209306
}
210307

211308
private extension BookingStoreTests {

0 commit comments

Comments
 (0)