-
-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathstdio-daemon-proxy.test.ts
More file actions
121 lines (104 loc) · 4.55 KB
/
Copy pathstdio-daemon-proxy.test.ts
File metadata and controls
121 lines (104 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { describe, expect, it } from "vitest";
import { stdioDaemonProxyBuilder } from "../../src/auto-config/transports/stdio-daemon-proxy.js";
import type { TransportBuildInput } from "../../src/auto-config/transports/index.js";
function baseInput(overrides: Partial<TransportBuildInput> = {}): TransportBuildInput {
return {
launcherPath: "/home/user/.perplexity-mcp/launcher.cjs",
daemonPort: null,
tunnelUrl: null,
tunnelProviderId: null,
tunnelReservedDomain: false,
bearerKind: "none",
...overrides,
};
}
describe("stdioDaemonProxyBuilder", () => {
it("has id 'stdio-daemon-proxy'", () => {
expect(stdioDaemonProxyBuilder.id).toBe("stdio-daemon-proxy");
});
it("declares support for both json and toml formats", () => {
expect(stdioDaemonProxyBuilder.supportedFormats).toContain("json");
expect(stdioDaemonProxyBuilder.supportedFormats).toContain("toml");
});
it("produces the minimal stdio proxy shape without PERPLEXITY_NO_DAEMON", () => {
const result = stdioDaemonProxyBuilder.build(baseInput());
expect(result).toEqual({
command: "node",
args: ["/home/user/.perplexity-mcp/launcher.cjs"],
env: {},
});
// Critical: proxy variant must NOT force the launcher into no-daemon mode.
expect("env" in result ? result.env : {}).not.toHaveProperty("PERPLEXITY_NO_DAEMON");
});
it("honors an explicit nodePath override", () => {
const result = stdioDaemonProxyBuilder.build(
baseInput({ nodePath: "/usr/local/bin/node-custom" }),
);
expect("command" in result ? result.command : null).toBe("/usr/local/bin/node-custom");
expect("args" in result ? result.args : []).toEqual([
"/home/user/.perplexity-mcp/launcher.cjs",
]);
});
it("falls back to bare node when nodePath is an empty string", () => {
// Regression: mirrors stdio-in-process. `??` would leak the empty string
// through as `command: ""`; fallback must not leak an IDE host execPath.
const result = stdioDaemonProxyBuilder.build(baseInput({ nodePath: "" }));
const command = "command" in result ? result.command : null;
expect(command).toBe("node");
expect(command).not.toBe("");
expect(command).not.toBe(process.execPath);
});
it("propagates chromePath into env when provided", () => {
const result = stdioDaemonProxyBuilder.build(
baseInput({ chromePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" }),
);
const env = "env" in result ? result.env ?? {} : {};
expect(env.PERPLEXITY_CHROME_PATH).toBe(
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
);
expect(env).not.toHaveProperty("PERPLEXITY_NO_DAEMON");
});
it("omits PERPLEXITY_CHROME_PATH when chromePath is absent", () => {
const result = stdioDaemonProxyBuilder.build(baseInput());
const env = "env" in result ? result.env ?? {} : {};
expect(env).not.toHaveProperty("PERPLEXITY_CHROME_PATH");
});
it("omits PERPLEXITY_CHROME_PATH when chromePath is an empty string", () => {
// Regression: keep the guard in lock-step with stdio-in-process. An empty
// string must not produce `PERPLEXITY_CHROME_PATH=""` in the env block —
// that would tell the launcher to use an empty Chrome path rather than
// auto-detect.
const result = stdioDaemonProxyBuilder.build(baseInput({ chromePath: "" }));
const env = "env" in result ? result.env ?? {} : {};
expect(env).not.toHaveProperty("PERPLEXITY_CHROME_PATH");
});
it("throws TypeError when launcherPath is empty", () => {
expect(() => stdioDaemonProxyBuilder.build(baseInput({ launcherPath: "" }))).toThrow(
TypeError,
);
expect(() => stdioDaemonProxyBuilder.build(baseInput({ launcherPath: "" }))).toThrow(
/launcherPath is required/,
);
});
it("ignores bearerKind 'local' + localToken (no Authorization, no token in env)", () => {
const result = stdioDaemonProxyBuilder.build(
baseInput({
bearerKind: "local",
localToken: "super-secret-local-token-xyz",
}),
);
// The stdio proxy transport never speaks HTTP, so bearer material must be dropped.
expect(result).toEqual({
command: "node",
args: ["/home/user/.perplexity-mcp/launcher.cjs"],
env: {},
});
const env = "env" in result ? result.env ?? {} : {};
for (const value of Object.values(env)) {
expect(value).not.toContain("super-secret-local-token-xyz");
}
// Defensive: stdio entries never carry HTTP headers.
expect(result).not.toHaveProperty("headers");
expect(result).not.toHaveProperty("url");
});
});