Skip to content

Commit f2994de

Browse files
committed
Update CLI tests
1 parent 9e79de6 commit f2994de

File tree

7 files changed

+154
-83
lines changed

7 files changed

+154
-83
lines changed

packages/snaps-cli/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@
101101
"querystring-es3": "^0.2.1",
102102
"readable-stream": "^3.6.2",
103103
"semver": "^7.5.4",
104-
"serve-handler": "^6.1.5",
105104
"stream-browserify": "^3.0.0",
106105
"stream-http": "^3.2.0",
107106
"string_decoder": "^1.3.0",
@@ -127,7 +126,6 @@
127126
"@types/express": "^5.0.1",
128127
"@types/jest": "^27.5.1",
129128
"@types/node": "18.14.2",
130-
"@types/serve-handler": "^6.1.0",
131129
"@types/yargs": "^17.0.24",
132130
"cross-fetch": "^3.1.5",
133131
"deepmerge": "^4.2.2",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import command from '.';
2+
import { sandboxHandler } from './sandbox';
3+
import { getMockConfig } from '../../test-utils';
4+
import type { YargsArgs } from '../../types/yargs';
5+
6+
jest.mock('./sandbox');
7+
8+
const getMockArgv = () => {
9+
return {
10+
context: { config: getMockConfig('webpack') },
11+
} as unknown as YargsArgs;
12+
};
13+
14+
describe('sandbox command', () => {
15+
it('calls the `sandboxHandler` function', async () => {
16+
await command.handler(getMockArgv());
17+
expect(sandboxHandler).toHaveBeenCalled();
18+
});
19+
});
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { getMockConfig } from '@metamask/snaps-cli/test-utils';
2+
import { DEFAULT_SNAP_BUNDLE } from '@metamask/snaps-utils/test-utils';
3+
import fs from 'fs';
4+
5+
import { sandboxHandler } from './sandbox';
6+
import { build } from '../build';
7+
8+
jest.mock('fs');
9+
jest.mock('./server', () => ({
10+
startSandbox: jest.fn().mockResolvedValue({ port: 8080 }),
11+
}));
12+
jest.mock('../build/implementation');
13+
jest.mock('../eval');
14+
15+
describe('sandboxHandler', () => {
16+
it('builds the Snap if the build option is `true`', async () => {
17+
await fs.promises.writeFile('/input.js', DEFAULT_SNAP_BUNDLE);
18+
19+
jest.spyOn(console, 'log').mockImplementation();
20+
const config = getMockConfig('webpack', {
21+
input: '/input.js',
22+
output: {
23+
path: '/foo',
24+
filename: 'output.js',
25+
},
26+
});
27+
28+
await sandboxHandler(config, {});
29+
30+
expect(process.exitCode).not.toBe(1);
31+
expect(build).toHaveBeenCalledWith(config, {
32+
analyze: false,
33+
evaluate: false,
34+
spinner: expect.any(Object),
35+
});
36+
37+
expect(console.log).toHaveBeenCalledWith(
38+
expect.stringContaining('Sandbox running at http://localhost:8080.'),
39+
);
40+
});
41+
42+
it('does not build the Snap if the build option is `false`', async () => {
43+
jest.spyOn(console, 'log').mockImplementation();
44+
const config = getMockConfig('webpack', {
45+
input: '/input.js',
46+
output: {
47+
path: '/foo',
48+
filename: 'output.js',
49+
},
50+
});
51+
52+
await sandboxHandler(config, { build: false });
53+
54+
expect(process.exitCode).not.toBe(1);
55+
expect(build).not.toHaveBeenCalled();
56+
57+
expect(console.log).toHaveBeenCalledWith(
58+
expect.stringContaining('Sandbox running at http://localhost:8080.'),
59+
);
60+
});
61+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { getMockConfig } from '@metamask/snaps-cli/test-utils';
2+
import fs from 'fs';
3+
import { dirname } from 'path';
4+
5+
import { startSandbox } from './server';
6+
7+
jest.mock('fs');
8+
9+
describe('startSandbox', () => {
10+
beforeAll(async () => {
11+
const sandboxPath = require.resolve(
12+
'@metamask/snaps-sandbox/dist/index.html',
13+
);
14+
15+
await fs.promises.mkdir(dirname(sandboxPath), { recursive: true });
16+
await fs.promises.writeFile(
17+
sandboxPath,
18+
'<html><body>Snaps Sandbox</body></html>',
19+
);
20+
});
21+
22+
it('starts the sandbox server', async () => {
23+
const config = getMockConfig('webpack', {
24+
server: {
25+
port: 8080,
26+
},
27+
});
28+
29+
const { port, close } = await startSandbox(config);
30+
31+
expect(port).toBe(8080);
32+
expect(close).toBeInstanceOf(Function);
33+
34+
const response = await fetch('http://localhost:8080');
35+
expect(response.status).toBe(200);
36+
37+
const text = await response.text();
38+
expect(text).toBe('<html><body>Snaps Sandbox</body></html>');
39+
40+
await close();
41+
});
42+
});

packages/snaps-cli/src/webpack/server.test.ts

Lines changed: 12 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { getSnapManifest } from '@metamask/snaps-utils/test-utils';
22
import fetch from 'cross-fetch';
33
import { promises as fs } from 'fs';
4-
import http, { IncomingMessage, Server, ServerResponse } from 'http';
5-
import serveMiddleware from 'serve-handler';
4+
import { Server } from 'http';
65

76
import { getAllowedPaths, getServer } from './server';
87
import { getMockConfig } from '../test-utils';
@@ -201,32 +200,6 @@ describe('getServer', () => {
201200
await close();
202201
});
203202

204-
it('calls the serve middleware for allowed files', async () => {
205-
const config = getMockConfig('webpack', {
206-
input: 'src/index.js',
207-
server: {
208-
root: '/foo',
209-
port: 0,
210-
},
211-
});
212-
213-
const server = getServer(config);
214-
const { port, close } = await server.listen();
215-
216-
const response = await fetch(`http://localhost:${port}/snap.manifest.json`);
217-
218-
expect(response.status).toBe(200);
219-
expect(await response.text()).toBe('');
220-
221-
expect(serveMiddleware).toHaveBeenCalledWith(
222-
expect.any(IncomingMessage),
223-
expect.any(ServerResponse),
224-
expect.objectContaining({ public: expect.stringContaining('foo') }),
225-
);
226-
227-
await close();
228-
});
229-
230203
it('ignores query strings', async () => {
231204
const config = getMockConfig('webpack', {
232205
input: 'src/index.js',
@@ -244,13 +217,7 @@ describe('getServer', () => {
244217
);
245218

246219
expect(response.status).toBe(200);
247-
expect(await response.text()).toBe('');
248-
249-
expect(serveMiddleware).toHaveBeenCalledWith(
250-
expect.any(IncomingMessage),
251-
expect.any(ServerResponse),
252-
expect.objectContaining({ public: expect.stringContaining('foo') }),
253-
);
220+
expect(await response.text()).toBe(JSON.stringify(getSnapManifest()));
254221

255222
await close();
256223
});
@@ -267,11 +234,10 @@ describe('getServer', () => {
267234
const server = getServer(config);
268235
const { port, close } = await server.listen();
269236

270-
const response = await fetch(`http://localhost:${port}/`);
237+
const response = await fetch(`http://localhost:${port}/.env`);
271238

272239
expect(response.status).toBe(404);
273240
expect(await response.text()).toBe('');
274-
expect(serveMiddleware).not.toHaveBeenCalled();
275241

276242
await close();
277243
});
@@ -281,21 +247,19 @@ describe('getServer', () => {
281247
input: 'src/index.js',
282248
server: {
283249
root: '/foo',
284-
port: 0,
250+
port: 13490,
285251
},
286252
});
287253

288-
const createServer = jest.spyOn(http, 'createServer');
289-
const server = getServer(config);
290-
const httpServer: Server = createServer.mock.results[0].value;
291-
292-
jest.spyOn(httpServer, 'listen').mockImplementationOnce(() => {
293-
throw new Error('Address already in use.');
294-
});
254+
const firstServer = getServer(config);
255+
const { close } = await firstServer.listen();
295256

296-
await expect(server.listen()).rejects.toThrow('Address already in use.');
257+
const secondServer = getServer(config);
258+
await expect(secondServer.listen()).rejects.toThrow(
259+
'listen EADDRINUSE: address already in use :::13490',
260+
);
297261

298-
httpServer.close();
262+
await close();
299263
});
300264

301265
it('throws if the server fails to close', async () => {
@@ -307,18 +271,15 @@ describe('getServer', () => {
307271
},
308272
});
309273

310-
const createServer = jest.spyOn(http, 'createServer');
311274
const server = getServer(config);
312-
const httpServer: Server = createServer.mock.results[0].value;
313275

276+
const { server: httpServer, close } = await server.listen();
314277
// @ts-expect-error - Invalid mock.
315278
jest.spyOn(httpServer, 'close').mockImplementationOnce((callback) => {
316279
return callback?.(new Error('Failed to close server.'));
317280
});
318281

319-
const { close } = await server.listen();
320282
await expect(close()).rejects.toThrow('Failed to close server.');
321-
322283
httpServer.close();
323284
});
324285
});

packages/snaps-cli/src/webpack/server.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -166,26 +166,27 @@ export function getServer(
166166
server: Server;
167167
close: () => Promise<void>;
168168
}>((resolve, reject) => {
169-
try {
170-
const server = app.listen(port, () => {
171-
const close = async () => {
172-
await new Promise<void>((resolveClose, rejectClose) => {
173-
server.close((closeError) => {
174-
if (closeError) {
175-
return rejectClose(closeError);
176-
}
177-
178-
return resolveClose();
179-
});
169+
// eslint-disable-next-line consistent-return
170+
const server = app.listen(port, (error) => {
171+
if (error) {
172+
return reject(error);
173+
}
174+
175+
const close = async () => {
176+
await new Promise<void>((resolveClose, rejectClose) => {
177+
server.close((closeError) => {
178+
if (closeError) {
179+
return rejectClose(closeError);
180+
}
181+
182+
return resolveClose();
180183
});
181-
};
182-
183-
const address = server.address() as AddressInfo;
184-
resolve({ port: address.port, server, close });
185-
});
186-
} catch (listenError) {
187-
reject(listenError);
188-
}
184+
});
185+
};
186+
187+
const address = server.address() as AddressInfo;
188+
resolve({ port: address.port, server, close });
189+
});
189190
});
190191
};
191192

yarn.lock

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5563,7 +5563,6 @@ __metadata:
55635563
"@types/express": "npm:^5.0.1"
55645564
"@types/jest": "npm:^27.5.1"
55655565
"@types/node": "npm:18.14.2"
5566-
"@types/serve-handler": "npm:^6.1.0"
55675566
"@types/yargs": "npm:^17.0.24"
55685567
assert: "npm:^2.0.0"
55695568
babelify: "npm:^10.0.0"
@@ -5597,7 +5596,6 @@ __metadata:
55975596
querystring-es3: "npm:^0.2.1"
55985597
readable-stream: "npm:^3.6.2"
55995598
semver: "npm:^7.5.4"
5600-
serve-handler: "npm:^6.1.5"
56015599
stream-browserify: "npm:^3.0.0"
56025600
stream-http: "npm:^3.2.0"
56035601
string_decoder: "npm:^1.3.0"
@@ -8077,15 +8075,6 @@ __metadata:
80778075
languageName: node
80788076
linkType: hard
80798077

8080-
"@types/serve-handler@npm:^6.1.0":
8081-
version: 6.1.1
8082-
resolution: "@types/serve-handler@npm:6.1.1"
8083-
dependencies:
8084-
"@types/node": "npm:*"
8085-
checksum: 10/f0931dea038b6cec92e51a693c447d27d491486486167a438349fb5a9776d7a3b5a2118ef1c94544e6ba85b2fc79401c0bdd99731b52331f8a538cd05b0a5dff
8086-
languageName: node
8087-
linkType: hard
8088-
80898078
"@types/serve-index@npm:^1.9.1":
80908079
version: 1.9.1
80918080
resolution: "@types/serve-index@npm:1.9.1"

0 commit comments

Comments
 (0)