Files
MobileMusicAssistant/MobileMusicAssistantTests/MAPlayerManagerTests.swift
T

122 lines
4.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Testing
import Foundation
import UIKit
@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]))
}
}