| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- import Foundation
- import Testing
- @testable import Trio
- @Suite("Trio Alerts: GlucoseAlertCoordinator breach/retract") struct GlucoseAlertCoordinatorTests {
- @Test("low breaches at or below threshold 70") func lowBreach() {
- #expect(GlucoseAlertCoordinator.breached(type: .low, latestMgDL: 70, thresholdMgDL: 70))
- #expect(!GlucoseAlertCoordinator.breached(type: .low, latestMgDL: 71, thresholdMgDL: 70))
- }
- @Test("low retracts only at threshold + margin (70 + 5)") func lowRetract() {
- #expect(!GlucoseAlertCoordinator.shouldRetract(
- type: .low, latestMgDL: 74, thresholdMgDL: 70, recoveryMarginMgDL: 5
- ))
- #expect(GlucoseAlertCoordinator.shouldRetract(
- type: .low, latestMgDL: 75, thresholdMgDL: 70, recoveryMarginMgDL: 5
- ))
- }
- @Test("urgentLow breaches at or below threshold 54") func urgentLowBreach() {
- #expect(GlucoseAlertCoordinator.breached(type: .urgentLow, latestMgDL: 54, thresholdMgDL: 54))
- #expect(!GlucoseAlertCoordinator.breached(type: .urgentLow, latestMgDL: 55, thresholdMgDL: 54))
- }
- @Test("high breaches at or above threshold 270") func highBreach() {
- #expect(GlucoseAlertCoordinator.breached(type: .high, latestMgDL: 270, thresholdMgDL: 270))
- #expect(!GlucoseAlertCoordinator.breached(type: .high, latestMgDL: 269, thresholdMgDL: 270))
- }
- @Test("high retracts only at threshold - margin (270 - 5)") func highRetract() {
- #expect(!GlucoseAlertCoordinator.shouldRetract(
- type: .high, latestMgDL: 266, thresholdMgDL: 270, recoveryMarginMgDL: 5
- ))
- #expect(GlucoseAlertCoordinator.shouldRetract(
- type: .high, latestMgDL: 265, thresholdMgDL: 270, recoveryMarginMgDL: 5
- ))
- }
- @Test("type priority order: urgentLow < low < forecastedLow < high < carbsRequired") func priorityOrder() {
- #expect(GlucoseAlertType.urgentLow.priority == 0)
- #expect(GlucoseAlertType.low.priority == 1)
- #expect(GlucoseAlertType.forecastedLow.priority == 2)
- #expect(GlucoseAlertType.high.priority == 3)
- #expect(GlucoseAlertType.carbsRequired.priority == 4)
- #expect(GlucoseAlertType.urgentLow.priority < GlucoseAlertType.low.priority)
- }
- @Test("shouldRetract uses the default 5 mg/dL margin when omitted") func defaultMarginWiring() {
- #expect(GlucoseAlertCoordinator.shouldRetract(type: .low, latestMgDL: 75, thresholdMgDL: 70))
- #expect(!GlucoseAlertCoordinator.shouldRetract(type: .low, latestMgDL: 74, thresholdMgDL: 70))
- }
- // MARK: - Carbs Required predicates (mg/dL-based gates are no-ops)
- /// Carbs Required is determination-driven (`evaluateCarbsRequired(_:)`),
- /// not reading-driven. The shared mg/dL `breached` predicate must never
- /// return true for it, regardless of value / threshold combination.
- @Test("carbsRequired never breaches via the mg/dL predicate") func carbsRequiredNeverBreaches() {
- #expect(!GlucoseAlertCoordinator.breached(type: .carbsRequired, latestMgDL: 0, thresholdMgDL: 0))
- #expect(!GlucoseAlertCoordinator.breached(type: .carbsRequired, latestMgDL: 200, thresholdMgDL: 10))
- #expect(!GlucoseAlertCoordinator.breached(type: .carbsRequired, latestMgDL: 10, thresholdMgDL: 200))
- }
- @Test("carbsRequired never retracts via the mg/dL predicate") func carbsRequiredNeverRetractsViaMgDL() {
- #expect(!GlucoseAlertCoordinator.shouldRetract(
- type: .carbsRequired, latestMgDL: 100, thresholdMgDL: 10, recoveryMarginMgDL: 5
- ))
- #expect(!GlucoseAlertCoordinator.shouldRetract(
- type: .carbsRequired, latestMgDL: 0, thresholdMgDL: 50, recoveryMarginMgDL: 5
- ))
- }
- }
|