Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Leader Key/UserConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,20 @@ class UserConfig: ObservableObject {
let fileName = "config.json"
private let alertHandler: AlertHandler
private let fileManager: FileManager
private let defaultDirectoryResolver: () -> String
private var lastReadChecksum: String?
private var isLoading = false
private let configIOQueue = DispatchQueue(label: "ConfigIO", qos: .userInitiated)
private var saveWorkItem: DispatchWorkItem?

init(
alertHandler: AlertHandler = DefaultAlertHandler(),
fileManager: FileManager = .default
fileManager: FileManager = .default,
defaultDirectoryResolver: @escaping () -> String = UserConfig.defaultDirectory
) {
self.alertHandler = alertHandler
self.fileManager = fileManager
self.defaultDirectoryResolver = defaultDirectoryResolver
}

// MARK: - Public Interface
Expand Down Expand Up @@ -194,7 +197,7 @@ class UserConfig: ObservableObject {

private func ensureValidConfigDirectory() {
let dir = Defaults[.configDir]
let defaultDir = Self.defaultDirectory()
let defaultDir = defaultDirectoryResolver()

if !fileManager.fileExists(atPath: dir) {
alertHandler.showAlert(
Expand Down
28 changes: 20 additions & 8 deletions Leader KeyTests/UserConfigTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class TestAlertManager: AlertHandler {

final class UserConfigTests: XCTestCase {
var tempBaseDir: String!
var testDefaultDir: String!
var testAlertManager: TestAlertManager!
var subject: UserConfig!
var originalSuite: UserDefaults!
Expand All @@ -38,12 +39,21 @@ final class UserConfigTests: XCTestCase {
// Create a unique temporary directory for each test
tempBaseDir = NSTemporaryDirectory().appending("/LeaderKeyTests-\(UUID().uuidString)")
try? FileManager.default.createDirectory(atPath: tempBaseDir, withIntermediateDirectories: true)
testDefaultDir = tempBaseDir.appending("/DefaultConfigDir")

testAlertManager = TestAlertManager()
subject = UserConfig(alertHandler: testAlertManager)

// Set the config directory to our temp directory by default
// Point config dir at temp location before creating UserConfig.
Defaults[.configDir] = tempBaseDir

testAlertManager = TestAlertManager()
let isolatedDefaultDir = testDefaultDir!
subject = UserConfig(
alertHandler: testAlertManager,
defaultDirectoryResolver: {
try? FileManager.default.createDirectory(
atPath: isolatedDefaultDir, withIntermediateDirectories: true)
return isolatedDefaultDir
}
)
}

override func tearDown() {
Expand All @@ -67,7 +77,7 @@ final class UserConfigTests: XCTestCase {
}

func testCreatesDefaultConfigDirIfNotExists() throws {
let defaultDir = UserConfig.defaultDirectory()
let defaultDir = testDefaultDir!
// Remove both directory and config file
try? FileManager.default.removeItem(atPath: defaultDir)
try? FileManager.default.removeItem(
Expand All @@ -90,7 +100,7 @@ final class UserConfigTests: XCTestCase {
subject.ensureAndLoad()
waitForConfigLoad()

XCTAssertEqual(Defaults[.configDir], UserConfig.defaultDirectory())
XCTAssertEqual(Defaults[.configDir], testDefaultDir)
XCTAssertEqual(testAlertManager.shownAlerts.count, 1)
XCTAssertEqual(testAlertManager.shownAlerts[0].style, .warning)
XCTAssertTrue(
Expand All @@ -99,8 +109,10 @@ final class UserConfigTests: XCTestCase {
}

func testShowsAlertWhenConfigFileFailsToParse() throws {
// First ensure we're in the default directory since custom dirs are no longer supported
Defaults[.configDir] = UserConfig.defaultDirectory()
// Ensure we're exercising the default directory path (isolated under tempBaseDir).
Defaults[.configDir] = testDefaultDir
try? FileManager.default.createDirectory(
atPath: testDefaultDir, withIntermediateDirectories: true)

let invalidJSON = "{ invalid json }"
try invalidJSON.write(to: subject.url, atomically: true, encoding: .utf8)
Expand Down