Reine Umbenennung, kein Verhalten geändert — bewusst als eigener Commit, damit „umbenannt" und „umgebaut" im Nachhinein auseinanderzuhalten sind. 712 mal `Flixy`, 778 mal `flixy`, 7 mal `FLIXY` in 169 Dateien, dazu 25 Pfade. Ziele: `Halo`, `HaloTV`, `HaloTopShelf`, `HaloUITests`, `HaloKit` mit `HaloDesign`, `HaloDownloads`, `HaloPlayback` und `HaloProbe`. `MediaKit`, `JellyfinKit` und `DownloadWidget` tragen den Namen nicht und bleiben. `docs/superpowers/specs/` ist ausgenommen. Datierte Entwurfsdokumente sind ein Protokoll getroffener Entscheidungen; sie nachträglich umzuschreiben hiesse, die Vergangenheit zu glätten. **Die Bundle-ID wandert mit** — ausdrücklich so gewollt, mit bekanntem Preis: `com.scarriffleservices.halo` ist für iOS eine *andere* App. Die installierte Fassung bleibt daneben stehen, mit Downloads und Anmeldung in ihrem Container; Halo startet leer. Einmal neu anmelden, heruntergeladene Folgen einmal neu laden. Dasselbe gilt für die App-Gruppe, die sich TV-App und Top Shelf teilen. **Eine Folge davon, die beim Entscheiden noch nicht auf dem Tisch lag:** der Aufräumschritt aus dem vorigen Commit kommt an die alten Plex-Token nicht mehr heran. Der Schlüsselbund grenzt nach Team und Bundle-Kennung ab — was unter `…flixy` liegt, ist für `…halo` unerreichbar. Erledigt wird es trotzdem, nur anders: **die alte App löschen.** iOS räumt deren Schlüsselbund-Einträge beim Deinstallieren mit ab. Der Code bleibt stehen, weil er für jeden Stand vor dieser Umbenennung richtig ist und im Jahr einen Startvergleich kostet. Die Projektdatei ist aus `project.yml` neu erzeugt, der alte Ordner gelöscht statt umbenannt — sie steht ohnehin nicht im Repo. Das Verzeichnis des Repos selbst heißt weiter `Flixy`; das umzubenennen ist ein Handgriff ausserhalb des Projekts. 368 Tests grün. iOS und tvOS bauen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
105 lines
4.5 KiB
Swift
105 lines
4.5 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import MediaKit
|
|
|
|
private func hub(_ identifier: String) -> MediaRowGroup {
|
|
MediaRowGroup(id: identifier, title: identifier.capitalized)
|
|
}
|
|
|
|
@Suite("Anordnung der Startseiten-Reihen")
|
|
struct ArrangementTests {
|
|
private let serverHubs = [hub("continue"), hub("recent"), hub("watchlist"), hub("collections")]
|
|
|
|
@Test("Ohne Einstellungen bleibt die Reihenfolge des Servers")
|
|
func defaultKeepsServerOrder() {
|
|
let result = Arrangement().apply(to: serverHubs)
|
|
#expect(result.map(\.id) == ["continue", "recent", "watchlist", "collections"])
|
|
}
|
|
|
|
@Test("Ausgeblendete Reihen verschwinden")
|
|
func hiddenRowsAreRemoved() {
|
|
let arrangement = Arrangement(hidden: ["watchlist", "collections"])
|
|
let result = arrangement.apply(to: serverHubs)
|
|
#expect(result.map(\.id) == ["continue", "recent"])
|
|
}
|
|
|
|
@Test("Die gespeicherte Reihenfolge wird angewendet")
|
|
func storedOrderIsApplied() {
|
|
let arrangement = Arrangement(order: ["watchlist", "continue", "recent", "collections"])
|
|
let result = arrangement.apply(to: serverHubs)
|
|
#expect(result.map(\.id) == ["watchlist", "continue", "recent", "collections"])
|
|
}
|
|
|
|
@Test("Neue Reihen vom Server landen am Ende statt zu verschwinden")
|
|
func unknownRowsAppearAtTheEnd() {
|
|
// Der Fall, der die einfachere Regel — nur Bekanntes anzeigen — zur
|
|
// Falle macht: ein neu angelegtes Regal auf dem Server wäre in der App
|
|
// nie aufgetaucht, ohne dass jemand den Grund gesehen hätte.
|
|
let arrangement = Arrangement(order: ["recent", "continue"])
|
|
let result = arrangement.apply(to: serverHubs)
|
|
#expect(result.map(\.id) == ["recent", "continue", "watchlist", "collections"])
|
|
}
|
|
|
|
@Test("Mehrere neue Reihen behalten die Reihenfolge des Servers")
|
|
func multipleUnknownRowsKeepServerOrder() {
|
|
// Ohne stabile Rückfalllinie wäre ihre Anordnung zufällig — und
|
|
// änderte sich bei jedem Start.
|
|
let arrangement = Arrangement(order: ["collections"])
|
|
let result = arrangement.apply(to: serverHubs)
|
|
#expect(result.map(\.id) == ["collections", "continue", "recent", "watchlist"])
|
|
}
|
|
|
|
@Test("Gespeicherte Reihen, die es nicht mehr gibt, stören nicht")
|
|
func staleOrderEntriesAreIgnored() {
|
|
// Entsteht beim Löschen einer Mediathek auf dem Server.
|
|
let arrangement = Arrangement(order: ["geloescht", "recent", "continue"])
|
|
let result = arrangement.apply(to: serverHubs)
|
|
#expect(result.map(\.id) == ["recent", "continue", "watchlist", "collections"])
|
|
}
|
|
|
|
@Test("Ein doppelter Eintrag in der Reihenfolge stürzt nicht ab")
|
|
func duplicateOrderEntriesAreTolerated() {
|
|
// Kann nach einem abgebrochenen Schreibvorgang entstehen. Ein
|
|
// Dictionary aus doppelten Schlüsseln wäre ein harter Absturz.
|
|
let arrangement = Arrangement(order: ["recent", "recent", "continue"])
|
|
let result = arrangement.apply(to: serverHubs)
|
|
#expect(result.first?.id == "recent")
|
|
#expect(result.count == 4)
|
|
}
|
|
|
|
@Test("Ausblenden und Sortieren greifen zusammen")
|
|
func hidingAndOrderingCombine() {
|
|
let arrangement = Arrangement(
|
|
hidden: ["recent"],
|
|
order: ["collections", "recent", "continue"]
|
|
)
|
|
let result = arrangement.apply(to: serverHubs)
|
|
#expect(result.map(\.id) == ["collections", "continue", "watchlist"])
|
|
}
|
|
|
|
// MARK: - Die Liste für die Einstellungen
|
|
|
|
@Test("Der Einstellungsbildschirm zeigt Gespeichertes zuerst")
|
|
func settingsListPutsStoredFirst() {
|
|
let arrangement = Arrangement(order: ["watchlist", "continue"])
|
|
let identifiers = arrangement.arrangedIdentifiers(from: serverHubs)
|
|
#expect(identifiers == ["watchlist", "continue", "recent", "collections"])
|
|
}
|
|
|
|
@Test("Der Einstellungsbildschirm zeigt auch ausgeblendete Reihen")
|
|
func settingsListIncludesHidden() {
|
|
// Sonst ließe sich eine einmal ausgeblendete Reihe nie wieder
|
|
// einschalten — eine Einbahnstraße.
|
|
let arrangement = Arrangement(hidden: ["recent"])
|
|
let identifiers = arrangement.arrangedIdentifiers(from: serverHubs)
|
|
#expect(identifiers.contains("recent"))
|
|
}
|
|
|
|
@Test("Verschwundene Reihen erscheinen nicht in den Einstellungen")
|
|
func settingsListDropsStaleEntries() {
|
|
let arrangement = Arrangement(order: ["geloescht", "recent"])
|
|
let identifiers = arrangement.arrangedIdentifiers(from: serverHubs)
|
|
#expect(!identifiers.contains("geloescht"))
|
|
}
|
|
}
|