Skip to content

Commit 4c12f80

Browse files
committed
feat(server): server mode ws string option
1 parent f984e53 commit 4c12f80

File tree

3 files changed

+224
-102
lines changed

3 files changed

+224
-102
lines changed

lib/utils/getSocketServerImplementation.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ function getSocketServerImplementation(options) {
99
if (options.serverMode === 'sockjs') {
1010
// eslint-disable-next-line global-require
1111
ServerImplementation = require('../servers/SockJSServer');
12+
} else if (options.serverMode === 'ws') {
13+
// eslint-disable-next-line global-require
14+
ServerImplementation = require('../servers/WebsocketServer');
1215
} else {
1316
try {
1417
// eslint-disable-next-line global-require, import/no-dynamic-require
@@ -29,7 +32,7 @@ function getSocketServerImplementation(options) {
2932

3033
if (!serverImplFound) {
3134
throw new Error(
32-
"serverMode must be a string denoting a default implementation (e.g. 'sockjs'), a full path to " +
35+
"serverMode must be a string denoting a default implementation (e.g. 'sockjs', 'ws'), a full path to " +
3336
'a JS file which exports a class extending BaseServer (webpack-dev-server/lib/servers/BaseServer) ' +
3437
'via require.resolve(...), or the class itself which extends BaseServer'
3538
);

test/server/serverMode-option.test.js

Lines changed: 180 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7,134 +7,216 @@ const request = require('supertest');
77
const sockjs = require('sockjs');
88
const SockJSServer = require('../../lib/servers/SockJSServer');
99
const config = require('../fixtures/simple-config/webpack.config');
10-
const testServer = require('../helpers/test-server');
1110
const BaseServer = require('../../lib/servers/BaseServer');
1211
const port = require('../ports-map')['serverMode-option'];
1312

1413
describe('serverMode option', () => {
14+
let mockedTestServer;
15+
let testServer;
1516
let server;
1617
let req;
18+
let getSocketServerImplementation;
19+
20+
const serverModes = [
21+
{
22+
title: 'as a string ("sockjs")',
23+
serverMode: 'sockjs',
24+
},
25+
{
26+
title: 'as a path ("sockjs")',
27+
serverMode: require.resolve('../../lib/servers/SockJSServer'),
28+
},
29+
{
30+
title: 'as a string ("ws")',
31+
serverMode: 'ws',
32+
},
33+
{
34+
title: 'as a path ("ws")',
35+
serverMode: require.resolve('../../lib/servers/WebsocketServer'),
36+
},
37+
{
38+
title: 'as a class (custom implementation)',
39+
serverMode: class CustomServer {},
40+
},
41+
{
42+
title: 'as a nonexistent path',
43+
serverMode: '/bad/path/to/implementation',
44+
},
45+
];
46+
47+
describe('is passed to getSocketServerImplementation correctly', () => {
48+
beforeEach(() => {
49+
jest.mock('../../lib/utils/getSocketServerImplementation');
50+
// eslint-disable-next-line global-require
51+
getSocketServerImplementation = require('../../lib/utils/getSocketServerImplementation');
52+
getSocketServerImplementation.mockImplementation(() => {
53+
return class MockServer {
54+
// eslint-disable-next-line no-empty-function
55+
onConnection() {}
56+
};
57+
});
58+
});
1759

18-
afterEach((done) => {
19-
testServer.close(done);
20-
req = null;
21-
server = null;
22-
});
60+
afterEach((done) => {
61+
jest.resetAllMocks();
62+
jest.resetModules();
2363

24-
describe('as a string ("sockjs")', () => {
25-
beforeEach((done) => {
26-
server = testServer.start(
27-
config,
28-
{
29-
serverMode: 'sockjs',
30-
port,
31-
},
32-
done
33-
);
34-
req = request(`http://localhost:${port}`);
64+
mockedTestServer.close(done);
3565
});
3666

37-
it('sockjs path responds with a 200', (done) => {
38-
req.get('/sockjs-node').expect(200, done);
67+
serverModes.forEach((data) => {
68+
it(data.title, (done) => {
69+
// eslint-disable-next-line global-require
70+
mockedTestServer = require('../helpers/test-server');
71+
mockedTestServer.start(
72+
config,
73+
{
74+
serverMode: data.serverMode,
75+
port,
76+
},
77+
() => {
78+
expect(getSocketServerImplementation.mock.calls.length).toEqual(1);
79+
expect(getSocketServerImplementation.mock.calls[0].length).toEqual(
80+
1
81+
);
82+
expect(
83+
getSocketServerImplementation.mock.calls[0][0].serverMode
84+
).toEqual(data.serverMode);
85+
done();
86+
}
87+
);
88+
});
3989
});
4090
});
4191

42-
describe('as a path ("sockjs")', () => {
43-
beforeEach((done) => {
44-
server = testServer.start(
45-
config,
46-
{
47-
serverMode: require.resolve('../../lib/servers/SockJSServer'),
48-
port,
49-
},
50-
done
51-
);
52-
req = request(`http://localhost:${port}`);
92+
describe('passed to server', () => {
93+
beforeAll(() => {
94+
jest.unmock('../../lib/utils/getSocketServerImplementation');
95+
// eslint-disable-next-line global-require
96+
testServer = require('../helpers/test-server');
5397
});
5498

55-
it('sockjs path responds with a 200', (done) => {
56-
req.get('/sockjs-node').expect(200, done);
99+
afterEach((done) => {
100+
testServer.close(done);
101+
req = null;
102+
server = null;
57103
});
58-
});
59104

60-
describe('as a class ("sockjs")', () => {
61-
beforeEach((done) => {
62-
server = testServer.start(
63-
config,
64-
{
65-
serverMode: SockJSServer,
66-
port,
67-
},
68-
done
69-
);
70-
req = request(`http://localhost:${port}`);
105+
describe('as a string ("sockjs")', () => {
106+
beforeEach((done) => {
107+
server = testServer.start(
108+
config,
109+
{
110+
serverMode: 'sockjs',
111+
port,
112+
},
113+
done
114+
);
115+
req = request(`http://localhost:${port}`);
116+
});
117+
118+
it('sockjs path responds with a 200', (done) => {
119+
req.get('/sockjs-node').expect(200, done);
120+
});
71121
});
72122

73-
it('sockjs path responds with a 200', (done) => {
74-
req.get('/sockjs-node').expect(200, done);
123+
describe('as a path ("sockjs")', () => {
124+
beforeEach((done) => {
125+
server = testServer.start(
126+
config,
127+
{
128+
serverMode: require.resolve('../../lib/servers/SockJSServer'),
129+
port,
130+
},
131+
done
132+
);
133+
req = request(`http://localhost:${port}`);
134+
});
135+
136+
it('sockjs path responds with a 200', (done) => {
137+
req.get('/sockjs-node').expect(200, done);
138+
});
75139
});
76-
});
77140

78-
describe('as a class (custom "sockjs" implementation)', () => {
79-
it('uses supplied server implementation', (done) => {
80-
server = testServer.start(
81-
config,
82-
{
83-
port,
84-
sockPath: '/foo/test/bar/',
85-
serverMode: class MySockJSServer extends BaseServer {
86-
constructor(serv) {
87-
super(serv);
88-
this.socket = sockjs.createServer({
89-
// Use provided up-to-date sockjs-client
90-
sockjs_url: '/__webpack_dev_server__/sockjs.bundle.js',
91-
// Limit useless logs
92-
log: (severity, line) => {
93-
if (severity === 'error') {
94-
this.server.log.error(line);
95-
} else {
96-
this.server.log.debug(line);
97-
}
98-
},
99-
});
100-
101-
this.socket.installHandlers(this.server.listeningApp, {
102-
prefix: this.server.sockPath,
103-
});
104-
105-
expect(server.options.sockPath).toEqual('/foo/test/bar/');
106-
}
107-
108-
send(connection, message) {
109-
connection.write(message);
110-
}
111-
112-
close(connection) {
113-
connection.close();
114-
}
115-
116-
onConnection(f) {
117-
this.socket.on('connection', f);
118-
}
141+
describe('as a class ("sockjs")', () => {
142+
beforeEach((done) => {
143+
server = testServer.start(
144+
config,
145+
{
146+
serverMode: SockJSServer,
147+
port,
119148
},
120-
},
121-
done
122-
);
149+
done
150+
);
151+
req = request(`http://localhost:${port}`);
152+
});
153+
154+
it('sockjs path responds with a 200', (done) => {
155+
req.get('/sockjs-node').expect(200, done);
156+
});
123157
});
124-
});
125158

126-
describe('as a path with nonexistent path', () => {
127-
it('should throw an error', () => {
128-
expect(() => {
159+
describe('as a class (custom "sockjs" implementation)', () => {
160+
it('uses supplied server implementation', (done) => {
129161
server = testServer.start(
130162
config,
131163
{
132-
serverMode: '/bad/path/to/implementation',
133164
port,
165+
sockPath: '/foo/test/bar/',
166+
serverMode: class MySockJSServer extends BaseServer {
167+
constructor(serv) {
168+
super(serv);
169+
this.socket = sockjs.createServer({
170+
// Use provided up-to-date sockjs-client
171+
sockjs_url: '/__webpack_dev_server__/sockjs.bundle.js',
172+
// Limit useless logs
173+
log: (severity, line) => {
174+
if (severity === 'error') {
175+
this.server.log.error(line);
176+
} else {
177+
this.server.log.debug(line);
178+
}
179+
},
180+
});
181+
182+
this.socket.installHandlers(this.server.listeningApp, {
183+
prefix: this.server.sockPath,
184+
});
185+
186+
expect(server.options.sockPath).toEqual('/foo/test/bar/');
187+
}
188+
189+
send(connection, message) {
190+
connection.write(message);
191+
}
192+
193+
close(connection) {
194+
connection.close();
195+
}
196+
197+
onConnection(f) {
198+
this.socket.on('connection', f);
199+
}
200+
},
134201
},
135-
() => {}
202+
done
136203
);
137-
}).toThrow(/serverMode must be a string/);
204+
});
205+
});
206+
207+
describe('as a path with nonexistent path', () => {
208+
it('should throw an error', () => {
209+
expect(() => {
210+
server = testServer.start(
211+
config,
212+
{
213+
serverMode: '/bad/path/to/implementation',
214+
port,
215+
},
216+
() => {}
217+
);
218+
}).toThrow(/serverMode must be a string/);
219+
});
138220
});
139221
});
140222
});

test/server/utils/getSocketServerImplementation.test.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
const getSocketServerImplementation = require('../../../lib/utils/getSocketServerImplementation');
44
const SockJSServer = require('../../../lib/servers/SockJSServer');
5+
const WebsocketServer = require('../../../lib/servers/WebsocketServer');
56

67
describe('getSocketServerImplementation util', () => {
7-
it("should works with string serverMode ('sockjs')", () => {
8+
it("should work with string serverMode ('sockjs')", () => {
89
let result;
910

1011
expect(() => {
@@ -16,7 +17,7 @@ describe('getSocketServerImplementation util', () => {
1617
expect(result).toEqual(SockJSServer);
1718
});
1819

19-
it('should works with serverMode (SockJSServer class)', () => {
20+
it('should work with serverMode (SockJSServer class)', () => {
2021
let result;
2122

2223
expect(() => {
@@ -40,7 +41,43 @@ describe('getSocketServerImplementation util', () => {
4041
expect(result).toEqual(SockJSServer);
4142
});
4243

43-
it('should throws with serverMode (bad path)', () => {
44+
it("should work with string serverMode ('ws')", () => {
45+
let result;
46+
47+
expect(() => {
48+
result = getSocketServerImplementation({
49+
serverMode: 'ws',
50+
});
51+
}).not.toThrow();
52+
53+
expect(result).toEqual(WebsocketServer);
54+
});
55+
56+
it('should work with serverMode (WebsocketServer class)', () => {
57+
let result;
58+
59+
expect(() => {
60+
result = getSocketServerImplementation({
61+
serverMode: WebsocketServer,
62+
});
63+
}).not.toThrow();
64+
65+
expect(result).toEqual(WebsocketServer);
66+
});
67+
68+
it('should work with serverMode (WebsocketServer full path)', () => {
69+
let result;
70+
71+
expect(() => {
72+
result = getSocketServerImplementation({
73+
serverMode: require.resolve('../../../lib/servers/WebsocketServer'),
74+
});
75+
}).not.toThrow();
76+
77+
expect(result).toEqual(WebsocketServer);
78+
});
79+
80+
it('should throw with serverMode (bad path)', () => {
4481
expect(() => {
4582
getSocketServerImplementation({
4683
serverMode: '/bad/path/to/implementation',

0 commit comments

Comments
 (0)