




















@@ -0,0 +1,116 @@
1+import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
2+const webSocketCtorMock = vi.hoisted(() =>
3+vi.fn(function webSocketCtorMockImpl(_url: string, _options?: Record<string, unknown>) {
4+return { readyState: 0 };
5+}),
6+);
7+const proxyAgentCtorMock = vi.hoisted(() =>
8+vi.fn(function proxyAgentCtorMockImpl() {
9+return { proxied: true };
10+}),
11+);
12+const proxyEnvKeys = ["https_proxy", "HTTPS_PROXY", "http_proxy", "HTTP_PROXY"] as const;
13+type ProxyEnvKey = (typeof proxyEnvKeys)[number];
14+15+vi.mock("ws", () => ({
16+default: webSocketCtorMock,
17+}));
18+19+type CreateQQWSClient = typeof import("./ws-client.js").createQQWSClient;
20+let createQQWSClient: CreateQQWSClient;
21+let priorProxyEnv: Partial<Record<ProxyEnvKey, string | undefined>> = {};
22+23+beforeAll(async () => {
24+vi.doMock("proxy-agent", () => ({
25+ProxyAgent: proxyAgentCtorMock,
26+}));
27+({ createQQWSClient } = await import("./ws-client.js"));
28+});
29+30+describe("createQQWSClient", () => {
31+beforeEach(() => {
32+priorProxyEnv = {};
33+for (const key of proxyEnvKeys) {
34+priorProxyEnv[key] = process.env[key];
35+delete process.env[key];
36+}
37+vi.clearAllMocks();
38+});
39+40+afterEach(() => {
41+for (const key of proxyEnvKeys) {
42+const value = priorProxyEnv[key];
43+if (value === undefined) {
44+delete process.env[key];
45+} else {
46+process.env[key] = value;
47+}
48+}
49+});
50+51+it("does not set a ws proxy agent when proxy env is absent", async () => {
52+await createQQWSClient({
53+gatewayUrl: "wss://qq.example.test/ws",
54+userAgent: "openclaw-qqbot-test",
55+});
56+57+expect(webSocketCtorMock).toHaveBeenCalledTimes(1);
58+expect(proxyAgentCtorMock).not.toHaveBeenCalled();
59+const [, options] = webSocketCtorMock.mock.calls[0] ?? [];
60+expect(options).toMatchObject({
61+headers: { "User-Agent": "openclaw-qqbot-test" },
62+});
63+expect(options).not.toHaveProperty("agent");
64+});
65+66+it("creates a ws proxy agent when lowercase https_proxy is set", async () => {
67+process.env.https_proxy = "http://lower-https:8001";
68+69+await createQQWSClient({
70+gatewayUrl: "wss://qq.example.test/ws",
71+userAgent: "openclaw-qqbot-test",
72+});
73+74+expect(webSocketCtorMock).toHaveBeenCalledTimes(1);
75+expect(proxyAgentCtorMock).toHaveBeenCalledTimes(1);
76+const [, options] = webSocketCtorMock.mock.calls[0] ?? [];
77+expect(options).toMatchObject({
78+headers: { "User-Agent": "openclaw-qqbot-test" },
79+agent: { proxied: true },
80+});
81+});
82+83+it("creates a ws proxy agent when uppercase HTTPS_PROXY is set", async () => {
84+process.env.HTTPS_PROXY = "http://upper-https:8002";
85+86+await createQQWSClient({
87+gatewayUrl: "wss://qq.example.test/ws",
88+userAgent: "openclaw-qqbot-test",
89+});
90+91+expect(webSocketCtorMock).toHaveBeenCalledTimes(1);
92+expect(proxyAgentCtorMock).toHaveBeenCalledTimes(1);
93+const [, options] = webSocketCtorMock.mock.calls[0] ?? [];
94+expect(options).toMatchObject({
95+headers: { "User-Agent": "openclaw-qqbot-test" },
96+agent: { proxied: true },
97+});
98+});
99+100+it("falls back to HTTP_PROXY for ws proxy agent creation", async () => {
101+process.env.HTTP_PROXY = "http://upper-http:8999";
102+103+await createQQWSClient({
104+gatewayUrl: "wss://qq.example.test/ws",
105+userAgent: "openclaw-qqbot-test",
106+});
107+108+expect(webSocketCtorMock).toHaveBeenCalledTimes(1);
109+expect(proxyAgentCtorMock).toHaveBeenCalledTimes(1);
110+const [, options] = webSocketCtorMock.mock.calls[0] ?? [];
111+expect(options).toMatchObject({
112+headers: { "User-Agent": "openclaw-qqbot-test" },
113+agent: { proxied: true },
114+});
115+});
116+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。