← All repositories

listless

A simple list app for Apple platforms

git clone https://code.inqk.net/listless.git


commit b519835d06d458d99207703f426a5648a16dd12a
parent 802ee8b3a94b99ed4820174626a05f62faf2fb04
Author: Michael Camilleri <[email protected]>
Date:   Fri, 13 Mar 2026 12:00:05 +0900

Add macOS as a target for test suite

This commit does not add any Mac specific tests but instead ensures that
the unit tests that currently can be run with an iOS-based test scheme
can now also be run with a macOS-based test scheme.

Co-Authored-By: Claude 4.6 Opus <[email protected]>

Diffstat

MListless.xcodeproj/project.pbxproj | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MListless.xcodeproj/xcshareddata/xcschemes/Listless macOS.xcscheme | 12++++++++++++
MTests/Support/TestHelpers.swift | 4++++
MTests/Unit/CloudKitErrorClassifierTests.swift | 4++++
MTests/Unit/TaskStoreCompletionTests.swift | 4++++
MTests/Unit/TaskStoreEdgeCaseTests.swift | 4++++
MTests/Unit/TaskStoreOrderingTests.swift | 4++++
MTests/Unit/TaskStoreTests.swift | 4++++
Mproject.yml | 21+++++++++++++++++++++

9 files changed, 158 insertions(+), 0 deletions(-)

diff --git a/Listless.xcodeproj/project.pbxproj b/Listless.xcodeproj/project.pbxproj

@@ -38,6 +38,7 @@
 		5035EC4C7518A5FF9AD454CA /* TaskRowDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F416DD868A4C044F0D64F8D0 /* TaskRowDragGesture.swift */; };
 		53700EA974FE4AD771FE89EC /* CloudKitSyncMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E3E82F6093EEFC94A41FED9 /* CloudKitSyncMonitor.swift */; };
 		543C8A0C8A9E2F77B2C0060F /* AccentColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DD7EDA74DAAFA27C84CA08 /* AccentColor.swift */; };
+		54FCE72978F20AA64855B521 /* TaskStoreEdgeCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B2BBE01D99CDA278BCB9F49 /* TaskStoreEdgeCaseTests.swift */; };
 		568635BB34CD7EBE24E66A15 /* SyncDiagnosticsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF3374CE58E7D9378C6997D2 /* SyncDiagnosticsView.swift */; };
 		5761B201BF46FCA9C5C98CEF /* PlatformScrollIndicatorsModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466F9B0E407DF1F5B4789531 /* PlatformScrollIndicatorsModifier.swift */; };
 		57E864F71C9C84B63A28E14F /* TaskStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3DEE364304587D280C5672 /* TaskStore.swift */; };
@@ -60,12 +61,14 @@
 		882695E7AE463C0F39ACFF3C /* HoverCursorModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5D8B5866362D422A2A331C /* HoverCursorModifier.swift */; };
 		889DCB2BB3C01DDA281EA81A /* CloudKitSyncMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E3E82F6093EEFC94A41FED9 /* CloudKitSyncMonitor.swift */; };
 		8A8D164CAA7B95B4C7435A7C /* TaskListView+PullToClear.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A6D74EDDD7E3FC150064FB5 /* TaskListView+PullToClear.swift */; };
+		8FA8398315B67F12EA25FA35 /* TaskStoreCompletionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E88DDD119EEEECCD45F36D2 /* TaskStoreCompletionTests.swift */; };
 		91EDF52C7C5C0B35E9D8B51E /* TaskStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3DEE364304587D280C5672 /* TaskStore.swift */; };
 		93275BD83342D6CE94272E6A /* TaskListTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F9754B32B2FD5AF8552BC85 /* TaskListTypes.swift */; };
 		96617677059FABDBB80D642B /* Listless.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C093494053E6C348F245D4EC /* Listless.xcdatamodeld */; };
 		99977BFA37FBAAA49AF6B71E /* TaskStoreEdgeCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B2BBE01D99CDA278BCB9F49 /* TaskStoreEdgeCaseTests.swift */; };
 		99D17075DA3F00F52A18BB4D /* AccentColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DD7EDA74DAAFA27C84CA08 /* AccentColor.swift */; };
 		A0AA8FD4C542E9AEB2437BC2 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14858BDFD1FD5119F1F24A6 /* PersistenceController.swift */; };
+		A10BF9D0C850105E4FA1A2AD /* CloudKitErrorClassifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C3B9FF63645B35E09CF1B1 /* CloudKitErrorClassifierTests.swift */; };
 		A119D0130DB77E30FBCB5436 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14858BDFD1FD5119F1F24A6 /* PersistenceController.swift */; };
 		A8D5A7B0DFBEC87501FD0526 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9404C09EE1A4D91DFF338464 /* Media.xcassets */; };
 		B7CFDCA5EA48EDE1C768FA21 /* AppCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C79ABB39A40D3E1828716C7 /* AppCommands.swift */; };
@@ -76,9 +79,12 @@
 		CAB42FAA253E2B347AB0594B /* CloudKitErrorClassifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A677CC11ACE0BF743AFCE5 /* CloudKitErrorClassifier.swift */; };
 		CAD142ED738A83371DFF8F5B /* TaskListView+Logic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72B4668483D05A6ECA142B89 /* TaskListView+Logic.swift */; };
 		CC99A96BBC089C423F582E4F /* TaskListViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C018476BD91B73870244B9 /* TaskListViewProtocol.swift */; };
+		CDE538A0B3CA14B1CB421ED8 /* TaskStoreOrderingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D3A2DDCE24E54ABCCFBBD4C /* TaskStoreOrderingTests.swift */; };
 		DB5FF6C1AA57D4C9BDDD50FD /* ClickableTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D640E7D21735C62A30A26DA4 /* ClickableTextField.swift */; };
 		DC73A39A269AB495BCE1AC48 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14858BDFD1FD5119F1F24A6 /* PersistenceController.swift */; };
 		DEE187A790A4058FE4AFDB2E /* PlatformTextFieldWidthModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8448C5778F75F52719114AF /* PlatformTextFieldWidthModifier.swift */; };
+		E12C1304464FC7799856B2BA /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75B048B19C5219862BBED2E7 /* TestHelpers.swift */; };
+		E14F8177232BBC75FEEE1E2C /* TaskStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967F7ECEB3915CEDCE584872 /* TaskStoreTests.swift */; };
 		E429067963379F99DD184FED /* CloudKitSyncMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E3E82F6093EEFC94A41FED9 /* CloudKitSyncMonitor.swift */; };
 		E47136CA7428927395D8C7C7 /* PullToCreate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF7D84B54AE70036D205CA4 /* PullToCreate.swift */; };
 		E4BD761E34CBB84CE80F7F49 /* CloudKitErrorClassifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A677CC11ACE0BF743AFCE5 /* CloudKitErrorClassifier.swift */; };
@@ -96,6 +102,13 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+		1CECC2E7FCB78843443C0C46 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 3256C2BF8F1DAF371DA32120 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 0FB4F07A37999BBC6DFE4DBB;
+			remoteInfo = "Listless macOS";
+		};
 		642EE6A5908DB4216F049E9C /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 3256C2BF8F1DAF371DA32120 /* Project object */;
@@ -176,6 +189,7 @@
 		A2EF927F09D67532F44BB80D /* TaskRowMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskRowMetrics.swift; sourceTree = "<group>"; };
 		AC245331D715EA85887C0BA0 /* ListlessiOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListlessiOSApp.swift; sourceTree = "<group>"; };
 		B7588879D0FA1C2A8BCEF14F /* HoverCursorModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverCursorModifier.swift; sourceTree = "<group>"; };
+		B88DC6E36FA41DCB6CEB9647 /* Listless macOS Unit Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Listless macOS Unit Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		BAE264D30C7692457B92E518 /* KeyValueSyncBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueSyncBridge.swift; sourceTree = "<group>"; };
 		BC845482926A73B0BF820328 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
 		BFF7D84B54AE70036D205CA4 /* PullToCreate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PullToCreate.swift; sourceTree = "<group>"; };
@@ -240,6 +254,7 @@
 			children = (
 				C71466C5CD1A5BA984352F8D /* Listless iOS Unit Tests.xctest */,
 				126108860D7878DDC3BECC4B /* Listless iOS.app */,
+				B88DC6E36FA41DCB6CEB9647 /* Listless macOS Unit Tests.xctest */,
 				5B0E22B8F7B2B7283CAF749E /* Listless macOS.app */,
 				C6812E535A24C599C28F9278 /* Listless watchOS.app */,
 			);
@@ -485,6 +500,24 @@
 			productReference = 126108860D7878DDC3BECC4B /* Listless iOS.app */;
 			productType = "com.apple.product-type.application";
 		};
+		7F0B17D1EC9FD4A80BC99002 /* Listless macOS Unit Tests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D6218056DB7B3D1C0ACF1443 /* Build configuration list for PBXNativeTarget "Listless macOS Unit Tests" */;
+			buildPhases = (
+				0421851ACA269BDB6CCA11C0 /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				A71FF92EBBB4C01F921B128B /* PBXTargetDependency */,
+			);
+			name = "Listless macOS Unit Tests";
+			packageProductDependencies = (
+			);
+			productName = "Listless macOS Unit Tests";
+			productReference = B88DC6E36FA41DCB6CEB9647 /* Listless macOS Unit Tests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 		9BDC1B2175AB9CE26790448D /* Listless watchOS */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = A549D68557611D588CB834B2 /* Build configuration list for PBXNativeTarget "Listless watchOS" */;
@@ -538,6 +571,10 @@
 						DevelopmentTeam = 7TD7PZBNXP;
 						ProvisioningStyle = Automatic;
 					};
+					7F0B17D1EC9FD4A80BC99002 = {
+						DevelopmentTeam = 7TD7PZBNXP;
+						ProvisioningStyle = Automatic;
+					};
 					9BDC1B2175AB9CE26790448D = {
 						DevelopmentTeam = 7TD7PZBNXP;
 						ProvisioningStyle = Automatic;
@@ -565,6 +602,7 @@
 				34A03D42B91730DEAC2EBD8E /* Listless iOS */,
 				D533FDEDCE6DFCA2E8CB70F5 /* Listless iOS Unit Tests */,
 				0FB4F07A37999BBC6DFE4DBB /* Listless macOS */,
+				7F0B17D1EC9FD4A80BC99002 /* Listless macOS Unit Tests */,
 				9BDC1B2175AB9CE26790448D /* Listless watchOS */,
 			);
 		};
@@ -599,6 +637,19 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
+		0421851ACA269BDB6CCA11C0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A10BF9D0C850105E4FA1A2AD /* CloudKitErrorClassifierTests.swift in Sources */,
+				8FA8398315B67F12EA25FA35 /* TaskStoreCompletionTests.swift in Sources */,
+				54FCE72978F20AA64855B521 /* TaskStoreEdgeCaseTests.swift in Sources */,
+				CDE538A0B3CA14B1CB421ED8 /* TaskStoreOrderingTests.swift in Sources */,
+				E14F8177232BBC75FEEE1E2C /* TaskStoreTests.swift in Sources */,
+				E12C1304464FC7799856B2BA /* TestHelpers.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		409D108909CBEC2F69B56D0E /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -721,9 +772,32 @@
 			target = 9BDC1B2175AB9CE26790448D /* Listless watchOS */;
 			targetProxy = 642EE6A5908DB4216F049E9C /* PBXContainerItemProxy */;
 		};
+		A71FF92EBBB4C01F921B128B /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 0FB4F07A37999BBC6DFE4DBB /* Listless macOS */;
+			targetProxy = 1CECC2E7FCB78843443C0C46 /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */
 
 /* Begin XCBuildConfiguration section */
+		05B5A346110EC651C700E86E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				CODE_SIGN_STYLE = Automatic;
+				COMBINE_HIDPI_IMAGES = YES;
+				GENERATE_INFOPLIST_FILE = YES;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+					"@loader_path/../Frameworks",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = net.inqk.listless.macos.unittests;
+				SDKROOT = macosx;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Listless.app/Contents/MacOS/Listless";
+			};
+			name = Release;
+		};
 		2D4E3CC5FF8E6299F754CCFC /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -873,6 +947,24 @@
 			};
 			name = Debug;
 		};
+		CF2E8B9803D045F7F301E05E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				CODE_SIGN_STYLE = Automatic;
+				COMBINE_HIDPI_IMAGES = YES;
+				GENERATE_INFOPLIST_FILE = YES;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+					"@loader_path/../Frameworks",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = net.inqk.listless.macos.unittests;
+				SDKROOT = macosx;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Listless.app/Contents/MacOS/Listless";
+			};
+			name = Debug;
+		};
 		D1B900A3E25ED5B39F0D9716 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = D43D37CE25806380C0B13466 /* BuildNumber.xcconfig */;
@@ -1047,6 +1139,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Debug;
 		};
+		D6218056DB7B3D1C0ACF1443 /* Build configuration list for PBXNativeTarget "Listless macOS Unit Tests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CF2E8B9803D045F7F301E05E /* Debug */,
+				05B5A346110EC651C700E86E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Debug;
+		};
 /* End XCConfigurationList section */
 
 /* Begin XCVersionGroup section */

diff --git a/Listless.xcodeproj/xcshareddata/xcschemes/Listless macOS.xcscheme b/Listless.xcodeproj/xcshareddata/xcschemes/Listless macOS.xcscheme

@@ -55,6 +55,18 @@
          </BuildableReference>
       </MacroExpansion>
       <Testables>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES"
+            testExecutionOrdering = "random">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "7F0B17D1EC9FD4A80BC99002"
+               BuildableName = "Listless macOS Unit Tests.xctest"
+               BlueprintName = "Listless macOS Unit Tests"
+               ReferencedContainer = "container:Listless.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
       </Testables>
    </TestAction>
    <LaunchAction

diff --git a/Tests/Support/TestHelpers.swift b/Tests/Support/TestHelpers.swift

@@ -1,7 +1,11 @@
 import Foundation
 import Testing
 
+#if os(macOS)
+@testable import Listless
+#else
 @testable import Listless_iOS
+#endif
 
 /// Creates a fresh TaskStore with in-memory persistence for isolated testing.
 @MainActor

diff --git a/Tests/Unit/CloudKitErrorClassifierTests.swift b/Tests/Unit/CloudKitErrorClassifierTests.swift

@@ -2,7 +2,11 @@ import CloudKit
 import Foundation
 import Testing
 
+#if os(macOS)
+@testable import Listless
+#else
 @testable import Listless_iOS
+#endif
 
 @Suite("CloudKitErrorClassifier")
 struct CloudKitErrorClassifierTests {

diff --git a/Tests/Unit/TaskStoreCompletionTests.swift b/Tests/Unit/TaskStoreCompletionTests.swift

@@ -1,7 +1,11 @@
 import Foundation
 import Testing
 
+#if os(macOS)
+@testable import Listless
+#else
 @testable import Listless_iOS
+#endif
 
 @Suite("TaskStore Completion Behavior", .serialized)
 @MainActor

diff --git a/Tests/Unit/TaskStoreEdgeCaseTests.swift b/Tests/Unit/TaskStoreEdgeCaseTests.swift

@@ -2,7 +2,11 @@ import Foundation
 import CoreData
 import Testing
 
+#if os(macOS)
+@testable import Listless
+#else
 @testable import Listless_iOS
+#endif
 
 @Suite("TaskStore Edge Cases", .serialized)
 @MainActor

diff --git a/Tests/Unit/TaskStoreOrderingTests.swift b/Tests/Unit/TaskStoreOrderingTests.swift

@@ -1,7 +1,11 @@
 import Foundation
 import Testing
 
+#if os(macOS)
+@testable import Listless
+#else
 @testable import Listless_iOS
+#endif
 
 @Suite("TaskStore Task Reordering", .serialized)
 @MainActor

diff --git a/Tests/Unit/TaskStoreTests.swift b/Tests/Unit/TaskStoreTests.swift

@@ -1,7 +1,11 @@
 import Foundation
 import Testing
 
+#if os(macOS)
+@testable import Listless
+#else
 @testable import Listless_iOS
+#endif
 
 @Suite("TaskStore CRUD Operations", .serialized)
 @MainActor

diff --git a/project.yml b/project.yml

@@ -161,6 +161,21 @@ targets:
       BUNDLE_LOADER: $(TEST_HOST)
       GENERATE_INFOPLIST_FILE: YES
 
+  Listless macOS Unit Tests:
+    type: bundle.unit-test
+    platform: macOS
+    sources:
+      - Tests/Unit
+      - Tests/Support
+    dependencies:
+      - target: Listless macOS
+    settings:
+      PRODUCT_BUNDLE_IDENTIFIER: net.inqk.listless.macos.unittests
+      CODE_SIGN_STYLE: Automatic
+      TEST_HOST: $(BUILT_PRODUCTS_DIR)/Listless.app/Contents/MacOS/Listless
+      BUNDLE_LOADER: $(TEST_HOST)
+      GENERATE_INFOPLIST_FILE: YES
+
 schemes:
   Listless iOS:
     build:
@@ -201,6 +216,12 @@ schemes:
           settingsTarget: Listless macOS
     run:
       config: Debug
+    test:
+      config: Debug
+      targets:
+        - name: Listless macOS Unit Tests
+          parallelizable: true
+          randomExecutionOrder: true
     profile:
       config: Release
     analyze: