


































@@ -7,6 +7,11 @@ installBaseProgramMocks();
7788let registerNodesCli: typeof import("./nodes-cli.js").registerNodesCli;
9910+type GatewayCallRequest = {
11+method?: string;
12+params?: unknown;
13+};
14+1015function formatRuntimeLogCallArg(value: unknown): string {
1116if (typeof value === "string") {
1217return value;
@@ -43,6 +48,18 @@ describe("cli program (nodes basics)", () => {
4348return runtime.log.mock.calls.map((c) => formatRuntimeLogCallArg(c[0])).join("\n");
4449}
455051+function gatewayRequests(): GatewayCallRequest[] {
52+return callGateway.mock.calls.map(([request]) => request as GatewayCallRequest);
53+}
54+55+function expectGatewayRequest(method: string, params?: unknown): void {
56+const request = gatewayRequests().find((candidate) => candidate.method === method);
57+expect(request?.method).toBe(method);
58+if (arguments.length > 1) {
59+expect(request?.params).toEqual(params);
60+}
61+}
62+4663function mockGatewayWithIosNodeListAnd(method: "node.describe" | "node.invoke", result: unknown) {
4764callGateway.mockImplementation(async (...args: unknown[]) => {
4865const opts = (args[0] ?? {}) as { method?: string };
@@ -121,31 +138,50 @@ describe("cli program (nodes basics)", () => {
121138122139await runProgram(["nodes", "list", "--json"]);
123140124-expect(callGateway).toHaveBeenCalledWith(expect.objectContaining({ method: "node.pair.list" }));
125-expect(callGateway).toHaveBeenCalledWith(expect.objectContaining({ method: "node.list" }));
126-expect(runtime.writeJson).toHaveBeenCalledWith({
127-pending: [{ requestId: "r1", nodeId: "pending-node", ts: now - 10_000 }],
128-paired: [
129-expect.objectContaining({
130-nodeId: "paired-store",
131-displayName: "Effective paired name",
132-remoteIp: "10.0.0.2",
133-lastConnectedAtMs: now - 5_000,
134-connected: true,
135-}),
136-expect.objectContaining({
137-nodeId: "catalog-only",
138-displayName: "Catalog Only",
139-paired: true,
140-}),
141-expect.objectContaining({
142-nodeId: "pair-only",
143-displayName: "Pair Only",
144-}),
145-],
146-});
147-expect(JSON.stringify(runtime.writeJson.mock.calls[0]?.[0])).not.toContain("paired-token");
148-expect(JSON.stringify(runtime.writeJson.mock.calls[0]?.[0])).not.toContain("pair-only-token");
141+expectGatewayRequest("node.pair.list", {});
142+expectGatewayRequest("node.list", {});
143+const json = runtime.writeJson.mock.calls[0]?.[0] as {
144+pending?: unknown[];
145+paired?: Array<Record<string, unknown>>;
146+};
147+expect(json.pending).toEqual([{ requestId: "r1", nodeId: "pending-node", ts: now - 10_000 }]);
148+expect(
149+json.paired?.map((node) => ({
150+nodeId: node.nodeId,
151+displayName: node.displayName,
152+remoteIp: node.remoteIp,
153+lastConnectedAtMs: node.lastConnectedAtMs,
154+connected: node.connected,
155+paired: node.paired,
156+})),
157+).toEqual([
158+{
159+nodeId: "paired-store",
160+displayName: "Effective paired name",
161+remoteIp: "10.0.0.2",
162+lastConnectedAtMs: now - 5_000,
163+connected: true,
164+paired: undefined,
165+},
166+{
167+nodeId: "catalog-only",
168+displayName: "Catalog Only",
169+remoteIp: "10.0.0.3",
170+lastConnectedAtMs: undefined,
171+connected: false,
172+paired: true,
173+},
174+{
175+nodeId: "pair-only",
176+displayName: "Pair Only",
177+remoteIp: undefined,
178+lastConnectedAtMs: undefined,
179+connected: undefined,
180+paired: undefined,
181+},
182+]);
183+expect(JSON.stringify(json)).not.toContain("paired-token");
184+expect(JSON.stringify(json)).not.toContain("pair-only-token");
149185const output = getRuntimeOutput();
150186expect(output).toContain("Pending: 1 · Paired: 3");
151187expect(output).not.toContain("Effective Only Unknown");
@@ -222,21 +258,15 @@ describe("cli program (nodes basics)", () => {
222258runtime.log.mockClear();
223259await runProgram(["nodes", "list", "--json"]);
224260225-expect(runtime.writeJson).toHaveBeenCalledWith({
226-pending: [
227-expect.objectContaining({
228-requestId: "request\u001b[2K-1",
229-displayName: "Pending\u001b[1A\nNode",
230-}),
231-],
232-paired: [
233-expect.objectContaining({
234-nodeId: "paired-node",
235-displayName: "Paired\u001b[2K\nNode",
236-remoteIp: "10.0.0.5\rrewritten",
237-}),
238-],
239-});
261+const json = runtime.writeJson.mock.calls.at(-1)?.[0] as {
262+pending?: Array<Record<string, unknown>>;
263+paired?: Array<Record<string, unknown>>;
264+};
265+expect(json.pending?.[0]?.requestId).toBe("request\u001b[2K-1");
266+expect(json.pending?.[0]?.displayName).toBe("Pending\u001b[1A\nNode");
267+expect(json.paired?.[0]?.nodeId).toBe("paired-node");
268+expect(json.paired?.[0]?.displayName).toBe("Paired\u001b[2K\nNode");
269+expect(json.paired?.[0]?.remoteIp).toBe("10.0.0.5\rrewritten");
240270});
241271242272it("runs nodes list --connected and filters to connected nodes", async () => {
@@ -274,7 +304,7 @@ describe("cli program (nodes basics)", () => {
274304});
275305await runProgram(["nodes", "list", "--connected"]);
276306277-expect(callGateway).toHaveBeenCalledWith(expect.objectContaining({ method: "node.list" }));
307+expectGatewayRequest("node.list", {});
278308const output = getRuntimeOutput();
279309expect(output).toContain("One");
280310expect(output).not.toContain("Two");
@@ -306,7 +336,7 @@ describe("cli program (nodes basics)", () => {
306336});
307337await runProgram(["nodes", "status", "--last-connected", "24h"]);
308338309-expect(callGateway).toHaveBeenCalledWith(expect.objectContaining({ method: "node.pair.list" }));
339+expectGatewayRequest("node.pair.list", {});
310340const output = getRuntimeOutput();
311341expect(output).toContain("One");
312342expect(output).not.toContain("Two");
@@ -373,9 +403,7 @@ describe("cli program (nodes basics)", () => {
373403});
374404await runProgram(["nodes", "status"]);
375405376-expect(callGateway).toHaveBeenCalledWith(
377-expect.objectContaining({ method: "node.list", params: {} }),
378-);
406+expectGatewayRequest("node.list", {});
379407380408const output = getRuntimeOutput();
381409for (const expected of expectedOutput) {
@@ -395,15 +423,8 @@ describe("cli program (nodes basics)", () => {
395423396424await runProgram(["nodes", "describe", "--node", "ios-node"]);
397425398-expect(callGateway).toHaveBeenCalledWith(
399-expect.objectContaining({ method: "node.list", params: {} }),
400-);
401-expect(callGateway).toHaveBeenCalledWith(
402-expect.objectContaining({
403-method: "node.describe",
404-params: { nodeId: "ios-node" },
405-}),
406-);
426+expectGatewayRequest("node.list", {});
427+expectGatewayRequest("node.describe", { nodeId: "ios-node" });
407428408429const out = getRuntimeOutput();
409430expect(out).toContain("Commands");
@@ -416,12 +437,7 @@ describe("cli program (nodes basics)", () => {
416437node: { nodeId: "n1", token: "t1" },
417438});
418439await runProgram(["nodes", "approve", "r1"]);
419-expect(callGateway).toHaveBeenCalledWith(
420-expect.objectContaining({
421-method: "node.pair.approve",
422-params: { requestId: "r1" },
423-}),
424-);
440+expectGatewayRequest("node.pair.approve", { requestId: "r1" });
425441});
426442427443it("runs nodes remove and calls node.pair.remove", async () => {
@@ -445,12 +461,7 @@ describe("cli program (nodes basics)", () => {
445461});
446462447463await runProgram(["nodes", "remove", "--node", "iOS Node"]);
448-expect(callGateway).toHaveBeenCalledWith(
449-expect.objectContaining({
450-method: "node.pair.remove",
451-params: { nodeId: "ios-node" },
452-}),
453-);
464+expectGatewayRequest("node.pair.remove", { nodeId: "ios-node" });
454465});
455466456467it("runs nodes invoke and calls node.invoke", async () => {
@@ -472,20 +483,13 @@ describe("cli program (nodes basics)", () => {
472483'{"javaScript":"1+1"}',
473484]);
474485475-expect(callGateway).toHaveBeenCalledWith(
476-expect.objectContaining({ method: "node.list", params: {} }),
477-);
478-expect(callGateway).toHaveBeenCalledWith(
479-expect.objectContaining({
480-method: "node.invoke",
481-params: {
482-nodeId: "ios-node",
483-command: "canvas.eval",
484-params: { javaScript: "1+1" },
485-timeoutMs: 15000,
486-idempotencyKey: "idem-test",
487-},
488-}),
489-);
486+expectGatewayRequest("node.list", {});
487+expectGatewayRequest("node.invoke", {
488+nodeId: "ios-node",
489+command: "canvas.eval",
490+params: { javaScript: "1+1" },
491+timeoutMs: 15000,
492+idempotencyKey: "idem-test",
493+});
490494});
491495});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。