Christopher Hotchkiss Christopher Hotchkiss
Login

Code

remindwall / RWPureSwift / Tests / EditSettingsNewTests / TopLevel / BatterySettingsTests.swift

Back to remindwall — Current RemindWall

Download this file

import AppTypes
import ComposableArchitecture
import Dao
import DependenciesTestSupport
import Foundation
import HomeKitAsync
import Testing

@testable import EditSettingsNew_TopLevel

@MainActor
@Suite("BatterySettings Feature Tests", .dependencies {
    $0.defaultDatabase = try! $0.appDatabase()
    $0.uuid = .incrementing
    $0.date = .constant(Date(timeIntervalSince1970: 0))
})
struct BatterySettingsTests {

    @Test("threshold writes and clamps to 5-50")
    func threshold() async {
        let store = TestStore(initialState: BatterySettingsFeature.State()) {
            BatterySettingsFeature()
        }

        await store.send(.thresholdChanged(35)) {
            $0.$thresholdPercent.withLock { $0 = 35 }
        }
        await store.send(.thresholdChanged(0)) {
            $0.$thresholdPercent.withLock { $0 = 5 }
        }
        await store.send(.thresholdChanged(95)) {
            $0.$thresholdPercent.withLock { $0 = 50 }
        }
    }

    @Test("window toggle flips between nil (always) and the default window")
    func windowToggle() async {
        let store = TestStore(initialState: BatterySettingsFeature.State()) {
            BatterySettingsFeature()
        }

        await store.send(.windowedToggled(true)) {
            $0.$window.withLock { $0 = .default }
        }
        await store.send(.setWindowStart(hour: 8, minute: 30)) {
            $0.$window.withLock { $0 = AlertWindow.default.withStart(hour: 8, minute: 30) }
        }
        await store.send(.windowedToggled(false)) {
            $0.$window.withLock { $0 = nil }
        }
    }

    @Test("refresh loads and sorts discovered batteries lowest-first")
    func refreshDiscovers() async {
        let store = TestStore(initialState: BatterySettingsFeature.State()) {
            BatterySettingsFeature()
        } withDependencies: {
            $0.homeKitAsync.batteryStatuses = {
                [
                    BatteryStatus(id: UUID(0), accessoryName: "Thermostat", roomName: "Bedroom", levelPercent: 76, isLow: false),
                    BatteryStatus(id: UUID(1), accessoryName: "Door Sensor", roomName: "Entry", levelPercent: 8, isLow: true),
                ]
            }
        }

        await store.send(.refreshBatteries) {
            $0.isLoadingBatteries = true
        }
        await store.receive(\._batteriesLoaded) {
            $0.isLoadingBatteries = false
            $0.discovered = [
                BatteryStatus(id: UUID(1), accessoryName: "Door Sensor", roomName: "Entry", levelPercent: 8, isLow: true),
                BatteryStatus(id: UUID(0), accessoryName: "Thermostat", roomName: "Bedroom", levelPercent: 76, isLow: false),
            ]
        }
    }

    @Test("summary compresses the config into one row")
    func summaryLine() async {
        let state = BatterySettingsFeature.State()
        #expect(state.summary == "Below 20% · always")

        state.$window.withLock { $0 = .default }
        state.$ignored.withLock { $0 = BatteryIgnoreList.empty.toggling("Doorbell") }
        #expect(state.summary == "Below 20% · MTWTF · 6:30 AM–9:00 AM · 1 ignored")
    }

    @Test("detail sheet presentation round-trips")
    func detailPresentation() async {
        let store = TestStore(initialState: BatterySettingsFeature.State()) {
            BatterySettingsFeature()
        }

        await store.send(.setDetailPresented(true)) {
            $0.isDetailPresented = true
        }
        await store.send(.setDetailPresented(false)) {
            $0.isDetailPresented = false
        }
    }

    @Test("ignore toggling round-trips through the synced list")
    func ignoreToggle() async {
        let store = TestStore(initialState: BatterySettingsFeature.State()) {
            BatterySettingsFeature()
        }

        await store.send(.ignoreToggled(accessoryName: "Front Door")) {
            $0.$ignored.withLock { $0 = BatteryIgnoreList(rawValue: #"["Front Door"]"#) }
        }
        #expect(store.state.ignored.contains("Front Door"))

        await store.send(.ignoreToggled(accessoryName: "Front Door")) {
            $0.$ignored.withLock { $0 = .empty }
        }
        #expect(!store.state.ignored.contains("Front Door"))
    }

    @Test("onAppear kicks off a browser refresh")
    func onAppearRefreshes() async {
        let store = TestStore(initialState: BatterySettingsFeature.State()) {
            BatterySettingsFeature()
        } withDependencies: {
            $0.homeKitAsync.batteryStatuses = { [] }
        }
        store.exhaustivity = .off

        await store.send(.onAppear)
        await store.receive(\._batteriesLoaded)
    }
}