e9c16325cc
Musterseite entfernt (companion-app/muster, vite.muster.config.ts, /config/www/dmmuster). Ansage des Eigentuemers: sie fuehrt nur zu neuen Fehlerquellen. Ausloeser war ein Befund, den ich als App-Fehler gemeldet hatte - Ringe und Typenschild schwarz auf schwarz - und der nur dort bestand. Behoben: * Das Zahnrad im Autohaus-Kasten hatte seine Ecke verlassen (58/288 statt 8/8). Ursache war mein HIG-Durchgang von gestern: .zahnrad kam in die Gruppe fuer die 44x44-Trefferflaeche und bekam damit position:relative, was das absolute aus dem Basisblatt ueberschrieb. Die Auflage war ueberfluessig - .zahnrad ist dort schon 44x44. * Das Fotomenue hing mit position:absolute an der Kachel statt am Bildschirm und lag bei der hohen Raeder-Kachel ausserhalb des Sichtfelds; einen Abbrechen-Knopf hatte es nie. Das Panel benutzt jetzt dasselbe Aktionsblatt wie die App. .bildmenu ist samt Zustand, Markup, totem Handler und CSS entfernt. * Der Blattkopf las sich als dritte Auswahl (linksbuendig, 15px, --fg). Jetzt zentriert, 13px, gedaempft - Apples Muster, in beiden Codebasen. * "Anstehende Termine" stand 5px ueber "Oelwechsel" und wirkte als dessen Beischrift. Entfernt. * Wartungsplan-Formular: Art nach oben, Datum 124px statt Browser-Vorgabe, Werkstatt ueber die volle Zeile (218 -> 306px), Kosten 116px. Zwei Erklaertexte entfernt. * Thema folgt jetzt einer Systemumstellung im laufenden Betrieb. Vorher las es prefers-color-scheme genau einmal beim Laden. Drei Tests, die ohne die Behebung nachweislich fallen. Geprueft: 295 App-Tests, Panel node --check, 0 Tracebacks, alle Aenderungen live an der Testinstanz gemessen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
98 lines
3.3 KiB
TypeScript
98 lines
3.3 KiB
TypeScript
/**
|
|
* Der Startwert des Themas wird beim Laden des Moduls **einmal** aus der
|
|
* Ablage gelesen und danach im Speicher gehalten — das verlangt
|
|
* `useSyncExternalStore`, dessen Momentaufnahme zwischen zwei Änderungen
|
|
* stabil sein muss (siehe theme.ts).
|
|
*
|
|
* Deshalb muss jeder Fall das Modul frisch laden, statt die Ablage zu
|
|
* beschreiben und dieselbe Instanz erneut zu fragen. Das ist keine
|
|
* Umständlichkeit des Tests, sondern genau das, was in der App passiert: die
|
|
* gespeicherte Wahl wirkt beim Start.
|
|
*/
|
|
|
|
import { beforeEach, describe, expect, it, vi } from "vitest"
|
|
|
|
async function startwertNachLaden(): Promise<string> {
|
|
vi.resetModules()
|
|
const { themeStartwert } = await import("./theme")
|
|
return themeStartwert()
|
|
}
|
|
|
|
describe("Theme", () => {
|
|
beforeEach(() => {
|
|
localStorage.clear()
|
|
})
|
|
|
|
it("startet ohne gespeicherte Wahl im Nachtmodus", async () => {
|
|
expect(await startwertNachLaden()).toBe("nacht")
|
|
})
|
|
|
|
it("übernimmt eine gespeicherte Wahl", async () => {
|
|
localStorage.setItem("dm360.theme", "tag")
|
|
expect(await startwertNachLaden()).toBe("tag")
|
|
})
|
|
|
|
it("ignoriert unsinnige gespeicherte Werte", async () => {
|
|
localStorage.setItem("dm360.theme", "irgendwas")
|
|
expect(await startwertNachLaden()).toBe("nacht")
|
|
})
|
|
|
|
})
|
|
|
|
/* Stellt das Gerät im laufenden Betrieb um - etwa durch die automatische
|
|
Umschaltung bei Sonnenuntergang -, muss das Thema folgen. Bis zum
|
|
05.09.2026 las theme.ts die Systemeinstellung genau einmal beim Laden des
|
|
Moduls und horchte danach nie wieder; ein Wechsel wirkte erst nach dem
|
|
nächsten Neuladen. */
|
|
describe("Systemumstellung im laufenden Betrieb", () => {
|
|
function medienabfrageStellen(dunkel: boolean) {
|
|
const horcher: (() => void)[] = []
|
|
const stand = { dunkel }
|
|
// matches als Getter, nicht als kopierter Wert: theme.ts haelt die
|
|
// Abfrage vom Laden fest und liest matches erst im Horcher wieder.
|
|
vi.stubGlobal("matchMedia", (text: string) => ({
|
|
get matches() {
|
|
return text.includes("dark") ? stand.dunkel : !stand.dunkel
|
|
},
|
|
addEventListener: (_art: string, bei: () => void) => horcher.push(bei),
|
|
removeEventListener: () => {},
|
|
}))
|
|
return {
|
|
umstellenAuf(neuDunkel: boolean) {
|
|
stand.dunkel = neuDunkel
|
|
for (const bei of horcher) bei()
|
|
},
|
|
}
|
|
}
|
|
|
|
beforeEach(() => {
|
|
localStorage.clear()
|
|
vi.resetModules()
|
|
})
|
|
|
|
it("folgt dem Wechsel nach hell, ohne neu zu laden", async () => {
|
|
const system = medienabfrageStellen(true)
|
|
const { themeStartwert } = await import("./theme")
|
|
expect(themeStartwert()).toBe("nacht")
|
|
system.umstellenAuf(false)
|
|
expect(themeStartwert()).toBe("tag")
|
|
})
|
|
|
|
it("folgt dem Wechsel nach dunkel, ohne neu zu laden", async () => {
|
|
const system = medienabfrageStellen(false)
|
|
const { themeStartwert } = await import("./theme")
|
|
expect(themeStartwert()).toBe("tag")
|
|
system.umstellenAuf(true)
|
|
expect(themeStartwert()).toBe("nacht")
|
|
})
|
|
|
|
it("lässt eine selbst getroffene Wahl unangetastet", async () => {
|
|
localStorage.setItem("dm360.theme", "tag")
|
|
const system = medienabfrageStellen(false)
|
|
const { themeStartwert } = await import("./theme")
|
|
expect(themeStartwert()).toBe("tag")
|
|
system.umstellenAuf(true)
|
|
expect(themeStartwert()).toBe("tag")
|
|
})
|
|
})
|