146 lines
4.0 KiB
Swift
146 lines
4.0 KiB
Swift
import XCTest
|
||
@testable import MacTools
|
||
@testable import QuitAppsPlugin
|
||
|
||
@MainActor
|
||
final class QuitAppsPluginTests: XCTestCase {
|
||
|
||
// MARK: - Plugin Metadata
|
||
|
||
func testMetadataIdentifiesQuitAppsPlugin() {
|
||
let plugin = QuitAppsPlugin()
|
||
|
||
XCTAssertEqual(plugin.metadata.id, "quit-apps")
|
||
XCTAssertEqual(plugin.metadata.title, "退出应用")
|
||
}
|
||
|
||
func testIconIsPower() {
|
||
let plugin = QuitAppsPlugin()
|
||
|
||
XCTAssertEqual(plugin.metadata.iconName, "power")
|
||
}
|
||
|
||
func testControlStyleIsButton() {
|
||
let plugin = QuitAppsPlugin()
|
||
|
||
XCTAssertEqual(plugin.primaryPanelDescriptor.controlStyle, .button)
|
||
XCTAssertEqual(plugin.primaryPanelDescriptor.buttonTitle, "选择")
|
||
}
|
||
|
||
func testMenuActionBehaviorIsDismissBeforeHandling() {
|
||
let plugin = QuitAppsPlugin()
|
||
|
||
XCTAssertEqual(plugin.primaryPanelDescriptor.menuActionBehavior, .dismissBeforeHandling)
|
||
}
|
||
|
||
func testInitialPanelStateIsNotOn() {
|
||
let plugin = QuitAppsPlugin()
|
||
|
||
let state = plugin.primaryPanelState
|
||
XCTAssertFalse(state.isOn)
|
||
XCTAssertFalse(state.isExpanded)
|
||
XCTAssertNil(state.errorMessage)
|
||
}
|
||
|
||
func testPermissionRequirementsIsEmpty() {
|
||
let plugin = QuitAppsPlugin()
|
||
|
||
XCTAssertTrue(plugin.permissionRequirements.isEmpty)
|
||
}
|
||
|
||
func testPluginHostIncludesQuitApps() {
|
||
let host = makePluginHostForTests(plugins: [QuitAppsPlugin()])
|
||
|
||
XCTAssertTrue(host.featureManagementItems.contains { $0.id == "quit-apps" })
|
||
}
|
||
|
||
func testDescriptionMatchesManifest() {
|
||
let plugin = QuitAppsPlugin()
|
||
|
||
XCTAssertEqual(plugin.metadata.defaultDescription, "选择并退出正在运行的应用")
|
||
}
|
||
|
||
// MARK: - QuitAppsViewModel – confirmTitle
|
||
|
||
func testConfirmTitleIsQuitAllWhenNothingSelected() {
|
||
let vm = QuitAppsViewModel()
|
||
|
||
XCTAssertEqual(vm.confirmTitle, "退出全部应用")
|
||
}
|
||
|
||
func testConfirmTitleReflectsSelectionCount() {
|
||
let vm = QuitAppsViewModel()
|
||
vm.entries = [
|
||
QuitAppEntry(id: "a", app: .current, isSelected: true),
|
||
QuitAppEntry(id: "b", app: .current, isSelected: true),
|
||
QuitAppEntry(id: "c", app: .current, isSelected: false),
|
||
]
|
||
|
||
XCTAssertEqual(vm.confirmTitle, "退出 2 个应用")
|
||
}
|
||
|
||
// MARK: - QuitAppsViewModel – invertSelection
|
||
|
||
func testInvertSelectionOnEmptyEntriesIsNoop() {
|
||
let vm = QuitAppsViewModel()
|
||
vm.invertSelection()
|
||
|
||
XCTAssertTrue(vm.entries.isEmpty)
|
||
}
|
||
|
||
func testInvertSelectionTogglesAllEntries() {
|
||
let vm = QuitAppsViewModel()
|
||
vm.entries = [
|
||
QuitAppEntry(id: "a", app: .current, isSelected: false),
|
||
QuitAppEntry(id: "b", app: .current, isSelected: true),
|
||
]
|
||
|
||
vm.invertSelection()
|
||
|
||
XCTAssertTrue(vm.entries[0].isSelected)
|
||
XCTAssertFalse(vm.entries[1].isSelected)
|
||
}
|
||
|
||
// MARK: - QuitAppsViewModel – toggleEntry
|
||
|
||
func testToggleEntryChangesSelectionState() {
|
||
let vm = QuitAppsViewModel()
|
||
vm.entries = [QuitAppEntry(id: "x", app: .current, isSelected: false)]
|
||
|
||
vm.toggleEntry(id: "x")
|
||
|
||
XCTAssertTrue(vm.entries[0].isSelected)
|
||
}
|
||
|
||
func testToggleEntryUnknownIDIsNoop() {
|
||
let vm = QuitAppsViewModel()
|
||
vm.entries = [QuitAppEntry(id: "x", app: .current, isSelected: false)]
|
||
|
||
vm.toggleEntry(id: "unknown")
|
||
|
||
XCTAssertFalse(vm.entries[0].isSelected)
|
||
}
|
||
|
||
// MARK: - QuitAppsViewModel – load
|
||
|
||
func testLoadExcludesHostApp() {
|
||
let vm = QuitAppsViewModel()
|
||
vm.load()
|
||
|
||
let containsHost = vm.entries.contains { $0.id == Bundle.main.bundleIdentifier }
|
||
XCTAssertFalse(containsHost)
|
||
}
|
||
|
||
func testLoadPreservesExistingSelection() {
|
||
let vm = QuitAppsViewModel()
|
||
vm.load()
|
||
|
||
guard let first = vm.entries.first else { return }
|
||
vm.toggleEntry(id: first.id)
|
||
|
||
vm.load()
|
||
|
||
XCTAssertTrue(vm.entries.first { $0.id == first.id }?.isSelected == true)
|
||
}
|
||
}
|