diff --git a/setupTest.js b/setupTest.js index c6223d215a..4d648782b3 100644 --- a/setupTest.js +++ b/setupTest.js @@ -1,3 +1,3 @@ 'use strict'; -jest.setTimeout(30000); +jest.setTimeout(60000); diff --git a/test/InvalidateCallback.test.js b/test/InvalidateCallback.test.js deleted file mode 100644 index c95781f24e..0000000000 --- a/test/InvalidateCallback.test.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -const webpack = require('webpack'); -const { noop } = require('webpack-dev-middleware/lib/util'); -const Server = require('../lib/Server'); -const config = require('./fixtures/simple-config/webpack.config'); - -describe('Invalidate Callback', () => { - describe('Testing callback functions on calling invalidate without callback', () => { - it('should be `noop` (the default callback function)', (done) => { - const compiler = webpack(config); - const server = new Server(compiler); - - server.invalidate(); - expect(server.middleware.context.callbacks[0]).toBe(noop); - - compiler.hooks.done.tap('webpack-dev-server', () => { - server.close(done); - }); - - compiler.run(() => {}); - }); - }); - - describe('Testing callback functions on calling invalidate with callback', () => { - it('should be `callback` function', (done) => { - const compiler = webpack(config); - const callback = jest.fn(); - const server = new Server(compiler); - server.invalidate(callback); - - expect(server.middleware.context.callbacks[0]).toBe(callback); - - compiler.hooks.done.tap('webpack-dev-server', () => { - server.close(done); - }); - - compiler.run(() => {}); - }); - }); -}); diff --git a/test/MimeTypes.test.js b/test/MimeTypes.test.js deleted file mode 100644 index dcf2f725e2..0000000000 --- a/test/MimeTypes.test.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/simple-config/webpack.config'); - -describe('MimeTypes configuration', () => { - afterEach(testServer.close); - - it('remapping mime type without force should throw an error', () => { - expect(() => { - testServer.start(config, { - mimeTypes: { 'application/octet-stream': ['js'] }, - }); - }).toThrow(/Attempt to change mapping for/); - }); - - it('remapping mime type with force should not throw an error', (done) => { - testServer.start( - config, - { - mimeTypes: { - typeMap: { 'application/octet-stream': ['js'] }, - force: true, - }, - }, - done - ); - }); -}); - -describe('custom mimeTypes', () => { - let server; - let req; - - beforeAll((done) => { - server = testServer.start( - config, - { - mimeTypes: { - typeMap: { 'application/octet-stream': ['js'] }, - force: true, - }, - }, - done - ); - req = request(server.app); - }); - - afterAll(testServer.close); - - it('request to bundle file with modified mime type', (done) => { - req - .get('/main.js') - .expect('Content-Type', /application\/octet-stream/) - .expect(200, done); - }); -}); diff --git a/test/Server.test.js b/test/Server.test.js deleted file mode 100644 index 23acfaa9bf..0000000000 --- a/test/Server.test.js +++ /dev/null @@ -1,503 +0,0 @@ -'use strict'; - -const { relative, sep } = require('path'); -const webpack = require('webpack'); -const request = require('supertest'); -// Mock opn before loading Server -jest.mock('opn'); -// eslint-disable-next-line import/newline-after-import -const opn = require('opn'); -opn.mockImplementation(() => { - return { - catch: jest.fn(), - }; -}); -jest.mock('sockjs/lib/transport'); -// eslint-disable-next-line import/newline-after-import -const sockjs = require('sockjs/lib/transport'); -const Server = require('../lib/Server'); -const config = require('./fixtures/simple-config/webpack.config'); -const testServer = require('./helpers/test-server'); - -describe('Server', () => { - describe('sockjs', () => { - it('add decorateConnection', () => { - expect(typeof sockjs.Session.prototype.decorateConnection).toEqual( - 'function' - ); - }); - }); - - describe('addEntries', () => { - it('add hot option', (done) => { - const compiler = webpack(config); - const server = new Server(compiler, { - hot: true, - }); - - expect( - server.middleware.context.compiler.options.entry.map((p) => { - return relative('.', p).split(sep); - }) - ).toMatchSnapshot(); - expect( - server.middleware.context.compiler.options.plugins - ).toMatchSnapshot(); - - compiler.hooks.done.tap('webpack-dev-server', () => { - server.close(done); - }); - - compiler.run(() => {}); - }); - - it('add hotOnly option', (done) => { - const compiler = webpack(config); - const server = new Server(compiler, { - hotOnly: true, - }); - - expect( - server.middleware.context.compiler.options.entry.map((p) => { - return relative('.', p).split(sep); - }) - ).toMatchSnapshot(); - expect( - server.middleware.context.compiler.options.plugins - ).toMatchSnapshot(); - - compiler.hooks.done.tap('webpack-dev-server', () => { - server.close(done); - }); - - compiler.run(() => {}); - }); - }); - - // issue: https://github.com/webpack/webpack-dev-server/issues/1724 - describe('express.static.mine.types', () => { - beforeEach(() => { - jest.resetModules(); - }); - - afterEach(() => { - jest.unmock('express'); - }); - - it("should success even if mine.types doesn't exist", (done) => { - jest.mock('express', () => { - const data = jest.requireActual('express'); - const { static: st } = data; - const { mime } = st; - - delete mime.types; - - expect(typeof mime.types).toEqual('undefined'); - - return Object.assign(data, { - static: Object.assign(st, { - mime, - }), - }); - }); - - const compiler = webpack(config); - const server = new Server(compiler); - - compiler.hooks.done.tap('webpack-dev-server', (s) => { - const output = server.getStats(s); - expect(output.errors.length).toEqual(0); - - server.close(done); - }); - - compiler.run(() => {}); - server.listen(8080, 'localhost'); - }); - }); - - describe('stats', () => { - it(`should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors')`, () => { - const allStats = [ - {}, - // eslint-disable-next-line no-undefined - undefined, - false, - 'errors-only', - { - assets: false, - }, - ]; - - return allStats.reduce((p, stats) => { - return p.then(() => { - return new Promise((resolve) => { - const compiler = webpack(config); - const server = new Server(compiler, { stats }); - - compiler.hooks.done.tap('webpack-dev-server', (s) => { - expect(Object.keys(server.getStats(s))).toMatchSnapshot(); - - server.close(resolve); - }); - - compiler.run(() => {}); - server.listen(8080, 'localhost'); - }); - }); - }, Promise.resolve()); - }); - - it('should respect warningsFilter', (done) => { - const compiler = webpack(config); - const server = new Server(compiler, { - stats: { warningsFilter: 'test' }, - }); - - compiler.hooks.done.tap('webpack-dev-server', (s) => { - s.compilation.warnings = ['test', 'another warning']; - - const output = server.getStats(s); - - expect(output.warnings.length).toBe(1); - expect(output.warnings[0]).toBe('another warning'); - - server.close(done); - }); - - compiler.run(() => {}); - server.listen(8080, 'localhost'); - }); - - it('should open', (done) => { - const compiler = webpack(config); - const server = new Server(compiler, { - open: true, - }); - - compiler.hooks.done.tap('webpack-dev-server', () => { - expect(opn.mock.calls[0]).toEqual(['http://localhost:8080/', {}]); - expect(opn.mock.invocationCallOrder[0]).toEqual(1); - server.close(done); - }); - - compiler.run(() => {}); - server.listen(8080, 'localhost'); - }); - }); - - describe('host', () => { - let server = null; - let req = null; - - describe('is not be specified', () => { - beforeAll((done) => { - server = testServer.start(config, {}, done); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - expect(address.port).toBe(8080); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is undefined', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - // eslint-disable-next-line no-undefined - host: undefined, - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('::'); - expect(address.port).toBe(8080); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is null', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - host: null, - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('::'); - expect(address.port).toBe(8080); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is 127.0.0.1 (IPv4)', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - host: '127.0.0.1', - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - expect(address.port).toBe(8080); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is localhost', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - host: 'localhost', - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - expect(address.port).toBe(8080); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is 0.0.0.0', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - host: '0.0.0.0', - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('0.0.0.0'); - expect(address.port).toBe(8080); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - }); - - describe('port', () => { - let server = null; - let req = null; - - describe('is not be specified', () => { - beforeAll((done) => { - server = testServer.start(config, {}, done); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - // Random port - expect(address.port).toBeDefined(); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is undefined', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - // eslint-disable-next-line no-undefined - port: undefined, - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - // Random port - expect(address.port).toBeDefined(); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is null', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - port: null, - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - // Random port - expect(address.port).toBeDefined(); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is "33333"', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - port: '33333', - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - expect(address.port).toBe(33333); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - - describe('is 33333', () => { - beforeAll((done) => { - server = testServer.start( - config, - { - port: '33333', - }, - done - ); - req = request(server.app); - }); - - it('server address', () => { - const address = server.listeningApp.address(); - - expect(address.address).toBe('127.0.0.1'); - expect(address.port).toBe(33333); - }); - - it('Request to index', (done) => { - req.get('/').expect(200, done); - }); - - afterAll(testServer.close); - }); - }); - - describe('WEBPACK_DEV_SERVER environment variable', () => { - const OLD_ENV = process.env; - - beforeEach(() => { - // this is important - it clears the cache - jest.resetModules(); - - process.env = { ...OLD_ENV }; - - delete process.env.WEBPACK_DEV_SERVER; - }); - - afterEach(() => { - process.env = OLD_ENV; - }); - - it('should be present', () => { - expect(process.env.WEBPACK_DEV_SERVER).toBeUndefined(); - - // eslint-disable-next-line global-require - require('../lib/Server'); - - expect(process.env.WEBPACK_DEV_SERVER).toBe(true); - }); - }); -}); diff --git a/test/__snapshots__/Server.test.js.snap b/test/__snapshots__/Server.test.js.snap deleted file mode 100644 index afd2139df5..0000000000 --- a/test/__snapshots__/Server.test.js.snap +++ /dev/null @@ -1,116 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Server addEntries add hot option 1`] = ` -Array [ - Array [ - "client", - "index.js?http:", - "localhost", - ], - Array [ - "node_modules", - "webpack", - "hot", - "dev-server.js", - ], - Array [ - "foo.js", - ], -] -`; - -exports[`Server addEntries add hot option 2`] = ` -Array [ - HotModuleReplacementPlugin { - "fullBuildTimeout": 200, - "multiStep": undefined, - "options": Object {}, - "requestTimeout": 10000, - }, -] -`; - -exports[`Server addEntries add hotOnly option 1`] = ` -Array [ - Array [ - "client", - "index.js?http:", - "localhost", - ], - Array [ - "node_modules", - "webpack", - "hot", - "only-dev-server.js", - ], - Array [ - "foo.js", - ], -] -`; - -exports[`Server addEntries add hotOnly option 2`] = ` -Array [ - HotModuleReplacementPlugin { - "fullBuildTimeout": 200, - "multiStep": undefined, - "options": Object {}, - "requestTimeout": 10000, - }, -] -`; - -exports[`Server stats should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 1`] = ` -Array [ - "errors", - "warnings", - "hash", - "assetsByChunkName", - "assets", - "filteredAssets", -] -`; - -exports[`Server stats should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 2`] = ` -Array [ - "errors", - "warnings", - "hash", - "assetsByChunkName", - "assets", - "filteredAssets", -] -`; - -exports[`Server stats should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 3`] = ` -Array [ - "errors", - "warnings", - "hash", - "assetsByChunkName", - "assets", - "filteredAssets", -] -`; - -exports[`Server stats should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 4`] = ` -Array [ - "errors", - "warnings", - "hash", - "assetsByChunkName", - "assets", - "filteredAssets", -] -`; - -exports[`Server stats should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 5`] = ` -Array [ - "errors", - "warnings", - "hash", - "assetsByChunkName", - "assets", - "filteredAssets", -] -`; diff --git a/test/cli.test.js b/test/cli/cli.test.js similarity index 84% rename from test/cli.test.js rename to test/cli/cli.test.js index d9b7b72b41..0a009c3503 100644 --- a/test/cli.test.js +++ b/test/cli/cli.test.js @@ -1,18 +1,18 @@ 'use strict'; -/* eslint-disable - array-bracket-spacing, -*/ const { unlink } = require('fs'); const { join, resolve } = require('path'); const execa = require('execa'); -const testBin = require('./helpers/test-bin'); +const testBin = require('../helpers/test-bin'); -const httpsCertificateDirectory = join(__dirname, 'fixtures/https-certificate'); -const caPath = join(httpsCertificateDirectory, 'ca.pem'); -const pfxPath = join(httpsCertificateDirectory, 'server.pfx'); -const keyPath = join(httpsCertificateDirectory, 'server.key'); -const certPath = join(httpsCertificateDirectory, 'server.crt'); +const httpsCertificateDirectory = resolve( + __dirname, + '../fixtures/https-certificate' +); +const caPath = resolve(httpsCertificateDirectory, 'ca.pem'); +const pfxPath = resolve(httpsCertificateDirectory, 'server.pfx'); +const keyPath = resolve(httpsCertificateDirectory, 'server.key'); +const certPath = resolve(httpsCertificateDirectory, 'server.crt'); describe('CLI', () => { it('--progress', (done) => { @@ -92,6 +92,7 @@ describe('CLI', () => { done(); } else { expect(output.stdout.includes(socketPath)).toBe(true); + unlink(socketPath, () => { done(); }); @@ -103,7 +104,7 @@ describe('CLI', () => { it('should accept the promise function of webpack.config.js', (done) => { testBin( false, - resolve(__dirname, 'fixtures/promise-config/webpack.config.js') + resolve(__dirname, '../fixtures/promise-config/webpack.config.js') ) .then((output) => { expect(output.code).toEqual(0); @@ -117,14 +118,16 @@ describe('CLI', () => { }); it('should exit the process when SIGINT is detected', (done) => { - const cliPath = resolve(__dirname, '../bin/webpack-dev-server.js'); - const examplePath = resolve(__dirname, '../examples/cli/public'); + const cliPath = resolve(__dirname, '../../bin/webpack-dev-server.js'); + const examplePath = resolve(__dirname, '../../examples/cli/public'); const cp = execa('node', [cliPath], { cwd: examplePath }); cp.stdout.on('data', (data) => { const bits = data.toString(); + if (/Compiled successfully/.test(bits)) { expect(cp.pid !== 0).toBe(true); + cp.kill('SIGINT'); } }); @@ -135,16 +138,18 @@ describe('CLI', () => { }); it('should exit the process when SIGINT is detected, even before the compilation is done', (done) => { - const cliPath = resolve(__dirname, '../bin/webpack-dev-server.js'); - const examplePath = resolve(__dirname, '../examples/cli/public'); + const cliPath = resolve(__dirname, '../../bin/webpack-dev-server.js'); + const examplePath = resolve(__dirname, '../../examples/cli/public'); const cp = execa('node', [cliPath], { cwd: examplePath }); let killed = false; cp.stdout.on('data', () => { if (!killed) { expect(cp.pid !== 0).toBe(true); + cp.kill('SIGINT'); } + killed = true; }); @@ -154,8 +159,8 @@ describe('CLI', () => { }); it('should use different random port when multiple instances are started on different processes', (done) => { - const cliPath = resolve(__dirname, '../bin/webpack-dev-server.js'); - const examplePath = resolve(__dirname, '../examples/cli/public'); + const cliPath = resolve(__dirname, '../../bin/webpack-dev-server.js'); + const examplePath = resolve(__dirname, '../../examples/cli/public'); const cp = execa('node', [cliPath], { cwd: examplePath }); const cp2 = execa('node', [cliPath], { cwd: examplePath }); diff --git a/test/client/default/__snapshots__/index.test.js.snap b/test/client/__snapshots__/index.test.js.snap similarity index 100% rename from test/client/default/__snapshots__/index.test.js.snap rename to test/client/__snapshots__/index.test.js.snap diff --git a/test/SockJSClient.test.js b/test/client/clients/SockJSClient.test.js similarity index 90% rename from test/SockJSClient.test.js rename to test/client/clients/SockJSClient.test.js index b6fbed8ac3..ceb6fdc26e 100644 --- a/test/SockJSClient.test.js +++ b/test/client/clients/SockJSClient.test.js @@ -3,7 +3,7 @@ const http = require('http'); const express = require('express'); const sockjs = require('sockjs'); -const SockJSClient = require('../client-src/clients/SockJSClient'); +const SockJSClient = require('../../../client-src/clients/SockJSClient'); describe('SockJSClient', () => { let socketServer; @@ -12,6 +12,7 @@ describe('SockJSClient', () => { beforeAll((done) => { // eslint-disable-next-line new-cap const app = new express(); + listeningApp = http.createServer(app); listeningApp.listen(8080, 'localhost', () => { socketServer = sockjs.createServer(); @@ -23,15 +24,18 @@ describe('SockJSClient', () => { }); describe('client', () => { - it('should open, recieve message, and close', (done) => { + it('should open, receive message, and close', (done) => { socketServer.on('connection', (connection) => { connection.write('hello world'); + setTimeout(() => { connection.close(); }, 1000); }); + const client = new SockJSClient('http://localhost:8080/sockjs-node'); const data = []; + client.onOpen(() => { data.push('open'); }); @@ -41,6 +45,7 @@ describe('SockJSClient', () => { client.onMessage((msg) => { data.push(msg); }); + setTimeout(() => { expect(data.length).toEqual(3); expect(data[0]).toEqual('open'); diff --git a/test/client/default/index.test.js b/test/client/index.test.js similarity index 87% rename from test/client/default/index.test.js rename to test/client/index.test.js index 935ecb04be..053ee295bc 100644 --- a/test/client/default/index.test.js +++ b/test/client/index.test.js @@ -21,41 +21,41 @@ describe('index', () => { self.location.reload = jest.fn(); // log - jest.setMock('../../../client-src/default/utils/log.js', { + jest.setMock('../../client-src/default/utils/log.js', { log: { info: jest.fn(), warn: jest.fn(), error: jest.fn(), }, }); - log = require('../../../client-src/default/utils/log'); + log = require('../../client-src/default/utils/log'); // socket - jest.setMock('../../../client-src/default/socket.js', jest.fn()); - socket = require('../../../client-src/default/socket'); + jest.setMock('../../client-src/default/socket.js', jest.fn()); + socket = require('../../client-src/default/socket'); // overlay - jest.setMock('../../../client-src/default/overlay.js', { + jest.setMock('../../client-src/default/overlay.js', { clear: jest.fn(), showMessage: jest.fn(), }); - overlay = require('../../../client-src/default/overlay'); + overlay = require('../../client-src/default/overlay'); // reloadApp - jest.setMock('../../../client-src/default/utils/reloadApp.js', jest.fn()); - reloadApp = require('../../../client-src/default/utils/reloadApp'); + jest.setMock('../../client-src/default/utils/reloadApp.js', jest.fn()); + reloadApp = require('../../client-src/default/utils/reloadApp'); // sendMessage - jest.setMock('../../../client-src/default/utils/sendMessage.js', jest.fn()); - sendMessage = require('../../../client-src/default/utils/sendMessage'); + jest.setMock('../../client-src/default/utils/sendMessage.js', jest.fn()); + sendMessage = require('../../client-src/default/utils/sendMessage'); // createSocketUrl jest.setMock( - '../../../client-src/default/utils/createSocketUrl.js', + '../../client-src/default/utils/createSocketUrl.js', () => 'mock-url' ); - require('../../../client-src/default'); + require('../../client-src/default'); onSocketMessage = socket.mock.calls[0][1]; }); diff --git a/test/client/default/utils/__snapshots__/createSocketUrl.test.js.snap b/test/client/utils/__snapshots__/createSocketUrl.test.js.snap similarity index 100% rename from test/client/default/utils/__snapshots__/createSocketUrl.test.js.snap rename to test/client/utils/__snapshots__/createSocketUrl.test.js.snap diff --git a/test/client/default/utils/__snapshots__/getCurrentScriptSource.test.js.snap b/test/client/utils/__snapshots__/getCurrentScriptSource.test.js.snap similarity index 100% rename from test/client/default/utils/__snapshots__/getCurrentScriptSource.test.js.snap rename to test/client/utils/__snapshots__/getCurrentScriptSource.test.js.snap diff --git a/test/client/default/utils/__snapshots__/log.test.js.snap b/test/client/utils/__snapshots__/log.test.js.snap similarity index 100% rename from test/client/default/utils/__snapshots__/log.test.js.snap rename to test/client/utils/__snapshots__/log.test.js.snap diff --git a/test/client/default/utils/__snapshots__/reloadApp.test.js.snap b/test/client/utils/__snapshots__/reloadApp.test.js.snap similarity index 100% rename from test/client/default/utils/__snapshots__/reloadApp.test.js.snap rename to test/client/utils/__snapshots__/reloadApp.test.js.snap diff --git a/test/client/default/utils/__snapshots__/sendMessage.test.js.snap b/test/client/utils/__snapshots__/sendMessage.test.js.snap similarity index 100% rename from test/client/default/utils/__snapshots__/sendMessage.test.js.snap rename to test/client/utils/__snapshots__/sendMessage.test.js.snap diff --git a/test/client/default/utils/createSocketUrl.test.js b/test/client/utils/createSocketUrl.test.js similarity index 85% rename from test/client/default/utils/createSocketUrl.test.js rename to test/client/utils/createSocketUrl.test.js index cd2aab7f66..892e8204eb 100644 --- a/test/client/default/utils/createSocketUrl.test.js +++ b/test/client/utils/createSocketUrl.test.js @@ -17,12 +17,12 @@ describe('createSocketUrl', () => { samples.forEach((url) => { jest.doMock( - '../../../../client-src/default/utils/getCurrentScriptSource.js', + '../../../client-src/default/utils/getCurrentScriptSource.js', () => () => url ); // eslint-disable-next-line global-require - const createSocketUrl = require('../../../../client-src/default/utils/createSocketUrl'); + const createSocketUrl = require('../../../client-src/default/utils/createSocketUrl'); test(`should return the url when __resourceQuery is ${url}`, () => { expect(createSocketUrl(url)).toMatchSnapshot(); diff --git a/test/client/default/utils/getCurrentScriptSource.test.js b/test/client/utils/getCurrentScriptSource.test.js similarity index 91% rename from test/client/default/utils/getCurrentScriptSource.test.js rename to test/client/utils/getCurrentScriptSource.test.js index a7cf0777d6..8fb953b1f3 100644 --- a/test/client/default/utils/getCurrentScriptSource.test.js +++ b/test/client/utils/getCurrentScriptSource.test.js @@ -1,6 +1,6 @@ 'use strict'; -const getCurrentScriptSource = require('../../../../client-src/default/utils/getCurrentScriptSource'); +const getCurrentScriptSource = require('../../../client-src/default/utils/getCurrentScriptSource'); describe('getCurrentScriptSource', () => { afterEach(() => { diff --git a/test/client/default/utils/log.test.js b/test/client/utils/log.test.js similarity index 94% rename from test/client/default/utils/log.test.js rename to test/client/utils/log.test.js index b18f8d815c..79021d13d7 100644 --- a/test/client/default/utils/log.test.js +++ b/test/client/utils/log.test.js @@ -18,8 +18,7 @@ describe('log', () => { }); // eslint-disable-next-line global-require - setLogLevel = require('../../../../client-src/default/utils/log') - .setLogLevel; + setLogLevel = require('../../../client-src/default/utils/log').setLogLevel; }); afterEach(() => { diff --git a/test/client/default/utils/reloadApp.test.js b/test/client/utils/reloadApp.test.js similarity index 97% rename from test/client/default/utils/reloadApp.test.js rename to test/client/utils/reloadApp.test.js index d4c4261929..13a392b117 100644 --- a/test/client/default/utils/reloadApp.test.js +++ b/test/client/utils/reloadApp.test.js @@ -9,10 +9,12 @@ describe('reloadApp', () => { beforeEach(() => { locationValue = self.location; + self.postMessage = jest.fn(); self.location.reload = jest.fn(); jest.mock('loglevel'); + // eslint-disable-next-line global-require log = require('loglevel'); log.getLogger.mockImplementation(() => { @@ -23,7 +25,7 @@ describe('reloadApp', () => { }); // eslint-disable-next-line global-require - reloadApp = require('../../../../client-src/default/utils/reloadApp'); + reloadApp = require('../../../client-src/default/utils/reloadApp'); }); afterEach(() => { diff --git a/test/client/default/utils/sendMessage.test.js b/test/client/utils/sendMessage.test.js similarity index 81% rename from test/client/default/utils/sendMessage.test.js rename to test/client/utils/sendMessage.test.js index 11e176175f..a60f2548bc 100644 --- a/test/client/default/utils/sendMessage.test.js +++ b/test/client/utils/sendMessage.test.js @@ -2,7 +2,7 @@ /* global self */ -const sendMessage = require('../../../../client-src/default/utils/sendMessage'); +const sendMessage = require('../../../client-src/default/utils/sendMessage'); describe('sendMessage', () => { afterEach(() => { @@ -11,7 +11,9 @@ describe('sendMessage', () => { test('should run self.postMessage', () => { self.postMessage = jest.fn(); + sendMessage('foo', 'bar'); + expect(self.postMessage).toBeCalled(); expect(self.postMessage.mock.calls[0]).toMatchSnapshot(); }); diff --git a/test/MultiCompiler.test.js b/test/integration/MultiCompiler.test.js similarity index 66% rename from test/MultiCompiler.test.js rename to test/integration/MultiCompiler.test.js index a59fa2df77..2b203a7065 100644 --- a/test/MultiCompiler.test.js +++ b/test/integration/MultiCompiler.test.js @@ -1,12 +1,13 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/multi-compiler-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/multi-compiler-config/webpack.config'); -describe('MultiCompiler', () => { +describe('multi compiler', () => { let server; let req; + beforeAll((done) => { server = testServer.start(config, {}, done); req = request(server.app); @@ -15,7 +16,7 @@ describe('MultiCompiler', () => { afterAll(testServer.close); // TODO: this is a very basic test, optimally it should test multiple configs etc. - it('GET request to bundle', (done) => { + it('should handle GET request to bundle', (done) => { req .get('/main.js') .expect('Content-Type', 'application/javascript; charset=UTF-8') diff --git a/test/UniversalCompiler.test.js b/test/integration/UniversalCompiler.test.js similarity index 87% rename from test/UniversalCompiler.test.js rename to test/integration/UniversalCompiler.test.js index 2588a47391..1eaec5ed70 100644 --- a/test/UniversalCompiler.test.js +++ b/test/integration/UniversalCompiler.test.js @@ -1,12 +1,13 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/universal-compiler-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/universal-compiler-config/webpack.config'); -describe('UniversalCompiler', () => { +describe('universal compiler', () => { let server; let req; + beforeAll((done) => { server = testServer.start(config, { inline: true }, done); req = request(server.app); diff --git a/test/server/Server.test.js b/test/server/Server.test.js new file mode 100644 index 0000000000..b2b44731e2 --- /dev/null +++ b/test/server/Server.test.js @@ -0,0 +1,170 @@ +'use strict'; + +const { relative, sep } = require('path'); +const webpack = require('webpack'); +const sockjs = require('sockjs/lib/transport'); +const { noop } = require('webpack-dev-middleware/lib/util'); +const Server = require('../../lib/Server'); +const config = require('../fixtures/simple-config/webpack.config'); + +jest.mock('sockjs/lib/transport'); + +describe('Server', () => { + describe('sockjs', () => { + it('add decorateConnection', () => { + expect(typeof sockjs.Session.prototype.decorateConnection).toEqual( + 'function' + ); + }); + }); + + describe('addEntries', () => { + it('add hot option', (done) => { + const compiler = webpack(config); + const server = new Server(compiler, { + hot: true, + }); + + expect( + server.middleware.context.compiler.options.entry.map((p) => { + return relative('.', p).split(sep); + }) + ).toMatchSnapshot(); + expect( + server.middleware.context.compiler.options.plugins + ).toMatchSnapshot(); + + compiler.hooks.done.tap('webpack-dev-server', () => { + server.close(done); + }); + + compiler.run(() => {}); + }); + + it('add hotOnly option', (done) => { + const compiler = webpack(config); + const server = new Server(compiler, { + hotOnly: true, + }); + + expect( + server.middleware.context.compiler.options.entry.map((p) => { + return relative('.', p).split(sep); + }) + ).toMatchSnapshot(); + expect( + server.middleware.context.compiler.options.plugins + ).toMatchSnapshot(); + + compiler.hooks.done.tap('webpack-dev-server', () => { + server.close(done); + }); + + compiler.run(() => {}); + }); + }); + + // issue: https://github.com/webpack/webpack-dev-server/issues/1724 + describe('express.static.mine.types', () => { + beforeEach(() => { + jest.resetModules(); + }); + + afterEach(() => { + jest.unmock('express'); + }); + + it("should success even if mine.types doesn't exist", (done) => { + jest.mock('express', () => { + const data = jest.requireActual('express'); + const { static: st } = data; + const { mime } = st; + + delete mime.types; + + expect(typeof mime.types).toEqual('undefined'); + + return Object.assign(data, { + static: Object.assign(st, { + mime, + }), + }); + }); + + const compiler = webpack(config); + const server = new Server(compiler); + + compiler.hooks.done.tap('webpack-dev-server', (s) => { + const output = server.getStats(s); + expect(output.errors.length).toEqual(0); + + server.close(done); + }); + + compiler.run(() => {}); + server.listen(8080, 'localhost'); + }); + }); + + describe('WEBPACK_DEV_SERVER environment variable', () => { + const OLD_ENV = process.env; + + beforeEach(() => { + // this is important - it clears the cache + jest.resetModules(); + + process.env = { ...OLD_ENV }; + + delete process.env.WEBPACK_DEV_SERVER; + }); + + afterEach(() => { + process.env = OLD_ENV; + }); + + it('should be present', () => { + expect(process.env.WEBPACK_DEV_SERVER).toBeUndefined(); + + // eslint-disable-next-line global-require + require('../../lib/Server'); + + expect(process.env.WEBPACK_DEV_SERVER).toBe(true); + }); + }); + + describe('Invalidate Callback', () => { + describe('Testing callback functions on calling invalidate without callback', () => { + it('should be `noop` (the default callback function)', (done) => { + const compiler = webpack(config); + const server = new Server(compiler); + + server.invalidate(); + expect(server.middleware.context.callbacks[0]).toBe(noop); + + compiler.hooks.done.tap('webpack-dev-server', () => { + server.close(done); + }); + + compiler.run(() => {}); + }); + }); + + describe('Testing callback functions on calling invalidate with callback', () => { + it('should be `callback` function', (done) => { + const compiler = webpack(config); + const callback = jest.fn(); + const server = new Server(compiler); + + server.invalidate(callback); + + expect(server.middleware.context.callbacks[0]).toBe(callback); + + compiler.hooks.done.tap('webpack-dev-server', () => { + server.close(done); + }); + + compiler.run(() => {}); + }); + }); + }); +}); diff --git a/test/server/__snapshots__/Server.test.js.snap b/test/server/__snapshots__/Server.test.js.snap new file mode 100644 index 0000000000..b606b0561f --- /dev/null +++ b/test/server/__snapshots__/Server.test.js.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Server addEntries add hot option 1`] = ` +Array [ + Array [ + "client", + "index.js?http:", + "localhost", + ], + Array [ + "node_modules", + "webpack", + "hot", + "dev-server.js", + ], + Array [ + "foo.js", + ], +] +`; + +exports[`Server addEntries add hot option 2`] = ` +Array [ + HotModuleReplacementPlugin { + "fullBuildTimeout": 200, + "multiStep": undefined, + "options": Object {}, + "requestTimeout": 10000, + }, +] +`; + +exports[`Server addEntries add hotOnly option 1`] = ` +Array [ + Array [ + "client", + "index.js?http:", + "localhost", + ], + Array [ + "node_modules", + "webpack", + "hot", + "only-dev-server.js", + ], + Array [ + "foo.js", + ], +] +`; + +exports[`Server addEntries add hotOnly option 2`] = ` +Array [ + HotModuleReplacementPlugin { + "fullBuildTimeout": 200, + "multiStep": undefined, + "options": Object {}, + "requestTimeout": 10000, + }, +] +`; diff --git a/test/server/__snapshots__/stats-option.test.js.snap b/test/server/__snapshots__/stats-option.test.js.snap new file mode 100644 index 0000000000..b5405f897e --- /dev/null +++ b/test/server/__snapshots__/stats-option.test.js.snap @@ -0,0 +1,56 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`stats option should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 1`] = ` +Array [ + "errors", + "warnings", + "hash", + "assetsByChunkName", + "assets", + "filteredAssets", +] +`; + +exports[`stats option should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 2`] = ` +Array [ + "errors", + "warnings", + "hash", + "assetsByChunkName", + "assets", + "filteredAssets", +] +`; + +exports[`stats option should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 3`] = ` +Array [ + "errors", + "warnings", + "hash", + "assetsByChunkName", + "assets", + "filteredAssets", +] +`; + +exports[`stats option should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 4`] = ` +Array [ + "errors", + "warnings", + "hash", + "assetsByChunkName", + "assets", + "filteredAssets", +] +`; + +exports[`stats option should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors') 5`] = ` +Array [ + "errors", + "warnings", + "hash", + "assetsByChunkName", + "assets", + "filteredAssets", +] +`; diff --git a/test/server/after-option.test.js b/test/server/after-option.test.js new file mode 100644 index 0000000000..69f0b48f1a --- /dev/null +++ b/test/server/after-option.test.js @@ -0,0 +1,49 @@ +'use strict'; + +const request = require('supertest'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); + +describe('after option', () => { + let server; + let req; + + beforeAll((done) => { + server = testServer.start( + config, + { + after: (appArg, serverArg, compilerArg) => { + if (!appArg) { + throw new Error('app is not defined'); + } + + if (!serverArg) { + throw new Error('server is not defined'); + } + + if (!compilerArg) { + throw new Error('compiler is not defined'); + } + + appArg.get('/after/some/path', (_, response) => { + response.send('after'); + }); + }, + }, + done + ); + req = request(server.app); + }); + + afterAll(testServer.close); + + it('should handle after route', () => { + return req + .get('/after/some/path') + .expect('Content-Type', 'text/html; charset=utf-8') + .expect(200) + .then((response) => { + expect(response.text).toBe('after'); + }); + }); +}); diff --git a/test/BeforeAndAfter.test.js b/test/server/before-option.test.js similarity index 52% rename from test/BeforeAndAfter.test.js rename to test/server/before-option.test.js index c6e4a5b817..0966d28e18 100644 --- a/test/BeforeAndAfter.test.js +++ b/test/server/before-option.test.js @@ -1,10 +1,10 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); -describe('Before And After options', () => { +describe('before option', () => { let server; let req; @@ -29,23 +29,6 @@ describe('Before And After options', () => { response.send('before'); }); }, - after: (appArg, serverArg, compilerArg) => { - if (!appArg) { - throw new Error('app is not defined'); - } - - if (!serverArg) { - throw new Error('server is not defined'); - } - - if (!compilerArg) { - throw new Error('compiler is not defined'); - } - - appArg.get('/after/some/path', (_, response) => { - response.send('after'); - }); - }, }, done ); @@ -63,14 +46,4 @@ describe('Before And After options', () => { expect(response.text).toBe('before'); }); }); - - it('should handle after route', () => { - return req - .get('/after/some/path') - .expect('Content-Type', 'text/html; charset=utf-8') - .expect(200) - .then((response) => { - expect(response.text).toBe('after'); - }); - }); }); diff --git a/test/Compress.test.js b/test/server/compress-option.test.js similarity index 86% rename from test/Compress.test.js rename to test/server/compress-option.test.js index 4329cecb37..451639fa79 100644 --- a/test/Compress.test.js +++ b/test/server/compress-option.test.js @@ -6,14 +6,14 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/simple-config-other/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config-other/webpack.config'); -describe('Compress', () => { +describe('compress option', () => { let server; let req; - describe('undefined', () => { + describe('not specify', () => { beforeAll((done) => { server = testServer.start(config, {}, done); req = request(server.app); @@ -33,7 +33,7 @@ describe('Compress', () => { }); }); - describe('true', () => { + describe('as a true', () => { beforeAll((done) => { server = testServer.start( config, @@ -55,7 +55,7 @@ describe('Compress', () => { }); }); - describe('false', () => { + describe('as a false', () => { beforeAll((done) => { server = testServer.start( config, diff --git a/test/ContentBase.test.js b/test/server/contentBase-option.test.js similarity index 94% rename from test/ContentBase.test.js rename to test/server/contentBase-option.test.js index 24311dc396..9187c16e77 100644 --- a/test/ContentBase.test.js +++ b/test/server/contentBase-option.test.js @@ -3,24 +3,24 @@ const path = require('path'); const fs = require('fs'); const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/contentbase-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/contentbase-config/webpack.config'); -const contentBasePublic = path.join( +const contentBasePublic = path.resolve( __dirname, - 'fixtures/contentbase-config/public' + '../fixtures/contentbase-config/public' ); -const contentBaseOther = path.join( +const contentBaseOther = path.resolve( __dirname, - 'fixtures/contentbase-config/other' + '../fixtures/contentbase-config/other' ); -describe('ContentBase', () => { +describe('contentBase option', () => { let server; let req; describe('to directory', () => { - const nestedFile = path.join(contentBasePublic, 'assets/example.txt'); + const nestedFile = path.resolve(contentBasePublic, 'assets/example.txt'); beforeAll((done) => { server = testServer.start( @@ -38,6 +38,7 @@ describe('ContentBase', () => { testServer.close(() => { done(); }); + fs.truncateSync(nestedFile); }); @@ -112,6 +113,7 @@ describe('ContentBase', () => { req.get('/bar/').expect(200, /Heyo/, done); }); }); + describe('test listing files in folders without index.html using the option serveIndex:true', () => { beforeAll((done) => { server = testServer.start( @@ -140,6 +142,7 @@ describe('ContentBase', () => { req.get('/bar/').expect(200, /Heyo/, done); }); }); + describe('test listing files in folders without index.html using the option serveIndex default (true)', () => { beforeAll((done) => { server = testServer.start( @@ -167,6 +170,7 @@ describe('ContentBase', () => { req.get('/bar/').expect(200, /Heyo/, done); }); }); + describe('to directories', () => { beforeAll((done) => { server = testServer.start( @@ -258,6 +262,7 @@ describe('ContentBase', () => { describe('default to PWD', () => { beforeAll((done) => { jest.spyOn(process, 'cwd').mockImplementation(() => contentBasePublic); + server = testServer.start(config, {}, done); req = request(server.app); }); @@ -278,6 +283,7 @@ describe('ContentBase', () => { // This is a somewhat weird test, but it is important that we mock // the PWD here, and test if /other.html in our "fake" PWD really is not requested. jest.spyOn(process, 'cwd').mockImplementation(() => contentBasePublic); + server = testServer.start( config, { diff --git a/test/Headers.test.js b/test/server/headers-option.test.js similarity index 88% rename from test/Headers.test.js rename to test/server/headers-option.test.js index 5d7a79689f..813635511f 100644 --- a/test/Headers.test.js +++ b/test/server/headers-option.test.js @@ -1,10 +1,10 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); -describe('Headers', () => { +describe('headers option', () => { let server; let req; diff --git a/test/HistoryApiFallback.test.js b/test/server/historyApiFallback-option.test.js similarity index 86% rename from test/HistoryApiFallback.test.js rename to test/server/historyApiFallback-option.test.js index 996a1875f2..51ad09c506 100644 --- a/test/HistoryApiFallback.test.js +++ b/test/server/historyApiFallback-option.test.js @@ -2,12 +2,12 @@ const path = require('path'); const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/historyapifallback-config/webpack.config'); -const config2 = require('./fixtures/historyapifallback-2-config/webpack.config'); -const config3 = require('./fixtures/historyapifallback-3-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/historyapifallback-config/webpack.config'); +const config2 = require('../fixtures/historyapifallback-2-config/webpack.config'); +const config3 = require('../fixtures/historyapifallback-3-config/webpack.config'); -describe('HistoryApiFallback', () => { +describe('historyApiFallback option', () => { let server; let req; @@ -60,9 +60,9 @@ describe('HistoryApiFallback', () => { server = testServer.start( config2, { - contentBase: path.join( + contentBase: path.resolve( __dirname, - 'fixtures/historyapifallback-2-config' + '../fixtures/historyapifallback-2-config' ), historyApiFallback: { index: '/bar.html', @@ -96,7 +96,9 @@ describe('HistoryApiFallback', () => { if (err) { done(err); } + expect(res.body.toString().trim()).toEqual('Random file'); + done(); }); }); @@ -130,9 +132,9 @@ describe('HistoryApiFallback', () => { server = testServer.start( config2, { - contentBase: path.join( + contentBase: path.resolve( __dirname, - 'fixtures/historyapifallback-2-config' + '../fixtures/historyapifallback-2-config' ), historyApiFallback: { rewrites: [ @@ -179,9 +181,9 @@ describe('HistoryApiFallback', () => { server = testServer.start( config3, { - contentBase: path.join( + contentBase: path.resolve( __dirname, - 'fixtures/historyapifallback-3-config' + '../fixtures/historyapifallback-3-config' ), historyApiFallback: true, }, diff --git a/test/server/host-option.test.js b/test/server/host-option.test.js new file mode 100644 index 0000000000..043c7d5536 --- /dev/null +++ b/test/server/host-option.test.js @@ -0,0 +1,161 @@ +'use strict'; + +const request = require('supertest'); +const config = require('../fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); + +describe('host option', () => { + let server = null; + let req = null; + + describe('is not be specified', () => { + beforeAll((done) => { + server = testServer.start(config, {}, done); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + expect(address.port).toBe(8080); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is undefined', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + // eslint-disable-next-line no-undefined + host: undefined, + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('::'); + expect(address.port).toBe(8080); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is null', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + host: null, + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('::'); + expect(address.port).toBe(8080); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is 127.0.0.1 (IPv4)', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + host: '127.0.0.1', + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + expect(address.port).toBe(8080); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is localhost', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + host: 'localhost', + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + expect(address.port).toBe(8080); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is 0.0.0.0', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + host: '0.0.0.0', + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('0.0.0.0'); + expect(address.port).toBe(8080); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); +}); diff --git a/test/Hot.test.js b/test/server/hot-option.test.js similarity index 72% rename from test/Hot.test.js rename to test/server/hot-option.test.js index 3109340a9e..3754e6ea7d 100644 --- a/test/Hot.test.js +++ b/test/server/hot-option.test.js @@ -1,11 +1,11 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/client-config/webpack.config'); -const multiCompilerConfig = require('./fixtures/multi-compiler-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/client-config/webpack.config'); +const multiCompilerConfig = require('../fixtures/multi-compiler-config/webpack.config'); -describe('Hot Module Replacement (hot/hotOnly options)', () => { +describe('hot option', () => { let server; let req; @@ -30,29 +30,6 @@ describe('Hot Module Replacement (hot/hotOnly options)', () => { }); }); - describe('simple hotOnly config entries', () => { - beforeAll((done) => { - const options = { - port: 9000, - inline: true, - hotOnly: true, - watchOptions: { - poll: true, - }, - }; - server = testServer.startAwaitingCompilation(config, options, done); - req = request(server.app); - }); - - afterAll(testServer.close); - - it('should include hotOnly script in the bundle', (done) => { - req - .get('/main.js') - .expect(200, /webpack\/hot\/only-dev-server\.js/, done); - }); - }); - describe('multi compiler hot config entries', () => { beforeAll((done) => { const options = { @@ -142,40 +119,6 @@ describe('Hot Module Replacement (hot/hotOnly options)', () => { afterAll(testServer.close); }); - describe('simple hotOnly config HMR plugin', () => { - it('should register the HMR plugin before compilation is complete', (done) => { - let pluginFound = false; - const options = { - port: 9000, - inline: true, - hotOnly: true, - watchOptions: { - poll: true, - }, - }; - const fullSetup = testServer.startAwaitingCompilationFullSetup( - config, - options, - () => { - expect(pluginFound).toBeTruthy(); - done(); - } - ); - - const compiler = fullSetup.compiler; - compiler.hooks.compilation.intercept({ - register: (tapInfo) => { - if (tapInfo.name === 'HotModuleReplacementPlugin') { - pluginFound = true; - } - return tapInfo; - }, - }); - }); - - afterAll(testServer.close); - }); - describe('multi compiler hot config HMR plugin', () => { it('should register the HMR plugin before compilation is complete', (done) => { let pluginFound = false; diff --git a/test/server/hotOnly-option.test.js b/test/server/hotOnly-option.test.js new file mode 100644 index 0000000000..0e48019381 --- /dev/null +++ b/test/server/hotOnly-option.test.js @@ -0,0 +1,67 @@ +'use strict'; + +const request = require('supertest'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/client-config/webpack.config'); + +describe('hotOnly options', () => { + let server; + let req; + + describe('simple hotOnly config entries', () => { + beforeAll((done) => { + const options = { + port: 9000, + inline: true, + hotOnly: true, + watchOptions: { + poll: true, + }, + }; + server = testServer.startAwaitingCompilation(config, options, done); + req = request(server.app); + }); + + afterAll(testServer.close); + + it('should include hotOnly script in the bundle', (done) => { + req + .get('/main.js') + .expect(200, /webpack\/hot\/only-dev-server\.js/, done); + }); + }); + + describe('simple hotOnly config HMR plugin', () => { + it('should register the HMR plugin before compilation is complete', (done) => { + let pluginFound = false; + const options = { + port: 9000, + inline: true, + hotOnly: true, + watchOptions: { + poll: true, + }, + }; + const fullSetup = testServer.startAwaitingCompilationFullSetup( + config, + options, + () => { + expect(pluginFound).toBeTruthy(); + done(); + } + ); + + const compiler = fullSetup.compiler; + compiler.hooks.compilation.intercept({ + register: (tapInfo) => { + if (tapInfo.name === 'HotModuleReplacementPlugin') { + pluginFound = true; + } + return tapInfo; + }, + }); + }); + + afterAll(testServer.close); + }); +}); diff --git a/test/Http2.test.js b/test/server/http2-option.test.js similarity index 92% rename from test/Http2.test.js rename to test/server/http2-option.test.js index 4433006c74..1dd74c68e9 100644 --- a/test/Http2.test.js +++ b/test/server/http2-option.test.js @@ -3,15 +3,15 @@ const path = require('path'); const request = require('supertest'); const semver = require('semver'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/contentbase-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/contentbase-config/webpack.config'); -const contentBasePublic = path.join( +const contentBasePublic = path.resolve( __dirname, - 'fixtures/contentbase-config/public' + '../fixtures/contentbase-config/public' ); -describe('http2', () => { +describe('http2 option', () => { let server; let req; diff --git a/test/Https.test.js b/test/server/https-option.test.js similarity index 84% rename from test/Https.test.js rename to test/server/https-option.test.js index 8f780ac9f3..189bd48286 100644 --- a/test/Https.test.js +++ b/test/server/https-option.test.js @@ -3,25 +3,25 @@ const path = require('path'); const fs = require('fs'); const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/contentbase-config/webpack.config'); -const skipTestOnWindows = require('./helpers/conditional-test') +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/contentbase-config/webpack.config'); +const skipTestOnWindows = require('../helpers/conditional-test') .skipTestOnWindows; -const httpsCertificateDirectory = path.join( +const httpsCertificateDirectory = path.resolve( __dirname, - 'fixtures/https-certificate' + '../fixtures/https-certificate' ); -const contentBasePublic = path.join( +const contentBasePublic = path.resolve( __dirname, - 'fixtures/contentbase-config/public' + '../fixtures/contentbase-config/public' ); -describe('HTTPS', () => { +describe('https option', () => { let server; let req; - describe('is boolean', () => { + describe('as a boolean', () => { beforeAll((done) => { server = testServer.start( config, @@ -43,7 +43,7 @@ describe('HTTPS', () => { }); }); - describe('ca, pfx, key and cert are buffer', () => { + describe('as an object when ca, pfx, key and cert are buffer', () => { beforeAll((done) => { server = testServer.start( config, @@ -73,7 +73,7 @@ describe('HTTPS', () => { }); }); - describe('ca, pfx, key and cert are paths', () => { + describe('as an object when ca, pfx, key and cert are paths', () => { beforeAll((done) => { server = testServer.start( config, @@ -97,7 +97,7 @@ describe('HTTPS', () => { }); }); - describe('ca, pfx, key and cert are symlinks', () => { + describe('as an object when ca, pfx, key and cert are symlinks', () => { if (skipTestOnWindows('Symlinks are not supported on Windows')) { return; } @@ -127,7 +127,7 @@ describe('HTTPS', () => { afterAll(testServer.close); }); - describe('ca, pfx, key and cert are raw strings', () => { + describe('as an object when ca, pfx, key and cert are raw strings', () => { beforeAll((done) => { server = testServer.start( config, diff --git a/test/Inline.test.js b/test/server/inline-option.test.js similarity index 89% rename from test/Inline.test.js rename to test/server/inline-option.test.js index 00f7a273c7..c25b953401 100644 --- a/test/Inline.test.js +++ b/test/server/inline-option.test.js @@ -1,11 +1,11 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/client-config/webpack.config'); -const multiCompilerConfig = require('./fixtures/multi-compiler-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/client-config/webpack.config'); +const multiCompilerConfig = require('../fixtures/multi-compiler-config/webpack.config'); -describe('inline', () => { +describe('inline option', () => { let server; let req; diff --git a/test/Lazy.test.js b/test/server/lazy-option.test.js similarity index 75% rename from test/Lazy.test.js rename to test/server/lazy-option.test.js index 4641c7f1c9..515126f8ed 100644 --- a/test/Lazy.test.js +++ b/test/server/lazy-option.test.js @@ -1,9 +1,9 @@ 'use strict'; -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); -describe('Lazy', () => { +describe('lazy option', () => { afterEach(testServer.close); it('without filename option it should throw an error', () => { diff --git a/test/LiveReload.test.js b/test/server/liveReload-option.test.js similarity index 90% rename from test/LiveReload.test.js rename to test/server/liveReload-option.test.js index a4f66c15b2..6226f4d771 100644 --- a/test/LiveReload.test.js +++ b/test/server/liveReload-option.test.js @@ -2,16 +2,17 @@ const path = require('path'); const fs = require('fs'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/contentbase-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/contentbase-config/webpack.config'); -const contentBasePublic = path.join( +const contentBasePublic = path.resolve( __dirname, - 'fixtures/contentbase-config/public' + '../fixtures/contentbase-config/public' ); -describe('liveReload', () => { +describe('liveReload option', () => { let server; + describe('Test disabling live reloading', () => { const nestedFile = path.join(contentBasePublic, 'assets/example.txt'); diff --git a/test/server/mimeTypes-option.test.js b/test/server/mimeTypes-option.test.js new file mode 100644 index 0000000000..2fcde68a67 --- /dev/null +++ b/test/server/mimeTypes-option.test.js @@ -0,0 +1,60 @@ +'use strict'; + +const request = require('supertest'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); + +describe('mimeTypes option', () => { + describe('as an object', () => { + afterEach(testServer.close); + + it('should remapping mime type without force should throw an error', () => { + expect(() => { + testServer.start(config, { + mimeTypes: { 'application/octet-stream': ['js'] }, + }); + }).toThrow(/Attempt to change mapping for/); + }); + + it('should remapping mime type with force should not throw an error', (done) => { + testServer.start( + config, + { + mimeTypes: { + typeMap: { 'application/octet-stream': ['js'] }, + force: true, + }, + }, + done + ); + }); + }); + + describe('as an object with force option', () => { + let server; + let req; + + beforeAll((done) => { + server = testServer.start( + config, + { + mimeTypes: { + typeMap: { 'application/octet-stream': ['js'] }, + force: true, + }, + }, + done + ); + req = request(server.app); + }); + + afterAll(testServer.close); + + it('request to bundle file with modified mime type', (done) => { + req + .get('/main.js') + .expect('Content-Type', /application\/octet-stream/) + .expect(200, done); + }); + }); +}); diff --git a/test/onListening.test.js b/test/server/onListening-option.test.js similarity index 67% rename from test/onListening.test.js rename to test/server/onListening-option.test.js index 249507aca5..43db18eec8 100644 --- a/test/onListening.test.js +++ b/test/server/onListening-option.test.js @@ -1,9 +1,9 @@ 'use strict'; -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); -describe('Before And After options', () => { +describe('onListening option', () => { let onListeningIsRunning = false; beforeAll((done) => { @@ -24,7 +24,7 @@ describe('Before And After options', () => { afterAll(testServer.close); - it('should handle before route', () => { + it('should runs onListening callback', () => { expect(onListeningIsRunning).toBe(true); }); }); diff --git a/test/server/open-option.test.js b/test/server/open-option.test.js new file mode 100644 index 0000000000..c0f1768b99 --- /dev/null +++ b/test/server/open-option.test.js @@ -0,0 +1,32 @@ +'use strict'; + +jest.mock('opn'); + +const webpack = require('webpack'); +const opn = require('opn'); +const Server = require('../../lib/Server'); +const config = require('../fixtures/simple-config/webpack.config'); + +opn.mockImplementation(() => { + return { + catch: jest.fn(), + }; +}); + +describe('open option', () => { + it('should open', (done) => { + const compiler = webpack(config); + const server = new Server(compiler, { + open: true, + }); + + compiler.hooks.done.tap('webpack-dev-server', () => { + expect(opn.mock.calls[0]).toEqual(['http://localhost:8080/', {}]); + expect(opn.mock.invocationCallOrder[0]).toEqual(1); + server.close(done); + }); + + compiler.run(() => {}); + server.listen(8080, 'localhost'); + }); +}); diff --git a/test/server/port-option.test.js b/test/server/port-option.test.js new file mode 100644 index 0000000000..0cb2046962 --- /dev/null +++ b/test/server/port-option.test.js @@ -0,0 +1,138 @@ +'use strict'; + +const request = require('supertest'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); + +describe('port', () => { + let server = null; + let req = null; + + describe('is not be specified', () => { + beforeAll((done) => { + server = testServer.start(config, {}, done); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + // Random port + expect(address.port).toBeDefined(); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is undefined', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + // eslint-disable-next-line no-undefined + port: undefined, + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + // Random port + expect(address.port).toBeDefined(); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is null', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + port: null, + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + // Random port + expect(address.port).toBeDefined(); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is "33333"', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + port: '33333', + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + expect(address.port).toBe(33333); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); + + describe('is 33333', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + port: '33333', + }, + done + ); + req = request(server.app); + }); + + it('server address', () => { + const address = server.listeningApp.address(); + + expect(address.address).toBe('127.0.0.1'); + expect(address.port).toBe(33333); + }); + + it('Request to index', (done) => { + req.get('/').expect(200, done); + }); + + afterAll(testServer.close); + }); +}); diff --git a/test/Proxy.test.js b/test/server/proxy-option.test.js similarity index 93% rename from test/Proxy.test.js rename to test/server/proxy-option.test.js index 954e8efb59..e28c8e6126 100644 --- a/test/Proxy.test.js +++ b/test/server/proxy-option.test.js @@ -5,11 +5,11 @@ const request = require('supertest'); const express = require('express'); const bodyParser = require('body-parser'); const WebSocket = require('ws'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/proxy-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const config = require('../fixtures/proxy-config/webpack.config'); const WebSocketServer = WebSocket.Server; -const contentBase = path.join(__dirname, 'fixtures/proxy-config'); +const contentBase = path.resolve(__dirname, '../fixtures/proxy-config'); const proxyOptionPathsAsProperties = { '/proxy1': { @@ -21,6 +21,7 @@ const proxyOptionPathsAsProperties = { }, '/foo': { bypass(req) { + console.log(req.path); if (/\.html$/.test(req.path)) { return '/index.html'; } @@ -57,6 +58,7 @@ function startProxyServers() { const listeners = []; const proxy1 = express(); const proxy2 = express(); + proxy1.get('/proxy1', (req, res) => { res.send('from proxy1'); }); @@ -66,8 +68,10 @@ function startProxyServers() { proxy2.get('/proxy2', (req, res) => { res.send('from proxy2'); }); + listeners.push(proxy1.listen(9000)); listeners.push(proxy2.listen(9001)); + // return a function to shutdown proxy servers return function proxy() { listeners.forEach((listener) => { @@ -76,8 +80,8 @@ function startProxyServers() { }; } -describe('Proxy', () => { - describe('proxy options is an object of paths as properties', () => { +describe('proxy option', () => { + describe('as an object of paths with properties', () => { let server; let req; let closeProxyServers; @@ -133,7 +137,7 @@ describe('Proxy', () => { }); }); - describe('proxy option is an object', () => { + describe('as an option is an object', () => { let server; let req; let closeProxyServers; @@ -163,7 +167,7 @@ describe('Proxy', () => { }); }); - describe('proxy option is an array', () => { + describe('as an array', () => { let server; let req; let closeProxyServers; @@ -197,7 +201,7 @@ describe('Proxy', () => { }); }); - describe('sharing a proxy option', () => { + describe('should sharing a proxy option', () => { let server; let req; let listener; @@ -207,10 +211,13 @@ describe('Proxy', () => { beforeAll((done) => { const proxy = express(); + proxy.get('*', (proxyReq, res) => { res.send('from proxy'); }); + listener = proxy.listen(9000); + server = testServer.start( config, { @@ -241,7 +248,7 @@ describe('Proxy', () => { }); }); - describe('External websocket upgrade', () => { + describe('should handles external websocket upgrade', () => { let ws; let wsServer; let responseMessage; @@ -291,7 +298,7 @@ describe('Proxy', () => { }); }); - describe('should support http methods', () => { + describe('should supports http methods', () => { let server; let req; let listener; diff --git a/test/ServerMode.test.js b/test/server/serverMode-option.test.js similarity index 82% rename from test/ServerMode.test.js rename to test/server/serverMode-option.test.js index 288322e1f4..ebe5aff3a8 100644 --- a/test/ServerMode.test.js +++ b/test/server/serverMode-option.test.js @@ -5,12 +5,12 @@ */ const request = require('supertest'); const sockjs = require('sockjs'); -const SockJSServer = require('../lib/servers/SockJSServer'); -const config = require('./fixtures/simple-config/webpack.config'); -const testServer = require('./helpers/test-server'); -const BaseServer = require('./../lib/servers/BaseServer'); +const SockJSServer = require('../../lib/servers/SockJSServer'); +const config = require('../fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const BaseServer = require('../../lib/servers/BaseServer'); -describe('serverMode', () => { +describe('serverMode option', () => { let server; let req; @@ -19,7 +19,8 @@ describe('serverMode', () => { req = null; server = null; }); - describe("supplying 'sockjs' as a string", () => { + + describe('as a string ("sockjs")', () => { beforeEach((done) => { server = testServer.start( config, @@ -36,12 +37,12 @@ describe('serverMode', () => { }); }); - describe('supplying path to sockjs implementation', () => { + describe('as a path ("sockjs")', () => { beforeEach((done) => { server = testServer.start( config, { - serverMode: require.resolve('../lib/servers/SockJSServer'), + serverMode: require.resolve('../../lib/servers/SockJSServer'), }, done ); @@ -53,7 +54,7 @@ describe('serverMode', () => { }); }); - describe('supplying sockjs implementation class', () => { + describe('as a class ("sockjs")', () => { beforeEach((done) => { server = testServer.start( config, @@ -70,7 +71,7 @@ describe('serverMode', () => { }); }); - describe('custom sockjs implementation', () => { + describe('as a class (custom "sockjs" implementation)', () => { it('uses supplied server implementation', (done) => { server = testServer.start( config, @@ -117,7 +118,7 @@ describe('serverMode', () => { }); }); - describe('supplying nonexistent path', () => { + describe('as a path with nonexistent path', () => { it('should throw an error', () => { expect(() => { server = testServer.start( diff --git a/test/SockJSServer.test.js b/test/server/servers/SockJSServer.test.js similarity index 95% rename from test/SockJSServer.test.js rename to test/server/servers/SockJSServer.test.js index 9456f277f0..86335b5c7a 100644 --- a/test/SockJSServer.test.js +++ b/test/server/servers/SockJSServer.test.js @@ -3,7 +3,7 @@ const http = require('http'); const express = require('express'); const SockJS = require('sockjs-client/dist/sockjs'); -const SockJSServer = require('../lib/servers/SockJSServer'); +const SockJSServer = require('../../../lib/servers/SockJSServer'); describe('SockJSServer', () => { let socketServer; @@ -12,6 +12,7 @@ describe('SockJSServer', () => { beforeAll((done) => { // eslint-disable-next-line new-cap const app = new express(); + listeningApp = http.createServer(app); listeningApp.listen(8080, 'localhost', () => { const server = { @@ -22,7 +23,9 @@ describe('SockJSServer', () => { sockPath: '/sockjs-node', listeningApp, }; + socketServer = new SockJSServer(server); + done(); }); }); @@ -30,6 +33,7 @@ describe('SockJSServer', () => { describe('server', () => { it('should recieve connection, send message, and close client', (done) => { const data = []; + socketServer.onConnection((connection) => { data.push('open'); socketServer.send(connection, 'hello world'); diff --git a/test/Socket.test.js b/test/server/sockPath-option.test.js similarity index 87% rename from test/Socket.test.js rename to test/server/sockPath-option.test.js index 0220b60eb0..5542dc985d 100644 --- a/test/Socket.test.js +++ b/test/server/sockPath-option.test.js @@ -1,10 +1,10 @@ 'use strict'; const request = require('supertest'); -const config = require('./fixtures/simple-config/webpack.config'); -const testServer = require('./helpers/test-server'); +const config = require('../fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); -describe('socket options', () => { +describe('sockPath options', () => { let server; let req; @@ -13,6 +13,7 @@ describe('socket options', () => { req = null; server = null; }); + describe('default behavior', () => { beforeEach((done) => { server = testServer.start(config, {}, done); @@ -30,6 +31,7 @@ describe('socket options', () => { describe('socksPath option', () => { const path = '/foo/test/bar'; + beforeEach((done) => { server = testServer.start( config, diff --git a/test/server/stats-option.test.js b/test/server/stats-option.test.js new file mode 100644 index 0000000000..299ce7aa63 --- /dev/null +++ b/test/server/stats-option.test.js @@ -0,0 +1,59 @@ +'use strict'; + +const webpack = require('webpack'); +const Server = require('../../lib/Server'); +const config = require('../fixtures/simple-config/webpack.config'); + +describe('stats option', () => { + it(`should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors')`, () => { + const allStats = [ + {}, + // eslint-disable-next-line no-undefined + undefined, + false, + 'errors-only', + { + assets: false, + }, + ]; + + return allStats.reduce((p, stats) => { + return p.then(() => { + return new Promise((resolve) => { + const compiler = webpack(config); + const server = new Server(compiler, { stats }); + + compiler.hooks.done.tap('webpack-dev-server', (s) => { + expect(Object.keys(server.getStats(s))).toMatchSnapshot(); + + server.close(resolve); + }); + + compiler.run(() => {}); + server.listen(8080, 'localhost'); + }); + }); + }, Promise.resolve()); + }); + + it('should respect warningsFilter', (done) => { + const compiler = webpack(config); + const server = new Server(compiler, { + stats: { warningsFilter: 'test' }, + }); + + compiler.hooks.done.tap('webpack-dev-server', (s) => { + s.compilation.warnings = ['test', 'another warning']; + + const output = server.getStats(s); + + expect(output.warnings.length).toBe(1); + expect(output.warnings[0]).toBe('another warning'); + + server.close(done); + }); + + compiler.run(() => {}); + server.listen(8080, 'localhost'); + }); +}); diff --git a/test/__snapshots__/CreateConfig.test.js.snap b/test/server/utils/__snapshots__/createConfig.test.js.snap similarity index 100% rename from test/__snapshots__/CreateConfig.test.js.snap rename to test/server/utils/__snapshots__/createConfig.test.js.snap diff --git a/test/__snapshots__/Util.test.js.snap b/test/server/utils/__snapshots__/findPort.test.js.snap similarity index 100% rename from test/__snapshots__/Util.test.js.snap rename to test/server/utils/__snapshots__/findPort.test.js.snap diff --git a/test/Entry.test.js b/test/server/utils/addEntries.test.js similarity index 85% rename from test/Entry.test.js rename to test/server/utils/addEntries.test.js index 0ee7538b82..608bd61a30 100644 --- a/test/Entry.test.js +++ b/test/server/utils/addEntries.test.js @@ -1,23 +1,15 @@ 'use strict'; -/* eslint-disable - import/order, - arrow-parens, - array-bracket-spacing -*/ const path = require('path'); - const webpack = require('webpack'); - -const addEntries = require('../lib/utils/addEntries'); - -const config = require('./fixtures/simple-config/webpack.config'); -const configEntryAsFunction = require('./fixtures/entry-as-function/webpack.config'); +const addEntries = require('../../../lib/utils/addEntries'); +const config = require('./../../fixtures/simple-config/webpack.config'); +const configEntryAsFunction = require('./../../fixtures/entry-as-function/webpack.config'); const normalize = (entry) => entry.split(path.sep).join('/'); -describe('Entry', () => { - it('adds devServer entry points to a single entry point', () => { +describe('addEntries util', () => { + it('should adds devServer entry points to a single entry point', () => { const webpackOptions = Object.assign({}, config); const devServerOptions = {}; @@ -30,7 +22,7 @@ describe('Entry', () => { expect(normalize(webpackOptions.entry[1])).toEqual('./foo.js'); }); - it('adds devServer entry points to a multi-module entry point', () => { + it('should adds devServer entry points to a multi-module entry point', () => { const webpackOptions = Object.assign({}, config, { entry: ['./foo.js', './bar.js'], }); @@ -47,7 +39,7 @@ describe('Entry', () => { expect(webpackOptions.entry[2]).toEqual('./bar.js'); }); - it('adds devServer entry points to a multi entry point object', () => { + it('should adds devServer entry points to a multi entry point object', () => { const webpackOptions = Object.assign({}, config, { entry: { foo: './foo.js', @@ -68,7 +60,7 @@ describe('Entry', () => { expect(webpackOptions.entry.bar[1]).toEqual('./bar.js'); }); - it('defaults to src if no entry point is given', () => { + it('should set defaults to src if no entry point is given', () => { const webpackOptions = {}; const devServerOptions = {}; @@ -78,7 +70,7 @@ describe('Entry', () => { expect(webpackOptions.entry[1]).toEqual('./src'); }); - it('preserves dynamic entry points', (done) => { + it('should preserves dynamic entry points', (done) => { let i = 0; const webpackOptions = { // simulate dynamic entry @@ -108,7 +100,7 @@ describe('Entry', () => { .catch(done); }); - it('preserves asynchronous dynamic entry points', (done) => { + it('should preserves asynchronous dynamic entry points', (done) => { let i = 0; const webpackOptions = { // simulate async dynamic entry @@ -140,7 +132,7 @@ describe('Entry', () => { .catch(done); }); - it("prepends webpack's hot reload client script", () => { + it("should prepends webpack's hot reload client script", () => { const webpackOptions = Object.assign({}, config, { entry: { app: './app.js', @@ -161,7 +153,7 @@ describe('Entry', () => { expect(hotClientScript).toEqual(require.resolve(hotClientScript)); }); - it("prepends webpack's hot-only client script", () => { + it("should prepends webpack's hot-only client script", () => { const webpackOptions = Object.assign({}, config, { entry: { app: './app.js', @@ -182,7 +174,7 @@ describe('Entry', () => { expect(hotClientScript).toEqual(require.resolve(hotClientScript)); }); - it("doesn't add the HMR plugin if not hot and no plugins", () => { + it("should doesn't add the HMR plugin if not hot and no plugins", () => { const webpackOptions = Object.assign({}, config); const devServerOptions = {}; @@ -191,7 +183,7 @@ describe('Entry', () => { expect('plugins' in webpackOptions).toBeFalsy(); }); - it("doesn't add the HMR plugin if not hot and empty plugins", () => { + it("should doesn't add the HMR plugin if not hot and empty plugins", () => { const webpackOptions = Object.assign({}, config, { plugins: [] }); const devServerOptions = {}; @@ -200,7 +192,7 @@ describe('Entry', () => { expect(webpackOptions.plugins).toEqual([]); }); - it("doesn't add the HMR plugin if not hot and some plugins", () => { + it("should doesn't add the HMR plugin if not hot and some plugins", () => { const existingPlugin1 = new webpack.BannerPlugin('happy birthday'); const existingPlugin2 = new webpack.DefinePlugin({ foo: 'bar' }); const webpackOptions = Object.assign({}, config, { @@ -213,7 +205,7 @@ describe('Entry', () => { expect(webpackOptions.plugins).toEqual([existingPlugin1, existingPlugin2]); }); - it('adds the HMR plugin if hot', () => { + it('should adds the HMR plugin if hot', () => { const existingPlugin = new webpack.BannerPlugin('bruce'); const webpackOptions = Object.assign({}, config, { plugins: [existingPlugin], @@ -228,7 +220,7 @@ describe('Entry', () => { ]); }); - it('adds the HMR plugin if hot-only', () => { + it('should adds the HMR plugin if hot-only', () => { const webpackOptions = Object.assign({}, config); const devServerOptions = { hotOnly: true }; @@ -239,7 +231,7 @@ describe('Entry', () => { ]); }); - it("doesn't add the HMR plugin again if it's already there", () => { + it("should doesn't add the HMR plugin again if it's already there", () => { const existingPlugin = new webpack.BannerPlugin('bruce'); const webpackOptions = Object.assign({}, config, { plugins: [new webpack.HotModuleReplacementPlugin(), existingPlugin], @@ -254,7 +246,7 @@ describe('Entry', () => { ]); }); - it('can prevent duplicate entries from successive calls', () => { + it('should can prevent duplicate entries from successive calls', () => { const webpackOptions = Object.assign({}, config); const devServerOptions = { hot: true }; @@ -269,7 +261,7 @@ describe('Entry', () => { expect(result.length).toEqual(1); }); - it('supports entry as Function', () => { + it('should supports entry as Function', () => { const webpackOptions = Object.assign({}, configEntryAsFunction); const devServerOptions = {}; @@ -278,7 +270,7 @@ describe('Entry', () => { expect(typeof webpackOptions.entry === 'function').toBe(true); }); - it('only prepends devServer entry points to web targets by default', () => { + it('should only prepends devServer entry points to web targets by default', () => { const webpackOptions = [ Object.assign({}, config), Object.assign({ target: 'web' }, config), @@ -310,7 +302,7 @@ describe('Entry', () => { }); }); - it('allows selecting compilations to inline the client into', () => { + it('should allows selecting compilations to inline the client into', () => { const webpackOptions = [ Object.assign({}, config), Object.assign({ target: 'web' }, config), @@ -342,7 +334,7 @@ describe('Entry', () => { }); }); - it('when hot, prepends the hot runtime to all targets by default', () => { + it('should prepends the hot runtime to all targets by default (when hot)', () => { const webpackOptions = [ Object.assign({ target: 'web' }, config), Object.assign({ target: 'node' }, config), @@ -369,7 +361,7 @@ describe('Entry', () => { }); }); - it('allows selecting which compilations to inject the hot runtime into', () => { + it('should allows selecting which compilations to inject the hot runtime into', () => { const webpackOptions = [ Object.assign({ target: 'web' }, config), Object.assign({ target: 'node' }, config), diff --git a/test/CreateConfig.test.js b/test/server/utils/createConfig.test.js similarity index 98% rename from test/CreateConfig.test.js rename to test/server/utils/createConfig.test.js index a0b99047e2..67431598c4 100644 --- a/test/CreateConfig.test.js +++ b/test/server/utils/createConfig.test.js @@ -1,9 +1,9 @@ 'use strict'; const path = require('path'); -const createConfig = require('../lib/utils/createConfig'); -const webpackConfig = require('./fixtures/schema/webpack.config.simple'); -const webpackConfigNoStats = require('./fixtures/schema/webpack.config.no-dev-stats'); +const createConfig = require('../../../lib/utils/createConfig'); +const webpackConfig = require('./../../fixtures/schema/webpack.config.simple'); +const webpackConfigNoStats = require('./../../fixtures/schema/webpack.config.no-dev-stats'); const argv = { port: 8080, diff --git a/test/Util.test.js b/test/server/utils/createDomain.test.js similarity index 56% rename from test/Util.test.js rename to test/server/utils/createDomain.test.js index 9b71e85106..08b839c585 100644 --- a/test/Util.test.js +++ b/test/server/utils/createDomain.test.js @@ -1,12 +1,10 @@ 'use strict'; -const http = require('http'); const webpack = require('webpack'); const internalIp = require('internal-ip'); -const Server = require('../lib/Server'); -const createDomain = require('../lib/utils/createDomain'); -const findPort = require('../lib/utils/findPort'); -const config = require('./fixtures/simple-config/webpack.config'); +const Server = require('../../../lib/Server'); +const createDomain = require('../../../lib/utils/createDomain'); +const config = require('./../../fixtures/simple-config/webpack.config'); describe('check utility functions', () => { let compiler; @@ -116,67 +114,3 @@ describe('check utility functions', () => { }); }); }); - -describe('findPort cli utility function', () => { - let dummyServers = []; - - afterEach(() => { - delete process.env.DEFAULT_PORT_RETRY; - - return dummyServers - .reduce((p, server) => { - return p.then(() => { - return new Promise((resolve) => { - server.close(resolve); - }); - }); - }, Promise.resolve()) - .then(() => { - dummyServers = []; - }); - }); - - function createDummyServers(n) { - return [...new Array(n)].reduce((p, _, i) => { - return p.then(() => { - return new Promise((resolve) => { - const server = http.createServer(); - dummyServers.push(server); - server.listen(8080 + i, resolve); - }); - }); - }, Promise.resolve()); - } - - it('should return the port when the port is specified', () => { - process.env.DEFAULT_PORT_RETRY = 5; - - return findPort(8082).then((port) => { - expect(port).toEqual(8082); - }); - }); - - it('should retry finding the port for up to defaultPortRetry times', () => { - const retryCount = 5; - - process.env.DEFAULT_PORT_RETRY = retryCount; - - return createDummyServers(retryCount) - .then(findPort) - .then((port) => { - expect(port).toEqual(8080 + retryCount); - }); - }); - - it("should throw the error when the port isn't found", () => { - const retryCount = 5; - - process.env.DEFAULT_PORT_RETRY = retryCount; - - return createDummyServers(10) - .then(findPort) - .catch((err) => { - expect(err.message).toMatchSnapshot(); - }); - }); -}); diff --git a/test/server/utils/findPort.test.js b/test/server/utils/findPort.test.js new file mode 100644 index 0000000000..d618a82505 --- /dev/null +++ b/test/server/utils/findPort.test.js @@ -0,0 +1,66 @@ +'use strict'; + +const http = require('http'); +const findPort = require('../../../lib/utils/findPort'); + +describe('findPort cli utility function', () => { + let dummyServers = []; + + afterEach(() => { + delete process.env.DEFAULT_PORT_RETRY; + + return dummyServers + .reduce((p, server) => { + return p.then(() => { + return new Promise((resolve) => { + server.close(resolve); + }); + }); + }, Promise.resolve()) + .then(() => { + dummyServers = []; + }); + }); + + function createDummyServers(n) { + return [...new Array(n)].reduce((p, _, i) => { + return p.then(() => { + return new Promise((resolve) => { + const server = http.createServer(); + dummyServers.push(server); + server.listen(8080 + i, resolve); + }); + }); + }, Promise.resolve()); + } + + it('should return the port when the port is specified', () => { + process.env.DEFAULT_PORT_RETRY = 5; + + return findPort(8082).then((port) => { + expect(port).toEqual(8082); + }); + }); + + it('should retry finding the port for up to defaultPortRetry times', () => { + const retryCount = 5; + + process.env.DEFAULT_PORT_RETRY = retryCount; + + return createDummyServers(retryCount) + .then(findPort) + .then((port) => { + expect(port).toEqual(8080 + retryCount); + }); + }); + + it("should throw the error when the port isn't found", () => { + process.env.DEFAULT_PORT_RETRY = 5; + + return createDummyServers(10) + .then(findPort) + .catch((err) => { + expect(err.message).toMatchSnapshot(); + }); + }); +}); diff --git a/test/GetSocketServerImplementation.test.js b/test/server/utils/getSocketServerImplementation.test.js similarity index 77% rename from test/GetSocketServerImplementation.test.js rename to test/server/utils/getSocketServerImplementation.test.js index 830f49513f..51bcdf9143 100644 --- a/test/GetSocketServerImplementation.test.js +++ b/test/server/utils/getSocketServerImplementation.test.js @@ -1,9 +1,9 @@ 'use strict'; -const getSocketServerImplementation = require('../lib/utils/getSocketServerImplementation'); -const SockJSServer = require('../lib/servers/SockJSServer'); +const getSocketServerImplementation = require('../../../lib/utils/getSocketServerImplementation'); +const SockJSServer = require('../../../lib/servers/SockJSServer'); -describe('getSocketServerImplementation', () => { +describe('getSocketServerImplementation util', () => { it("should work with serverMode: 'sockjs'", () => { let result; @@ -33,7 +33,7 @@ describe('getSocketServerImplementation', () => { expect(() => { result = getSocketServerImplementation({ - serverMode: require.resolve('../lib/servers/SockJSServer'), + serverMode: require.resolve('../../../lib/servers/SockJSServer'), }); }).not.toThrow(); diff --git a/test/Routes.test.js b/test/server/utils/routes.test.js similarity index 72% rename from test/Routes.test.js rename to test/server/utils/routes.test.js index 75d485fc58..53e1029601 100644 --- a/test/Routes.test.js +++ b/test/server/utils/routes.test.js @@ -1,10 +1,10 @@ 'use strict'; const request = require('supertest'); -const testServer = require('./helpers/test-server'); -const config = require('./fixtures/simple-config/webpack.config'); +const testServer = require('../../helpers/test-server'); +const config = require('../../fixtures/simple-config/webpack.config'); -describe('Routes', () => { +describe('routes util', () => { let server; let req; @@ -15,7 +15,7 @@ describe('Routes', () => { afterAll(testServer.close); - it('GET request to live bundle', (done) => { + it('should handles GET request to live bundle', (done) => { req.get('/__webpack_dev_server__/live.bundle.js').then(({ res }) => { expect(res.headers['content-type']).toEqual('application/javascript'); expect(res.statusCode).toEqual(200); @@ -23,7 +23,7 @@ describe('Routes', () => { }); }); - it('HEAD request to live bundle', (done) => { + it('should handles HEAD request to live bundle', (done) => { req.head('/__webpack_dev_server__/live.bundle.js').then(({ res }) => { expect(res.headers['content-type']).toEqual('application/javascript'); expect(res.statusCode).toEqual(200); @@ -31,7 +31,7 @@ describe('Routes', () => { }); }); - it('GET request to sockjs bundle', (done) => { + it('should handles GET request to sockjs bundle', (done) => { req.get('/__webpack_dev_server__/sockjs.bundle.js').then(({ res }) => { expect(res.headers['content-type']).toEqual('application/javascript'); expect(res.statusCode).toEqual(200); @@ -39,7 +39,7 @@ describe('Routes', () => { }); }); - it('HEAD request to sockjs bundle', (done) => { + it('should handles HEAD request to sockjs bundle', (done) => { req.head('/__webpack_dev_server__/sockjs.bundle.js').then(({ res }) => { expect(res.headers['content-type']).toEqual('application/javascript'); expect(res.statusCode).toEqual(200); @@ -47,7 +47,7 @@ describe('Routes', () => { }); }); - it('GET request to inline bundle', (done) => { + it('should handles GET request to inline bundle', (done) => { req.get('/webpack-dev-server.js').then(({ res }) => { expect(res.headers['content-type']).toEqual('application/javascript'); expect(res.statusCode).toEqual(200); @@ -55,7 +55,7 @@ describe('Routes', () => { }); }); - it('HEAD request to inline bundle', (done) => { + it('should handles HEAD request to inline bundle', (done) => { req.head('/webpack-dev-server.js').then(({ res }) => { expect(res.headers['content-type']).toEqual('application/javascript'); expect(res.statusCode).toEqual(200); @@ -63,7 +63,7 @@ describe('Routes', () => { }); }); - it('GET request to live html', (done) => { + it('should handles GET request to live html', (done) => { req.get('/webpack-dev-server/').then(({ res }) => { expect(res.headers['content-type']).toEqual('text/html'); expect(res.statusCode).toEqual(200); @@ -71,7 +71,7 @@ describe('Routes', () => { }); }); - it('HEAD request to live html', (done) => { + it('should handles HEAD request to live html', (done) => { req.head('/webpack-dev-server/').then(({ res }) => { expect(res.headers['content-type']).toEqual('text/html'); expect(res.statusCode).toEqual(200); @@ -79,7 +79,7 @@ describe('Routes', () => { }); }); - it('GET request to directory index', (done) => { + it('should handles GET request to directory index', (done) => { req.get('/webpack-dev-server').then(({ res }) => { expect(res.headers['content-type']).toEqual('text/html'); expect(res.statusCode).toEqual(200); @@ -87,7 +87,7 @@ describe('Routes', () => { }); }); - it('HEAD request to directory index', (done) => { + it('should handles HEAD request to directory index', (done) => { req.head('/webpack-dev-server').then(({ res }) => { expect(res.headers['content-type']).toEqual('text/html'); expect(res.statusCode).toEqual(200); @@ -95,28 +95,28 @@ describe('Routes', () => { }); }); - it('GET request to magic html', (done) => { + it('should handles GET request to magic html', (done) => { req.get('/main').then(({ res }) => { expect(res.statusCode).toEqual(200); done(); }); }); - it('HEAD request to magic html', (done) => { + it('should handles HEAD request to magic html', (done) => { req.head('/main').then(({ res }) => { expect(res.statusCode).toEqual(200); done(); }); }); - it('GET request to main chunk', (done) => { + it('should handles GET request to main chunk', (done) => { req.get('/main.js').then(({ res }) => { expect(res.statusCode).toEqual(200); done(); }); }); - it('HEAD request to main chunk', (done) => { + it('should handles HEAD request to main chunk', (done) => { req.head('/main.js').then(({ res }) => { expect(res.statusCode).toEqual(200); done();