Files
openhuman/app/test/e2e/helpers/core-rpc-webview.ts
T
Mega MindandGitHub b7b3d62c58 test(e2e): skill execution flow (core RPC + Skills UI) (#283)
* test(e2e): skill execution flow (core RPC + Skills UI)

- Add skill-execution-flow.spec: core.ping, skills start/list_tools/call_tool/stop
  via shared RPC helper, seeded QuickJS echo skill (same tree as Rust json_rpc_e2e).
- Add core-rpc helpers: WebView invoke on tauri-driver, Node fetch + port probe on
  Appium Mac2 (no WKWebView execute).
- Extend navigateViaHash with Mac2 sidebar label fallbacks for /skills, /home, etc.
- Wire yarn test:e2e:skill-execution and e2e-run-all-flows.

Refs: #68
Made-with: Cursor

* fix(e2e): address CodeRabbit review for skill execution PR

- core-rpc-node: honor OPENHUMAN_CORE_HOST and OPENHUMAN_CORE_PORT before port scan
- shared-flows: Mac2 navigateViaHash for /settings/billing; throw on unmapped hash;
  navigateToBilling fallback without WebView execute on Mac2
- skill-e2e-runtime: javascript manifest + removeSeededEchoSkill teardown
- skill-execution-flow: teardown seeded skill; document RPC shapes vs json_rpc_e2e;
  skip placeholder for future agent chat tool_calls

Made-with: Cursor
2026-04-03 12:00:01 +05:30

56 lines
1.8 KiB
TypeScript

// @ts-nocheck
/**
* Invoke OpenHuman core JSON-RPC from the Tauri WebView (same transport as `callCoreRpc` in the app).
* Uses `invoke('core_rpc_url')` so the test follows the live sidecar port.
*/
export interface RpcCallResult<T = unknown> {
ok: boolean;
httpStatus?: number;
error?: string;
result?: T;
}
/** Linux tauri-driver only — Mac2 cannot run this (no WebView execute). Use `callOpenhumanRpc` from core-rpc.ts. */
export async function callOpenhumanRpcWebView<T = unknown>(
method: string,
params: Record<string, unknown> = {}
): Promise<RpcCallResult<T>> {
return browser.execute(
async (m: string, p: Record<string, unknown>) => {
try {
const { invoke } = await import('@tauri-apps/api/core');
const rpcUrl = await invoke<string>('core_rpc_url');
const id = Math.floor(Math.random() * 1e9);
const res = await fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id, method: m, params: p }),
});
const text = await res.text();
let json: { error?: { message?: string }; result?: unknown };
try {
json = JSON.parse(text) as typeof json;
} catch {
return {
ok: false,
httpStatus: res.status,
error: `Invalid JSON (${res.status}): ${text.slice(0, 240)}`,
};
}
if (!res.ok) {
return { ok: false, httpStatus: res.status, error: text.slice(0, 500) };
}
if (json.error) {
return { ok: false, error: json.error.message || JSON.stringify(json.error) };
}
return { ok: true, result: json.result as T };
} catch (e) {
return { ok: false, error: e instanceof Error ? e.message : String(e) };
}
},
method,
params
);
}