90 lines
3.9 KiB
Swift
90 lines
3.9 KiB
Swift
import AppKit
|
|
import ConjureKit
|
|
import Testing
|
|
@testable import Conjure
|
|
|
|
@MainActor
|
|
private func descendants(_ view: NSView) -> [NSView] {
|
|
[view] + view.subviews.flatMap { descendants($0) }
|
|
}
|
|
|
|
@Test @MainActor
|
|
func uninstallFilteringPreservesDiscoveryStateAndCheckedFiles() throws {
|
|
_ = NSApplication.shared
|
|
let controller = UninstallReviewController(
|
|
application: Application(url: URL(fileURLWithPath: "/Applications/Example.app"), name: "Example"),
|
|
uninstaller: ApplicationUninstaller())
|
|
let views = descendants(controller.view)
|
|
let filter = try #require(views.compactMap { $0 as? NSSearchField }.first)
|
|
let status = try #require(views.compactMap { $0 as? NSTextField }.first {
|
|
$0.accessibilityLabel() == "Uninstall selection and progress"
|
|
})
|
|
let table = try #require(views.compactMap { $0 as? NSTableView }.first)
|
|
let remove = try #require(views.compactMap { $0 as? NSButton }.first { $0.keyEquivalent == "\r" })
|
|
func filterBy(_ query: String) {
|
|
filter.stringValue = query
|
|
controller.controlTextDidChange(Notification(name: NSControl.textDidChangeNotification, object: filter))
|
|
}
|
|
let loading = status.stringValue
|
|
filterBy("cache")
|
|
#expect(status.stringValue == loading)
|
|
#expect(!remove.isEnabled)
|
|
|
|
struct ScanFailure: LocalizedError {
|
|
var errorDescription: String? { "Access denied by the filesystem" }
|
|
}
|
|
controller.applyDiscoveryResult(.failure(ScanFailure()))
|
|
let failure = status.stringValue
|
|
#expect(failure.contains(ScanFailure().localizedDescription))
|
|
#expect(status.textColor == .systemRed)
|
|
filterBy("different")
|
|
#expect(status.stringValue == failure)
|
|
#expect(!remove.isEnabled)
|
|
|
|
let candidate = UninstallCandidate(url: URL(fileURLWithPath: "/tmp/example-cache"), size: 1024,
|
|
isSelectable: true, defaultSelected: true, reason: nil)
|
|
controller.applyDiscoveryResult(.success([candidate]))
|
|
filterBy("")
|
|
let counts = status.stringValue
|
|
#expect(status.textColor == SunsetPalette.secondaryText)
|
|
#expect(remove.isEnabled)
|
|
#expect(table.numberOfRows == 1)
|
|
filterBy("no-match")
|
|
#expect(table.numberOfRows == 0)
|
|
#expect(remove.isEnabled)
|
|
filterBy("")
|
|
#expect(status.stringValue == counts)
|
|
#expect(table.numberOfRows == 1)
|
|
_ = controller.control(filter, textView: NSTextView(), doCommandBy: #selector(NSResponder.insertNewline(_:)))
|
|
#expect(!remove.isEnabled)
|
|
}
|
|
|
|
@Test @MainActor
|
|
func shortcutModifierGuidanceDoesNotAppearAsAnError() throws {
|
|
_ = NSApplication.shared
|
|
let suite = "Conjure.ToolFeedbackTests.\(UUID().uuidString)"
|
|
let defaults = try #require(UserDefaults(suiteName: suite))
|
|
defer { defaults.removePersistentDomain(forName: suite) }
|
|
let controller = SettingsWindowController(shortcut: GlobalShortcut(defaults: defaults, action: {}))
|
|
let window = try #require(controller.window)
|
|
let views = descendants(try #require(window.contentView))
|
|
let recorder = try #require(views.compactMap { $0 as? NSButton }.first {
|
|
$0.accessibilityLabel() == "Record global shortcut"
|
|
})
|
|
let error = try #require(views.compactMap { $0 as? NSTextField }.first {
|
|
$0.accessibilityLabel() == "Shortcut feedback"
|
|
})
|
|
let status = try #require(views.compactMap { $0 as? NSTextField }.first {
|
|
$0.accessibilityLabel() == "Global shortcut registration status"
|
|
})
|
|
recorder.performClick(nil)
|
|
defer { window.close() }
|
|
#expect(window.firstResponder === recorder)
|
|
let modifier = try #require(NSEvent.keyEvent(with: .flagsChanged, location: .zero,
|
|
modifierFlags: .command, timestamp: 1, windowNumber: window.windowNumber,
|
|
context: nil, characters: "", charactersIgnoringModifiers: "", isARepeat: false, keyCode: 55))
|
|
recorder.flagsChanged(with: modifier)
|
|
#expect(error.stringValue.isEmpty)
|
|
#expect(status.textColor == SunsetPalette.secondaryText)
|
|
}
|