Skip to main content
Glama
ServiceBridgeTests.swift8.31 kB
import CoreGraphics import Foundation import PeekabooCore import PeekabooFoundation import Testing @testable import PeekabooCLI @Suite("Service Bridge Routing") @MainActor struct ServiceBridgeTests { @Test func automationClickForwardsCalls() async throws { let automation = MockAutomationService() try await AutomationServiceBridge.click( automation: automation, target: .coordinates(CGPoint(x: 10, y: 20)), clickType: .double, sessionId: "session-123" ) #expect(automation.clickCalls.count == 1) #expect(automation.clickCalls.first?.sessionId == "session-123") } @Test func automationWaitReturnsMockResult() async throws { let element = DetectedElement( id: "B1", type: .button, label: "OK", value: nil, bounds: CGRect(x: 0, y: 0, width: 44, height: 20), isEnabled: true, isSelected: nil, attributes: [:] ) let mock = MockAutomationService(waitResult: .init(found: true, element: element, waitTime: 0.25)) let result = try await AutomationServiceBridge.waitForElement( automation: mock, target: .elementId("B1"), timeout: 1, sessionId: "S42" ) #expect(result.found) #expect(mock.waitCalls.count == 1) } @Test func windowBridgeReturnsStubbedWindows() async throws { let window = ServiceWindowInfo( windowID: 101, title: "Main", bounds: CGRect(x: 0, y: 0, width: 800, height: 600) ) let windows = try await WindowServiceBridge.listWindows( windows: MockWindowService(result: [window]), target: .frontmost ) #expect(windows == [window]) } @Test func menuBridgeListsMenuBarItems() async throws { let menuItems = [MenuBarItemInfo( title: "Item", index: 0, isVisible: true, description: nil, rawTitle: "Item", bundleIdentifier: "com.test", ownerName: "Test", frame: nil, identifier: "com.test.item" )] let items = try await MenuServiceBridge.listMenuBarItems(menu: MockMenuService(barItems: menuItems)) #expect(items.count == 1) #expect(items.first?.title == "Item") } @Test func dockBridgeListsItems() async throws { let dockItems = [DockItem( index: 0, title: "Peekaboo", itemType: .application, isRunning: true, bundleIdentifier: "boo.peekaboo", position: nil, size: nil )] let items = try await DockServiceBridge.listDockItems( dock: MockDockService(items: dockItems), includeAll: true ) #expect(items == dockItems) } } @MainActor final class MockAutomationService: UIAutomationServiceProtocol { struct ClickCall { let target: ClickTarget; let clickType: ClickType; let sessionId: String? } var clickCalls: [ClickCall] = [] var waitCalls: [ClickTarget] = [] var waitResult: WaitForElementResult init(waitResult: WaitForElementResult = .init(found: false, element: nil, waitTime: 0)) { self.waitResult = waitResult } func detectElements( in _: Data, sessionId _: String?, windowContext _: WindowContext? ) async throws -> ElementDetectionResult { throw PeekabooError.notImplemented("mock detectElements") } func click(target: ClickTarget, clickType: ClickType, sessionId: String?) async throws { self.clickCalls.append(.init(target: target, clickType: clickType, sessionId: sessionId)) } func type( text _: String, target _: String?, clearExisting _: Bool, typingDelay _: Int, sessionId _: String? ) async throws {} func typeActions( _ actions: [TypeAction], cadence _: TypingCadence, sessionId _: String? ) async throws -> TypeResult { TypeResult(totalCharacters: actions.count, keyPresses: actions.count) } func scroll(_ request: ScrollRequest) async throws { _ = request } func hotkey(keys _: String, holdDuration _: Int) async throws {} func swipe( from _: CGPoint, to _: CGPoint, duration _: Int, steps _: Int, profile _: MouseMovementProfile ) async throws {} func hasAccessibilityPermission() async -> Bool { true } func waitForElement( target: ClickTarget, timeout _: TimeInterval, sessionId _: String? ) async throws -> WaitForElementResult { self.waitCalls.append(target) return self.waitResult } // swiftlint:disable:next function_parameter_count func drag( from _: CGPoint, to _: CGPoint, duration _: Int, steps _: Int, modifiers _: String?, profile _: MouseMovementProfile ) async throws {} func moveMouse(to _: CGPoint, duration _: Int, steps _: Int, profile _: MouseMovementProfile) async throws {} func getFocusedElement() -> UIFocusInfo? { nil } func findElement(matching _: UIElementSearchCriteria, in _: String?) async throws -> DetectedElement { throw PeekabooError.elementNotFound("not implemented") } } @MainActor final class MockWindowService: WindowManagementServiceProtocol { let windowsResult: [ServiceWindowInfo] init(result: [ServiceWindowInfo]) { self.windowsResult = result } func closeWindow(target _: WindowTarget) async throws {} func minimizeWindow(target _: WindowTarget) async throws {} func maximizeWindow(target _: WindowTarget) async throws {} func moveWindow(target _: WindowTarget, to _: CGPoint) async throws {} func resizeWindow(target _: WindowTarget, to _: CGSize) async throws {} func setWindowBounds(target _: WindowTarget, bounds _: CGRect) async throws {} func focusWindow(target _: WindowTarget) async throws {} func listWindows(target _: WindowTarget) async throws -> [ServiceWindowInfo] { self.windowsResult } func getFocusedWindow() async throws -> ServiceWindowInfo? { self.windowsResult.first } } @MainActor final class MockMenuService: MenuServiceProtocol { var barItems: [MenuBarItemInfo] init(barItems: [MenuBarItemInfo]) { self.barItems = barItems } func listMenus(for _: String) async throws -> MenuStructure { self.emptyStructure } func listFrontmostMenus() async throws -> MenuStructure { self.emptyStructure } func clickMenuItem(app _: String, itemPath _: String) async throws {} func clickMenuItemByName(app _: String, itemName _: String) async throws {} func clickMenuExtra(title _: String) async throws {} func listMenuExtras() async throws -> [MenuExtraInfo] { [] } func listMenuBarItems(includeRaw _: Bool) async throws -> [MenuBarItemInfo] { self.barItems } func clickMenuBarItem(named _: String) async throws -> PeekabooCore.ClickResult { .init( elementDescription: "", location: nil ) } func clickMenuBarItem(at _: Int) async throws -> PeekabooCore.ClickResult { .init( elementDescription: "", location: nil ) } private var emptyStructure: MenuStructure { MenuStructure( application: ServiceApplicationInfo(processIdentifier: 1, bundleIdentifier: "test", name: "Test"), menus: [] ) } } @MainActor final class MockDockService: DockServiceProtocol { var items: [DockItem] init(items: [DockItem]) { self.items = items } func listDockItems(includeAll _: Bool) async throws -> [DockItem] { self.items } func launchFromDock(appName _: String) async throws {} func addToDock(path _: String, persistent _: Bool) async throws {} func removeFromDock(appName _: String) async throws {} func rightClickDockItem(appName _: String, menuItem _: String?) async throws {} func hideDock() async throws {} func showDock() async throws {} func isDockAutoHidden() async -> Bool { false } func findDockItem(name _: String) async throws -> DockItem { self.items.first! } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/steipete/Peekaboo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server