Files
onyx/Packages/OnyxKit/Tests/OnyxNotchTests/WallpaperIndexTests.swift
Scarriffle c6f0a5a848 Vorschau liest macOS' eigene Hintergrundverwaltung
NSWorkspace.desktopImageURL ist die alte Schnittstelle: sie meldet das letzte
Bild, das als Datei gesetzt wurde — auch dann noch, wenn es längst gelöscht
ist. Genau das war hier der Fall, der Pfad zeigt auf eine Datei, die es nicht
mehr gibt. Seit macOS 14 führt das System die Auswahl in
com.apple.wallpaper/Store/Index.plist, je Bildschirm und je Schreibtisch, und
Anbieter wie Fotos hinterlegen dort ihre Zwischenspeicher.

Die Datei ist doppelt verpackt: die Konfiguration je Bildschirm steckt als
eigene Property-Liste in einem Datenfeld der äußeren. Ohne den zweiten
Durchgang findet man gar nichts.

Gelesen wird nur der Eintrag dieses Bildschirms, nachgeschlagen über die
Display-Kennung. In der Datei stehen auch alte Bildschirme, der
Bildschirmschoner und alles, was einmal gesetzt war — das Neueste von allem zu
nehmen führt zuverlässig zu einem Bild, das mit dem Schreibtisch nichts zu tun
hat. Ausprobiert: dabei kam ein weißes Platzhalterbild aus einem Kurzbefehl
heraus. Fehlt der Eintrag oder die Datei, ist ein Systembild die ehrlichere
Antwort als ein Rateergebnis.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 00:08:44 +02:00

78 lines
3.2 KiB
Swift

import Testing
import Foundation
@testable import OnyxNotch
@Suite("Hintergrundbild aus macOS' Verwaltung")
struct WallpaperIndexTests {
/// Baut einen Eintrag, wie ihn macOS ablegt.
private func entry(_ path: String) -> [String: Any] {
["type": "imageFile", "url": ["relative": "file://" + path]]
}
private func nested(_ value: Any) throws -> Data {
try PropertyListSerialization.data(fromPropertyList: value, format: .binary, options: 0)
}
@Test("Ein Bild in der äußeren Liste wird gefunden")
func findsPlainEntry() {
var found: [URL] = []
WallpaperLoader.collectImageFiles(["Desktop": entry("/tmp/a.jpg")], into: &found)
#expect(found.map(\.path) == ["/tmp/a.jpg"])
}
@Test("Ein Bild in einer verschachtelten Liste wird auch gefunden")
func findsNestedEntry() throws {
// Genau daran hängt es: die Konfiguration je Bildschirm steckt als
// eigene Property-Liste in einem Datenfeld der äußeren.
var found: [URL] = []
let inner = try nested(entry("/tmp/b.jpg"))
WallpaperLoader.collectImageFiles(
["Displays": ["ABC": ["Desktop": ["Configuration": inner]]]], into: &found)
#expect(found.map(\.path) == ["/tmp/b.jpg"])
}
@Test("Mehrere Bildschirme ergeben mehrere Bilder")
func findsAllScreens() throws {
var found: [URL] = []
WallpaperLoader.collectImageFiles(
["Displays": ["A": try nested(entry("/tmp/a.jpg")),
"B": try nested(entry("/tmp/b.jpg"))]], into: &found)
#expect(Set(found.map(\.path)) == ["/tmp/a.jpg", "/tmp/b.jpg"])
}
@Test("Einträge ohne Datei bleiben liegen")
func ignoresNonFileEntries() {
// Fotos und Aerials stehen als asset" mit einer Kennung darin daraus
// lässt sich keine Datei machen, und ein Eintrag ohne Datei darf nicht
// als Bild durchgehen.
var found: [URL] = []
WallpaperLoader.collectImageFiles(
["Idle": ["type": "asset", "identifier": "3316307E-788F"],
"Web": ["type": "imageFile", "url": ["relative": "https://example.com/a.jpg"]]],
into: &found)
#expect(found.isEmpty)
}
@Test("Nur der eigene Bildschirm zählt")
func onlyOwnScreenCounts() throws {
// In der Datei stehen auch alte Bildschirme und der Bildschirmschoner.
// Das Neueste von allem zu nehmen führt zuverlässig zu einem Bild, das
// mit dem Schreibtisch nichts zu tun hat gemessen war das hier ein
// weißes Platzhalterbild aus einem Kurzbefehl.
var found: [URL] = []
let entry: [String: Any] = ["Desktop": ["Content": ["Choices": [
["Configuration": try nested(entry("/tmp/richtig.jpg"))]]]]]
WallpaperLoader.collectImageFiles(entry["Desktop"] as Any, into: &found)
#expect(found.map(\.path) == ["/tmp/richtig.jpg"])
}
@Test("Unbrauchbare Daten stürzen nicht ab")
func survivesGarbage() {
var found: [URL] = []
WallpaperLoader.collectImageFiles(
["A": Data("bplist00 aber kaputt".utf8), "B": 42, "C": Date()], into: &found)
#expect(found.isEmpty)
}
}