polscm32 aka Marvout преди 1 година
родител
ревизия
970384b57d

+ 1 - 1
Trio Watch App Extension/WatchState.swift

@@ -248,7 +248,7 @@ import WatchConnectivity
 
     // MARK: – Handle Acknowledgement Messages FROM Phone
 
-    private func handleAcknowledgment(success: Bool, message: String, isFinal: Bool = true) {
+    func handleAcknowledgment(success: Bool, message: String, isFinal: Bool = true) {
         if success {
             print("⌚️ Acknowledgment received: \(message)")
             showCommsAnimation = false // Hide progress animation

+ 0 - 8
Trio Watch App Tests/TrioWatchAppTests.swift

@@ -1,8 +0,0 @@
-import Testing
-@testable import TrioWatchApp
-
-struct TrioWatchAppTests {
-    @Test func example() async throws {
-        // Write your test here and use APIs like `#expect(...)` to check expected conditions.
-    }
-}

+ 44 - 18
Trio Watch App Tests/TrioWatchAppUITests.swift

@@ -1,33 +1,59 @@
 import XCTest
 
 final class TrioWatchAppUITests: XCTestCase {
-    override func setUpWithError() throws {
-        // Put setup code here. This method is called before the invocation of each test method in the class.
+    var app: XCUIApplication!
 
-        // In UI tests it is usually best to stop immediately when a failure occurs.
+    override func setUpWithError() throws {
         continueAfterFailure = false
+        app = XCUIApplication()
+        app.launch()
+    }
+
+    func testMainViewElements() throws {
+        // Test presence of main UI elements
+        XCTAssertTrue(app.staticTexts["--"].exists) // Initial glucose value
+        XCTAssertTrue(app.buttons["plus"].exists) // Treatment button
 
-        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+        // Test IOB and COB elements
+        let iobElement = app.staticTexts.matching(identifier: "iob").firstMatch
+        let cobElement = app.staticTexts.matching(identifier: "cob").firstMatch
+        XCTAssertTrue(iobElement.exists)
+        XCTAssertTrue(cobElement.exists)
     }
 
-    override func tearDownWithError() throws {
-        // Put teardown code here. This method is called after the invocation of each test method in the class.
+    func testTreatmentMenu() throws {
+        // Open treatment menu
+        app.buttons["plus"].tap()
+
+        // Verify treatment options
+        XCTAssertTrue(app.buttons["Carbs"].exists)
+        XCTAssertTrue(app.buttons["Bolus"].exists)
+        XCTAssertTrue(app.buttons["Meal Bolus"].exists)
     }
 
-    @MainActor func testExample() throws {
-        // UI tests must launch the application that they test.
-        let app = XCUIApplication()
-        app.launch()
+    func testBolusWorkflow() throws {
+        // Open treatment menu
+        app.buttons["plus"].tap()
+
+        // Select bolus option
+        app.buttons["Bolus"].tap()
 
-        // Use XCTAssert and related functions to verify your tests produce the correct results.
+        // Verify bolus input elements
+        XCTAssertTrue(app.buttons["minus.circle.fill"].exists)
+        XCTAssertTrue(app.buttons["plus.circle.fill"].exists)
+        XCTAssertTrue(app.buttons["Log Bolus"].exists)
     }
 
-    @MainActor func testLaunchPerformance() throws {
-        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
-            // This measures how long it takes to launch your application.
-            measure(metrics: [XCTApplicationLaunchMetric()]) {
-                XCUIApplication().launch()
-            }
-        }
+    func testCarbsWorkflow() throws {
+        // Open treatment menu
+        app.buttons["plus"].tap()
+
+        // Select carbs option
+        app.buttons["Carbs"].tap()
+
+        // Verify carbs input elements
+        XCTAssertTrue(app.buttons["minus.circle.fill"].exists)
+        XCTAssertTrue(app.buttons["plus.circle.fill"].exists)
+        XCTAssertTrue(app.buttons["Log Carbs"].exists)
     }
 }

+ 100 - 0
Trio Watch App Tests/Unit Tests.swift

@@ -0,0 +1,100 @@
+import SwiftUICore
+import Testing
+@testable import Trio_Watch_App
+import XCTest
+
+@Suite("Watch App Tests") final class TrioWatchAppTests {
+    var watchState = WatchState()
+
+    // MARK: - Color Conversion Tests
+
+    @Test("Hex string to color conversion") func testHexStringToColor() throws {
+        // Given
+        let whiteHex = "#FFFFFF"
+        let blackHex = "#000000"
+        let redHex = "#FF0000"
+        let invalidHex = "invalid"
+
+        // Then
+        #expect(whiteHex.toColor() == Color.white)
+        #expect(blackHex.toColor() == Color.black)
+        #expect(redHex.toColor() == Color(red: 1, green: 0, blue: 0))
+        #expect(invalidHex.toColor() == Color.black)
+    }
+
+    // MARK: - WatchState Tests
+
+    @Test("WatchState initialization with default values") func testWatchStateInitialization() throws {
+        #expect(watchState.currentGlucose == "--")
+        #expect(watchState.currentGlucoseColorString == "#ffffff")
+        #expect(watchState.glucoseValues.isEmpty)
+        #expect(watchState.iob == "--")
+        #expect(watchState.cob == "--")
+        #expect(watchState.lastLoopTime == "--")
+    }
+
+    @Test("Bolus limits have correct default values") func testBolusLimits() throws {
+        #expect(watchState.maxBolus == Decimal(10))
+        #expect(watchState.bolusIncrement == Decimal(0.05))
+    }
+
+    @Test("Carb limits have correct default values") func testCarbLimits() throws {
+        #expect(watchState.maxCarbs == Decimal(250))
+        #expect(watchState.maxCOB == Decimal(120))
+    }
+
+    @Test("Bolus cancellation resets all related values") func testBolusCancellation() throws {
+        // Given
+        watchState.bolusProgress = 0.5
+        watchState.activeBolusAmount = 5.0
+        watchState.isBolusCanceled = false
+
+        // When
+        watchState.sendCancelBolusRequest()
+
+        // Then
+        #expect(watchState.isBolusCanceled)
+        #expect(watchState.bolusProgress == 0)
+        #expect(watchState.activeBolusAmount == 0)
+    }
+
+    @Test("Meal bolus combo state transitions work correctly") func testMealBolusComboState() throws {
+        // Given - Initial state
+        #expect(!watchState.isMealBolusCombo)
+        #expect(watchState.mealBolusStep == .savingCarbs)
+
+        // When - Setup meal bolus combo
+        watchState.carbsAmount = 30
+        watchState.bolusAmount = 3.0
+
+        // Then - Test state transitions
+        watchState.handleAcknowledgment(success: true, message: "Saving carbs...", isFinal: false)
+        #expect(watchState.isMealBolusCombo)
+        #expect(watchState.mealBolusStep == .savingCarbs)
+
+        watchState.handleAcknowledgment(success: true, message: "Enacting bolus...", isFinal: false)
+        #expect(watchState.isMealBolusCombo)
+        #expect(watchState.mealBolusStep == .enactingBolus)
+
+        watchState.handleAcknowledgment(success: true, message: "Carbs and bolus logged successfully", isFinal: true)
+        #expect(!watchState.isMealBolusCombo)
+    }
+
+    @Test("Acknowledgment states transition correctly") func testAcknowledgmentStates() throws {
+        // Given - Initial state
+        #expect(watchState.acknowledgementStatus == .pending)
+        #expect(!watchState.showAcknowledgmentBanner)
+
+        // When/Then - Success acknowledgment
+        watchState.handleAcknowledgment(success: true, message: "Success")
+        #expect(watchState.acknowledgementStatus == .success)
+        #expect(watchState.showAcknowledgmentBanner)
+        #expect(watchState.acknowledgmentMessage == "Success")
+
+        // When/Then - Failure acknowledgment
+        watchState.handleAcknowledgment(success: false, message: "Error")
+        #expect(watchState.acknowledgementStatus == .failure)
+        #expect(watchState.showAcknowledgmentBanner)
+        #expect(watchState.acknowledgmentMessage == "Error")
+    }
+}

+ 43 - 0
Trio Watch AppUITests/Trio_Watch_AppUITests.swift

@@ -0,0 +1,43 @@
+//
+//  Trio_Watch_AppUITests.swift
+//  Trio Watch AppUITests
+//
+//  Created by Marvin Polscheit on 08.01.25.
+//
+
+import XCTest
+
+final class Trio_Watch_AppUITests: XCTestCase {
+
+    override func setUpWithError() throws {
+        // Put setup code here. This method is called before the invocation of each test method in the class.
+
+        // In UI tests it is usually best to stop immediately when a failure occurs.
+        continueAfterFailure = false
+
+        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+    }
+
+    override func tearDownWithError() throws {
+        // Put teardown code here. This method is called after the invocation of each test method in the class.
+    }
+
+    @MainActor
+    func testExample() throws {
+        // UI tests must launch the application that they test.
+        let app = XCUIApplication()
+        app.launch()
+
+        // Use XCTAssert and related functions to verify your tests produce the correct results.
+    }
+
+    @MainActor
+    func testLaunchPerformance() throws {
+        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
+            // This measures how long it takes to launch your application.
+            measure(metrics: [XCTApplicationLaunchMetric()]) {
+                XCUIApplication().launch()
+            }
+        }
+    }
+}

+ 11 - 2
Trio Watch App Tests/TrioWatchAppUITestsLaunchTests.swift

@@ -1,6 +1,14 @@
+//
+//  Trio_Watch_AppUITestsLaunchTests.swift
+//  Trio Watch AppUITests
+//
+//  Created by Marvin Polscheit on 08.01.25.
+//
+
 import XCTest
 
-final class TrioWatchAppUITestsLaunchTests: XCTestCase {
+final class Trio_Watch_AppUITestsLaunchTests: XCTestCase {
+
     override class var runsForEachTargetApplicationUIConfiguration: Bool {
         true
     }
@@ -9,7 +17,8 @@ final class TrioWatchAppUITestsLaunchTests: XCTestCase {
         continueAfterFailure = false
     }
 
-    @MainActor func testLaunch() throws {
+    @MainActor
+    func testLaunch() throws {
         let app = XCUIApplication()
         app.launch()
 

+ 16 - 140
Trio.xcodeproj/project.pbxproj

@@ -345,9 +345,7 @@
 		BDFF7A872D25F97D0016C40C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BDFF7A832D25F97D0016C40C /* Assets.xcassets */; };
 		BDFF7A882D25F97D0016C40C /* TrioMainWatchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF7A842D25F97D0016C40C /* TrioMainWatchView.swift */; };
 		BDFF7A892D25F97D0016C40C /* TrioWatchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF7A852D25F97D0016C40C /* TrioWatchApp.swift */; };
-		BDFF7A8B2D25F97D0016C40C /* TrioWatchAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF7A8A2D25F97D0016C40C /* TrioWatchAppTests.swift */; };
-		BDFF7A8E2D25F97D0016C40C /* TrioWatchAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF7A8C2D25F97D0016C40C /* TrioWatchAppUITests.swift */; };
-		BDFF7A8F2D25F97D0016C40C /* TrioWatchAppUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF7A8D2D25F97D0016C40C /* TrioWatchAppUITestsLaunchTests.swift */; };
+		BDFF7A8B2D25F97D0016C40C /* Unit Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF7A8A2D25F97D0016C40C /* Unit Tests.swift */; };
 		BF1667ADE69E4B5B111CECAE /* ManualTempBasalProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 680C4420C9A345D46D90D06C /* ManualTempBasalProvider.swift */; };
 		C2A0A42F2CE03131003B98E8 /* ConstantValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2A0A42E2CE0312C003B98E8 /* ConstantValues.swift */; };
 		C967DACD3B1E638F8B43BE06 /* ManualTempBasalStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFCFE0781F9074C2917890E8 /* ManualTempBasalStateModel.swift */; };
@@ -599,13 +597,6 @@
 			remoteGlobalIDString = BDFF797B2D25AA870016C40C;
 			remoteInfo = "TrioWatch Watch App";
 		};
-		BDFF79962D25AA890016C40C /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 388E595025AD948C0019842D /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = BDFF797B2D25AA870016C40C;
-			remoteInfo = "TrioWatch Watch App";
-		};
 		BDFF799D2D25AA890016C40C /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 388E595025AD948C0019842D /* Project object */;
@@ -1063,14 +1054,11 @@
 		BDF530D72B40F8AC002CAF43 /* LockScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenView.swift; sourceTree = "<group>"; };
 		BDFD16592AE40438007F0DDA /* TreatmentsRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreatmentsRootView.swift; sourceTree = "<group>"; };
 		BDFF797C2D25AA870016C40C /* Trio Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Trio Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
-		BDFF798B2D25AA890016C40C /* TrioWatch Watch AppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "TrioWatch Watch AppTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
-		BDFF79952D25AA890016C40C /* TrioWatch Watch AppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "TrioWatch Watch AppUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+		BDFF798B2D25AA890016C40C /* Trio Watch AppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Trio Watch AppTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		BDFF7A832D25F97D0016C40C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		BDFF7A842D25F97D0016C40C /* TrioMainWatchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioMainWatchView.swift; sourceTree = "<group>"; };
 		BDFF7A852D25F97D0016C40C /* TrioWatchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioWatchApp.swift; sourceTree = "<group>"; };
-		BDFF7A8A2D25F97D0016C40C /* TrioWatchAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioWatchAppTests.swift; sourceTree = "<group>"; };
-		BDFF7A8C2D25F97D0016C40C /* TrioWatchAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioWatchAppUITests.swift; sourceTree = "<group>"; };
-		BDFF7A8D2D25F97D0016C40C /* TrioWatchAppUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioWatchAppUITestsLaunchTests.swift; sourceTree = "<group>"; };
+		BDFF7A8A2D25F97D0016C40C /* Unit Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Unit Tests.swift"; sourceTree = "<group>"; };
 		BDFF7A902D25F97D0016C40C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		BDFF7A912D25F97D0016C40C /* TrioWatchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioWatchApp.swift; sourceTree = "<group>"; };
 		BDFF7A922D25F97D0016C40C /* TrioWatchAppExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioWatchAppExtension.swift; sourceTree = "<group>"; };
@@ -1300,6 +1288,7 @@
 /* End PBXFileReference section */
 
 /* Begin PBXFileSystemSynchronizedRootGroup section */
+		BD432C942D2E80F600D1EB79 /* Trio Watch AppUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "Trio Watch AppUITests"; sourceTree = "<group>"; };
 		BDFF7A9E2D25FA970016C40C /* Preview Content */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "Preview Content"; sourceTree = "<group>"; };
 		DDCEBF412CC1B42500DF4C36 /* Views */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Views; sourceTree = "<group>"; };
 /* End PBXFileSystemSynchronizedRootGroup section */
@@ -1366,13 +1355,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		BDFF79922D25AA890016C40C /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
@@ -2001,6 +1983,7 @@
 				CE1F6DE62BAF1A180064EB8D /* BuildDetails.plist */,
 				38F3783A2613555C009DB701 /* Config.xcconfig */,
 				BD1CF8B72C1A4A8400CB930A /* ConfigOverride.xcconfig */,
+				BD432C942D2E80F600D1EB79 /* Trio Watch AppUITests */,
 				3818AA48274C267000843DB3 /* Frameworks */,
 				6B1A8D1C2B14D91600E76752 /* LiveActivity */,
 				587A54C82BCDCE0F009D38E2 /* Model */,
@@ -2023,8 +2006,7 @@
 				38FCF3ED25E9028E0078B0D1 /* TrioTests.xctest */,
 				6B1A8D172B14D91600E76752 /* LiveActivityExtension.appex */,
 				BDFF797C2D25AA870016C40C /* Trio Watch App.app */,
-				BDFF798B2D25AA890016C40C /* TrioWatch Watch AppTests.xctest */,
-				BDFF79952D25AA890016C40C /* TrioWatch Watch AppUITests.xctest */,
+				BDFF798B2D25AA890016C40C /* Trio Watch AppTests.xctest */,
 				BD8207C32D2B42E50023339D /* Trio Watch Complication Extension.appex */,
 			);
 			name = Products;
@@ -2585,9 +2567,7 @@
 		BDFF7AA02D25FAA80016C40C /* Trio Watch App Tests */ = {
 			isa = PBXGroup;
 			children = (
-				BDFF7A8A2D25F97D0016C40C /* TrioWatchAppTests.swift */,
-				BDFF7A8C2D25F97D0016C40C /* TrioWatchAppUITests.swift */,
-				BDFF7A8D2D25F97D0016C40C /* TrioWatchAppUITestsLaunchTests.swift */,
+				BDFF7A8A2D25F97D0016C40C /* Unit Tests.swift */,
 			);
 			path = "Trio Watch App Tests";
 			sourceTree = "<group>";
@@ -3286,9 +3266,9 @@
 			productReference = BDFF797C2D25AA870016C40C /* Trio Watch App.app */;
 			productType = "com.apple.product-type.application";
 		};
-		BDFF798A2D25AA890016C40C /* TrioWatch Watch AppTests */ = {
+		BDFF798A2D25AA890016C40C /* Trio Watch AppTests */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = BDFF79A32D25AA890016C40C /* Build configuration list for PBXNativeTarget "TrioWatch Watch AppTests" */;
+			buildConfigurationList = BDFF79A32D25AA890016C40C /* Build configuration list for PBXNativeTarget "Trio Watch AppTests" */;
 			buildPhases = (
 				BDFF79872D25AA890016C40C /* Sources */,
 				BDFF79882D25AA890016C40C /* Frameworks */,
@@ -3299,33 +3279,13 @@
 			dependencies = (
 				BDFF798D2D25AA890016C40C /* PBXTargetDependency */,
 			);
-			name = "TrioWatch Watch AppTests";
+			name = "Trio Watch AppTests";
 			packageProductDependencies = (
 			);
 			productName = "TrioWatch Watch AppTests";
-			productReference = BDFF798B2D25AA890016C40C /* TrioWatch Watch AppTests.xctest */;
+			productReference = BDFF798B2D25AA890016C40C /* Trio Watch AppTests.xctest */;
 			productType = "com.apple.product-type.bundle.unit-test";
 		};
-		BDFF79942D25AA890016C40C /* TrioWatch Watch AppUITests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = BDFF79A62D25AA890016C40C /* Build configuration list for PBXNativeTarget "TrioWatch Watch AppUITests" */;
-			buildPhases = (
-				BDFF79912D25AA890016C40C /* Sources */,
-				BDFF79922D25AA890016C40C /* Frameworks */,
-				BDFF79932D25AA890016C40C /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				BDFF79972D25AA890016C40C /* PBXTargetDependency */,
-			);
-			name = "TrioWatch Watch AppUITests";
-			packageProductDependencies = (
-			);
-			productName = "TrioWatch Watch AppUITests";
-			productReference = BDFF79952D25AA890016C40C /* TrioWatch Watch AppUITests.xctest */;
-			productType = "com.apple.product-type.bundle.ui-testing";
-		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
@@ -3352,10 +3312,6 @@
 						CreatedOnToolsVersion = 16.2;
 						TestTargetID = BDFF797B2D25AA870016C40C;
 					};
-					BDFF79942D25AA890016C40C = {
-						CreatedOnToolsVersion = 16.2;
-						TestTargetID = BDFF797B2D25AA870016C40C;
-					};
 				};
 			};
 			buildConfigurationList = 388E595325AD948C0019842D /* Build configuration list for PBXProject "Trio" */;
@@ -3405,8 +3361,7 @@
 				38FCF3EC25E9028E0078B0D1 /* TrioTests */,
 				6B1A8D162B14D91500E76752 /* LiveActivityExtension */,
 				BDFF797B2D25AA870016C40C /* Trio Watch App */,
-				BDFF798A2D25AA890016C40C /* TrioWatch Watch AppTests */,
-				BDFF79942D25AA890016C40C /* TrioWatch Watch AppUITests */,
+				BDFF798A2D25AA890016C40C /* Trio Watch AppTests */,
 				BD8207C22D2B42E50023339D /* Trio Watch Complication Extension */,
 			);
 		};
@@ -3467,13 +3422,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		BDFF79932D25AA890016C40C /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
@@ -4112,16 +4060,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				BDFF7A8B2D25F97D0016C40C /* TrioWatchAppTests.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		BDFF79912D25AA890016C40C /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				BDFF7A8E2D25F97D0016C40C /* TrioWatchAppUITests.swift in Sources */,
-				BDFF7A8F2D25F97D0016C40C /* TrioWatchAppUITestsLaunchTests.swift in Sources */,
+				BDFF7A8B2D25F97D0016C40C /* Unit Tests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -4148,11 +4087,6 @@
 			target = BDFF797B2D25AA870016C40C /* Trio Watch App */;
 			targetProxy = BDFF798C2D25AA890016C40C /* PBXContainerItemProxy */;
 		};
-		BDFF79972D25AA890016C40C /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = BDFF797B2D25AA870016C40C /* Trio Watch App */;
-			targetProxy = BDFF79962D25AA890016C40C /* PBXContainerItemProxy */;
-		};
 		BDFF799E2D25AA890016C40C /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = BDFF797B2D25AA870016C40C /* Trio Watch App */;
@@ -4708,7 +4642,7 @@
 				SWIFT_EMIT_LOC_STRINGS = NO;
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = 4;
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TrioWatch Watch App.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/TrioWatch Watch App";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Trio Watch App.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Trio Watch App";
 				WATCHOS_DEPLOYMENT_TARGET = 10;
 			};
 			name = Debug;
@@ -4733,56 +4667,7 @@
 				SWIFT_EMIT_LOC_STRINGS = NO;
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = 4;
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TrioWatch Watch App.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/TrioWatch Watch App";
-				WATCHOS_DEPLOYMENT_TARGET = 10;
-			};
-			name = Release;
-		};
-		BDFF79A72D25AA890016C40C /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = 9X82U8BHFK;
-				ENABLE_USER_SCRIPT_SANDBOXING = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu17;
-				GENERATE_INFOPLIST_FILE = YES;
-				LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "org.nightscout.--DEVELOPMENT-TEAM-.trio.TrioWatch-Watch-AppUITests";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = watchos;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 4;
-				TEST_TARGET_NAME = "TrioWatch Watch App";
-				WATCHOS_DEPLOYMENT_TARGET = 10;
-			};
-			name = Debug;
-		};
-		BDFF79A82D25AA890016C40C /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = 9X82U8BHFK;
-				ENABLE_USER_SCRIPT_SANDBOXING = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu17;
-				GENERATE_INFOPLIST_FILE = YES;
-				LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "org.nightscout.--DEVELOPMENT-TEAM-.trio.TrioWatch-Watch-AppUITests";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = watchos;
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 4;
-				TEST_TARGET_NAME = "TrioWatch Watch App";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Trio Watch App.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Trio Watch App";
 				WATCHOS_DEPLOYMENT_TARGET = 10;
 			};
 			name = Release;
@@ -4844,7 +4729,7 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Debug;
 		};
-		BDFF79A32D25AA890016C40C /* Build configuration list for PBXNativeTarget "TrioWatch Watch AppTests" */ = {
+		BDFF79A32D25AA890016C40C /* Build configuration list for PBXNativeTarget "Trio Watch AppTests" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
 				BDFF79A42D25AA890016C40C /* Debug */,
@@ -4853,15 +4738,6 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Debug;
 		};
-		BDFF79A62D25AA890016C40C /* Build configuration list for PBXNativeTarget "TrioWatch Watch AppUITests" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				BDFF79A72D25AA890016C40C /* Debug */,
-				BDFF79A82D25AA890016C40C /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Debug;
-		};
 /* End XCConfigurationList section */
 
 /* Begin XCRemoteSwiftPackageReference section */

+ 55 - 0
Trio.xcodeproj/xcshareddata/xcschemes/Trio Watch AppTests.xcscheme

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "BDFF798A2D25AA890016C40C"
+               BuildableName = "Trio Watch AppTests.xctest"
+               BlueprintName = "Trio Watch AppTests"
+               ReferencedContainer = "container:Trio.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>