agent-relay 2.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +193 -63
- package/dist/src/cli/index.d.ts +11 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +112 -110
- package/dist/src/cli/index.js.map +1 -1
- package/package.json +18 -18
- package/packages/api-types/package.json +1 -1
- package/packages/benchmark/package.json +4 -4
- package/packages/bridge/package.json +8 -8
- package/packages/cli-tester/package.json +1 -1
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +2 -2
- package/packages/daemon/dist/connection.d.ts +5 -0
- package/packages/daemon/dist/connection.d.ts.map +1 -1
- package/packages/daemon/dist/connection.js +19 -1
- package/packages/daemon/dist/connection.js.map +1 -1
- package/packages/daemon/dist/server.js +2 -2
- package/packages/daemon/dist/server.js.map +1 -1
- package/packages/daemon/package.json +12 -12
- package/packages/daemon/src/connection.ts +22 -1
- package/packages/daemon/src/router.test.ts +32 -0
- package/packages/daemon/src/server.ts +2 -2
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/package.json +3 -3
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/dist/types.d.ts +5 -0
- package/packages/protocol/dist/types.d.ts.map +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/src/types.ts +5 -0
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/dist/client.d.ts +6 -0
- package/packages/sdk/dist/client.d.ts.map +1 -1
- package/packages/sdk/dist/client.js +1 -0
- package/packages/sdk/dist/client.js.map +1 -1
- package/packages/sdk/package.json +2 -2
- package/packages/sdk/src/client.ts +7 -0
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/dist/cjs/relay-pty-path.js +111 -55
- package/packages/utils/dist/relay-pty-path.d.ts +17 -12
- package/packages/utils/dist/relay-pty-path.d.ts.map +1 -1
- package/packages/utils/dist/relay-pty-path.js +144 -94
- package/packages/utils/dist/relay-pty-path.js.map +1 -1
- package/packages/utils/package.json +2 -2
- package/packages/utils/src/relay-pty-path.test.ts +373 -0
- package/packages/utils/src/relay-pty-path.ts +182 -91
- package/packages/wrapper/dist/base-wrapper.d.ts +5 -0
- package/packages/wrapper/dist/base-wrapper.d.ts.map +1 -1
- package/packages/wrapper/dist/base-wrapper.js +14 -1
- package/packages/wrapper/dist/base-wrapper.js.map +1 -1
- package/packages/wrapper/dist/shared.d.ts +36 -0
- package/packages/wrapper/dist/shared.d.ts.map +1 -1
- package/packages/wrapper/dist/shared.js +123 -2
- package/packages/wrapper/dist/shared.js.map +1 -1
- package/packages/wrapper/dist/tmux-wrapper.js +1 -1
- package/packages/wrapper/dist/tmux-wrapper.js.map +1 -1
- package/packages/wrapper/package.json +6 -6
- package/packages/wrapper/src/base-wrapper.ts +15 -0
- package/packages/wrapper/src/shared.test.ts +156 -11
- package/packages/wrapper/src/shared.ts +154 -2
- package/packages/wrapper/src/tmux-wrapper.ts +1 -1
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comprehensive tests for relay-pty binary path resolution.
|
|
3
|
+
*
|
|
4
|
+
* Tests all installation scenarios by verifying the search paths are correct:
|
|
5
|
+
* 1. npx (from @agent-relay/* scoped package)
|
|
6
|
+
* 2. npx (from agent-relay directly)
|
|
7
|
+
* 3. npm install -g (nvm)
|
|
8
|
+
* 4. npm install -g (Homebrew macOS)
|
|
9
|
+
* 5. npm install -g (Homebrew macOS arm64)
|
|
10
|
+
* 6. npm install (local project)
|
|
11
|
+
* 7. pnpm global
|
|
12
|
+
* 8. Development (monorepo)
|
|
13
|
+
* 9. Docker container
|
|
14
|
+
* 10. Environment variable override
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
18
|
+
import {
|
|
19
|
+
findRelayPtyBinary,
|
|
20
|
+
getLastSearchPaths,
|
|
21
|
+
clearBinaryCache,
|
|
22
|
+
isPlatformSupported,
|
|
23
|
+
getSupportedPlatforms,
|
|
24
|
+
} from './relay-pty-path.js';
|
|
25
|
+
|
|
26
|
+
describe('findRelayPtyBinary - search path verification', () => {
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
clearBinaryCache();
|
|
29
|
+
delete process.env.RELAY_PTY_BINARY;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('npx installation (scoped @agent-relay/* package)', () => {
|
|
33
|
+
// When running via npx, the code runs from:
|
|
34
|
+
// ~/.npm/_npx/{hash}/node_modules/@agent-relay/bridge/dist/
|
|
35
|
+
// Binary should be searched at:
|
|
36
|
+
// ~/.npm/_npx/{hash}/node_modules/agent-relay/bin/relay-pty-darwin-arm64
|
|
37
|
+
|
|
38
|
+
it('should include correct npx cache path for scoped package', () => {
|
|
39
|
+
const callerDirname = '/Users/testuser/.npm/_npx/abc123/node_modules/@agent-relay/bridge/dist';
|
|
40
|
+
|
|
41
|
+
findRelayPtyBinary(callerDirname);
|
|
42
|
+
const paths = getLastSearchPaths();
|
|
43
|
+
|
|
44
|
+
// Should include the sibling agent-relay package path
|
|
45
|
+
const expectedPath = '/Users/testuser/.npm/_npx/abc123/node_modules/agent-relay/bin';
|
|
46
|
+
expect(paths.some((p) => p.startsWith(expectedPath))).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should check platform-specific binary BEFORE generic binary', () => {
|
|
50
|
+
const callerDirname = '/Users/testuser/.npm/_npx/abc123/node_modules/@agent-relay/bridge/dist';
|
|
51
|
+
|
|
52
|
+
findRelayPtyBinary(callerDirname);
|
|
53
|
+
const paths = getLastSearchPaths();
|
|
54
|
+
|
|
55
|
+
// Find the first occurrence of the npx cache path
|
|
56
|
+
const npxBasePath = '/Users/testuser/.npm/_npx/abc123/node_modules/agent-relay/bin';
|
|
57
|
+
const platformIdx = paths.findIndex(
|
|
58
|
+
(p) => p.startsWith(npxBasePath) && p.includes('relay-pty-')
|
|
59
|
+
);
|
|
60
|
+
const genericIdx = paths.findIndex((p) => p === `${npxBasePath}/relay-pty`);
|
|
61
|
+
|
|
62
|
+
expect(platformIdx).toBeGreaterThanOrEqual(0);
|
|
63
|
+
expect(genericIdx).toBeGreaterThan(platformIdx);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('npx installation (direct agent-relay package)', () => {
|
|
68
|
+
// When CLI code itself calls findRelayPtyBinary:
|
|
69
|
+
// ~/.npm/_npx/{hash}/node_modules/agent-relay/dist/src/cli/
|
|
70
|
+
|
|
71
|
+
it('should include correct path for direct agent-relay in npx cache', () => {
|
|
72
|
+
const callerDirname = '/Users/testuser/.npm/_npx/xyz789/node_modules/agent-relay/dist/src/cli';
|
|
73
|
+
|
|
74
|
+
findRelayPtyBinary(callerDirname);
|
|
75
|
+
const paths = getLastSearchPaths();
|
|
76
|
+
|
|
77
|
+
const expectedPath = '/Users/testuser/.npm/_npx/xyz789/node_modules/agent-relay/bin';
|
|
78
|
+
expect(paths.some((p) => p.startsWith(expectedPath))).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('Global npm install (nvm)', () => {
|
|
83
|
+
// ~/.nvm/versions/node/v20.0.0/lib/node_modules/agent-relay/
|
|
84
|
+
|
|
85
|
+
it('should include nvm global install path', () => {
|
|
86
|
+
const callerDirname =
|
|
87
|
+
'/Users/testuser/.nvm/versions/node/v20.0.0/lib/node_modules/@agent-relay/bridge/dist';
|
|
88
|
+
|
|
89
|
+
findRelayPtyBinary(callerDirname);
|
|
90
|
+
const paths = getLastSearchPaths();
|
|
91
|
+
|
|
92
|
+
const expectedPath =
|
|
93
|
+
'/Users/testuser/.nvm/versions/node/v20.0.0/lib/node_modules/agent-relay/bin';
|
|
94
|
+
expect(paths.some((p) => p.startsWith(expectedPath))).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('Global npm install (Homebrew macOS)', () => {
|
|
99
|
+
// /usr/local/lib/node_modules/agent-relay/ (Intel)
|
|
100
|
+
// /opt/homebrew/lib/node_modules/agent-relay/ (Apple Silicon)
|
|
101
|
+
|
|
102
|
+
it('should include Homebrew Intel location', () => {
|
|
103
|
+
const callerDirname = '/usr/local/lib/node_modules/@agent-relay/bridge/dist';
|
|
104
|
+
|
|
105
|
+
findRelayPtyBinary(callerDirname);
|
|
106
|
+
const paths = getLastSearchPaths();
|
|
107
|
+
|
|
108
|
+
expect(paths.some((p) => p.startsWith('/usr/local/lib/node_modules/agent-relay/bin'))).toBe(
|
|
109
|
+
true
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should include Homebrew Apple Silicon location', () => {
|
|
114
|
+
const callerDirname = '/opt/homebrew/lib/node_modules/@agent-relay/bridge/dist';
|
|
115
|
+
|
|
116
|
+
findRelayPtyBinary(callerDirname);
|
|
117
|
+
const paths = getLastSearchPaths();
|
|
118
|
+
|
|
119
|
+
expect(
|
|
120
|
+
paths.some((p) => p.startsWith('/opt/homebrew/lib/node_modules/agent-relay/bin'))
|
|
121
|
+
).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe('Local project install (npm install agent-relay)', () => {
|
|
126
|
+
// /path/to/project/node_modules/agent-relay/
|
|
127
|
+
|
|
128
|
+
it('should include local node_modules path from scoped package', () => {
|
|
129
|
+
const callerDirname = '/path/to/myproject/node_modules/@agent-relay/bridge/dist';
|
|
130
|
+
|
|
131
|
+
findRelayPtyBinary(callerDirname);
|
|
132
|
+
const paths = getLastSearchPaths();
|
|
133
|
+
|
|
134
|
+
const expectedPath = '/path/to/myproject/node_modules/agent-relay/bin';
|
|
135
|
+
expect(paths.some((p) => p.startsWith(expectedPath))).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should include cwd-based node_modules path', () => {
|
|
139
|
+
const callerDirname = '/some/other/location';
|
|
140
|
+
|
|
141
|
+
findRelayPtyBinary(callerDirname);
|
|
142
|
+
const paths = getLastSearchPaths();
|
|
143
|
+
|
|
144
|
+
const cwdPath = `${process.cwd()}/node_modules/agent-relay/bin`;
|
|
145
|
+
expect(paths.some((p) => p.startsWith(cwdPath))).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('pnpm global install', () => {
|
|
150
|
+
// ~/.local/share/pnpm/global/node_modules/agent-relay/
|
|
151
|
+
|
|
152
|
+
it('should include pnpm global location', () => {
|
|
153
|
+
const callerDirname =
|
|
154
|
+
'/Users/testuser/.local/share/pnpm/global/node_modules/@agent-relay/bridge/dist';
|
|
155
|
+
|
|
156
|
+
findRelayPtyBinary(callerDirname);
|
|
157
|
+
const paths = getLastSearchPaths();
|
|
158
|
+
|
|
159
|
+
expect(
|
|
160
|
+
paths.some((p) =>
|
|
161
|
+
p.startsWith('/Users/testuser/.local/share/pnpm/global/node_modules/agent-relay/bin')
|
|
162
|
+
)
|
|
163
|
+
).toBe(true);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('Development (monorepo)', () => {
|
|
168
|
+
// /path/to/relay/packages/bridge/dist/
|
|
169
|
+
|
|
170
|
+
it('should include project root bin/ path', () => {
|
|
171
|
+
const callerDirname = '/path/to/relay/packages/bridge/dist';
|
|
172
|
+
|
|
173
|
+
findRelayPtyBinary(callerDirname);
|
|
174
|
+
const paths = getLastSearchPaths();
|
|
175
|
+
|
|
176
|
+
// Development path: go up 3 levels to project root
|
|
177
|
+
expect(paths.some((p) => p.startsWith('/path/to/relay/bin'))).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should include Rust target/release path', () => {
|
|
181
|
+
const callerDirname = '/path/to/relay/packages/bridge/dist';
|
|
182
|
+
|
|
183
|
+
findRelayPtyBinary(callerDirname);
|
|
184
|
+
const paths = getLastSearchPaths();
|
|
185
|
+
|
|
186
|
+
expect(paths.some((p) => p.includes('relay-pty/target/release/relay-pty'))).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('should include Rust target/debug path', () => {
|
|
190
|
+
const callerDirname = '/path/to/relay/packages/bridge/dist';
|
|
191
|
+
|
|
192
|
+
findRelayPtyBinary(callerDirname);
|
|
193
|
+
const paths = getLastSearchPaths();
|
|
194
|
+
|
|
195
|
+
expect(paths.some((p) => p.includes('relay-pty/target/debug/relay-pty'))).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('Docker container', () => {
|
|
200
|
+
it('should include /app/bin/relay-pty path', () => {
|
|
201
|
+
const callerDirname = '/app/node_modules/@agent-relay/bridge/dist';
|
|
202
|
+
|
|
203
|
+
findRelayPtyBinary(callerDirname);
|
|
204
|
+
const paths = getLastSearchPaths();
|
|
205
|
+
|
|
206
|
+
expect(paths).toContain('/app/bin/relay-pty');
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe('System-wide install', () => {
|
|
211
|
+
it('should include /usr/local/bin/relay-pty path', () => {
|
|
212
|
+
const callerDirname = '/some/path';
|
|
213
|
+
|
|
214
|
+
findRelayPtyBinary(callerDirname);
|
|
215
|
+
const paths = getLastSearchPaths();
|
|
216
|
+
|
|
217
|
+
expect(paths).toContain('/usr/local/bin/relay-pty');
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
describe('Platform-specific binary naming', () => {
|
|
222
|
+
it('should include platform-specific binary name in search paths', () => {
|
|
223
|
+
const callerDirname = '/path/node_modules/@agent-relay/bridge/dist';
|
|
224
|
+
|
|
225
|
+
findRelayPtyBinary(callerDirname);
|
|
226
|
+
const paths = getLastSearchPaths();
|
|
227
|
+
|
|
228
|
+
// Should have platform-specific binary names based on current platform
|
|
229
|
+
const platform = process.platform;
|
|
230
|
+
const arch = process.arch;
|
|
231
|
+
let expectedBinaryName: string | null = null;
|
|
232
|
+
|
|
233
|
+
if (platform === 'darwin' && arch === 'arm64') {
|
|
234
|
+
expectedBinaryName = 'relay-pty-darwin-arm64';
|
|
235
|
+
} else if (platform === 'darwin' && arch === 'x64') {
|
|
236
|
+
expectedBinaryName = 'relay-pty-darwin-x64';
|
|
237
|
+
} else if (platform === 'linux' && arch === 'arm64') {
|
|
238
|
+
expectedBinaryName = 'relay-pty-linux-arm64';
|
|
239
|
+
} else if (platform === 'linux' && arch === 'x64') {
|
|
240
|
+
expectedBinaryName = 'relay-pty-linux-x64';
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (expectedBinaryName) {
|
|
244
|
+
expect(paths.some((p) => p.includes(expectedBinaryName!))).toBe(true);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe('Search path order priority', () => {
|
|
250
|
+
it('should have platform-specific binaries before generic binaries for same location', () => {
|
|
251
|
+
const callerDirname = '/Users/testuser/.npm/_npx/abc123/node_modules/@agent-relay/bridge/dist';
|
|
252
|
+
|
|
253
|
+
findRelayPtyBinary(callerDirname);
|
|
254
|
+
const paths = getLastSearchPaths();
|
|
255
|
+
|
|
256
|
+
// For each unique bin directory, platform-specific should come before generic
|
|
257
|
+
const binDirs = new Set<string>();
|
|
258
|
+
for (const p of paths) {
|
|
259
|
+
const binDir = p.replace(/\/[^/]+$/, ''); // Remove filename
|
|
260
|
+
if (binDir.endsWith('/bin')) {
|
|
261
|
+
binDirs.add(binDir);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
for (const binDir of binDirs) {
|
|
266
|
+
const platformIdx = paths.findIndex(
|
|
267
|
+
(p) => p.startsWith(binDir) && p.includes('relay-pty-')
|
|
268
|
+
);
|
|
269
|
+
const genericIdx = paths.findIndex((p) => p === `${binDir}/relay-pty`);
|
|
270
|
+
|
|
271
|
+
// If both exist, platform should come first
|
|
272
|
+
if (platformIdx >= 0 && genericIdx >= 0) {
|
|
273
|
+
expect(platformIdx).toBeLessThan(genericIdx);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
describe('Environment variable override', () => {
|
|
280
|
+
it('should use RELAY_PTY_BINARY when file is executable', () => {
|
|
281
|
+
// Use an actual executable that exists on all Unix systems
|
|
282
|
+
// /bin/ls is guaranteed to exist and be executable
|
|
283
|
+
const executableFile = '/bin/ls';
|
|
284
|
+
process.env.RELAY_PTY_BINARY = executableFile;
|
|
285
|
+
|
|
286
|
+
const result = findRelayPtyBinary('/any/path');
|
|
287
|
+
|
|
288
|
+
// Should return the env var path since the file is executable
|
|
289
|
+
expect(result).toBe(executableFile);
|
|
290
|
+
|
|
291
|
+
delete process.env.RELAY_PTY_BINARY;
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('should fall back to normal search when RELAY_PTY_BINARY file does not exist', () => {
|
|
295
|
+
process.env.RELAY_PTY_BINARY = '/nonexistent/path/relay-pty';
|
|
296
|
+
|
|
297
|
+
findRelayPtyBinary('/any/path');
|
|
298
|
+
const paths = getLastSearchPaths();
|
|
299
|
+
|
|
300
|
+
// Should have searched multiple paths (not just the env var)
|
|
301
|
+
expect(paths.length).toBeGreaterThan(1);
|
|
302
|
+
|
|
303
|
+
delete process.env.RELAY_PTY_BINARY;
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
describe('Real binary resolution', () => {
|
|
308
|
+
it('should find actual relay-pty binary in development', () => {
|
|
309
|
+
// This test uses the real file system to verify the function works
|
|
310
|
+
// in development context
|
|
311
|
+
const devPath = `${process.cwd()}/packages/utils/dist`;
|
|
312
|
+
|
|
313
|
+
const result = findRelayPtyBinary(devPath);
|
|
314
|
+
|
|
315
|
+
// In development, we should find the binary in bin/
|
|
316
|
+
// This test only passes when run from the monorepo root
|
|
317
|
+
if (process.cwd().includes('relay')) {
|
|
318
|
+
expect(result).not.toBeNull();
|
|
319
|
+
expect(result).toMatch(/relay-pty/);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('isPlatformSupported', () => {
|
|
326
|
+
it('should return true for current platform (darwin/linux arm64/x64)', () => {
|
|
327
|
+
const platform = process.platform;
|
|
328
|
+
const arch = process.arch;
|
|
329
|
+
|
|
330
|
+
// This test runs on macOS/Linux CI, so current platform should be supported
|
|
331
|
+
if ((platform === 'darwin' || platform === 'linux') && (arch === 'arm64' || arch === 'x64')) {
|
|
332
|
+
expect(isPlatformSupported()).toBe(true);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('should be consistent with platform binary availability', () => {
|
|
337
|
+
// If platform is supported, we should have a binary name for it
|
|
338
|
+
const supported = isPlatformSupported();
|
|
339
|
+
const platforms = getSupportedPlatforms();
|
|
340
|
+
|
|
341
|
+
if (supported) {
|
|
342
|
+
const currentPlatformArch = `${process.platform}-${process.arch}`;
|
|
343
|
+
expect(platforms).toContain(currentPlatformArch);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
describe('getSupportedPlatforms', () => {
|
|
349
|
+
it('should return all supported platform-arch combinations', () => {
|
|
350
|
+
const platforms = getSupportedPlatforms();
|
|
351
|
+
|
|
352
|
+
// Should include all 4 supported combinations
|
|
353
|
+
expect(platforms).toContain('darwin-arm64');
|
|
354
|
+
expect(platforms).toContain('darwin-x64');
|
|
355
|
+
expect(platforms).toContain('linux-arm64');
|
|
356
|
+
expect(platforms).toContain('linux-x64');
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('should not include Windows', () => {
|
|
360
|
+
const platforms = getSupportedPlatforms();
|
|
361
|
+
|
|
362
|
+
expect(platforms).not.toContain('win32-x64');
|
|
363
|
+
expect(platforms).not.toContain('win32-arm64');
|
|
364
|
+
expect(platforms).not.toMatch(/win32/);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('should return a comma-separated string', () => {
|
|
368
|
+
const platforms = getSupportedPlatforms();
|
|
369
|
+
|
|
370
|
+
expect(typeof platforms).toBe('string');
|
|
371
|
+
expect(platforms).toMatch(/^[\w-]+(, [\w-]+)*$/);
|
|
372
|
+
});
|
|
373
|
+
});
|