Files
TUIkit/Tests/TUIkitTests/PreferenceStorageTests.swift
T
phranck f880208a05 Test: Add 140 tests for Core systems (H.8 Phase 2)
- PredefinedPaletteTests: Green, Amber, White, Red, NCurses palettes (12)
- PaletteDefaultTests: Protocol default implementations (12)
- GeneratedPaletteTests: Hue-based palette generation (7)
- PaletteRegistryTests: Registry lookup and cycling order (6)
- ThemeManagerCyclingTests: cycleNext/Previous, setCurrent, typed accessors (12)
- KeyEventTests: Key enum, KeyEvent creation, parse() for all input types (38)
- KeyEventDispatcherTests: Handler registration, reverse dispatch, cleanup (6)
- AppStateTests: Render flag, observer notification (6)
- BindingTests: Get/set, projectedValue, constant (6)
- StatePropertyTests: Initial value, mutation, render trigger, binding (8)
- PreferenceKeyTests: Default and custom reduce implementations (3)
- PreferenceValuesTests: Subscript access, merge behavior (6)
- PreferenceStorageTests: Stack push/pop, setValue, callbacks, reset (12)
- NavigationTitleKeyTests: Built-in preference key (3)

Each suite in its own file (14 new files). One suite per file convention.
Total: 288 → 428 tests (+140 new)
2026-01-30 22:18:26 +01:00

148 lines
4.9 KiB
Swift

//
// PreferenceStorageTests.swift
// TUIkit
//
// Tests for PreferenceStorage: stack behavior, setValue with reduce,
// callbacks, beginRenderPass, and reset.
//
import Testing
@testable import TUIkit
/// String preference key for storage tests.
private struct StorageStringKey: PreferenceKey {
static let defaultValue: String = "default"
}
/// Additive counter preference key for storage tests.
private struct StorageCounterKey: PreferenceKey {
static let defaultValue: Int = 0
static func reduce(value: inout Int, nextValue: () -> Int) {
value += nextValue()
}
}
@Suite("PreferenceStorage Tests")
struct PreferenceStorageTests {
@Test("New storage has default values")
func newStorageDefaults() {
let storage = PreferenceStorage()
#expect(storage.current[StorageStringKey.self] == "default")
}
@Test("setValue stores value")
func setValueStores() {
let storage = PreferenceStorage()
storage.setValue("hello", forKey: StorageStringKey.self)
#expect(storage.current[StorageStringKey.self] == "hello")
}
@Test("setValue with additive reduce accumulates")
func setValueAccumulates() {
let storage = PreferenceStorage()
storage.setValue(5, forKey: StorageCounterKey.self)
storage.setValue(3, forKey: StorageCounterKey.self)
#expect(storage.current[StorageCounterKey.self] == 8)
}
@Test("Push creates new context")
func pushNewContext() {
let storage = PreferenceStorage()
storage.setValue("outer", forKey: StorageStringKey.self)
storage.push()
#expect(storage.current[StorageStringKey.self] == "default")
}
@Test("Pop merges into parent")
func popMerges() {
let storage = PreferenceStorage()
storage.push()
storage.setValue("inner", forKey: StorageStringKey.self)
_ = storage.pop()
#expect(storage.current[StorageStringKey.self] == "inner")
}
@Test("Nested push/pop preserves outer values")
func nestedPushPop() {
let storage = PreferenceStorage()
storage.setValue("outer", forKey: StorageStringKey.self)
storage.push()
storage.setValue("inner", forKey: StorageStringKey.self)
_ = storage.pop()
#expect(storage.current[StorageStringKey.self] == "inner")
}
@Test("Multiple nested levels work correctly")
func multipleNesting() {
let storage = PreferenceStorage()
storage.setValue(1, forKey: StorageCounterKey.self)
storage.push()
storage.setValue(2, forKey: StorageCounterKey.self)
storage.push()
storage.setValue(3, forKey: StorageCounterKey.self)
_ = storage.pop()
_ = storage.pop()
#expect(storage.current[StorageCounterKey.self] != 0)
}
@Test("Pop on single context returns current values")
func popSingleContext() {
let storage = PreferenceStorage()
storage.setValue("value", forKey: StorageStringKey.self)
let popped = storage.pop()
#expect(popped[StorageStringKey.self] == "value")
#expect(storage.current[StorageStringKey.self] == "value")
}
@Test("onPreferenceChange callback is triggered")
func changeCallback() {
let storage = PreferenceStorage()
nonisolated(unsafe) var received: String?
storage.onPreferenceChange(StorageStringKey.self) { value in
received = value
}
storage.setValue("updated", forKey: StorageStringKey.self)
#expect(received == "updated")
}
@Test("Multiple callbacks for same key all fire")
func multipleCallbacks() {
let storage = PreferenceStorage()
nonisolated(unsafe) var count = 0
storage.onPreferenceChange(StorageStringKey.self) { _ in count += 1 }
storage.onPreferenceChange(StorageStringKey.self) { _ in count += 1 }
storage.setValue("trigger", forKey: StorageStringKey.self)
#expect(count == 2)
}
@Test("beginRenderPass resets callbacks and stack")
func beginRenderPass() {
let storage = PreferenceStorage()
storage.setValue("old", forKey: StorageStringKey.self)
nonisolated(unsafe) var callbackFired = false
storage.onPreferenceChange(StorageStringKey.self) { _ in callbackFired = true }
storage.beginRenderPass()
#expect(storage.current[StorageStringKey.self] == "default")
storage.setValue("new", forKey: StorageStringKey.self)
#expect(callbackFired == false)
}
@Test("reset clears everything")
func resetClears() {
let storage = PreferenceStorage()
storage.setValue("data", forKey: StorageStringKey.self)
storage.push()
storage.setValue(42, forKey: StorageCounterKey.self)
storage.reset()
#expect(storage.current[StorageStringKey.self] == "default")
#expect(storage.current[StorageCounterKey.self] == 0)
}
}