Skip to content

Commit 7d5d625

Browse files
committed
fix(e2e): preserve null rpc results
1 parent cc6a6f5 commit 7d5d625

4 files changed

Lines changed: 58 additions & 4 deletions

File tree

scripts/e2e/kitchen-sink-rpc-walk.mjs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,27 @@ function findBalancedJsonObjectEnd(text, startIndex) {
404404
return -1;
405405
}
406406

407-
function unwrapRpcPayload(raw) {
407+
function hasOwnPayloadField(raw, field) {
408+
return (
409+
((typeof raw === "object" && raw !== null) || typeof raw === "function") &&
410+
Object.hasOwn(raw, field)
411+
);
412+
}
413+
414+
export function unwrapRpcPayload(raw) {
408415
if (raw?.ok === false) {
409416
throw new Error(`gateway RPC failed: ${JSON.stringify(raw.error ?? raw)}`);
410417
}
411-
return raw?.result ?? raw?.payload ?? raw?.data ?? raw;
418+
if (hasOwnPayloadField(raw, "result")) {
419+
return raw.result;
420+
}
421+
if (hasOwnPayloadField(raw, "payload")) {
422+
return raw.payload;
423+
}
424+
if (hasOwnPayloadField(raw, "data")) {
425+
return raw.data;
426+
}
427+
return raw;
412428
}
413429

414430
async function rpcCall(method, params, options) {

scripts/e2e/lib/bundled-plugin-install-uninstall/runtime-smoke.mjs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -830,11 +830,27 @@ function parseJsonOutput(stdout) {
830830
}
831831
}
832832

833-
function unwrapRpcPayload(raw) {
833+
function hasOwnPayloadField(raw, field) {
834+
return (
835+
((typeof raw === "object" && raw !== null) || typeof raw === "function") &&
836+
Object.hasOwn(raw, field)
837+
);
838+
}
839+
840+
export function unwrapRpcPayload(raw) {
834841
if (raw?.ok === false) {
835842
throw new Error(`gateway RPC failed: ${JSON.stringify(raw.error ?? raw)}`);
836843
}
837-
return raw?.result ?? raw?.payload ?? raw?.data ?? raw;
844+
if (hasOwnPayloadField(raw, "result")) {
845+
return raw.result;
846+
}
847+
if (hasOwnPayloadField(raw, "payload")) {
848+
return raw.payload;
849+
}
850+
if (hasOwnPayloadField(raw, "data")) {
851+
return raw.data;
852+
}
853+
return raw;
838854
}
839855

840856
async function smokePlugin(pluginId, pluginDir, requiresConfig, pluginIndex, pluginRoot) {

test/scripts/bundled-plugin-install-uninstall-probe.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ describe("bundled plugin install/uninstall probe", () => {
220220
expect(second).toEqual({ text: "fghij", truncatedChars: 5 });
221221
});
222222

223+
it("preserves explicit nullish runtime RPC result fields", async () => {
224+
const runtimeSmoke = await import(pathToFileURL(runtimeSmokePath).href);
225+
226+
expect(runtimeSmoke.unwrapRpcPayload({ jsonrpc: "2.0", result: null })).toBeNull();
227+
expect(runtimeSmoke.unwrapRpcPayload({ jsonrpc: "2.0", result: undefined })).toBeUndefined();
228+
expect(runtimeSmoke.unwrapRpcPayload({ payload: null, data: { stale: true } })).toBeNull();
229+
});
230+
223231
it("caps noisy runtime gateway logs", async () => {
224232
const runtimeSmoke = await importRuntimeSmokeWithEnv({
225233
OPENCLAW_BUNDLED_PLUGIN_RUNTIME_GATEWAY_LOG_BYTES: "64",

test/scripts/kitchen-sink-rpc-walk.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
stopGateway,
3333
summarizeProcessSamples,
3434
tailFile,
35+
unwrapRpcPayload,
3536
usesBuiltOpenClawEntry,
3637
waitForGatewayReady,
3738
} from "../../scripts/e2e/kitchen-sink-rpc-walk.mjs";
@@ -447,6 +448,19 @@ describe("kitchen-sink RPC caller loading", () => {
447448
});
448449
});
449450

451+
describe("kitchen-sink RPC payload unwrapping", () => {
452+
it("preserves explicit nullish JSON-RPC result fields", () => {
453+
expect(unwrapRpcPayload({ jsonrpc: "2.0", result: null })).toBeNull();
454+
expect(unwrapRpcPayload({ jsonrpc: "2.0", result: undefined })).toBeUndefined();
455+
});
456+
457+
it("prefers result before legacy payload and data envelopes", () => {
458+
expect(unwrapRpcPayload({ result: false, payload: { stale: true } })).toBe(false);
459+
expect(unwrapRpcPayload({ payload: null, data: { stale: true } })).toBeNull();
460+
expect(unwrapRpcPayload({ data: 0 })).toBe(0);
461+
});
462+
});
463+
450464
describe("kitchen-sink RPC command catalog assertions", () => {
451465
it("keeps plugin commands and deduplicates aliases", () => {
452466
expect(

0 commit comments

Comments
 (0)