Files
orca/mobile/scripts/hosted-webview-control-point.mjs
T
Jinwoo-H d39be4951d fix(mobile): repair hosted journey accessibility and route checks
Label standalone toolbar actions, match WebView accessibility values, and fence workspace return checks by pathname. Reuse Android labelled navigation and support adversarial journeys without native screenshot baselines. Record passing iOS file parity and the unresolved terminal file-link gate on both platforms.
2026-09-06 18:11:18 -04:00

53 lines
1.8 KiB
JavaScript

import { WebSocket } from 'ws'
import {
evaluateHostedDocumentWithRetry,
readHostedWebViewState
} from './hosted-webview-cdp-session.mjs'
export async function readHostedWebViewControlPoint(document, label, WebSocketCtor = WebSocket) {
const expression = `(() => {
const element = Array.from(document.querySelectorAll('[aria-label]'))
.find((candidate) => candidate.getAttribute('aria-label') === ${JSON.stringify(label)});
if (!(element instanceof HTMLElement)) return '';
element.scrollIntoView({ block: 'nearest', inline: 'nearest' });
const rect = element.getBoundingClientRect();
const screenWidth = Number(screen.width);
const screenHeight = Number(screen.height);
const viewportTop = Math.max(0, screenHeight - Number(innerHeight));
return JSON.stringify({
x: (rect.left + rect.width / 2) / screenWidth,
y: (viewportTop + rect.top + rect.height / 2) / screenHeight
});
})()`
const value = await evaluateHostedDocumentWithRetry(document, expression, WebSocketCtor)
let point
try {
point = JSON.parse(value)
} catch {
const state = await readHostedWebViewState(document, WebSocketCtor).catch(() => null)
throw new Error(
`Hosted WebView control was not measurable: ${label}. State: ${JSON.stringify({
path: state ? new URL(state.href).pathname : null,
labels: state?.labels?.slice(0, 40),
text: state?.bodyText?.slice(0, 1000)
})}`
)
}
if (!isNormalizedPoint(point)) {
throw new Error(`Hosted WebView returned an invalid control point: ${label}`)
}
return point
}
function isNormalizedPoint(point) {
return (
point &&
Number.isFinite(point.x) &&
Number.isFinite(point.y) &&
point.x >= 0 &&
point.x <= 1 &&
point.y >= 0 &&
point.y <= 1
)
}