import Foundation import Testing @testable import PlexKit @Suite("Schriftzüge und Bildliste") struct ClearLogoTests { private func item(from json: String) throws -> PlexItem { let data = Data(#"{"MediaContainer":{"Metadata":[\#(json)]}}"#.utf8) return try #require( try PlexResponse.decode(PlexMediaContainer.self, from: data).content.first ) } @Test("Der Schriftzug wird aus der Bildliste gelesen") func findsClearLogo() throws { let decoded = try item(from: """ { "ratingKey": "1", "type": "movie", "title": "Harry Potter", "Image": [ {"alt": "Harry Potter", "type": "coverPoster", "url": "/library/metadata/1/thumb/1"}, {"alt": "Harry Potter", "type": "background", "url": "/library/metadata/1/art/1"}, {"alt": "Harry Potter", "type": "clearLogo", "url": "/library/metadata/1/clearLogo/1"} ] } """) #expect(decoded.clearLogoPath == "/library/metadata/1/clearLogo/1") } @Test("Ohne Schriftzug bleibt es beim Titel") func withoutClearLogo() throws { // Der Normalfall bei selbst zusammengestellten Mediatheken. let decoded = try item(from: """ { "ratingKey": "1", "type": "movie", "title": "Ein Film", "Image": [{"type": "coverPoster", "url": "/library/metadata/1/thumb/1"}] } """) #expect(decoded.clearLogoPath == nil) } @Test("Eine fehlende Bildliste ist kein Fehler") func missingImageList() throws { // Listen liefern keine Bildliste mit — nur die Einzelabfrage tut das. let decoded = try item(from: #"{"ratingKey": "1", "type": "movie", "title": "Ein Film"}"#) #expect(decoded.images.isEmpty) #expect(decoded.clearLogoPath == nil) } } @Suite("Empfänger und Sender") struct TunerDecodingTests { @Test("Sender werden aus dem Empfänger gelesen") func readsChannelsFromDevice() throws { // Der Fall, an dem „Keine Sender" hing: Plex liefert sie verschachtelt // in der Antwort auf /livetv/dvrs mit, nicht über einen eigenen // Endpunkt. let json = """ {"MediaContainer":{"Dvr":[{ "key": "1", "lineupTitle": "Kabel", "Device": [{ "key": "2", "uuid": "tuner-1", "title": "HDHomeRun", "Channel": [ {"id": 10, "channelIdentifier": "1.1", "title": "SRF 1 HD", "key": "/livetv/channel/1"}, {"id": 11, "channelIdentifier": "1.2", "title": "SRF zwei"} ] }] }]}} """ let container = try PlexResponse.decode( PlexMediaContainer.self, from: Data(json.utf8) ) let dvr = try #require(container.content.first) #expect(dvr.devices.count == 1) #expect(dvr.channels.count == 2) #expect(dvr.channels.first?.title == "SRF 1 HD") #expect(dvr.channels.first?.channelIdentifier == "1.1") } @Test("Auch die ältere Schreibweise ChannelMapping wird gelesen") func readsChannelMapping() throws { let json = """ {"MediaContainer":{"Dvr":[{ "key": "1", "Device": [{"uuid": "t", "ChannelMapping": [{"id": "a", "title": "3sat"}]}] }]}} """ let container = try PlexResponse.decode( PlexMediaContainer.self, from: Data(json.utf8) ) #expect(container.content.first?.channels.first?.title == "3sat") } @Test("Ein Empfänger ohne Sender ergibt eine leere Liste, keinen Fehler") func deviceWithoutChannels() throws { let json = #"{"MediaContainer":{"Dvr":[{"key":"1","Device":[{"uuid":"t"}]}]}}"# let container = try PlexResponse.decode( PlexMediaContainer.self, from: Data(json.utf8) ) #expect(container.content.first?.channels.isEmpty == true) } @Test("Ein Empfänger-Schlüssel als Zahl wird gelesen") func numericDVRKey() throws { // Je nach Serverfassung kommt er als Zahl oder als Zeichenkette. Ein // fester Typ hätte die ganze Empfängerliste unlesbar gemacht. let json = #"{"MediaContainer":{"Dvr":[{"key":42}]}}"# let container = try PlexResponse.decode( PlexMediaContainer.self, from: Data(json.utf8) ) #expect(container.content.first?.key == "42") } }