Files
2026-06-25 09:21:42 +02:00

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)
}
}