Skip to main content
Glama
PressCommandTests.swift4.43 kB
import Foundation import PeekabooCore import PeekabooFoundation import Testing @testable import PeekabooCLI #if !PEEKABOO_SKIP_AUTOMATION @Suite( "PressCommand Tests", .serialized, .tags(.safe), .enabled(if: CLITestEnvironment.runAutomationRead) ) struct PressCommandTests { @Test("press --help documents command") func pressHelp() async throws { let context = await self.makeContext() let result = try await self.runPress(arguments: ["--help"], context: context) #expect(result.exitStatus == 0) #expect(self.output(from: result).contains("Press individual keys or key sequences")) } @Test("Press command forwards keys to automation service") func forwardsKeys() async throws { let context = await self.makeContext() let result = try await self.runPress(arguments: ["return", "--json-output"], context: context) #expect(result.exitStatus == 0) let calls = await self.automationState(context) { $0.typeActionsCalls } let call = try #require(calls.first) #expect(call.actions.count == 1) let payloadData = try #require(self.output(from: result).data(using: .utf8)) let payload = try JSONDecoder().decode(PressResult.self, from: payloadData) #expect(payload.success) #expect(payload.keys == ["return"]) #expect(payload.totalPresses == 1) } @Test("Repeat count multiplies key actions") func repeatCount() async throws { let context = await self.makeContext() let result = try await self.runPress(arguments: ["tab", "--count", "3"], context: context) #expect(result.exitStatus == 0) let calls = await self.automationState(context) { $0.typeActionsCalls } let call = try #require(calls.first) #expect(call.actions.count == 3) #expect(call.cadence == .fixed(milliseconds: 100)) } @Test("Press command supports multiple keys in sequence") func multipleKeysSequence() async throws { let context = await self.makeContext() let result = try await self.runPress(arguments: ["up", "down", "left", "right"], context: context) #expect(result.exitStatus == 0) let calls = await self.automationState(context) { $0.typeActionsCalls } let call = try #require(calls.first) #expect(call.actions.count == 4) #expect(call.actions.allSatisfy { if case .key = $0 { true } else { false } }) } @Test("Session argument is forwarded") func forwardsSession() async throws { let context = await self.makeContext() let result = try await self.runPress(arguments: ["escape", "--session", "session-42"], context: context) #expect(result.exitStatus == 0) let calls = await self.automationState(context) { $0.typeActionsCalls } let call = try #require(calls.first) #expect(call.sessionId == "session-42") } @Test("Invalid key results in failure") func invalidKey() async throws { let context = await self.makeContext() let result = try await self.runPress(arguments: ["notakey"], context: context) #expect(result.exitStatus != 0) let calls = await self.automationState(context) { $0.typeActionsCalls } #expect(calls.isEmpty) } // MARK: - Helpers private func runPress( arguments: [String], context: TestServicesFactory.AutomationTestContext ) async throws -> CommandRunResult { try await InProcessCommandRunner.run(["press"] + arguments, services: context.services) } private func output(from result: CommandRunResult) -> String { result.stdout.isEmpty ? result.stderr : result.stdout } private func makeContext( configure: (@MainActor (StubAutomationService, StubSessionManager) -> Void)? = nil ) async -> TestServicesFactory.AutomationTestContext { await MainActor.run { let context = TestServicesFactory.makeAutomationTestContext() configure?(context.automation, context.sessions) return context } } private func automationState<T: Sendable>( _ context: TestServicesFactory.AutomationTestContext, _ operation: @MainActor (StubAutomationService) -> T ) async -> T { await MainActor.run { operation(context.automation) } } } #endif

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