Sie auszublenden reichte nicht: solange `mode` auf `tabSidebar` steht, gehört die Seitenleiste zur Darstellung, und das System stellte sie wieder her — mit eigenem Pfeil und eigenem Knopf, hinter unserer. Auf dem Simulator fiel das nicht auf, auf dem Mac standen beide da. Jetzt wird erst die Form auf `tabBar` gestellt und dann die Tableiste ausgeblendet. Damit gibt es keine Seitenleiste mehr, die zurückkommen könnte. Der Test setzt die Stellung der Leiste über ein Startargument, statt zu nehmen, was ein voriger Lauf hinterlassen hat — er fing sonst beim falschen Bild an. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
100 lines
4.2 KiB
Swift
100 lines
4.2 KiB
Swift
import XCTest
|
|
|
|
/// Fährt die App in die Zustände, über die geredet wird, und legt Bilder davon ab.
|
|
///
|
|
/// Der Grund für diese Datei ist ein wiederkehrender Fehler: Aussagen über das
|
|
/// Aussehen waren Vermutungen, weil niemand hinsehen konnte. Der Simulator
|
|
/// kennt keinen Befehl fürs Antippen, und dieses Xcode bringt kein
|
|
/// Simulator-Fenster mehr mit, das sich fernsteuern ließe. Ein UI-Test kann
|
|
/// beides — tippen und fotografieren.
|
|
///
|
|
/// Die Bilder landen im Dokumentenordner des Testläufers, der vom Rechner aus
|
|
/// über `simctl get_app_container` erreichbar ist. Anhänge im Ergebnisbündel
|
|
/// wären der vorgesehene Weg, müssten aber erst wieder herausgeschält werden.
|
|
///
|
|
/// Die Inhalte kommen aus `Tools/JellyfinStub` — kein echter Server, kein
|
|
/// echtes Konto, kein echter Token.
|
|
final class LayoutSnapshots: XCTestCase {
|
|
override func setUp() {
|
|
continueAfterFailure = false
|
|
}
|
|
|
|
/// `XCUIScreen` fotografiert in der Lage des **Geräts**, nicht in der der
|
|
/// Oberfläche — im Querformat kommt das Bild dann hochkant und um
|
|
/// neunzig Grad gedreht heraus, und jedes Maß daran ist falsch herum.
|
|
/// Die App selbst fotografiert richtig herum.
|
|
private func shoot(_ app: XCUIApplication, _ name: String) {
|
|
let data = app.screenshot().pngRepresentation
|
|
let folder = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
|
try? data.write(to: folder.appendingPathComponent("\(name).png"))
|
|
}
|
|
|
|
/// Das Umschalten zwischen Seitenleiste und Leiste oben.
|
|
///
|
|
/// Beim Umschalten steht die Leiste kurz falsch, bevor sie sich fängt.
|
|
/// Fotografiert wird in Serie, weil genau der Zwischenzustand gesucht ist
|
|
/// und ein einzelnes Bild danach nichts zeigt.
|
|
func testSidebarToggle() throws {
|
|
let app = XCUIApplication()
|
|
// Die Stellung der Leiste wird gespeichert, und ein voriger Lauf hat
|
|
// sie womöglich umgestellt. Ein Startargument überschreibt sie, damit
|
|
// jeder Lauf beim selben Bild anfängt.
|
|
app.launchArguments = [
|
|
"-FlixyStubServer", "http://127.0.0.1:8096",
|
|
"-flixy.navigation.placement", "sidebar",
|
|
]
|
|
app.launch()
|
|
|
|
XCUIDevice.shared.orientation = .landscapeLeft
|
|
XCTAssertTrue(app.staticTexts["Weiterschauen"].waitForExistence(timeout: 20))
|
|
Thread.sleep(forTimeInterval: 2)
|
|
shoot(app, "10-seitenleiste")
|
|
|
|
// Über die Beschriftung gesucht, nicht über die Stellung: „der zweite
|
|
// Knopf" war einmal der Umschalter und nach einem Umbau die Kontozeile,
|
|
// und der Test öffnete fortan das Kontomenü.
|
|
let toggle = app.buttons["Navigation nach oben"]
|
|
XCTAssertTrue(toggle.waitForExistence(timeout: 5))
|
|
toggle.tap()
|
|
|
|
for step in 0..<8 {
|
|
shoot(app, String(format: "11-umschalten-%d", step))
|
|
Thread.sleep(forTimeInterval: 0.1)
|
|
}
|
|
Thread.sleep(forTimeInterval: 2)
|
|
shoot(app, "12-oben")
|
|
}
|
|
|
|
func testHomeAndDetail() throws {
|
|
let app = XCUIApplication()
|
|
// Die Stellung der Leiste wird gespeichert, und ein voriger Lauf hat
|
|
// sie womöglich umgestellt. Ein Startargument überschreibt sie, damit
|
|
// jeder Lauf beim selben Bild anfängt.
|
|
app.launchArguments = [
|
|
"-FlixyStubServer", "http://127.0.0.1:8096",
|
|
"-flixy.navigation.placement", "sidebar",
|
|
]
|
|
app.launch()
|
|
|
|
XCUIDevice.shared.orientation = .landscapeLeft
|
|
|
|
// Die Startseite muss stehen, bevor fotografiert wird — sonst ist auf
|
|
// dem Bild nur der Ladekreis.
|
|
XCTAssertTrue(app.staticTexts["Weiterschauen"].waitForExistence(timeout: 20))
|
|
Thread.sleep(forTimeInterval: 3)
|
|
shoot(app, "01-start-oben")
|
|
|
|
// Der Aufmacher wechselt nach sieben Sekunden. Kurz davor anfangen
|
|
// und in Serie fotografieren: nur so ist der Übergang selbst zu sehen
|
|
// und nicht bloß sein Ergebnis.
|
|
Thread.sleep(forTimeInterval: 4.2)
|
|
for step in 0..<6 {
|
|
shoot(app, String(format: "02-wechsel-%d", step))
|
|
Thread.sleep(forTimeInterval: 0.12)
|
|
}
|
|
|
|
Thread.sleep(forTimeInterval: 2)
|
|
shoot(app, "03-danach")
|
|
}
|
|
}
|