Unit tests und nudging screen
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import Mobile_Music_Assistant
|
||||
|
||||
// MARK: - Live Activity Player Selection
|
||||
|
||||
@Suite("MAPlayerManager – Live Activity Selection")
|
||||
struct LiveActivitySelectionTests {
|
||||
|
||||
/// Build a minimal MAPlayer from JSON for testing.
|
||||
private func makePlayer(
|
||||
id: String,
|
||||
state: String = "playing",
|
||||
currentItem: String? = nil
|
||||
) throws -> MAPlayer {
|
||||
var json = """
|
||||
{"player_id":"\(id)","name":"Player \(id)","state":"\(state)"}
|
||||
"""
|
||||
if let item = currentItem {
|
||||
json = """
|
||||
{"player_id":"\(id)","name":"Player \(id)","state":"\(state)","current_item":{"queue_item_id":"qi1","name":"\(item)"}}
|
||||
"""
|
||||
}
|
||||
return try JSONDecoder().decode(MAPlayer.self, from: Data(json.utf8))
|
||||
}
|
||||
|
||||
// The selection logic is internal to MAPlayerManager; we test it via
|
||||
// a whitebox helper that replicates the exact algorithm.
|
||||
private func selectBestPlayer(
|
||||
from players: [MAPlayer],
|
||||
queues: [String: MAPlayerQueue]
|
||||
) -> MAPlayer? {
|
||||
players
|
||||
.filter { $0.state == .playing }
|
||||
.first { p in p.currentItem != nil || queues[p.playerId]?.currentItem != nil }
|
||||
?? players.first { $0.state == .playing }
|
||||
}
|
||||
|
||||
@Test("Selects the playing player with a known currentItem")
|
||||
func selectsPlayingWithItem() throws {
|
||||
let playing = try makePlayer(id: "1", state: "playing", currentItem: "Song A")
|
||||
let idle = try makePlayer(id: "2", state: "idle")
|
||||
let selected = selectBestPlayer(from: [idle, playing], queues: [:])
|
||||
#expect(selected?.playerId == "1")
|
||||
}
|
||||
|
||||
@Test("Falls back to any playing player when no current item is set")
|
||||
func fallsBackToAnyPlayingPlayer() throws {
|
||||
let playing = try makePlayer(id: "1", state: "playing")
|
||||
let idle = try makePlayer(id: "2", state: "idle")
|
||||
let selected = selectBestPlayer(from: [idle, playing], queues: [:])
|
||||
#expect(selected?.playerId == "1")
|
||||
}
|
||||
|
||||
@Test("Returns nil when no player is playing")
|
||||
func returnsNilWhenNobodyPlaying() throws {
|
||||
let p1 = try makePlayer(id: "1", state: "idle")
|
||||
let p2 = try makePlayer(id: "2", state: "paused")
|
||||
let selected = selectBestPlayer(from: [p1, p2], queues: [:])
|
||||
#expect(selected == nil)
|
||||
}
|
||||
|
||||
@Test("Prefers player whose queue has a currentItem")
|
||||
func prefersPlayerWithQueueItem() throws {
|
||||
let p1 = try makePlayer(id: "1", state: "playing") // no direct item
|
||||
let p2 = try makePlayer(id: "2", state: "playing") // no direct item
|
||||
|
||||
let queue2: MAPlayerQueue = try {
|
||||
let json = """
|
||||
{"queue_id":"q2","current_item":{"queue_item_id":"qi2","name":"Track"}}
|
||||
"""
|
||||
return try JSONDecoder().decode(MAPlayerQueue.self, from: Data(json.utf8))
|
||||
}()
|
||||
|
||||
// p1 has no item in players or queues; p2 has item in queue
|
||||
let selected = selectBestPlayer(from: [p1, p2], queues: ["2": queue2])
|
||||
#expect(selected?.playerId == "2")
|
||||
}
|
||||
|
||||
@Test("Returns nil with empty player list")
|
||||
func emptyPlayerList() {
|
||||
let selected = selectBestPlayer(from: [], queues: [:])
|
||||
#expect(selected == nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ResizeAndEncode
|
||||
|
||||
@Suite("MAPlayerManager – resizeAndEncode")
|
||||
struct ResizeAndEncodeTests {
|
||||
|
||||
@Test("Encodes UIImage to JPEG data under 4 KB")
|
||||
func encodedDataIsBelowActivityKitLimit() {
|
||||
let size = CGSize(width: 400, height: 400)
|
||||
let renderer = UIGraphicsImageRenderer(size: size)
|
||||
let image = renderer.image { ctx in
|
||||
UIColor.systemBlue.setFill()
|
||||
ctx.fill(CGRect(origin: .zero, size: size))
|
||||
}
|
||||
let data = MAPlayerManager.testResizeAndEncode(image)
|
||||
#expect(data != nil)
|
||||
// ActivityKit limit is 4 KB; we target <1 KB for the image
|
||||
#expect((data?.count ?? Int.max) < 4096)
|
||||
}
|
||||
|
||||
@Test("Returns valid JPEG data")
|
||||
func returnsValidJpeg() {
|
||||
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 100, height: 100))
|
||||
let image = renderer.image { ctx in
|
||||
UIColor.red.setFill()
|
||||
ctx.fill(CGRect(origin: .zero, size: CGSize(width: 100, height: 100)))
|
||||
}
|
||||
guard let data = MAPlayerManager.testResizeAndEncode(image) else {
|
||||
Issue.record("resizeAndEncode returned nil")
|
||||
return
|
||||
}
|
||||
// JPEG magic bytes: FF D8
|
||||
#expect(data.prefix(2) == Data([0xFF, 0xD8]))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user