import Foundation @testable import PlexKit /// Ein Transport, der vorbereitete Antworten liefert. /// /// Statt `URLProtocol` zu unterwandern: das ist global und bringt bei parallel /// laufenden Tests die Antworten durcheinander. Hier hat jeder Test seinen /// eigenen Transport. struct FakeTransport: PlexTransport { let handler: @Sendable (URLRequest) async throws -> (Data, URLResponse) func data(for request: URLRequest) async throws -> (Data, URLResponse) { try await handler(request) } /// Antwortet auf jeden Pfad, der als Schlüssel hinterlegt ist, und mit 404 /// auf alle übrigen. static func routes( _ routes: [String: String], status: Int = 200 ) -> FakeTransport { FakeTransport { request in let path = request.url?.path() ?? "" guard let body = routes.first(where: { path.hasSuffix($0.key) })?.value else { return (Data(), response(for: request, status: 404)) } return (Data(body.utf8), response(for: request, status: status)) } } /// Verweigert jede Verbindung — für die Wege, die im Test nicht gewinnen /// sollen. static func unreachable() -> FakeTransport { FakeTransport { _ in throw URLError(.cannotConnectToHost) } } /// Antwortet je nach Adresse unterschiedlich — und lässt einzelne Adressen /// ins Leere laufen. /// /// Bildet den Fall nach, der in der Wirklichkeit am meisten weh tut: eine /// lokale Adresse, die nicht ablehnt, sondern schweigt. Ein abgelehnter /// Verbindungsversuch ist sofort vorbei; ein schweigender läuft bis zur /// Zeitgrenze. static func hosts( answering answers: [String: String], hanging: Set = [] ) -> FakeTransport { FakeTransport { request in let host = request.url?.host() ?? "" if hanging.contains(host) { // Länger als jede Zeitgrenze, die ein Test setzen würde. try await Task.sleep(for: .seconds(3600)) } guard let body = answers[host] else { throw URLError(.cannotConnectToHost) } return (Data(body.utf8), response(for: request, status: 200)) } } static func response(for request: URLRequest, status: Int) -> HTTPURLResponse { HTTPURLResponse( url: request.url ?? URL(string: "http://example.invalid")!, statusCode: status, httpVersion: nil, headerFields: nil )! } } extension PlexClientIdentity { static let test = PlexClientIdentity( product: "FlixyTests", version: "0", clientIdentifier: "test-client", platform: "iOS", platformVersion: "26.0", device: "iPhone", deviceName: "Testgerät" ) }