Unit tests und nudging screen

This commit is contained in:
2026-04-20 11:10:53 +02:00
parent e1aebdb916
commit 3858500a45
8 changed files with 1223 additions and 0 deletions
@@ -0,0 +1,157 @@
import Testing
import Foundation
@testable import Mobile_Music_Assistant
// MARK: - ConnectionState
@Suite("MAWebSocketClient ConnectionState")
struct ConnectionStateTests {
@Test("Fresh client starts disconnected")
func startsDisconnected() {
let client = MAWebSocketClient()
if case .disconnected = client.connectionState {
// pass
} else {
Issue.record("Expected .disconnected, got \(client.connectionState)")
}
}
@Test("isConnected is false when disconnected")
func isConnectedFalseWhenDisconnected() {
let client = MAWebSocketClient()
#expect(client.isConnected == false)
}
@Test("ConnectionState descriptions are distinct")
func statesAreDistinct() {
// Regression: ensure no two states resolve to the same string representation
let states: [MAWebSocketClient.ConnectionState] = [
.disconnected,
.connecting,
.connected,
.reconnecting(attempt: 1),
.reconnecting(attempt: 2)
]
let descriptions = states.map { "\($0)" }
let unique = Set(descriptions)
#expect(unique.count == descriptions.count)
}
}
// MARK: - Reconnection Backoff
@Suite("MAWebSocketClient Reconnection Backoff")
struct ReconnectionBackoffTests {
/// Replicates the exact formula used in MAWebSocketClient.
private func backoffDelay(attempt: Int) -> Double {
let base = 3.0
let maxDelay = 30.0
return min(base * pow(2.0, Double(attempt - 1)), maxDelay)
}
@Test("Attempt 1 gives 3 seconds")
func attempt1() {
#expect(backoffDelay(attempt: 1) == 3.0)
}
@Test("Attempt 2 gives 6 seconds")
func attempt2() {
#expect(backoffDelay(attempt: 2) == 6.0)
}
@Test("Attempt 3 gives 12 seconds")
func attempt3() {
#expect(backoffDelay(attempt: 3) == 12.0)
}
@Test("Attempt 4 gives 24 seconds")
func attempt4() {
#expect(backoffDelay(attempt: 4) == 24.0)
}
@Test("Attempt 5 is capped at 30 seconds")
func attempt5Capped() {
#expect(backoffDelay(attempt: 5) == 30.0)
}
@Test("High attempt numbers stay capped at 30 seconds")
func highAttemptStaysCapped() {
for attempt in 6...20 {
#expect(backoffDelay(attempt: attempt) == 30.0)
}
}
@Test("Backoff is strictly increasing up to the cap")
func strictlyIncreasing() {
var previous = 0.0
for attempt in 1...5 {
let delay = backoffDelay(attempt: attempt)
#expect(delay > previous)
previous = delay
}
}
}
// MARK: - AnyCodable
@Suite("AnyCodable")
struct AnyCodableTests {
@Test("Bool encodes and decodes correctly")
func boolRoundTrip() throws {
let encoded = try JSONEncoder().encode(AnyCodable(true))
let decoded = try JSONDecoder().decode(AnyCodable.self, from: encoded)
#expect(try decoded.decode(as: Bool.self) == true)
}
@Test("Int encodes and decodes correctly")
func intRoundTrip() throws {
let encoded = try JSONEncoder().encode(AnyCodable(42))
let decoded = try JSONDecoder().decode(AnyCodable.self, from: encoded)
#expect(try decoded.decode(as: Int.self) == 42)
}
@Test("String encodes and decodes correctly")
func stringRoundTrip() throws {
let encoded = try JSONEncoder().encode(AnyCodable("hello"))
let decoded = try JSONDecoder().decode(AnyCodable.self, from: encoded)
#expect(try decoded.decode(as: String.self) == "hello")
}
@Test("Double encodes and decodes correctly")
func doubleRoundTrip() throws {
let encoded = try JSONEncoder().encode(AnyCodable(3.14))
let decoded = try JSONDecoder().decode(AnyCodable.self, from: encoded)
let value = try decoded.decode(as: Double.self)
#expect(abs(value - 3.14) < 0.001)
}
@Test("Array encodes and decodes correctly")
func arrayRoundTrip() throws {
let arr = AnyCodable(["a", "b", "c"])
let encoded = try JSONEncoder().encode(arr)
let decoded = try JSONDecoder().decode(AnyCodable.self, from: encoded)
let values = try decoded.decode(as: [AnyCodable].self)
#expect(values.count == 3)
}
@Test("decode(as:) throws for wrong type")
func decodeThrowsForWrongType() throws {
let encoded = try JSONEncoder().encode(AnyCodable("text"))
let decoded = try JSONDecoder().decode(AnyCodable.self, from: encoded)
#expect(throws: (any Error).self) {
try decoded.decode(as: Int.self)
}
}
@Test("Dictionary decodes keys correctly")
func dictRoundTrip() throws {
let dict = AnyCodable(["key": AnyCodable("value")])
let encoded = try JSONEncoder().encode(dict)
let decoded = try JSONDecoder().decode(AnyCodable.self, from: encoded)
let map = try decoded.decode(as: [String: AnyCodable].self)
#expect(try map["key"]?.decode(as: String.self) == "value")
}
}