Implement incremental sync and offline recovery
This commit is contained in:
@@ -4,6 +4,7 @@ import VelodyDomain
|
||||
import VelodyNetworking
|
||||
import VelodyPlayback
|
||||
import VelodyPersistence
|
||||
import VelodyUtilities
|
||||
@testable import VelodyiPhone
|
||||
|
||||
@MainActor
|
||||
@@ -449,9 +450,35 @@ final class iPhoneLibraryViewModelPolishTests: XCTestCase {
|
||||
let remoteTrack = try XCTUnwrap(remoteRow(in: viewModel, trackID: track.trackId))
|
||||
XCTAssertEqual(remoteTrack.status, .missing)
|
||||
XCTAssertEqual(remoteTrack.statusBadgeTitle, "Missing")
|
||||
XCTAssertTrue(remoteTrack.canDownload)
|
||||
XCTAssertEqual(remoteTrack.downloadButtonTitle, "Re-download")
|
||||
XCTAssertFalse(remoteTrack.canPlay)
|
||||
XCTAssertTrue(viewModel.availableOfflineTracks.isEmpty)
|
||||
XCTAssertEqual(viewModel.availableOfflineSectionTitle, "Available Offline (0)")
|
||||
}
|
||||
|
||||
func testDownloadedTrackAppearsInAvailableOfflineState() async throws {
|
||||
let track = makeRemoteTrack(
|
||||
trackId: "remote-recovered-download",
|
||||
assetId: "asset-recovered-download",
|
||||
title: "Recovered Download"
|
||||
)
|
||||
let viewModel = makeViewModel(
|
||||
remoteTracks: [track],
|
||||
downloadStates: [makeDownloadedState(for: track)],
|
||||
audioFiles: [localFilePath(for: track): Data([0x1, 0x2, 0x3])]
|
||||
)
|
||||
|
||||
await viewModel.loadIfNeeded()
|
||||
|
||||
let remoteTrack = try XCTUnwrap(remoteRow(in: viewModel, trackID: track.trackId))
|
||||
let offlineTrack = try XCTUnwrap(offlineRow(in: viewModel, trackID: track.trackId))
|
||||
|
||||
XCTAssertEqual(remoteTrack.status, .downloaded)
|
||||
XCTAssertEqual(remoteTrack.statusBadgeTitle, "Downloaded")
|
||||
XCTAssertEqual(offlineTrack.statusBadgeTitle, "Downloaded")
|
||||
XCTAssertEqual(viewModel.availableOfflineSectionTitle, "Available Offline (1)")
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@@ -479,7 +506,8 @@ final class iPhoneLibraryViewModelDeviceAuthTests: XCTestCase {
|
||||
forKey: "velody.iphone.device-access-token"
|
||||
)
|
||||
|
||||
XCTAssertEqual(await counter.count, 1)
|
||||
let registerCount = await counter.currentCount()
|
||||
XCTAssertEqual(registerCount, 1)
|
||||
XCTAssertFalse((storedDeviceID ?? "").isEmpty)
|
||||
XCTAssertFalse((storedDeviceAccessToken ?? "").isEmpty)
|
||||
}
|
||||
@@ -513,7 +541,8 @@ final class iPhoneLibraryViewModelDeviceAuthTests: XCTestCase {
|
||||
forKey: "velody.iphone.device-access-token"
|
||||
)
|
||||
|
||||
XCTAssertEqual(await counter.count, 1)
|
||||
let registerCount = await counter.currentCount()
|
||||
XCTAssertEqual(registerCount, 1)
|
||||
XCTAssertNotEqual(storedDeviceID, legacyDeviceID)
|
||||
XCTAssertFalse((storedDeviceAccessToken ?? "").isEmpty)
|
||||
}
|
||||
@@ -525,6 +554,10 @@ private actor RegisterCallCounter {
|
||||
func increment() {
|
||||
count += 1
|
||||
}
|
||||
|
||||
func currentCount() -> Int {
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestRegisterAPIClient: VelodyAPIClient {
|
||||
@@ -563,6 +596,12 @@ private struct TestRegisterAPIClient: VelodyAPIClient {
|
||||
try await stubClient.fetchSyncBootstrap()
|
||||
}
|
||||
|
||||
func fetchSyncChanges(
|
||||
cursor: SyncCursor
|
||||
) async throws -> SyncChangesResponse {
|
||||
try await stubClient.fetchSyncChanges(cursor: cursor)
|
||||
}
|
||||
|
||||
func fetchRemoteLibrary(
|
||||
deviceId: String
|
||||
) async throws -> RemoteLibraryResponseDTO {
|
||||
|
||||
Reference in New Issue
Block a user