Преглед изворни кода

Test: TrioAlertCategory severity + dwell mapping

Exhaustively pin interruptionLevel for every category (so a re-bucketing
that demotes a critical pump/glucose alert out of .critical fails the test)
and shouldFireImmediately (only .commsTransient is dwell-suppressed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
James Woglom пре 2 недеља
родитељ
комит
c332c9b49b
2 измењених фајлова са 78 додато и 0 уклоњено
  1. 4 0
      Trio.xcodeproj/project.pbxproj
  2. 74 0
      TrioTests/TrioAlertCategoryTests.swift

+ 4 - 0
Trio.xcodeproj/project.pbxproj

@@ -237,6 +237,7 @@
 		38FCF3D625E8FDF40078B0D1 /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FCF3D525E8FDF40078B0D1 /* MD5.swift */; };
 		38FCF3D625E8FDF40078B0D1 /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FCF3D525E8FDF40078B0D1 /* MD5.swift */; };
 		38FCF3F925E902C20078B0D1 /* FileStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FCF3F825E902C20078B0D1 /* FileStorageTests.swift */; };
 		38FCF3F925E902C20078B0D1 /* FileStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FCF3F825E902C20078B0D1 /* FileStorageTests.swift */; };
 		BD11A001000000000000A002 /* AlertMuterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A002 /* AlertMuterTests.swift */; };
 		BD11A001000000000000A002 /* AlertMuterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A002 /* AlertMuterTests.swift */; };
+		BD11A001000000000000A009 /* TrioAlertCategoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A009 /* TrioAlertCategoryTests.swift */; };
 		BD11A001000000000000A008 /* GlucoseAlertTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A008 /* GlucoseAlertTests.swift */; };
 		BD11A001000000000000A008 /* GlucoseAlertTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A008 /* GlucoseAlertTests.swift */; };
 		BD11A001000000000000A007 /* GlucoseAlertConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */; };
 		BD11A001000000000000A007 /* GlucoseAlertConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */; };
 		BD11A001000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */; };
 		BD11A001000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */; };
@@ -1242,6 +1243,7 @@
 		38FCF3F125E9028E0078B0D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		38FCF3F125E9028E0078B0D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		38FCF3F825E902C20078B0D1 /* FileStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileStorageTests.swift; sourceTree = "<group>"; };
 		38FCF3F825E902C20078B0D1 /* FileStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileStorageTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A002 /* AlertMuterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertMuterTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A002 /* AlertMuterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertMuterTests.swift; sourceTree = "<group>"; };
+		BD11A000000000000000A009 /* TrioAlertCategoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioAlertCategoryTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A008 /* GlucoseAlertTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A008 /* GlucoseAlertTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertConfigurationTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertConfigurationTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastedGlucoseEvaluatorTests.swift; sourceTree = "<group>"; };
 		BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastedGlucoseEvaluatorTests.swift; sourceTree = "<group>"; };
@@ -3003,6 +3005,7 @@
 				3BAAE60B2DE776630049589B /* DynamicISFEnableTests.swift */,
 				3BAAE60B2DE776630049589B /* DynamicISFEnableTests.swift */,
 				38FCF3F825E902C20078B0D1 /* FileStorageTests.swift */,
 				38FCF3F825E902C20078B0D1 /* FileStorageTests.swift */,
 				BD11A000000000000000A002 /* AlertMuterTests.swift */,
 				BD11A000000000000000A002 /* AlertMuterTests.swift */,
+				BD11A000000000000000A009 /* TrioAlertCategoryTests.swift */,
 				BD11A000000000000000A008 /* GlucoseAlertTests.swift */,
 				BD11A000000000000000A008 /* GlucoseAlertTests.swift */,
 				BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */,
 				BD11A000000000000000A007 /* GlucoseAlertConfigurationTests.swift */,
 				BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */,
 				BD11A000000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift */,
@@ -5574,6 +5577,7 @@
 				3B1C5C482D68E269004E9273 /* IobHistoryTests.swift in Sources */,
 				3B1C5C482D68E269004E9273 /* IobHistoryTests.swift in Sources */,
 				38FCF3F925E902C20078B0D1 /* FileStorageTests.swift in Sources */,
 				38FCF3F925E902C20078B0D1 /* FileStorageTests.swift in Sources */,
 				BD11A001000000000000A002 /* AlertMuterTests.swift in Sources */,
 				BD11A001000000000000A002 /* AlertMuterTests.swift in Sources */,
+				BD11A001000000000000A009 /* TrioAlertCategoryTests.swift in Sources */,
 				BD11A001000000000000A008 /* GlucoseAlertTests.swift in Sources */,
 				BD11A001000000000000A008 /* GlucoseAlertTests.swift in Sources */,
 				BD11A001000000000000A007 /* GlucoseAlertConfigurationTests.swift in Sources */,
 				BD11A001000000000000A007 /* GlucoseAlertConfigurationTests.swift in Sources */,
 				BD11A001000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift in Sources */,
 				BD11A001000000000000A006 /* ForecastedGlucoseEvaluatorTests.swift in Sources */,

+ 74 - 0
TrioTests/TrioAlertCategoryTests.swift

@@ -0,0 +1,74 @@
+import Foundation
+import LoopKit
+import Testing
+
+@testable import Trio
+
+/// Pins the severity + immediacy mapping for every `TrioAlertCategory` case.
+/// A re-bucketing of any case (or an added/removed case) fails these tables.
+@Suite("Trio Alerts: TrioAlertCategory") struct TrioAlertCategoryTests {
+    @Test("interruptionLevel maps each category to its severity tier", arguments: [
+        // .critical
+        (TrioAlertCategory.batteryEmpty, Alert.InterruptionLevel.critical),
+        (.deliveryUncertain, .critical),
+        (.glucoseUrgentLow, .critical),
+        (.hardwareFault, .critical),
+        (.notLooping, .critical),
+        (.occlusion, .critical),
+        (.reservoirEmpty, .critical),
+        (.sensorFailure, .critical),
+        // .timeSensitive
+        (.batteryLow, .timeSensitive),
+        (.bolusFailed, .timeSensitive),
+        (.carbsRequired, .timeSensitive),
+        (.deviceExpired, .timeSensitive),
+        (.glucoseDataStale, .timeSensitive),
+        (.glucoseForecastedLow, .timeSensitive),
+        (.glucoseHigh, .timeSensitive),
+        (.glucoseLow, .timeSensitive),
+        (.manualTempBasalActive, .timeSensitive),
+        (.podShutdownImminent, .timeSensitive),
+        (.reservoirLow, .timeSensitive),
+        (.suspendTimeExpired, .timeSensitive),
+        // .active
+        (.algorithmError, .active),
+        (.commsTransient, .active),
+        (.deviceExpirationReminder, .active),
+        (.other("x"), .active)
+    ]) func interruptionLevelMapping(category: TrioAlertCategory, expected: Alert.InterruptionLevel) {
+        #expect(category.interruptionLevel == expected)
+    }
+
+    @Test("shouldFireImmediately is true for every category except commsTransient", arguments: [
+        (TrioAlertCategory.algorithmError, true),
+        (.batteryEmpty, true),
+        (.batteryLow, true),
+        (.bolusFailed, true),
+        (.carbsRequired, true),
+        (.deliveryUncertain, true),
+        (.deviceExpirationReminder, true),
+        (.deviceExpired, true),
+        (.glucoseDataStale, true),
+        (.glucoseForecastedLow, true),
+        (.glucoseHigh, true),
+        (.glucoseLow, true),
+        (.glucoseUrgentLow, true),
+        (.hardwareFault, true),
+        (.manualTempBasalActive, true),
+        (.notLooping, true),
+        (.occlusion, true),
+        (.other("x"), true),
+        (.podShutdownImminent, true),
+        (.reservoirEmpty, true),
+        (.reservoirLow, true),
+        (.sensorFailure, true),
+        (.suspendTimeExpired, true),
+        (.commsTransient, false)
+    ]) func shouldFireImmediatelyMapping(category: TrioAlertCategory, expected: Bool) {
+        #expect(category.shouldFireImmediately == expected)
+    }
+
+    @Test("commsTransient is dwell-suppressed") func commsTransientDoesNotFireImmediately() {
+        #expect(TrioAlertCategory.commsTransient.shouldFireImmediately == false)
+    }
+}