velody/packages/apple/VelodyDomain/Tests/VelodyDomainTests/OfflineLibrarySearchTests.swift
2026-05-31 08:57:54 +02:00

171 lines
5.8 KiB
Swift

import Foundation
import XCTest
@testable import VelodyDomain
final class OfflineLibrarySearchTests: XCTestCase {
func testSearchByTitleFiltersMatchingTracks() {
let snapshot = makeSnapshot()
let filtered = snapshot.filtered(searchText: "trap")
XCTAssertEqual(filtered.remoteTracks.map(\.remoteTrack.trackId), ["remote-light-trap"])
XCTAssertEqual(filtered.availableTracks.map(\.remoteTrackId), ["remote-light-trap"])
}
func testSearchByArtistFiltersMatchingTracks() {
let snapshot = makeSnapshot()
let filtered = snapshot.filtered(searchText: "unknown")
XCTAssertEqual(filtered.remoteTracks.map(\.remoteTrack.trackId), ["remote-light-trap"])
XCTAssertEqual(filtered.availableTracks.map(\.remoteTrackId), ["remote-light-trap"])
}
func testSearchIsCaseInsensitiveAndTrimsWhitespace() {
let snapshot = makeSnapshot()
let filtered = snapshot.filtered(searchText: " TRAP ")
XCTAssertEqual(filtered.remoteTracks.map(\.remoteTrack.trackId), ["remote-light-trap"])
XCTAssertEqual(filtered.availableTracks.map(\.remoteTrackId), ["remote-light-trap"])
}
func testEmptySearchResultReturnsEmptySections() {
let snapshot = makeSnapshot()
let filtered = snapshot.filtered(searchText: "nope")
XCTAssertTrue(filtered.remoteTracks.isEmpty)
XCTAssertTrue(filtered.availableTracks.isEmpty)
}
func testClearingSearchRestoresFullList() {
let snapshot = makeSnapshot()
let filtered = snapshot.filtered(searchText: "")
XCTAssertEqual(filtered.remoteTracks, snapshot.remoteTracks)
XCTAssertEqual(filtered.availableTracks, snapshot.availableTracks)
}
func testOfflineSectionFilteringUsesAvailableOfflineTracks() {
let snapshot = makeSnapshot()
let filtered = snapshot.filtered(searchText: "harbor")
XCTAssertEqual(filtered.remoteTracks.map(\.remoteTrack.trackId), ["remote-harbor-lights"])
XCTAssertEqual(filtered.availableTracks.map(\.remoteTrackId), ["remote-harbor-lights"])
}
func testRemoteSectionFilteringUsesRemoteLibraryTracks() {
let snapshot = makeSnapshot()
let filtered = snapshot.filtered(searchText: "shadow")
XCTAssertEqual(filtered.remoteTracks.map(\.remoteTrack.trackId), ["remote-shadow-city"])
XCTAssertTrue(filtered.availableTracks.isEmpty)
}
func testFilteringDoesNotMutateUnderlyingSnapshotData() {
let snapshot = makeSnapshot()
let originalRemoteTracks = snapshot.remoteTracks
let originalAvailableTracks = snapshot.availableTracks
_ = snapshot.filtered(searchText: "light")
XCTAssertEqual(snapshot.remoteTracks, originalRemoteTracks)
XCTAssertEqual(snapshot.availableTracks, originalAvailableTracks)
}
private func makeSnapshot() -> OfflineLibrarySnapshot {
let remoteTracks = [
makeRemoteLibraryTrack(
trackId: "remote-light-trap",
assetId: "asset-light-trap",
title: "Light Trap",
artist: "Unknown Artist",
isFileAvailable: true
),
makeRemoteLibraryTrack(
trackId: "remote-shadow-city",
assetId: "asset-shadow-city",
title: "Shadow City",
artist: "Night Runner",
isFileAvailable: false
),
makeRemoteLibraryTrack(
trackId: "remote-harbor-lights",
assetId: "asset-harbor-lights",
title: "Harbor Lights",
artist: "The Northline",
isFileAvailable: true
),
]
let availableTracks = [
makeOfflineTrack(
trackId: "remote-light-trap",
assetId: "asset-light-trap",
title: "Light Trap",
artist: "Unknown Artist"
),
makeOfflineTrack(
trackId: "remote-harbor-lights",
assetId: "asset-harbor-lights",
title: "Harbor Lights",
artist: "The Northline"
),
]
return OfflineLibrarySnapshot(
remoteTracks: remoteTracks,
availableTracks: availableTracks
)
}
private func makeRemoteLibraryTrack(
trackId: String,
assetId: String,
title: String,
artist: String,
isFileAvailable: Bool
) -> OfflineLibraryRemoteTrack {
OfflineLibraryRemoteTrack(
remoteTrack: RemoteTrack(
trackId: trackId,
title: title,
artist: artist,
durationSeconds: 180,
sha256: String(repeating: "a", count: 64),
assetId: assetId,
createdAt: "2026-05-30T10:00:00.000Z",
updatedAt: "2026-05-30T10:00:00.000Z"
),
localFilePath: isFileAvailable ? "/tmp/\(assetId).mp3" : "",
downloadedAt: isFileAvailable ? Date(timeIntervalSince1970: 1_000) : nil,
isFileAvailable: isFileAvailable,
status: isFileAvailable ? .downloaded : .notDownloaded,
lastDownloadError: nil
)
}
private func makeOfflineTrack(
trackId: String,
assetId: String,
title: String,
artist: String
) -> OfflineLibraryTrack {
OfflineLibraryTrack(
remoteTrackId: trackId,
assetId: assetId,
title: title,
artist: artist,
durationSeconds: 180,
sha256: String(repeating: "b", count: 64),
localFilePath: "/tmp/\(assetId).mp3",
downloadedAt: Date(timeIntervalSince1970: 1_000),
isFileAvailable: true
)
}
}