import Foundation import Testing @testable import PlexKit @Suite("Anmelde-Adresse") struct AuthorizationURLTests { private let pin = PlexPin(id: 42, code: "5474") private func url() throws -> URL { try #require(pin.authorizationURL(clientIdentifier: "abc-123", product: "Flixy")) } @Test("Die Klammern der Kontext-Parameter werden nicht doppelt kodiert") func bracketsAreEncodedExactlyOnce() throws { // Der Fehler, der plex.tv „Diese Anfrage konnte nicht abgeschlossen // werden" antworten ließ: eine bereits kodierte Klammer (%5B) wurde // beim Setzen des Fragments ein zweites Mal kodiert (%255B). Plex sah // dann einen Parameter namens „context%5Bdevice%5D…" statt // „context[device]…" und konnte nichts damit anfangen. let text = try url().absoluteString #expect(!text.contains("%25"), "doppelt kodiert: \(text)") #expect(text.contains("context%5Bdevice%5D%5Bproduct%5D=Flixy")) } @Test("Code und Client-Kennung stehen im Fragment") func carriesCodeAndClient() throws { let text = try url().absoluteString #expect(text.hasPrefix("https://app.plex.tv/auth#?")) #expect(text.contains("clientID=abc-123")) #expect(text.contains("code=5474")) } @Test("Produktnamen mit Leerzeichen werden kodiert") func productNamesWithSpacesAreEncoded() throws { // Der Name steht noch nicht fest. Wird daraus „Flixy Player", darf // das Leerzeichen die Adresse nicht zerreißen. let url = try #require(pin.authorizationURL(clientIdentifier: "abc", product: "Flixy Player")) #expect(url.absoluteString.contains("Flixy%20Player")) #expect(!url.absoluteString.contains("Flixy Player")) } } @Suite("Anmelde-Adresse mit Rücksprung") struct AuthorizationForwardURLTests { private let pin = PlexPin(id: 42, code: "5474") @Test("Ohne Rückadresse bleibt die Adresse wie bisher") func withoutForwardURL() throws { let url = try #require(pin.authorizationURL(clientIdentifier: "abc", product: "Flixy")) #expect(!url.absoluteString.contains("forwardUrl")) } @Test("Die Rückadresse wird angehängt und kodiert") func forwardURLIsAppendedAndEncoded() throws { // Das Schema enthält Doppelpunkte und Schrägstriche. Unkodiert // zerrissen sie die Adresse, und Plex führte den Rücksprung nie aus — // das Anmeldefenster bliebe offen stehen. let url = try #require(pin.authorizationURL( clientIdentifier: "abc", product: "Flixy", forwardURL: URL(string: "com.scarriffleservices.flixy://auth")! )) let text = url.absoluteString #expect(text.contains("forwardUrl=com.scarriffleservices.flixy%3A%2F%2Fauth")) #expect(!text.contains("%25")) } @Test("Die übrigen Parameter bleiben unversehrt") func otherParametersSurvive() throws { let url = try #require(pin.authorizationURL( clientIdentifier: "abc", product: "Flixy", forwardURL: URL(string: "flixy://auth")! )) let text = url.absoluteString #expect(text.contains("clientID=abc")) #expect(text.contains("code=5474")) #expect(text.contains("context%5Bdevice%5D%5Bproduct%5D=Flixy")) } } @Suite("Verknüpfungsseite") struct LinkURLTests { @Test("Der Code steht in der Adresse") func carriesTheCode() throws { let pin = PlexPin(id: 1, code: "S6J9") let url = try #require(pin.linkURL) #expect(url.absoluteString == "https://plex.tv/link/?pin=S6J9") } @Test("Sonderzeichen im Code werden kodiert") func encodesUnusualCodes() throws { // Kurze Codes sind alphanumerisch, aber darauf verlassen möchte ich // mich nicht — ein ungeschütztes `&` würde die Adresse zerreißen. let pin = PlexPin(id: 1, code: "A&B=C") let url = try #require(pin.linkURL) #expect(!url.absoluteString.contains("&B")) #expect(url.absoluteString.contains("A%26B%3DC")) } }