Skip to content

Commit 3a2ba8c

Browse files
committed
Add unit tests for the config.
1 parent 6b7703b commit 3a2ba8c

16 files changed

+2224
-14
lines changed

Anykey.xcodeproj/project.pbxproj

+141
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
C0274BC1261ABDAC00D67214 /* HotkeyConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0274BC0261ABDAC00D67214 /* HotkeyConfigTests.swift */; };
11+
C0274BDC261C068100D67214 /* TestConfigs in Resources */ = {isa = PBXBuildFile; fileRef = C0274BDB261C068100D67214 /* TestConfigs */; };
1012
C05B608225DDBC1200B0CECC /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05B608125DDBC1200B0CECC /* Notifications.swift */; };
1113
C05B608725DF28F100B0CECC /* UserDefaults+AnykeySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05B608625DF28F100B0CECC /* UserDefaults+AnykeySettings.swift */; };
1214
C05B609025E5B21200B0CECC /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = C05B608F25E5B21200B0CECC /* README.md */; };
@@ -23,7 +25,21 @@
2325
C0E386B925D60D3D006D9B7D /* FileWatcher in Frameworks */ = {isa = PBXBuildFile; productRef = C0E386B825D60D3D006D9B7D /* FileWatcher */; };
2426
/* End PBXBuildFile section */
2527

28+
/* Begin PBXContainerItemProxy section */
29+
C0274BB7261ABD6A00D67214 /* PBXContainerItemProxy */ = {
30+
isa = PBXContainerItemProxy;
31+
containerPortal = C0E3866525D1E60F006D9B7D /* Project object */;
32+
proxyType = 1;
33+
remoteGlobalIDString = C0E3866C25D1E60F006D9B7D;
34+
remoteInfo = Anykey;
35+
};
36+
/* End PBXContainerItemProxy section */
37+
2638
/* Begin PBXFileReference section */
39+
C0274BB2261ABD6A00D67214 /* AnykeyUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AnykeyUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
40+
C0274BB6261ABD6A00D67214 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
41+
C0274BC0261ABDAC00D67214 /* HotkeyConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HotkeyConfigTests.swift; sourceTree = "<group>"; };
42+
C0274BDB261C068100D67214 /* TestConfigs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = TestConfigs; sourceTree = "<group>"; };
2743
C05B608125DDBC1200B0CECC /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
2844
C05B608625DF28F100B0CECC /* UserDefaults+AnykeySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+AnykeySettings.swift"; sourceTree = "<group>"; };
2945
C05B608F25E5B21200B0CECC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; };
@@ -42,6 +58,13 @@
4258
/* End PBXFileReference section */
4359

4460
/* Begin PBXFrameworksBuildPhase section */
61+
C0274BAF261ABD6A00D67214 /* Frameworks */ = {
62+
isa = PBXFrameworksBuildPhase;
63+
buildActionMask = 2147483647;
64+
files = (
65+
);
66+
runOnlyForDeploymentPostprocessing = 0;
67+
};
4568
C0E3866A25D1E60F006D9B7D /* Frameworks */ = {
4669
isa = PBXFrameworksBuildPhase;
4770
buildActionMask = 2147483647;
@@ -54,10 +77,21 @@
5477
/* End PBXFrameworksBuildPhase section */
5578

5679
/* Begin PBXGroup section */
80+
C0274BB3261ABD6A00D67214 /* AnykeyUnitTests */ = {
81+
isa = PBXGroup;
82+
children = (
83+
C0274BDB261C068100D67214 /* TestConfigs */,
84+
C0274BB6261ABD6A00D67214 /* Info.plist */,
85+
C0274BC0261ABDAC00D67214 /* HotkeyConfigTests.swift */,
86+
);
87+
path = AnykeyUnitTests;
88+
sourceTree = "<group>";
89+
};
5790
C0E3866425D1E60F006D9B7D = {
5891
isa = PBXGroup;
5992
children = (
6093
C0E3866F25D1E60F006D9B7D /* Anykey */,
94+
C0274BB3261ABD6A00D67214 /* AnykeyUnitTests */,
6195
C0E3866E25D1E60F006D9B7D /* Products */,
6296
);
6397
sourceTree = "<group>";
@@ -66,6 +100,7 @@
66100
isa = PBXGroup;
67101
children = (
68102
C0E3866D25D1E60F006D9B7D /* Anykey.app */,
103+
C0274BB2261ABD6A00D67214 /* AnykeyUnitTests.xctest */,
69104
);
70105
name = Products;
71106
sourceTree = "<group>";
@@ -102,6 +137,24 @@
102137
/* End PBXGroup section */
103138

104139
/* Begin PBXNativeTarget section */
140+
C0274BB1261ABD6A00D67214 /* AnykeyUnitTests */ = {
141+
isa = PBXNativeTarget;
142+
buildConfigurationList = C0274BBB261ABD6A00D67214 /* Build configuration list for PBXNativeTarget "AnykeyUnitTests" */;
143+
buildPhases = (
144+
C0274BAE261ABD6A00D67214 /* Sources */,
145+
C0274BAF261ABD6A00D67214 /* Frameworks */,
146+
C0274BB0261ABD6A00D67214 /* Resources */,
147+
);
148+
buildRules = (
149+
);
150+
dependencies = (
151+
C0274BB8261ABD6A00D67214 /* PBXTargetDependency */,
152+
);
153+
name = AnykeyUnitTests;
154+
productName = AnykeyUnitTests;
155+
productReference = C0274BB2261ABD6A00D67214 /* AnykeyUnitTests.xctest */;
156+
productType = "com.apple.product-type.bundle.unit-test";
157+
};
105158
C0E3866C25D1E60F006D9B7D /* Anykey */ = {
106159
isa = PBXNativeTarget;
107160
buildConfigurationList = C0E3868025D1E611006D9B7D /* Build configuration list for PBXNativeTarget "Anykey" */;
@@ -132,6 +185,11 @@
132185
LastSwiftUpdateCheck = 1240;
133186
LastUpgradeCheck = 1240;
134187
TargetAttributes = {
188+
C0274BB1261ABD6A00D67214 = {
189+
CreatedOnToolsVersion = 12.4;
190+
LastSwiftMigration = 1240;
191+
TestTargetID = C0E3866C25D1E60F006D9B7D;
192+
};
135193
C0E3866C25D1E60F006D9B7D = {
136194
CreatedOnToolsVersion = 12.4;
137195
};
@@ -155,11 +213,20 @@
155213
projectRoot = "";
156214
targets = (
157215
C0E3866C25D1E60F006D9B7D /* Anykey */,
216+
C0274BB1261ABD6A00D67214 /* AnykeyUnitTests */,
158217
);
159218
};
160219
/* End PBXProject section */
161220

162221
/* Begin PBXResourcesBuildPhase section */
222+
C0274BB0261ABD6A00D67214 /* Resources */ = {
223+
isa = PBXResourcesBuildPhase;
224+
buildActionMask = 2147483647;
225+
files = (
226+
C0274BDC261C068100D67214 /* TestConfigs in Resources */,
227+
);
228+
runOnlyForDeploymentPostprocessing = 0;
229+
};
163230
C0E3866B25D1E60F006D9B7D /* Resources */ = {
164231
isa = PBXResourcesBuildPhase;
165232
buildActionMask = 2147483647;
@@ -175,6 +242,14 @@
175242
/* End PBXResourcesBuildPhase section */
176243

177244
/* Begin PBXSourcesBuildPhase section */
245+
C0274BAE261ABD6A00D67214 /* Sources */ = {
246+
isa = PBXSourcesBuildPhase;
247+
buildActionMask = 2147483647;
248+
files = (
249+
C0274BC1261ABDAC00D67214 /* HotkeyConfigTests.swift in Sources */,
250+
);
251+
runOnlyForDeploymentPostprocessing = 0;
252+
};
178253
C0E3866925D1E60F006D9B7D /* Sources */ = {
179254
isa = PBXSourcesBuildPhase;
180255
buildActionMask = 2147483647;
@@ -191,7 +266,64 @@
191266
};
192267
/* End PBXSourcesBuildPhase section */
193268

269+
/* Begin PBXTargetDependency section */
270+
C0274BB8261ABD6A00D67214 /* PBXTargetDependency */ = {
271+
isa = PBXTargetDependency;
272+
target = C0E3866C25D1E60F006D9B7D /* Anykey */;
273+
targetProxy = C0274BB7261ABD6A00D67214 /* PBXContainerItemProxy */;
274+
};
275+
/* End PBXTargetDependency section */
276+
194277
/* Begin XCBuildConfiguration section */
278+
C0274BB9261ABD6A00D67214 /* Debug */ = {
279+
isa = XCBuildConfiguration;
280+
buildSettings = {
281+
BUNDLE_LOADER = "$(TEST_HOST)";
282+
CLANG_ENABLE_MODULES = YES;
283+
CODE_SIGN_IDENTITY = "-";
284+
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = YES;
285+
CODE_SIGN_STYLE = Automatic;
286+
COMBINE_HIDPI_IMAGES = YES;
287+
INFOPLIST_FILE = AnykeyUnitTests/Info.plist;
288+
LD_RUNPATH_SEARCH_PATHS = (
289+
"$(inherited)",
290+
"@executable_path/../Frameworks",
291+
"@loader_path/../Frameworks",
292+
);
293+
MACOSX_DEPLOYMENT_TARGET = 11.1;
294+
OTHER_CODE_SIGN_FLAGS = "";
295+
PRODUCT_BUNDLE_IDENTIFIER = com.temochka.AnykeyUnitTests;
296+
PRODUCT_NAME = "$(TARGET_NAME)";
297+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
298+
SWIFT_VERSION = 5.0;
299+
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Anykey.app/Contents/MacOS/Anykey";
300+
};
301+
name = Debug;
302+
};
303+
C0274BBA261ABD6A00D67214 /* Release */ = {
304+
isa = XCBuildConfiguration;
305+
buildSettings = {
306+
BUNDLE_LOADER = "$(TEST_HOST)";
307+
CLANG_ENABLE_MODULES = YES;
308+
CODE_SIGN_IDENTITY = "-";
309+
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = YES;
310+
CODE_SIGN_STYLE = Automatic;
311+
COMBINE_HIDPI_IMAGES = YES;
312+
INFOPLIST_FILE = AnykeyUnitTests/Info.plist;
313+
LD_RUNPATH_SEARCH_PATHS = (
314+
"$(inherited)",
315+
"@executable_path/../Frameworks",
316+
"@loader_path/../Frameworks",
317+
);
318+
MACOSX_DEPLOYMENT_TARGET = 11.1;
319+
OTHER_CODE_SIGN_FLAGS = "";
320+
PRODUCT_BUNDLE_IDENTIFIER = com.temochka.AnykeyUnitTests;
321+
PRODUCT_NAME = "$(TARGET_NAME)";
322+
SWIFT_VERSION = 5.0;
323+
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Anykey.app/Contents/MacOS/Anykey";
324+
};
325+
name = Release;
326+
};
195327
C0E3867E25D1E611006D9B7D /* Debug */ = {
196328
isa = XCBuildConfiguration;
197329
buildSettings = {
@@ -358,6 +490,15 @@
358490
/* End XCBuildConfiguration section */
359491

360492
/* Begin XCConfigurationList section */
493+
C0274BBB261ABD6A00D67214 /* Build configuration list for PBXNativeTarget "AnykeyUnitTests" */ = {
494+
isa = XCConfigurationList;
495+
buildConfigurations = (
496+
C0274BB9261ABD6A00D67214 /* Debug */,
497+
C0274BBA261ABD6A00D67214 /* Release */,
498+
);
499+
defaultConfigurationIsVisible = 0;
500+
defaultConfigurationName = Release;
501+
};
361502
C0E3866825D1E60F006D9B7D /* Build configuration list for PBXProject "Anykey" */ = {
362503
isa = XCConfigurationList;
363504
buildConfigurations = (

Anykey.xcodeproj/xcshareddata/xcschemes/Anykey.xcscheme

+10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
2929
shouldUseLaunchSchemeArgsEnv = "YES">
3030
<Testables>
31+
<TestableReference
32+
skipped = "NO">
33+
<BuildableReference
34+
BuildableIdentifier = "primary"
35+
BlueprintIdentifier = "C0274BB1261ABD6A00D67214"
36+
BuildableName = "AnykeyUnitTests.xctest"
37+
BlueprintName = "AnykeyUnitTests"
38+
ReferencedContainer = "container:Anykey.xcodeproj">
39+
</BuildableReference>
40+
</TestableReference>
3141
</Testables>
3242
</TestAction>
3343
<LaunchAction

Anykey/AppDelegate.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
104104
private func loadConfig() {
105105
do {
106106
os_log("Reloading hotkey config at %s", log: OSLog.default, type: .debug, self.configPath())
107-
config = try HotkeyConfig(filePath: configPath())
107+
config = try HotkeyConfig(url: URL(fileURLWithPath: configPath()))
108108
} catch let error as ConfigError {
109109
os_log("Error when loading the config at %s", log: OSLog.default, type: .error, self.configPath())
110110
notifications.configError(error: error)

Anykey/HotkeyConfig.swift

+9-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Cocoa
99
import Foundation
1010
import OSLog
1111

12-
enum ConfigError : Error {
12+
enum ConfigError : Error, Equatable {
1313
case access(String)
1414
case invalid(String)
1515
case unknown(String)
@@ -20,7 +20,7 @@ extension NSEvent.ModifierFlags : Decodable {
2020
let jsonModifiers = try decoder.singleValueContainer().decode([String].self)
2121

2222
guard !jsonModifiers.isEmpty else {
23-
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Found an empty array of modifiers"))
23+
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Found an empty array of modifiers."))
2424
}
2525

2626
self = NSEvent.ModifierFlags(try jsonModifiers.map { mod in
@@ -36,7 +36,7 @@ extension NSEvent.ModifierFlags : Decodable {
3636
case "fn", "function":
3737
return .function
3838
default:
39-
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown modifier \(mod)"))
39+
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown modifier \(mod)."))
4040
}
4141
})
4242
}
@@ -46,7 +46,7 @@ extension Key : Decodable {
4646
public init(from decoder: Decoder) throws {
4747
let jsonKey = try decoder.singleValueContainer().decode(String.self)
4848
guard let knownKey = Key(string: jsonKey) else {
49-
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown key \(jsonKey)"))
49+
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unknown key \(jsonKey)."))
5050
}
5151
self = knownKey
5252
}
@@ -81,27 +81,26 @@ struct HotkeyConfig : Decodable {
8181
let workingDirectory: String?
8282
var isEmpty: Bool { hotkeys.isEmpty }
8383

84-
init(filePath: String) throws {
85-
let url = URL(fileURLWithPath: filePath)
84+
init(url: URL) throws {
8685
do {
8786
let data = try Data(contentsOf: url)
8887
let decoder = JSONDecoder()
8988
self = try decoder.decode(HotkeyConfig.self, from: data)
9089
} catch CocoaError.fileNoSuchFile, CocoaError.fileReadNoSuchFile {
91-
throw ConfigError.access("configuration file is missing")
90+
throw ConfigError.access("The specified configuration file is missing.")
9291
} catch CocoaError.fileLocking, CocoaError.fileReadCorruptFile, CocoaError.fileReadNoPermission, CocoaError.fileReadTooLarge {
93-
throw ConfigError.access("couldn’t read from the configuration file")
92+
throw ConfigError.access("Couldn’t read from the configuration file.")
9493
} catch let error as ConfigError {
9594
os_log("Error when loading the config: %s", log: OSLog.default, type: .error, error.localizedDescription)
9695
throw error
9796
} catch DecodingError.keyNotFound(let key, let context) {
9897
os_log("Config parse error: %s", context.debugDescription)
99-
throw ConfigError.invalid("Missing required key \(key.stringValue)")
98+
throw ConfigError.invalid("Missing required key \(key.stringValue).")
10099
} catch DecodingError.valueNotFound(_, let context),
101100
DecodingError.typeMismatch(_, let context),
102101
DecodingError.dataCorrupted(let context) {
103102
os_log("Config parse error: %s", context.debugDescription)
104-
throw ConfigError.invalid("Invalid value for key \(context.codingPath.last?.stringValue ?? ""). \(context.debugDescription)")
103+
throw ConfigError.invalid("Invalid value for \(context.codingPath.last?.stringValue ?? "config root"). \(context.debugDescription)")
105104
} catch {
106105
os_log("Unexpected error %s when loading the config", log: OSLog.default, type: .error, error.localizedDescription)
107106
throw ConfigError.unknown("Unknown error when reading from the configuration file. Please check the log.")

Anykey/Key.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,10 @@ public enum Key {
199199
case "minus", "-": self = .minus
200200
case "eight", "8": self = .eight
201201
case "zero", "0": self = .zero
202-
case "rightBracket", "]": self = .rightBracket
202+
case "rightbracket", "]": self = .rightBracket
203203
case "o": self = .o
204204
case "u": self = .u
205-
case "leftBracket", "[": self = .leftBracket
205+
case "leftbracket", "[": self = .leftBracket
206206
case "i": self = .i
207207
case "p": self = .p
208208
case "l": self = .l

Anykey/PreferencesView.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct PreferencesView: View {
3535

3636
dynamic var configStatus: ConfigStatus {
3737
do {
38-
_ = try HotkeyConfig(filePath: NSString(string: self.configPathText).expandingTildeInPath)
38+
_ = try HotkeyConfig(url: URL(fileURLWithPath: NSString(string: self.configPathText).expandingTildeInPath))
3939
return .valid
4040
} catch let error as ConfigError {
4141
switch error {

0 commit comments

Comments
 (0)