

























1-import fs from "node:fs/promises";
2-import { createServer } from "node:http";
31import type { AddressInfo } from "node:net";
4-import os from "node:os";
52import path from "node:path";
6-import { afterEach, describe, expect, it } from "vitest";
7-import { type RawData, WebSocketServer } from "ws";
8-import { PROTOCOL_VERSION } from "../../packages/gateway-protocol/src/index.js";
3+import { afterAll, beforeAll, describe, expect, it } from "vitest";
4+import { WebSocketServer } from "ws";
95import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js";
6+import { createSuiteTempRootTracker } from "../test-helpers/temp-dir.js";
107import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
118import { connectTestGatewayClient } from "./gateway-cli-backend.live-helpers.js";
9+import {
10+buildMinimalGatewayHelloOkPayload,
11+closeMinimalGatewayServer,
12+parseMinimalGatewayRequestFrame,
13+sendMinimalGatewayConnectChallenge,
14+sendMinimalGatewayResponse,
15+} from "./minimal-gateway.test-helpers.js";
12161317const GATEWAY_CONNECT_TIMEOUT_MS = 5_000;
14-const tempRoots: string[] = [];
18+const tempDirs = createSuiteTempRootTracker({ prefix: "openclaw-gateway-connect-" });
15191620async function createTempDeviceIdentity() {
17-const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-gateway-connect-"));
18-tempRoots.push(tempRoot);
21+const tempRoot = await tempDirs.make("device");
1922return loadOrCreateDeviceIdentity(path.join(tempRoot, "device.json"));
2023}
21242225async function startMinimalGatewayServer(params: { token: string }) {
23-const httpServer = createServer();
24-const wss = new WebSocketServer({ server: httpServer });
26+const wss = new WebSocketServer({ host: "127.0.0.1", port: 0 });
2527const requests: string[] = [];
2628let connectParams: Record<string, unknown> | undefined;
27292830wss.on("connection", (ws) => {
29-ws.send(
30-JSON.stringify({
31-type: "event",
32-event: "connect.challenge",
33-payload: { nonce: "test-nonce" },
34-}),
35-);
31+sendMinimalGatewayConnectChallenge(ws);
3632ws.on("message", (data) => {
37-const frame = JSON.parse(rawWsDataToString(data)) as {
38-type?: string;
39-id?: string;
40-method?: string;
41-params?: { auth?: { token?: string }; device?: { nonce?: string } };
42-};
33+const frame = parseMinimalGatewayRequestFrame(data);
4334if (frame.type !== "req" || !frame.id) {
4435return;
4536}
@@ -48,80 +39,56 @@ async function startMinimalGatewayServer(params: { token: string }) {
4839connectParams = frame.params as Record<string, unknown> | undefined;
4940expect(frame.params?.auth?.token).toBe(params.token);
5041expect(frame.params?.device?.nonce).toBe("test-nonce");
51-ws.send(
52-JSON.stringify({
53-type: "res",
54-id: frame.id,
55-ok: true,
56-payload: {
57-type: "hello-ok",
58-protocol: PROTOCOL_VERSION,
59-server: { version: "test", connId: "conn-1" },
60-features: { methods: ["health"], events: ["connect.challenge"] },
61-snapshot: {
62-presence: [],
63-health: { ok: true },
64-stateVersion: { presence: 0, health: 0 },
65-uptimeMs: 0,
66-},
67-policy: {
68-maxPayload: 1,
69-maxBufferedBytes: 1,
70-tickIntervalMs: 60_000,
71-},
42+sendMinimalGatewayResponse(
43+ws,
44+frame.id,
45+buildMinimalGatewayHelloOkPayload({
46+connId: "conn-1",
47+methods: ["health"],
48+snapshot: {
49+presence: [],
50+health: { ok: true },
51+stateVersion: { presence: 0, health: 0 },
52+uptimeMs: 0,
53+},
54+policy: {
55+maxPayload: 1,
56+maxBufferedBytes: 1,
57+tickIntervalMs: 60_000,
7258},
7359}),
7460);
7561return;
7662}
7763if (frame.method === "health") {
78-ws.send(JSON.stringify({ type: "res", id: frame.id, ok: true, payload: { ok: true } }));
64+sendMinimalGatewayResponse(ws, frame.id, { ok: true });
7965}
8066});
8167});
82688369await new Promise<void>((resolve) => {
84-httpServer.listen(0, "127.0.0.1", resolve);
70+wss.once("listening", resolve);
8571});
86-const address = httpServer.address() as AddressInfo;
72+const address = wss.address() as AddressInfo;
8773return {
8874 requests,
8975get connectParams() {
9076return connectParams;
9177},
9278url: `ws://127.0.0.1:${address.port}`,
9379close: async () => {
94-for (const client of wss.clients) {
95-client.terminate();
96-}
97-await new Promise<void>((resolve, reject) => {
98-wss.close((error) => (error ? reject(error) : resolve()));
99-});
100-await new Promise<void>((resolve, reject) => {
101-httpServer.close((error) => (error ? reject(error) : resolve()));
102-});
80+await closeMinimalGatewayServer(wss);
10381},
10482};
10583}
10684107-function rawWsDataToString(data: RawData): string {
108-if (typeof data === "string") {
109-return data;
110-}
111-if (Buffer.isBuffer(data)) {
112-return data.toString("utf8");
113-}
114-if (Array.isArray(data)) {
115-return Buffer.concat(data).toString("utf8");
116-}
117-return Buffer.from(data).toString("utf8");
118-}
119-12085describe("gateway cli backend connect", () => {
121-afterEach(async () => {
122-await Promise.all(
123-tempRoots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true })),
124-);
86+beforeAll(async () => {
87+await tempDirs.setup();
88+});
89+90+afterAll(async () => {
91+await tempDirs.cleanup();
12592});
1269312794it(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。