feat: learn launch suggestions and preserve selection during refresh
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import ConjureKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@Test @MainActor
|
||||
func suggestionsPreferFrequencyThenRecencyAndKeepUnusedAppsAlphabetical() {
|
||||
let suite = "ConjureHistoryTests.\(UUID().uuidString)"
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defer { defaults.removePersistentDomain(forName: suite) }
|
||||
var instant = Date(timeIntervalSinceReferenceDate: 1_000)
|
||||
let history = LaunchHistory(defaults: defaults, now: { instant })
|
||||
let apps = ["Unused Zebra", "Recent", "Frequent", "Unused Alpha", "Older"].map(historyApplication)
|
||||
#expect(history.suggestions(in: apps).map(\.name) == [
|
||||
"Frequent", "Older", "Recent", "Unused Alpha", "Unused Zebra",
|
||||
])
|
||||
|
||||
history.recordLaunch(of: apps[4])
|
||||
instant += 10
|
||||
history.recordLaunch(of: apps[2])
|
||||
history.recordLaunch(of: apps[2])
|
||||
instant += 10
|
||||
history.recordLaunch(of: apps[1])
|
||||
#expect(history.suggestions(in: apps).map(\.name) == [
|
||||
"Frequent", "Recent", "Older", "Unused Alpha", "Unused Zebra",
|
||||
])
|
||||
}
|
||||
|
||||
@Test @MainActor
|
||||
func suggestionsRetainUsageAcrossHistoryInstancesAndDoNotReintroduceMissingApps() {
|
||||
let suite = "ConjureHistoryTests.\(UUID().uuidString)"
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defer { defaults.removePersistentDomain(forName: suite) }
|
||||
let instant = Date(timeIntervalSinceReferenceDate: 2_000)
|
||||
let alpha = historyApplication("Alpha")
|
||||
let zebra = historyApplication("Zebra")
|
||||
let removed = historyApplication("Removed")
|
||||
let history = LaunchHistory(defaults: defaults, now: { instant })
|
||||
history.recordLaunch(of: zebra)
|
||||
history.recordLaunch(of: removed)
|
||||
history.recordLaunch(of: removed)
|
||||
|
||||
let reloaded = LaunchHistory(defaults: UserDefaults(suiteName: suite)!, now: { instant })
|
||||
#expect(reloaded.suggestions(in: [alpha, zebra]).map(\.name) == ["Zebra", "Alpha"])
|
||||
reloaded.recordLaunch(of: alpha)
|
||||
#expect(reloaded.suggestions(in: [zebra, alpha]).map(\.name) == ["Alpha", "Zebra"])
|
||||
}
|
||||
|
||||
@Test @MainActor
|
||||
func usageTracksApplicationIdentityRatherThanDisplayNameAndKeepsTiesDeterministic() {
|
||||
let suite = "ConjureHistoryTests.\(UUID().uuidString)"
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defer { defaults.removePersistentDomain(forName: suite) }
|
||||
let instant = Date(timeIntervalSinceReferenceDate: 3_000)
|
||||
let history = LaunchHistory(defaults: defaults, now: { instant })
|
||||
let first = Application(url: URL(fileURLWithPath: "/First/Editor.app"), name: "Editor")
|
||||
let second = Application(url: URL(fileURLWithPath: "/Second/Editor.app"), name: "Editor")
|
||||
#expect(history.suggestions(in: [second, first]).map(\.url) == [first.url, second.url])
|
||||
history.recordLaunch(of: second)
|
||||
#expect(history.suggestions(in: [first, second]).map(\.url) == [second.url, first.url])
|
||||
|
||||
let renamed = Application(url: second.url, name: "Renamed Editor")
|
||||
#expect(history.suggestions(in: [first, renamed]).map(\.url) == [second.url, first.url])
|
||||
history.recordLaunch(of: first)
|
||||
#expect(history.suggestions(in: [second, first]).map(\.url) == [first.url, second.url])
|
||||
}
|
||||
|
||||
@Test @MainActor
|
||||
func applicationIdentityIgnoresDirectoryURLFormattingInLaunchHistory() {
|
||||
let suite = "ConjureHistoryTests.\(UUID().uuidString)"
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defer { defaults.removePersistentDomain(forName: suite) }
|
||||
let instant = Date(timeIntervalSinceReferenceDate: 4_000)
|
||||
let history = LaunchHistory(defaults: defaults, now: { instant })
|
||||
let path = "/Applications/HistoryTests/Editor.app"
|
||||
let plain = Application(url: URL(fileURLWithPath: path, isDirectory: false), name: "Editor")
|
||||
let directory = Application(url: URL(fileURLWithPath: path, isDirectory: true), name: "Editor")
|
||||
#expect(plain.id == directory.id)
|
||||
history.recordLaunch(of: directory)
|
||||
#expect(history.suggestions(in: [historyApplication("Alpha"), plain]).first?.id == plain.id)
|
||||
}
|
||||
|
||||
private func historyApplication(_ name: String) -> Application {
|
||||
Application(url: URL(fileURLWithPath: "/Applications/HistoryTests/\(name).app"), name: name)
|
||||
}
|
||||
Reference in New Issue
Block a user