Skip to content

Commit 55a5e56

Browse files
committed
test: add unit tests for Device, Command, Collection, and String extensions
1 parent bf28acd commit 55a5e56

5 files changed

Lines changed: 320 additions & 4 deletions

File tree

MiniSim.xcodeproj/project.pbxproj

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
162A369BC040E62A74C782D1 /* CollectionGetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 912D7A2027F3DDA86839E7AE /* CollectionGetTests.swift */; };
11+
16B53AB50DDD40DC4880CCB8 /* DeviceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470EFF3B34FB31AC5A22B024 /* DeviceTests.swift */; };
12+
2549AC06811CB09AF7D5A4DF /* CommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E9205F1463934FDB7D92FF /* CommandTests.swift */; };
1013
4AFACC742AD730BE00EC369F /* SubMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AFACC732AD730BE00EC369F /* SubMenuItem.swift */; };
1114
4AFACC762AD73D7900EC369F /* NSMenuItem+ConvenienceInit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AFACC752AD73D7900EC369F /* NSMenuItem+ConvenienceInit.swift */; };
1215
4AFACC782AD74E9000EC369F /* DeviceListSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AFACC772AD74E9000EC369F /* DeviceListSection.swift */; };
@@ -107,6 +110,7 @@
107110
76F2A914299050F9002D4EF6 /* UserDefaults+Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F2A913299050F9002D4EF6 /* UserDefaults+Configuration.swift */; };
108111
76F2A9172991B7B6002D4EF6 /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F2A9162991B7B6002D4EF6 /* ViewModifiers.swift */; };
109112
76FCABAB29B390D5003BBF9A /* Collection+get.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76FCABAA29B390D5003BBF9A /* Collection+get.swift */; };
113+
7D850183B2E53A3E4F17994A /* StringMatchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A9C6AA804E851167EA01B17 /* StringMatchTests.swift */; };
110114
9B225A9C2C7E360D002620BA /* DeviceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B225A9B2C7E360D002620BA /* DeviceType.swift */; };
111115
/* End PBXBuildFile section */
112116

@@ -121,6 +125,7 @@
121125
/* End PBXContainerItemProxy section */
122126

123127
/* Begin PBXFileReference section */
128+
470EFF3B34FB31AC5A22B024 /* DeviceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeviceTests.swift; sourceTree = "<group>"; };
124129
4AFACC732AD730BE00EC369F /* SubMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubMenuItem.swift; sourceTree = "<group>"; };
125130
4AFACC752AD73D7900EC369F /* NSMenuItem+ConvenienceInit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMenuItem+ConvenienceInit.swift"; sourceTree = "<group>"; };
126131
4AFACC772AD74E9000EC369F /* DeviceListSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceListSection.swift; sourceTree = "<group>"; };
@@ -129,6 +134,8 @@
129134
52B363ED2AEC10B3006F515C /* ParametersTableFormViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParametersTableFormViewModel.swift; sourceTree = "<group>"; };
130135
551B88292B1385E900B8D325 /* Terminal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Terminal.swift; sourceTree = "<group>"; };
131136
55CDB0772B1B6D24002418D7 /* TerminalApps.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalApps.swift; sourceTree = "<group>"; };
137+
63E9205F1463934FDB7D92FF /* CommandTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CommandTests.swift; sourceTree = "<group>"; };
138+
6A9C6AA804E851167EA01B17 /* StringMatchTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StringMatchTests.swift; sourceTree = "<group>"; };
132139
760554A22C085BEA001607FE /* Thread+Asserts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Thread+Asserts.swift"; sourceTree = "<group>"; };
133140
76059BF42AD4361C0008D38B /* SetupPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupPreferences.swift; sourceTree = "<group>"; };
134141
76059BF62AD449DC0008D38B /* OnboardingHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingHeader.swift; sourceTree = "<group>"; };
@@ -217,6 +224,7 @@
217224
76F2A913299050F9002D4EF6 /* UserDefaults+Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Configuration.swift"; sourceTree = "<group>"; };
218225
76F2A9162991B7B6002D4EF6 /* ViewModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModifiers.swift; sourceTree = "<group>"; };
219226
76FCABAA29B390D5003BBF9A /* Collection+get.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+get.swift"; sourceTree = "<group>"; };
227+
912D7A2027F3DDA86839E7AE /* CollectionGetTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CollectionGetTests.swift; sourceTree = "<group>"; };
220228
9B225A9B2C7E360D002620BA /* DeviceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceType.swift; sourceTree = "<group>"; };
221229
/* End PBXFileReference section */
222230

@@ -460,6 +468,10 @@
460468
76BF0AF32C90A74E003BE568 /* AppleUtilsTests.swift */,
461469
76BF0AF52C90AB03003BE568 /* DeviceDiscoveryTests.swift */,
462470
76BF0AF72C90ACF2003BE568 /* ActionFactoryTests.swift */,
471+
470EFF3B34FB31AC5A22B024 /* DeviceTests.swift */,
472+
6A9C6AA804E851167EA01B17 /* StringMatchTests.swift */,
473+
912D7A2027F3DDA86839E7AE /* CollectionGetTests.swift */,
474+
63E9205F1463934FDB7D92FF /* CommandTests.swift */,
463475
);
464476
path = MiniSimTests;
465477
sourceTree = "<group>";
@@ -737,6 +749,10 @@
737749
76B70F7E2B0D361A009D87A4 /* UserDefaultsTests.swift in Sources */,
738750
760DEACE2B0DFB6600253576 /* ShellStub.swift in Sources */,
739751
76B70F822B0D50FE009D87A4 /* ADBTests.swift in Sources */,
752+
16B53AB50DDD40DC4880CCB8 /* DeviceTests.swift in Sources */,
753+
7D850183B2E53A3E4F17994A /* StringMatchTests.swift in Sources */,
754+
162A369BC040E62A74C782D1 /* CollectionGetTests.swift in Sources */,
755+
2549AC06811CB09AF7D5A4DF /* CommandTests.swift in Sources */,
740756
);
741757
runOnlyForDeploymentPostprocessing = 0;
742758
};
@@ -745,7 +761,7 @@
745761
/* Begin PBXTargetDependency section */
746762
4A78928A2AF1A9A3004D3FC8 /* PBXTargetDependency */ = {
747763
isa = PBXTargetDependency;
748-
productRef = 4A7892892AF1A9A3004D3FC8 /* SwiftLintPlugin */;
764+
productRef = 4A7892892AF1A9A3004D3FC8 /* plugin:SwiftLintPlugin */;
749765
};
750766
76B70F792B0D359D009D87A4 /* PBXTargetDependency */ = {
751767
isa = PBXTargetDependency;
@@ -754,7 +770,7 @@
754770
};
755771
76B70F802B0D4F9D009D87A4 /* PBXTargetDependency */ = {
756772
isa = PBXTargetDependency;
757-
productRef = 76B70F7F2B0D4F9D009D87A4 /* SwiftLintPlugin */;
773+
productRef = 76B70F7F2B0D4F9D009D87A4 /* plugin:SwiftLintPlugin */;
758774
};
759775
/* End PBXTargetDependency section */
760776

@@ -1106,7 +1122,7 @@
11061122
/* End XCRemoteSwiftPackageReference section */
11071123

11081124
/* Begin XCSwiftPackageProductDependency section */
1109-
4A7892892AF1A9A3004D3FC8 /* SwiftLintPlugin */ = {
1125+
4A7892892AF1A9A3004D3FC8 /* plugin:SwiftLintPlugin */ = {
11101126
isa = XCSwiftPackageProductDependency;
11111127
package = 4A7892862AF1A767004D3FC8 /* XCRemoteSwiftPackageReference "SwiftLint" */;
11121128
productName = "plugin:SwiftLintPlugin";
@@ -1141,7 +1157,7 @@
11411157
package = 76AC9AF72A0EB50800864A8B /* XCRemoteSwiftPackageReference "SymbolPicker" */;
11421158
productName = SymbolPicker;
11431159
};
1144-
76B70F7F2B0D4F9D009D87A4 /* SwiftLintPlugin */ = {
1160+
76B70F7F2B0D4F9D009D87A4 /* plugin:SwiftLintPlugin */ = {
11451161
isa = XCSwiftPackageProductDependency;
11461162
package = 4A7892862AF1A767004D3FC8 /* XCRemoteSwiftPackageReference "SwiftLint" */;
11471163
productName = "plugin:SwiftLintPlugin";
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import XCTest
2+
3+
@testable import MiniSim
4+
5+
final class CollectionGetTests: XCTestCase {
6+
func testGetAtValidIndex() {
7+
let array = ["a", "b", "c"]
8+
9+
XCTAssertEqual(array.get(at: 0), "a")
10+
XCTAssertEqual(array.get(at: 1), "b")
11+
XCTAssertEqual(array.get(at: 2), "c")
12+
}
13+
14+
func testGetAtInvalidIndex() {
15+
let array = ["a", "b", "c"]
16+
17+
XCTAssertNil(array.get(at: 3))
18+
XCTAssertNil(array.get(at: 100))
19+
}
20+
21+
func testGetOnEmptyCollection() {
22+
let array: [String] = []
23+
24+
XCTAssertNil(array.get(at: 0))
25+
}
26+
27+
func testGetWithDifferentTypes() {
28+
let intArray = [1, 2, 3]
29+
XCTAssertEqual(intArray.get(at: 1), 2)
30+
31+
let deviceArray = [
32+
Device(name: "iPhone", identifier: "uuid1", platform: .ios, type: .virtual),
33+
Device(name: "Pixel", identifier: "uuid2", platform: .android, type: .virtual)
34+
]
35+
XCTAssertEqual(deviceArray.get(at: 0)?.name, "iPhone")
36+
XCTAssertEqual(deviceArray.get(at: 1)?.platform, .android)
37+
XCTAssertNil(deviceArray.get(at: 2))
38+
}
39+
40+
func testGetOnDictionary() {
41+
let dict = ["a": 1, "b": 2]
42+
let keys = Array(dict.keys).sorted()
43+
44+
XCTAssertNotNil(keys.get(at: 0))
45+
XCTAssertNil(keys.get(at: 10))
46+
}
47+
}

MiniSimTests/CommandTests.swift

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import XCTest
2+
3+
@testable import MiniSim
4+
5+
final class CommandTests: XCTestCase {
6+
func testEncodingDecoding() throws {
7+
let command = Command(
8+
name: "Test Command",
9+
command: "adb devices",
10+
icon: "terminal",
11+
platform: .android,
12+
needBootedDevice: true,
13+
bootsDevice: false,
14+
tag: 42
15+
)
16+
17+
let encoded = try JSONEncoder().encode(command)
18+
let decoded = try JSONDecoder().decode(Command.self, from: encoded)
19+
20+
XCTAssertEqual(decoded.name, command.name)
21+
XCTAssertEqual(decoded.command, command.command)
22+
XCTAssertEqual(decoded.icon, command.icon)
23+
XCTAssertEqual(decoded.platform, command.platform)
24+
XCTAssertEqual(decoded.needBootedDevice, command.needBootedDevice)
25+
XCTAssertEqual(decoded.bootsDevice, command.bootsDevice)
26+
XCTAssertEqual(decoded.tag, command.tag)
27+
}
28+
29+
func testDecodingOptionalFieldsNil() throws {
30+
let json = """
31+
{
32+
"id": "550e8400-e29b-41d4-a716-446655440000",
33+
"name": "Test",
34+
"command": "echo test",
35+
"icon": "star",
36+
"platform": "ios",
37+
"needBootedDevice": false
38+
}
39+
"""
40+
41+
let data = json.data(using: .utf8)!
42+
let decoded = try JSONDecoder().decode(Command.self, from: data)
43+
44+
XCTAssertEqual(decoded.name, "Test")
45+
XCTAssertEqual(decoded.platform, .ios)
46+
XCTAssertNil(decoded.bootsDevice)
47+
XCTAssertNil(decoded.tag)
48+
}
49+
50+
func testDecodingOptionalFieldsPresent() throws {
51+
let json = """
52+
{
53+
"id": "550e8400-e29b-41d4-a716-446655440000",
54+
"name": "Test",
55+
"command": "echo test",
56+
"icon": "star",
57+
"platform": "android",
58+
"needBootedDevice": true,
59+
"bootsDevice": true,
60+
"tag": 99
61+
}
62+
"""
63+
64+
let data = json.data(using: .utf8)!
65+
let decoded = try JSONDecoder().decode(Command.self, from: data)
66+
67+
XCTAssertEqual(decoded.bootsDevice, true)
68+
XCTAssertEqual(decoded.tag, 99)
69+
}
70+
71+
func testCommandHashable() {
72+
let command1 = Command(
73+
name: "Test",
74+
command: "echo",
75+
icon: "star",
76+
platform: .ios,
77+
needBootedDevice: false
78+
)
79+
80+
let command2 = Command(
81+
name: "Test",
82+
command: "echo",
83+
icon: "star",
84+
platform: .ios,
85+
needBootedDevice: false
86+
)
87+
88+
// Different UUIDs, so not equal
89+
XCTAssertNotEqual(command1, command2)
90+
91+
// Same command in set should work
92+
var commandSet: Set<Command> = []
93+
commandSet.insert(command1)
94+
commandSet.insert(command2)
95+
XCTAssertEqual(commandSet.count, 2)
96+
}
97+
98+
func testCommandIdentifiable() {
99+
let command = Command(
100+
name: "Test",
101+
command: "echo",
102+
icon: "star",
103+
platform: .ios,
104+
needBootedDevice: false
105+
)
106+
107+
XCTAssertNotNil(command.id)
108+
}
109+
}

MiniSimTests/DeviceTests.swift

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import XCTest
2+
3+
@testable import MiniSim
4+
5+
final class DeviceTests: XCTestCase {
6+
func testDisplayNameIOSWithVersion() {
7+
let device = Device(
8+
name: "iPhone 15 Pro",
9+
version: "iOS 17.5",
10+
identifier: "test-uuid",
11+
booted: false,
12+
platform: .ios,
13+
type: .virtual
14+
)
15+
16+
XCTAssertEqual(device.displayName, "iPhone 15 Pro - (iOS 17.5)")
17+
}
18+
19+
func testDisplayNameIOSWithoutVersion() {
20+
let device = Device(
21+
name: "iPhone 15 Pro",
22+
version: nil,
23+
identifier: "test-uuid",
24+
booted: false,
25+
platform: .ios,
26+
type: .virtual
27+
)
28+
29+
XCTAssertEqual(device.displayName, "iPhone 15 Pro")
30+
}
31+
32+
func testDisplayNameAndroid() {
33+
let device = Device(
34+
name: "Pixel_5_API_33",
35+
version: "13",
36+
identifier: "emulator-5554",
37+
booted: true,
38+
platform: .android,
39+
type: .virtual
40+
)
41+
42+
XCTAssertEqual(device.displayName, "Pixel_5_API_33")
43+
}
44+
45+
func testEncodingDecoding() throws {
46+
let device = Device(
47+
name: "iPhone 15 Pro",
48+
version: "iOS 17.5",
49+
identifier: "test-uuid",
50+
booted: true,
51+
platform: .ios,
52+
type: .virtual
53+
)
54+
55+
let encoded = try JSONEncoder().encode(device)
56+
let decoded = try JSONDecoder().decode(Device.self, from: encoded)
57+
58+
XCTAssertEqual(decoded.name, device.name)
59+
XCTAssertEqual(decoded.version, device.version)
60+
XCTAssertEqual(decoded.identifier, device.identifier)
61+
XCTAssertEqual(decoded.booted, device.booted)
62+
XCTAssertEqual(decoded.platform, device.platform)
63+
XCTAssertEqual(decoded.type, device.type)
64+
}
65+
66+
func testEncodingIncludesDisplayName() throws {
67+
let device = Device(
68+
name: "iPhone 15",
69+
version: "iOS 17.5",
70+
identifier: "uuid",
71+
booted: false,
72+
platform: .ios,
73+
type: .virtual
74+
)
75+
76+
let encoded = try JSONEncoder().encode(device)
77+
let json = try JSONSerialization.jsonObject(with: encoded) as? [String: Any]
78+
79+
XCTAssertEqual(json?["displayName"] as? String, "iPhone 15 - (iOS 17.5)")
80+
}
81+
}

0 commit comments

Comments
 (0)