83 lines
4.0 KiB
Swift
83 lines
4.0 KiB
Swift
import Foundation
|
|
@testable import BearWaveCore
|
|
|
|
try checkRadioBrowserDecoding()
|
|
checkPercentEncoding()
|
|
checkNormalizedSearch()
|
|
await checkStationLibrary()
|
|
print("BearWave checks passed")
|
|
|
|
private func checkRadioBrowserDecoding() throws {
|
|
let url = Bundle.module.url(forResource: "stations", withExtension: "json")!
|
|
let stations = try RadioBrowserClient.decodeStations(from: Data(contentsOf: url))
|
|
expect(stations.count == 2, "decode should filter invalid stations")
|
|
expect(stations[0].id == "alpha", "station id should prefer UUID")
|
|
expect(stations[0].playbackURLString == "https://example.test/alpha-resolved", "resolved URL should be playback URL")
|
|
expect(stations[1].bitrate == 96, "bitrate should decode from string")
|
|
expect(stations[1].votes == 50, "votes should decode from string")
|
|
}
|
|
|
|
private func checkPercentEncoding() {
|
|
expect(RadioBrowserClient.percentEncodePathComponent("classic rock") == "classic%20rock", "path values should be percent encoded")
|
|
}
|
|
|
|
private func checkNormalizedSearch() {
|
|
expect(RadioBrowserClient.normalizedSearchText("SLAM!") == "slam", "normalization should ignore punctuation")
|
|
expect(RadioBrowserClient.normalizedSearchText("SLÁM Radio") == "slamradio", "normalization should fold accents and separators")
|
|
expect(RadioBrowserClient.normalizedSearchTokens("Radio Islamabad").contains("slam") == false, "tokens should not match inside another word")
|
|
expect(RadioBrowserClient.normalizedSearchTokens("SLAM! Radio").contains("slam"), "tokens should match punctuation-separated station names")
|
|
}
|
|
|
|
@MainActor
|
|
private func checkStationLibrary() {
|
|
let library = makeLibrary()
|
|
let favorite = RadioStation(uuid: "one", name: "One", resolvedURL: "https://example.test/one")
|
|
library.toggleFavorite(favorite)
|
|
library.toggleFavorite(favorite)
|
|
expect(library.favorites.isEmpty, "favorites should deduplicate by UUID")
|
|
|
|
for index in 0..<25 {
|
|
library.recordPlayback(RadioStation(uuid: "\(index)", name: "Station \(index)", resolvedURL: "https://example.test/\(index)"))
|
|
}
|
|
library.recordPlayback(RadioStation(uuid: "24", name: "Station 24", resolvedURL: "https://example.test/24"))
|
|
expect(library.recentStations.count == 20, "recent stations should be limited to 20")
|
|
expect(library.recentStations.first?.uuid == "24", "recent stations should move duplicates to the front")
|
|
expect(Set(library.recentStations.map(\.uuid)).count == 20, "recent stations should stay unique")
|
|
|
|
library.stations = [
|
|
RadioStation(name: "Zoo News", resolvedURL: "https://example.test/zoo", tags: "news", bitrate: 96, votes: 3),
|
|
RadioStation(name: "Alpha Rock", resolvedURL: "https://example.test/alpha", tags: "rock", bitrate: 192, votes: 1)
|
|
]
|
|
library.filterQuery = "rock"
|
|
expect(library.visibleStations.map(\.name) == ["Alpha Rock"], "filter should match tags")
|
|
library.filterQuery = ""
|
|
library.sortMode = .bitrate
|
|
expect(library.visibleStations.map(\.name) == ["Alpha Rock", "Zoo News"], "bitrate sort should be descending")
|
|
}
|
|
|
|
@MainActor
|
|
private func makeLibrary() -> StationLibrary {
|
|
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
|
let persistence = PersistenceStore(
|
|
applicationSupportDirectory: root.appendingPathComponent("ApplicationSupport"),
|
|
cacheDirectory: root.appendingPathComponent("Caches"),
|
|
linuxConfigDirectory: root.appendingPathComponent("Linux")
|
|
)
|
|
let client = RadioBrowserClient(cacheDirectory: persistence.apiCacheDirectory, session: MockSession())
|
|
return StationLibrary(client: client, persistence: persistence)
|
|
}
|
|
|
|
private func expect(_ condition: @autoclosure () -> Bool, _ message: String) {
|
|
if !condition() {
|
|
fatalError(message)
|
|
}
|
|
}
|
|
|
|
struct MockSession: URLSessionProtocol {
|
|
func data(for request: URLRequest) async throws -> (Data, URLResponse) {
|
|
let data = "[]".data(using: .utf8)!
|
|
let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)!
|
|
return (data, response)
|
|
}
|
|
}
|