Files
openclaw/apps/macos/Tests/OpenClawIPCTests/ComputerControlSettingsTests.swift
2026-08-20 06:39:06 -07:00

155 lines
7.3 KiB
Swift

import Foundation
import OpenClawIPC
import Testing
@testable import OpenClaw
struct ComputerControlSettingsTests {
@Test func `computer control defaults on while preserving explicit choices`() throws {
let suiteName = "ComputerControlSettingsTests.\(UUID().uuidString)"
let defaults = try #require(UserDefaults(suiteName: suiteName))
defer { defaults.removePersistentDomain(forName: suiteName) }
#expect(isComputerControlEnabled(defaults: defaults))
defaults.set(false, forKey: computerControlEnabledKey)
#expect(!isComputerControlEnabled(defaults: defaults))
defaults.set(true, forKey: computerControlEnabledKey)
#expect(isComputerControlEnabled(defaults: defaults))
}
@Test func `computer control provider defaults to Peekaboo and preserves CUA selection`() throws {
let suiteName = "ComputerControlProviderSettingsTests.\(UUID().uuidString)"
let defaults = try #require(UserDefaults(suiteName: suiteName))
defer { defaults.removePersistentDomain(forName: suiteName) }
#expect(ComputerControlProvider.current(defaults: defaults, cuaAvailable: true) == .peekaboo)
defaults.set(ComputerControlProvider.cua.rawValue, forKey: computerControlProviderKey)
#expect(ComputerControlProvider.current(defaults: defaults, cuaAvailable: true) == .cua)
#expect(ComputerControlProvider.current(defaults: defaults, cuaAvailable: false) == .peekaboo)
defaults.set("retired-provider", forKey: computerControlProviderKey)
#expect(ComputerControlProvider.current(defaults: defaults, cuaAvailable: true) == .peekaboo)
}
@Test func `elevation host ignores enabled CUA defaults while normal launches preserve them`() throws {
let suiteName = "ComputerControlElevationHostTests.\(UUID().uuidString)"
let defaults = try #require(UserDefaults(suiteName: suiteName))
defer { defaults.removePersistentDomain(forName: suiteName) }
let interactivePlan = AppLaunchRuntimePlan(arguments: ["OpenClaw"])
let elevationPlan = AppLaunchRuntimePlan(arguments: ["OpenClaw", "--elevation-host"])
defaults.set(true, forKey: computerControlEnabledKey)
defaults.set(ComputerControlProvider.cua.rawValue, forKey: computerControlProviderKey)
#expect(isComputerControlEnabled(defaults: defaults))
#expect(ComputerControlProvider.current(
defaults: defaults,
cuaAvailable: true,
launchPlan: interactivePlan) == .cua)
#expect(ComputerControlProvider.current(
defaults: defaults,
cuaAvailable: true,
launchPlan: elevationPlan) == .peekaboo)
defaults.set(false, forKey: computerControlEnabledKey)
#expect(!isComputerControlEnabled(defaults: defaults, launchPlan: interactivePlan))
#expect(isComputerControlEnabled(defaults: defaults, launchPlan: elevationPlan))
}
@Test func `bundled CUA locator accepts only a regular executable and never follows a symlink`() throws {
let root = FileManager.default.temporaryDirectory
.appendingPathComponent("openclaw-cua-artifact-\(UUID().uuidString)", isDirectory: true)
defer { try? FileManager.default.removeItem(at: root) }
try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true)
let binary = root.appendingPathComponent(CuaDriverArtifact.resourceName)
try Data("driver".utf8).write(to: binary)
try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: binary.path)
#expect(CuaDriverArtifact.executableURL(in: root) == binary)
try FileManager.default.removeItem(at: binary)
let target = root.appendingPathComponent("real-driver")
try Data("driver".utf8).write(to: target)
try FileManager.default.setAttributes([.posixPermissions: 0o755], ofItemAtPath: target.path)
try FileManager.default.createSymbolicLink(at: binary, withDestinationURL: target)
#expect(CuaDriverArtifact.executableURL(in: root) == nil)
}
@Test func `CUA worker endpoint uses versioned JSON with escaped paths`() throws {
let endpoint = CuaDriverWorkerEndpoint(
socketPath: #"/tmp/openclaw-"quoted"/cua.sock"#,
binaryPath: #"/Applications/OpenClaw\Test.app/Contents/Resources/cua-driver"#)
let value = try endpoint.environmentValue()
let decoded = try #require(
JSONSerialization.jsonObject(with: Data(value.utf8)) as? [String: Any])
#expect(decoded.count == 3)
#expect(decoded["v"] as? Int == 1)
#expect(decoded["socketPath"] as? String == endpoint.socketPath)
#expect(decoded["binaryPath"] as? String == endpoint.binaryPath)
}
@Test func `readiness rows never promote unknown or unavailable state`() {
struct Scenario {
let provider: ComputerControlProvider
let cuaDriverAvailable: Bool
let permissions: [Capability: CapabilityAuthorizationStatus]
let cuaDaemonReady: Bool?
let expectedStatuses: [ComputerControlReadinessRow.Status]
}
let granted: [Capability: CapabilityAuthorizationStatus] = [
.accessibility: .granted,
.screenRecording: .granted,
]
let scenarios = [
Scenario(
provider: .peekaboo,
cuaDriverAvailable: false,
permissions: granted,
cuaDaemonReady: nil,
expectedStatuses: [.available, .granted, .granted]),
Scenario(
provider: .cua,
cuaDriverAvailable: true,
permissions: granted,
cuaDaemonReady: true,
expectedStatuses: [.available, .granted, .granted, .running]),
Scenario(
provider: .cua,
cuaDriverAvailable: true,
permissions: [:],
cuaDaemonReady: nil,
expectedStatuses: [.available, .unknown, .unknown, .unknown]),
Scenario(
provider: .cua,
cuaDriverAvailable: true,
permissions: [.accessibility: .notGranted, .screenRecording: .notGranted],
cuaDaemonReady: false,
expectedStatuses: [.available, .notGranted, .notGranted, .notReady]),
Scenario(
provider: .cua,
cuaDriverAvailable: false,
permissions: granted,
cuaDaemonReady: true,
expectedStatuses: [.unavailable, .granted, .granted, .unavailable]),
]
for scenario in scenarios {
let rows = ComputerControlReadinessPresentation.rows(
provider: scenario.provider,
cuaDriverAvailable: scenario.cuaDriverAvailable,
permissions: scenario.permissions,
cuaDaemonReady: scenario.cuaDaemonReady)
#expect(rows.map(\.status) == scenario.expectedStatuses)
for row in rows {
switch row.status {
case .available, .granted, .running:
#expect(row.nextStep == nil)
case .unavailable, .notGranted, .notReady, .unknown:
#expect(row.nextStep?.isEmpty == false)
}
}
}
}
}