669 lines
23 KiB
Swift
669 lines
23 KiB
Swift
import XCTest
|
|
import MacToolsPluginKit
|
|
@testable import MacTools
|
|
@testable import MouseEnhancerPlugin
|
|
|
|
@MainActor
|
|
private final class MouseEnhancerMemoryStorage: PluginStorage {
|
|
var values: [String: Any] = [:]
|
|
|
|
func object(forKey key: String) -> Any? {
|
|
values[key]
|
|
}
|
|
|
|
func data(forKey key: String) -> Data? {
|
|
values[key] as? Data
|
|
}
|
|
|
|
func string(forKey key: String) -> String? {
|
|
values[key] as? String
|
|
}
|
|
|
|
func stringArray(forKey key: String) -> [String]? {
|
|
values[key] as? [String]
|
|
}
|
|
|
|
func integer(forKey key: String) -> Int {
|
|
values[key] as? Int ?? 0
|
|
}
|
|
|
|
func bool(forKey key: String) -> Bool {
|
|
values[key] as? Bool ?? false
|
|
}
|
|
|
|
func set(_ value: Any?, forKey key: String) {
|
|
values[key] = value
|
|
}
|
|
|
|
func removeObject(forKey key: String) {
|
|
values.removeValue(forKey: key)
|
|
}
|
|
|
|
func migrateValueIfNeeded(fromLegacyKey legacyKey: String, to key: String) {
|
|
guard values[key] == nil, let value = values[legacyKey] else {
|
|
return
|
|
}
|
|
|
|
values[key] = value
|
|
values.removeValue(forKey: legacyKey)
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
private final class MockMouseEnhancerSession: MouseEnhancerSessionManaging {
|
|
private(set) var state: MouseEnhancerSessionState = .inactive
|
|
private(set) var activatedConfigurations: [MouseEnhancerConfiguration] = []
|
|
private(set) var updatedConfigurations: [MouseEnhancerConfiguration] = []
|
|
private(set) var deactivateCallCount = 0
|
|
var activationSucceeds = true
|
|
|
|
@discardableResult
|
|
func activate(configuration: MouseEnhancerConfiguration) -> Bool {
|
|
activatedConfigurations.append(configuration)
|
|
state.scrollTapInstalled = activationSucceeds
|
|
state.gestureTapInstalled = activationSucceeds
|
|
return activationSucceeds
|
|
}
|
|
|
|
func update(configuration: MouseEnhancerConfiguration) {
|
|
updatedConfigurations.append(configuration)
|
|
}
|
|
|
|
func deactivate() {
|
|
deactivateCallCount += 1
|
|
state = .inactive
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
private final class MockMouseEnhancerMiddleClickSession: MouseEnhancerMiddleClickSessionManaging {
|
|
private(set) var assignedFingerCounts: [Int] = []
|
|
private(set) var activateCallCount = 0
|
|
private(set) var deactivateCallCount = 0
|
|
|
|
var requiredFingerCount: Int = 3 {
|
|
didSet {
|
|
assignedFingerCounts.append(requiredFingerCount)
|
|
}
|
|
}
|
|
|
|
func activate() {
|
|
activateCallCount += 1
|
|
}
|
|
|
|
func deactivate() {
|
|
deactivateCallCount += 1
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
final class MouseEnhancerPluginTests: XCTestCase {
|
|
func testMetadataIdentifiesPlugin() {
|
|
let plugin = makePlugin()
|
|
|
|
XCTAssertEqual(plugin.metadata.id, "mouse-enhancer")
|
|
XCTAssertEqual(plugin.metadata.title, "鼠标增强")
|
|
XCTAssertEqual(plugin.primaryPanelDescriptor.controlStyle, .button)
|
|
XCTAssertEqual(plugin.primaryPanelDescriptor.buttonTitle, "设置")
|
|
}
|
|
|
|
func testDefaultConfigurationStartsWithAllDirectionsOff() {
|
|
let store = MouseEnhancerStore(storage: MouseEnhancerMemoryStorage())
|
|
|
|
XCTAssertFalse(store.configuration.reverseMouseHorizontal)
|
|
XCTAssertFalse(store.configuration.reverseMouseVertical)
|
|
XCTAssertFalse(store.configuration.reverseTrackpadHorizontal)
|
|
XCTAssertFalse(store.configuration.reverseTrackpadVertical)
|
|
XCTAssertFalse(store.configuration.middleClickEnabled)
|
|
XCTAssertEqual(store.configuration.middleClickFingerCount, 3)
|
|
XCTAssertFalse(store.configuration.shouldInstallEventTap)
|
|
}
|
|
|
|
func testStoreIgnoresLegacyMiddleClickStorageKeys() {
|
|
let storage = MouseEnhancerMemoryStorage()
|
|
storage.values["middle-click.enabled"] = true
|
|
storage.values["middle-click.required-finger-count"] = 5
|
|
|
|
let store = MouseEnhancerStore(storage: storage)
|
|
|
|
XCTAssertFalse(store.configuration.middleClickEnabled)
|
|
XCTAssertEqual(store.configuration.middleClickFingerCount, 3)
|
|
}
|
|
|
|
func testMiddleClickConfigurationPersistsUnderMouseEnhancerKeys() {
|
|
let storage = MouseEnhancerMemoryStorage()
|
|
let store = MouseEnhancerStore(storage: storage)
|
|
|
|
store.setMiddleClickEnabled(true)
|
|
store.setMiddleClickFingerCount(5)
|
|
|
|
XCTAssertEqual(storage.values["mouse-enhancer.middle-click.enabled"] as? Bool, true)
|
|
XCTAssertEqual(storage.values["mouse-enhancer.middle-click.finger-count"] as? Int, 5)
|
|
}
|
|
|
|
func testPanelButtonRequestsConfigurationPresentation() {
|
|
let plugin = makePlugin()
|
|
var didRequestConfigurationPresentation = false
|
|
plugin.requestConfigurationPresentation = {
|
|
didRequestConfigurationPresentation = true
|
|
}
|
|
|
|
plugin.handleAction(.invokeAction(controlID: "execute"))
|
|
|
|
XCTAssertTrue(didRequestConfigurationPresentation)
|
|
}
|
|
|
|
func testConfigurationChangeEnablesSessionWhenAccessibilityGranted() {
|
|
let session = MockMouseEnhancerSession()
|
|
let plugin = makePlugin(session: session, accessibilityTrusted: true)
|
|
|
|
plugin.store.setReverseMouseVertical(true)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertEqual(session.activatedConfigurations.count, 1)
|
|
XCTAssertTrue(session.activatedConfigurations[0].reverseMouseVertical)
|
|
XCTAssertFalse(session.activatedConfigurations[0].reverseMouseHorizontal)
|
|
}
|
|
|
|
func testConfigurationChangeRequestsPermissionWhenAccessibilityDenied() {
|
|
let session = MockMouseEnhancerSession()
|
|
var didRequestPermission = false
|
|
let plugin = makePlugin(
|
|
session: session,
|
|
accessibilityTrusted: false,
|
|
requestAccessibilityTrust: false
|
|
)
|
|
plugin.requestPermissionGuidance = { id in
|
|
didRequestPermission = id == "accessibility"
|
|
}
|
|
|
|
plugin.store.setReverseMouseVertical(true)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertTrue(didRequestPermission)
|
|
XCTAssertTrue(session.activatedConfigurations.isEmpty)
|
|
XCTAssertNotNil(plugin.primaryPanelState.errorMessage)
|
|
}
|
|
|
|
func testTurningOffAllDirectionsStopsSession() {
|
|
let session = MockMouseEnhancerSession()
|
|
let plugin = makePlugin(session: session, accessibilityTrusted: true)
|
|
|
|
plugin.store.setReverseMouseVertical(true)
|
|
plugin.configurationDidChange()
|
|
plugin.store.setReverseMouseVertical(false)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertFalse(plugin.store.configuration.shouldInstallEventTap)
|
|
XCTAssertGreaterThanOrEqual(session.deactivateCallCount, 1)
|
|
}
|
|
|
|
func testConfigurationChangeUpdatesRunningSession() {
|
|
let session = MockMouseEnhancerSession()
|
|
let plugin = makePlugin(session: session, accessibilityTrusted: true)
|
|
|
|
plugin.store.setReverseMouseVertical(true)
|
|
plugin.configurationDidChange()
|
|
plugin.store.setReverseMouseHorizontal(true)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertFalse(session.updatedConfigurations.isEmpty)
|
|
XCTAssertTrue(session.updatedConfigurations.last?.reverseMouseHorizontal == true)
|
|
}
|
|
|
|
func testMiddleClickStartsWhenEnabledAndAccessibilityGranted() {
|
|
let scrollSession = MockMouseEnhancerSession()
|
|
let middleClickSession = MockMouseEnhancerMiddleClickSession()
|
|
let plugin = makePlugin(
|
|
session: scrollSession,
|
|
middleClickSession: middleClickSession,
|
|
accessibilityTrusted: true
|
|
)
|
|
|
|
plugin.store.setMiddleClickFingerCount(4)
|
|
plugin.store.setMiddleClickEnabled(true)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertTrue(scrollSession.activatedConfigurations.isEmpty)
|
|
XCTAssertEqual(middleClickSession.activateCallCount, 1)
|
|
XCTAssertEqual(middleClickSession.requiredFingerCount, 4)
|
|
}
|
|
|
|
func testMiddleClickFingerCountChangeUpdatesRunningSession() {
|
|
let middleClickSession = MockMouseEnhancerMiddleClickSession()
|
|
let plugin = makePlugin(
|
|
middleClickSession: middleClickSession,
|
|
accessibilityTrusted: true
|
|
)
|
|
|
|
plugin.store.setMiddleClickEnabled(true)
|
|
plugin.configurationDidChange()
|
|
plugin.store.setMiddleClickFingerCount(5)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertEqual(middleClickSession.activateCallCount, 1)
|
|
XCTAssertEqual(middleClickSession.requiredFingerCount, 5)
|
|
XCTAssertTrue(middleClickSession.assignedFingerCounts.contains(5))
|
|
}
|
|
|
|
func testTurningMiddleClickOffStopsSession() {
|
|
let middleClickSession = MockMouseEnhancerMiddleClickSession()
|
|
let plugin = makePlugin(
|
|
middleClickSession: middleClickSession,
|
|
accessibilityTrusted: true
|
|
)
|
|
|
|
plugin.store.setMiddleClickEnabled(true)
|
|
plugin.configurationDidChange()
|
|
plugin.store.setMiddleClickEnabled(false)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertEqual(middleClickSession.activateCallCount, 1)
|
|
XCTAssertEqual(middleClickSession.deactivateCallCount, 1)
|
|
}
|
|
|
|
func testMiddleClickRequestsPermissionWhenAccessibilityDenied() {
|
|
let middleClickSession = MockMouseEnhancerMiddleClickSession()
|
|
var didRequestPermission = false
|
|
let plugin = makePlugin(
|
|
middleClickSession: middleClickSession,
|
|
accessibilityTrusted: false,
|
|
requestAccessibilityTrust: false
|
|
)
|
|
plugin.requestPermissionGuidance = { id in
|
|
didRequestPermission = id == "accessibility"
|
|
}
|
|
|
|
plugin.store.setMiddleClickEnabled(true)
|
|
plugin.configurationDidChange()
|
|
|
|
XCTAssertTrue(didRequestPermission)
|
|
XCTAssertEqual(middleClickSession.activateCallCount, 0)
|
|
XCTAssertEqual(plugin.primaryPanelState.subtitle, "启用前需要辅助功能授权")
|
|
XCTAssertNotNil(plugin.primaryPanelState.errorMessage)
|
|
}
|
|
|
|
func testPermissionRequirementsIncludeAccessibilityAndInputMonitoring() {
|
|
let plugin = makePlugin()
|
|
|
|
XCTAssertEqual(plugin.permissionRequirements.map(\.id), ["accessibility", "input-monitoring"])
|
|
}
|
|
|
|
func testPluginHostIncludesMouseEnhancerPlugin() {
|
|
let host = makePluginHostForTests(plugins: [makePlugin(accessibilityTrusted: true)])
|
|
|
|
XCTAssertTrue(host.featureManagementItems.contains { $0.id == "mouse-enhancer" })
|
|
}
|
|
|
|
func testProcessorReversesDiscreteMouseVerticalDeltas() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: true,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
let result = processor.process(
|
|
snapshot: .discreteWheel,
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 3,
|
|
deltaAxis2: 4,
|
|
pointDeltaAxis1: 24,
|
|
pointDeltaAxis2: 32,
|
|
fixedPointDeltaAxis1: 3,
|
|
fixedPointDeltaAxis2: 4
|
|
)
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .mouse)
|
|
XCTAssertTrue(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, -3)
|
|
XCTAssertEqual(result.deltas.pointDeltaAxis1, -24)
|
|
XCTAssertEqual(result.deltas.fixedPointDeltaAxis1, -3)
|
|
XCTAssertEqual(result.deltas.deltaAxis2, 4)
|
|
}
|
|
|
|
func testProcessorReversesHorizontalOnlyWhenConfigured() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: true,
|
|
reverseMouseVertical: false,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
let result = processor.process(
|
|
snapshot: .discreteWheel,
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 3,
|
|
deltaAxis2: 4,
|
|
pointDeltaAxis1: 24,
|
|
pointDeltaAxis2: 32,
|
|
fixedPointDeltaAxis1: 3,
|
|
fixedPointDeltaAxis2: 4
|
|
)
|
|
)
|
|
|
|
XCTAssertEqual(result.deltas.deltaAxis1, 3)
|
|
XCTAssertEqual(result.deltas.deltaAxis2, -4)
|
|
XCTAssertEqual(result.deltas.pointDeltaAxis2, -32)
|
|
XCTAssertEqual(result.deltas.fixedPointDeltaAxis2, -4)
|
|
}
|
|
|
|
func testProcessorClassifiesRecentGestureScrollAsTrackpad() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: false,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: true
|
|
)
|
|
)
|
|
|
|
processor.setGestureMonitoringAvailable(true)
|
|
processor.recordGestureTouchingCount(2, timestamp: 1_000)
|
|
let result = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 1,
|
|
momentumPhase: 0
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 10,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 0
|
|
),
|
|
timestamp: 1_000 + 10_000_000
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .trackpad)
|
|
XCTAssertTrue(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, -2)
|
|
}
|
|
|
|
func testProcessorReversesTrackpadHorizontalIndependently() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: false,
|
|
reverseTrackpadHorizontal: true,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
processor.setGestureMonitoringAvailable(true)
|
|
processor.recordGestureTouchingCount(2, timestamp: 1_000)
|
|
let result = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 1,
|
|
momentumPhase: 0
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 4,
|
|
pointDeltaAxis1: 10,
|
|
pointDeltaAxis2: 20,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 4
|
|
),
|
|
timestamp: 1_000 + 10_000_000
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .trackpad)
|
|
XCTAssertTrue(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, 2)
|
|
XCTAssertEqual(result.deltas.deltaAxis2, -4)
|
|
}
|
|
|
|
func testProcessorTreatsPhaseLessContinuousScrollAsMouse() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: true,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
processor.setGestureMonitoringAvailable(false)
|
|
let result = processor.process(
|
|
snapshot: .phaseLessContinuousWheel,
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 10,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 0
|
|
)
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .mouse)
|
|
XCTAssertTrue(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, -2)
|
|
}
|
|
|
|
func testProcessorConservativelyTreatsContinuousPhaseWithoutGestureAsTrackpad() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: true,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
let result = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 1,
|
|
momentumPhase: 0
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 10,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 0
|
|
)
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .trackpad)
|
|
XCTAssertFalse(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, 2)
|
|
}
|
|
|
|
func testProcessorClassifiesStaleNormalContinuousScrollAsMouseAfterGestureMonitoringStarts() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: true,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
processor.setGestureMonitoringAvailable(true)
|
|
let result = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 1,
|
|
momentumPhase: 0
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 10,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 0
|
|
),
|
|
timestamp: 500_000_000
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .mouse)
|
|
XCTAssertTrue(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, -2)
|
|
}
|
|
|
|
func testProcessorDoesNotReverseWhenNoDirectionIsEnabled() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: false,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
let result = processor.process(
|
|
snapshot: .discreteWheel,
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 3,
|
|
pointDeltaAxis1: 16,
|
|
pointDeltaAxis2: 24,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 3
|
|
)
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .mouse)
|
|
XCTAssertFalse(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, 2)
|
|
XCTAssertEqual(result.deltas.deltaAxis2, 3)
|
|
}
|
|
|
|
func testProcessorKeepsTrackpadSourceForMomentumAfterTrackpadGesture() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: false,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: true
|
|
)
|
|
)
|
|
|
|
processor.setGestureMonitoringAvailable(true)
|
|
processor.recordGestureTouchingCount(2, timestamp: 1_000)
|
|
_ = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 1,
|
|
momentumPhase: 0
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 10,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 0
|
|
),
|
|
timestamp: 10_000_000
|
|
)
|
|
|
|
let result = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 0,
|
|
momentumPhase: 1
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 1,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 8,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 1,
|
|
fixedPointDeltaAxis2: 0
|
|
),
|
|
timestamp: 400_000_000
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .trackpad)
|
|
XCTAssertTrue(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, -1)
|
|
}
|
|
|
|
func testProcessorResetsClassificationStateWhenGestureMonitoringStops() {
|
|
let processor = MouseScrollEventProcessor(
|
|
configuration: MouseEnhancerConfiguration(
|
|
reverseMouseHorizontal: false,
|
|
reverseMouseVertical: true,
|
|
reverseTrackpadHorizontal: false,
|
|
reverseTrackpadVertical: false
|
|
)
|
|
)
|
|
|
|
processor.setGestureMonitoringAvailable(true)
|
|
processor.recordGestureTouchingCount(2, timestamp: 1_000)
|
|
_ = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 1,
|
|
momentumPhase: 0
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 2,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 10,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 2,
|
|
fixedPointDeltaAxis2: 0
|
|
),
|
|
timestamp: 10_000_000
|
|
)
|
|
|
|
processor.setGestureMonitoringAvailable(false)
|
|
let result = processor.process(
|
|
snapshot: MouseScrollEventSnapshot(
|
|
isContinuous: true,
|
|
scrollPhase: 0,
|
|
momentumPhase: 1
|
|
),
|
|
deltas: MouseScrollDeltas(
|
|
deltaAxis1: 1,
|
|
deltaAxis2: 0,
|
|
pointDeltaAxis1: 8,
|
|
pointDeltaAxis2: 0,
|
|
fixedPointDeltaAxis1: 1,
|
|
fixedPointDeltaAxis2: 0
|
|
),
|
|
timestamp: 400_000_000
|
|
)
|
|
|
|
XCTAssertEqual(result.source, .trackpad)
|
|
XCTAssertFalse(result.shouldReverse)
|
|
XCTAssertEqual(result.deltas.deltaAxis1, 1)
|
|
}
|
|
|
|
private func makePlugin(
|
|
session: MockMouseEnhancerSession? = nil,
|
|
middleClickSession: MockMouseEnhancerMiddleClickSession? = nil,
|
|
accessibilityTrusted: Bool = true,
|
|
requestAccessibilityTrust: Bool = true,
|
|
inputMonitoringStatus: MouseEnhancerInputMonitoringAuthorizationStatus = .granted
|
|
) -> MouseEnhancerPlugin {
|
|
let storage = MouseEnhancerMemoryStorage()
|
|
return MouseEnhancerPlugin(
|
|
context: PluginRuntimeContext(pluginID: "mouse-enhancer", storage: storage),
|
|
session: session ?? MockMouseEnhancerSession(),
|
|
makeMiddleClickSession: {
|
|
middleClickSession ?? MockMouseEnhancerMiddleClickSession()
|
|
},
|
|
accessibilityTrusted: { accessibilityTrusted },
|
|
requestAccessibilityTrust: { _ in requestAccessibilityTrust },
|
|
inputMonitoringAuthorizationStatus: { inputMonitoringStatus },
|
|
openURL: { _ in }
|
|
)
|
|
}
|
|
}
|