mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
e5fca42952
* fix(apps): open session desktop on its machine * fix(ui): scope the desktop session lookup to the key's own agent `sessions.list` has no exact-key filter, so the viewer resolves a `session=` parameter by searching for the key and matching it exactly in the response. A key that prefixes longer ones — `agent:main:main` alongside user-named sessions that start the same way — could push the exact row outside a five-row page and silently fall back to the picker. Session keys encode their agent and the list API accepts `agentId`, so scope the search to that agent and widen the page. * refactor(ui): stop parking a session key in the desktop environment id Document-mode inventory failures stashed the requested session key in `environmentId` purely so the Retry button's non-null guard would pass, even though document-mode retry refreshes the inventory and never reads the value. A session key only names a machine once the inventory loads, so it now stays out of `environmentId`, and the retry branch that ignores it runs before the guard. Adds E2E coverage for recovering a session-preselected desktop. * fix(ui): resolve the desktop session with an exact-key lookup The session-preselect path searched `sessions.list` and scoped the search to the key's own agent, but a bounded search cannot rule a key out: 25 newer same-agent sessions sharing the requested key's prefix would push the exact row off the page, and the viewer would report the source as unavailable for a session that exists. `sessions.describe` is the exact-key operation and already projects placement, so the panel calls it directly and the app-root resolver plumbing goes away with it. * refactor(ui): move the desktop document keyboard bridge into its own controller `desktop-panel.ts` crossed the 700-line cap. The mobile keyboard bridge — the padded sentinel, the value diffing that turns composed input into backspaces and text, and the field focus/reset helpers — is a self-contained concern, so it moves into a `DesktopMobileKeyboard` controller alongside the existing fullscreen controller instead of taking a `max-lines` suppression. * test(ios): drain text fields instead of assuming a delete burst lands `testReleaseChatScreenshot` typed a 5-character probe, sent 5 deletes in one `typeText`, then asserted the field was empty. CI dropped one synthetic keystroke under simulator load and the assertion failed with a leftover "f". XCUITest makes no lossless-burst guarantee, so clearing now re-sends against whatever the field actually still holds, bounded. The two gateway-setup fields that overtyped through the same burst use the helper for the same reason. * fix(ui): keep the chat placement owner out of the startup chunk `desktop-document-mode.ts` is imported by bootstrap, so importing the chat placement owner from it pulled the chat page's dependency tree into the startup bundle and pushed startup JS past its gzip budget (331075 B against a 330507 B allowance). The route module now only parses the URL; resolving a session to its machine moves next to the lazily loaded desktop panel, which is the only caller. Startup JS is back to 329710 B.
94 lines
3.7 KiB
Swift
94 lines
3.7 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import OpenClaw
|
|
@testable import OpenClawKit
|
|
|
|
@MainActor
|
|
struct DesktopHubScreenTests {
|
|
private static func makeConfig(
|
|
url: URL,
|
|
token: String? = nil,
|
|
password: String? = nil) -> GatewayConnectConfig
|
|
{
|
|
GatewayConnectConfig(
|
|
url: url,
|
|
stableID: "manual|gateway.example.com|443",
|
|
tls: nil,
|
|
token: token,
|
|
bootstrapToken: nil,
|
|
password: password,
|
|
nodeOptions: GatewayConnectOptions(
|
|
role: "node",
|
|
scopes: [],
|
|
caps: [],
|
|
commands: [],
|
|
permissions: [:],
|
|
clientId: "ios",
|
|
clientMode: "node",
|
|
clientDisplayName: "Phone"))
|
|
}
|
|
|
|
@Test func `standalone desktop URL uses document mode without credentials`() throws {
|
|
let config = try Self.makeConfig(
|
|
url: #require(URL(string: "wss://gateway.example.com:8443/openclaw")),
|
|
token: "secret-token",
|
|
password: "secret-password")
|
|
|
|
let url = DesktopHubScreen.desktopURL(config: config, source: nil, session: nil)
|
|
|
|
#expect(url?.absoluteString == "https://gateway.example.com:8443/openclaw/?view=desktop")
|
|
#expect(url?.absoluteString.contains("secret-token") == false)
|
|
#expect(url?.absoluteString.contains("secret-password") == false)
|
|
}
|
|
|
|
@Test func `session desktop URL includes the session key`() throws {
|
|
let config = try Self.makeConfig(
|
|
url: #require(URL(string: "ws://192.168.1.10:18789")),
|
|
token: "secret-token")
|
|
|
|
let url = DesktopHubScreen.desktopURL(
|
|
config: config,
|
|
source: nil,
|
|
session: "agent:main:mobile session")
|
|
|
|
#expect(url?.absoluteString == "http://192.168.1.10:18789/?view=desktop&session=agent%3Amain%3Amobile%20session")
|
|
#expect(url?.absoluteString.contains("secret-token") == false)
|
|
}
|
|
|
|
@Test func `explicit desktop source is retained alongside the session`() throws {
|
|
let config = try Self.makeConfig(url: #require(URL(string: "wss://gateway.example.com")))
|
|
|
|
let url = DesktopHubScreen.desktopURL(
|
|
config: config,
|
|
source: "node:worker-1",
|
|
session: "agent:main:mobile")
|
|
|
|
#expect(url?.absoluteString == "https://gateway.example.com/?view=desktop&source=node%3Aworker-1&session=agent%3Amain%3Amobile")
|
|
}
|
|
|
|
@Test func `empty desktop source is omitted`() throws {
|
|
let config = try Self.makeConfig(url: #require(URL(string: "wss://gateway.example.com")))
|
|
|
|
let url = DesktopHubScreen.desktopURL(config: config, source: " ", session: " ")
|
|
|
|
#expect(url?.absoluteString == "https://gateway.example.com/?view=desktop")
|
|
}
|
|
|
|
@Test func `desktop auth script carries credentials outside the URL`() throws {
|
|
let config = try Self.makeConfig(
|
|
url: #require(URL(string: "wss://gateway.example.com")),
|
|
token: " secret-token ",
|
|
password: "secret-password")
|
|
|
|
let url = DesktopHubScreen.desktopURL(config: config, source: "gateway")
|
|
let script = DesktopHubScreen.desktopAuthUserScript(config: config, source: "gateway")
|
|
|
|
#expect(url?.absoluteString == "https://gateway.example.com/?view=desktop&source=gateway")
|
|
#expect(url?.absoluteString.contains("secret-token") == false)
|
|
#expect(url?.absoluteString.contains("secret-password") == false)
|
|
#expect(script?.contains("__OPENCLAW_NATIVE_CONTROL_AUTH__") == true)
|
|
#expect(script?.contains("\"token\":\"secret-token\"") == true)
|
|
#expect(script?.contains("\"password\":\"secret-password\"") == true)
|
|
}
|
|
}
|