- ManaTheme.kollekta ergänzt (Label/Charakter/Signatur-App/-URL 1:1 aus dem Web-SOT packages/themes/src/index.ts), GeneratedThemes per Generator nachgezogen → 21 Apps ↔ 21 Themes - frischgruen-Primary (Nutriphi) dunkler: light 142 62% 31% → 64% 25%, dark 142 60% 52% → 58% 43% - ThemeTests-Snapshot auf 21 Variants aktualisiert (kollekta eingefügt) - CHANGELOG [Unreleased] ergänzt Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
121 lines
4.6 KiB
Swift
121 lines
4.6 KiB
Swift
import SwiftUI
|
|
import Testing
|
|
@testable import ManaTokens
|
|
|
|
@Suite("ManaTheme Variants")
|
|
struct ThemeTests {
|
|
@Test("Alle 21 Variants sind im enum vorhanden")
|
|
func allCasesPresent() {
|
|
// Explizite Snapshot-Liste: fängt versehentliche Renames/Entfernungen.
|
|
// Eine neue Variant (z. B. Theme-Pass-Signatur-App) muss hier bewusst
|
|
// nachgetragen werden — gewollte Friktion. Seit 2026-06-03: N Apps ↔
|
|
// N Themes, keine Baseline-Variants mehr (forest/neutral/monochrome
|
|
// entfernt, schaenke = Who-Signatur ergänzt). 2026-06-08: kollekta =
|
|
// Kollekta-Signatur ergänzt → 21.
|
|
let cases = ManaTheme.allCases.map(\.rawValue).sorted()
|
|
#expect(cases == [
|
|
"bodensee",
|
|
"buchseite",
|
|
"buehne",
|
|
"frischgruen",
|
|
"garderobe",
|
|
"herbar",
|
|
"hoerweg",
|
|
"kollekta",
|
|
"kreisel",
|
|
"lume",
|
|
"mana",
|
|
"panel",
|
|
"paper",
|
|
"pinnwand",
|
|
"schaenke",
|
|
"skylight",
|
|
"spektrum",
|
|
"twilight",
|
|
"waldlichtung",
|
|
"wegspur",
|
|
"wolke",
|
|
])
|
|
}
|
|
|
|
@Test("Jede Variant liefert nicht-leere Colors")
|
|
func everyVariantHasColors() {
|
|
for variant in ManaTheme.allCases {
|
|
let colors = variant.colors
|
|
// Existenz-Smoke — Color hat keinen Equatable-Color-Vergleich,
|
|
// aber wir können die Properties gegen Optional/Crash absichern.
|
|
let _: Color = colors.background
|
|
let _: Color = colors.foreground
|
|
let _: Color = colors.surface
|
|
let _: Color = colors.surfaceHover
|
|
let _: Color = colors.muted
|
|
let _: Color = colors.mutedForeground
|
|
let _: Color = colors.border
|
|
let _: Color = colors.primary
|
|
let _: Color = colors.primaryForeground
|
|
let _: Color = colors.error
|
|
let _: Color = colors.success
|
|
let _: Color = colors.warning
|
|
}
|
|
}
|
|
|
|
@Test("Convenience-Accessor matcht colors-Accessor")
|
|
func convenienceMatchesColors() {
|
|
// Identitäts-Smoke — beide Pfade müssen denselben Color-Wert liefern.
|
|
// Color ist nicht Equatable, also testen wir, dass es überhaupt
|
|
// möglich ist, beide Pfade typkorrekt zu nutzen.
|
|
let theme = ManaTheme.schaenke
|
|
let direct = theme.background
|
|
let viaColors = theme.colors.background
|
|
let _: (Color, Color) = (direct, viaColors)
|
|
}
|
|
|
|
@Test("schaenke.primary entspricht schaenke.css (10, 72, 42)")
|
|
func schaenkePrimaryMatchesSpec() {
|
|
// Wir rekonstruieren den erwarteten Light-Wert aus HSL und
|
|
// vergleichen mit dem, was `Color.manaToken` für denselben Input
|
|
// liefert. Da `Color`-Vergleich nicht direkt möglich ist, prüfen
|
|
// wir indirekt über PlatformColor.fromHSL.
|
|
let expected = PlatformColor.fromHSL(10, 72, 42)
|
|
let components = rgbComponents(of: expected)
|
|
// Schänke-Primary Light: HSL(10, 72, 42) → ~RGB(0.722, 0.218, 0.118)
|
|
#expect(approxEqual(components.r, 0.722, tolerance: 0.02))
|
|
#expect(approxEqual(components.g, 0.218, tolerance: 0.02))
|
|
#expect(approxEqual(components.b, 0.118, tolerance: 0.02))
|
|
}
|
|
|
|
@Test("ManaTheme ist via rawValue rekonstruierbar")
|
|
func rawValueRoundtrip() {
|
|
for variant in ManaTheme.allCases {
|
|
let raw = variant.rawValue
|
|
let roundtrip = ManaTheme(rawValue: raw)
|
|
#expect(roundtrip == variant)
|
|
}
|
|
}
|
|
|
|
@Test("Environment-Default ist mana")
|
|
func environmentDefault() {
|
|
// Wir können das Environment hier nicht direkt anzapfen ohne
|
|
// einen Host-View, aber wir spiegeln das Default per Konstante:
|
|
// ManaThemeEnvironmentKey.defaultValue ist auf .mana gesetzt.
|
|
// Smoke-Test, der die Konvention dokumentiert.
|
|
#expect(ManaTheme.allCases.contains(.mana))
|
|
}
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private func rgbComponents(of color: PlatformColor) -> (r: Double, g: Double, b: Double) {
|
|
#if canImport(UIKit)
|
|
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
|
|
color.getRed(&r, green: &g, blue: &b, alpha: &a)
|
|
return (Double(r), Double(g), Double(b))
|
|
#else
|
|
let space = color.usingColorSpace(.deviceRGB) ?? color
|
|
return (Double(space.redComponent), Double(space.greenComponent), Double(space.blueComponent))
|
|
#endif
|
|
}
|
|
|
|
private func approxEqual(_ a: Double, _ b: Double, tolerance: Double = 0.001) -> Bool {
|
|
abs(a - b) < tolerance
|
|
}
|