Files
wehub-resource-sync 1d1286fadb
Build / Build and test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:18:38 +08:00

151 lines
4.3 KiB
Swift

import XCTest
@testable import MacTools
@testable import EmptyTrashPlugin
@MainActor
final class EmptyTrashPluginTests: XCTestCase {
func testMetadataIdentifiesEmptyTrashPlugin() {
let plugin = EmptyTrashPlugin()
XCTAssertEqual(plugin.metadata.id, "empty-trash")
XCTAssertEqual(plugin.metadata.title, "清空废纸篓")
}
func testControlStyleIsButton() {
let plugin = EmptyTrashPlugin()
XCTAssertEqual(plugin.primaryPanelDescriptor.controlStyle, .button)
XCTAssertEqual(plugin.primaryPanelDescriptor.buttonTitle, "清空")
}
func testInitialStateIsOffAndDisabled() {
let plugin = EmptyTrashPlugin()
let state = plugin.primaryPanelState
XCTAssertFalse(state.isOn)
XCTAssertFalse(state.isEnabled)
}
func testInitialSubtitleShowsEmpty() {
let plugin = EmptyTrashPlugin()
XCTAssertEqual(plugin.primaryPanelState.subtitle, "废纸篓为空")
}
func testPermissionRequirementsIsEmpty() {
let plugin = EmptyTrashPlugin()
XCTAssertTrue(plugin.permissionRequirements.isEmpty)
}
func testPluginHostIncludesEmptyTrashWhenProvided() {
let host = makePluginHostForTests(plugins: [EmptyTrashPlugin()])
XCTAssertTrue(host.featureManagementItems.contains { $0.id == "empty-trash" })
}
func testPluginDescriptionMatches() {
let plugin = EmptyTrashPlugin()
XCTAssertEqual(plugin.metadata.defaultDescription, "清空废纸篓中的所有项目")
}
func testMenuActionBehaviorIsKeepPresented() {
let plugin = EmptyTrashPlugin()
XCTAssertEqual(plugin.primaryPanelDescriptor.menuActionBehavior, .keepPresented)
}
func testRefreshDoesNotCountItemsWhilePrimaryPanelIsHidden() async {
let counter = TrashCountProbe(itemCount: 3)
let plugin = EmptyTrashPlugin(
countItems: { await counter.countItems() },
countRefreshDelay: .zero
)
plugin.refresh()
await Task.yield()
let requestCount = await counter.requestCountValue()
XCTAssertEqual(requestCount, 0)
XCTAssertFalse(plugin.primaryPanelState.isEnabled)
}
func testPrimaryPanelVisibilityRefreshesTrashCount() async {
let counter = TrashCountProbe(itemCount: 3)
let plugin = EmptyTrashPlugin(
countItems: { await counter.countItems() },
countRefreshDelay: .zero
)
plugin.panelSurfaceDidBecomeVisible(.primary)
await waitForRequestCount(1, counter: counter)
let requestCount = await counter.requestCountValue()
XCTAssertEqual(requestCount, 1)
XCTAssertTrue(plugin.primaryPanelState.isEnabled)
XCTAssertEqual(plugin.primaryPanelState.subtitle, "3 个项目")
}
func testVisibleCountRefreshesAreDebounced() async {
let counter = TrashCountProbe(itemCount: 2)
let plugin = EmptyTrashPlugin(
countItems: { await counter.countItems() },
countRefreshDelay: .zero
)
plugin.panelSurfaceDidBecomeVisible(.primary)
plugin.refresh()
plugin.refresh()
await waitForRequestCount(1, counter: counter)
for _ in 0..<5 {
await Task.yield()
}
let requestCount = await counter.requestCountValue()
XCTAssertEqual(requestCount, 1)
}
private func waitForRequestCount(
_ expectedRequestCount: Int,
counter: TrashCountProbe,
file: StaticString = #filePath,
line: UInt = #line
) async {
for _ in 0..<20 {
if await counter.requestCountValue() == expectedRequestCount {
return
}
await Task.yield()
}
try? await Task.sleep(for: .milliseconds(50))
if await counter.requestCountValue() == expectedRequestCount {
return
}
let requestCount = await counter.requestCountValue()
XCTAssertEqual(requestCount, expectedRequestCount, file: file, line: line)
}
}
private actor TrashCountProbe {
private(set) var requestCount = 0
private let itemCount: Int
init(itemCount: Int) {
self.itemCount = itemCount
}
func countItems() async -> Int {
requestCount += 1
return itemCount
}
func requestCountValue() -> Int {
requestCount
}
}