From 06f6c53aa0a3868e5c7773054bcd2588ec1f4c24 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Wed, 5 Jun 2019 20:19:56 +0200 Subject: [PATCH 01/32] chore: don't support Node6 (#1976) --- azure-pipelines.yml | 9 --------- package.json | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8977de369e..d0fdf318cd 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -47,9 +47,6 @@ jobs: node-8: node_version: ^8.9.0 webpack_version: latest - node-6: - node_version: ^6.9.0 - webpack_version: latest steps: - task: NodeTool@0 inputs: @@ -98,9 +95,6 @@ jobs: node-8: node_version: ^8.9.0 webpack_version: latest - node-6: - node_version: ^6.9.0 - webpack_version: latest steps: - task: NodeTool@0 inputs: @@ -149,9 +143,6 @@ jobs: node-8: node_version: ^8.9.0 webpack_version: latest - node-6: - node_version: ^6.9.0 - webpack_version: latest steps: - script: 'git config --global core.autocrlf input' displayName: 'Config git core.autocrlf' diff --git a/package.json b/package.json index acc642de21..569f7f0e4c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "client" ], "engines": { - "node": ">= 6.11.5" + "node": ">= 8.9.0" }, "scripts": { "lint:prettier": "prettier \"{**/*,*}.{js,json,md,yml,css}\" --list-different", From af768911baa7498dff76c420822dfc2aee9ff7f7 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Wed, 5 Jun 2019 21:08:33 +0200 Subject: [PATCH 02/32] refactor(client): make use of ESM instead of CJS (#1967) --- .eslintrc | 6 +++- client-src/.eslintrc | 5 ++++ client-src/clients/BaseClient.js | 2 -- client-src/clients/SockJSClient.js | 2 -- client-src/clients/WebsocketClient.js | 2 -- client-src/default/index.js | 30 +++++++++---------- client-src/default/overlay.js | 19 ++++-------- client-src/default/socket.js | 5 +--- client-src/default/utils/createSocketUrl.js | 12 +++----- .../default/utils/getCurrentScriptSource.js | 4 +-- client-src/default/utils/log.js | 11 ++----- client-src/default/utils/reloadApp.js | 8 ++--- client-src/default/utils/sendMessage.js | 8 ++--- client-src/default/webpack.config.js | 2 -- client-src/live/index.js | 10 +++---- client-src/live/webpack.config.js | 2 -- client-src/sockjs/index.js | 4 +-- client-src/sockjs/webpack.config.js | 2 -- test/client/index.test.js | 1 - test/client/utils/createSocketUrl.test.js | 5 +++- .../utils/getCurrentScriptSource.test.js | 4 ++- test/client/utils/reloadApp.test.js | 5 ++-- test/client/utils/sendMessage.test.js | 6 ++-- 23 files changed, 62 insertions(+), 93 deletions(-) create mode 100644 client-src/.eslintrc diff --git a/.eslintrc b/.eslintrc index b851edc92b..9547a7446f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,7 +2,11 @@ "extends": ["webpack", "prettier"], "globals": { "document": true, - "window": true + "window": true, + "self": true, + "WorkerGlobalScope": true, + "__resourceQuery": true, + "__webpack_dev_server_client__": true }, "parserOptions": { "sourceType": "script", diff --git a/client-src/.eslintrc b/client-src/.eslintrc new file mode 100644 index 0000000000..bd14a19ef2 --- /dev/null +++ b/client-src/.eslintrc @@ -0,0 +1,5 @@ +{ + "parserOptions": { + "sourceType": "module" + } +} diff --git a/client-src/clients/BaseClient.js b/client-src/clients/BaseClient.js index 1dfa65911b..7c47b70e2a 100644 --- a/client-src/clients/BaseClient.js +++ b/client-src/clients/BaseClient.js @@ -1,5 +1,3 @@ -'use strict'; - /* eslint-disable no-unused-vars */ diff --git a/client-src/clients/SockJSClient.js b/client-src/clients/SockJSClient.js index 193c571d26..9a1fd729fa 100644 --- a/client-src/clients/SockJSClient.js +++ b/client-src/clients/SockJSClient.js @@ -1,5 +1,3 @@ -'use strict'; - /* eslint-disable no-unused-vars */ diff --git a/client-src/clients/WebsocketClient.js b/client-src/clients/WebsocketClient.js index 0089f6faed..9785bb5517 100644 --- a/client-src/clients/WebsocketClient.js +++ b/client-src/clients/WebsocketClient.js @@ -1,5 +1,3 @@ -'use strict'; - /* global WebSocket */ /* eslint-disable diff --git a/client-src/default/index.js b/client-src/default/index.js index dede6f0763..df7432b5ea 100644 --- a/client-src/default/index.js +++ b/client-src/default/index.js @@ -1,14 +1,14 @@ -'use strict'; - -/* global __resourceQuery WorkerGlobalScope self */ /* eslint prefer-destructuring: off */ -const stripAnsi = require('strip-ansi'); -const socket = require('./socket'); -const overlay = require('./overlay'); -const { log, setLogLevel } = require('./utils/log'); -const sendMessage = require('./utils/sendMessage'); -const reloadApp = require('./utils/reloadApp'); -const createSocketUrl = require('./utils/createSocketUrl'); +import stripAnsi from 'strip-ansi'; +import socket from './socket'; +import { + clear as clearOverlay, + showMessage as showMessageOverlay, +} from './overlay'; +import { log, setLogLevel } from './utils/log'; +import sendMessage from './utils/sendMessage'; +import reloadApp from './utils/reloadApp'; +import createSocketUrl from './utils/createSocketUrl'; const status = { isUnloading: false, @@ -47,7 +47,7 @@ const onSocketMessage = { log.info('[WDS] App updated. Recompiling...'); // fixes #1042. overlay doesn't clear if errors are fixed but warnings remain. if (options.useWarningOverlay || options.useErrorOverlay) { - overlay.clear(); + clearOverlay(); } sendMessage('Invalid'); }, @@ -57,7 +57,7 @@ const onSocketMessage = { 'still-ok': function stillOk() { log.info('[WDS] Nothing changed.'); if (options.useWarningOverlay || options.useErrorOverlay) { - overlay.clear(); + clearOverlay(); } sendMessage('StillOk'); }, @@ -93,7 +93,7 @@ const onSocketMessage = { ok() { sendMessage('Ok'); if (options.useWarningOverlay || options.useErrorOverlay) { - overlay.clear(); + clearOverlay(); } if (options.initial) { return (options.initial = false); @@ -112,7 +112,7 @@ const onSocketMessage = { log.warn(strippedWarnings[i]); } if (options.useWarningOverlay) { - overlay.showMessage(warnings); + showMessageOverlay(warnings); } if (options.initial) { @@ -128,7 +128,7 @@ const onSocketMessage = { log.error(strippedErrors[i]); } if (options.useErrorOverlay) { - overlay.showMessage(errors); + showMessageOverlay(errors); } options.initial = false; }, diff --git a/client-src/default/overlay.js b/client-src/default/overlay.js index a1bb6cef2b..f73cb29578 100644 --- a/client-src/default/overlay.js +++ b/client-src/default/overlay.js @@ -1,12 +1,10 @@ -'use strict'; - // The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app) // They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware). -const ansiHTML = require('ansi-html'); -const { AllHtmlEntities } = require('html-entities'); +import ansiHTML from 'ansi-html'; +import { AllHtmlEntities as Entities } from 'html-entities'; -const entities = new AllHtmlEntities(); +const entities = new Entities(); const colors = { reset: ['transparent', 'transparent'], black: '181818', @@ -95,8 +93,8 @@ function ensureOverlayDivExists(onOverlayDivReady) { document.body.appendChild(overlayIframe); } -// Successful compilation. -function clear() { +// successful compilation. +export function clear() { if (!overlayDiv) { // It is not there in the first place. return; @@ -110,7 +108,7 @@ function clear() { } // Compilation with errors (e.g. syntax error or missing modules). -function showMessage(messages) { +export function showMessage(messages) { ensureOverlayDivExists((div) => { // Make it look similar to our terminal. div.innerHTML = ` Date: Wed, 5 Jun 2019 21:48:02 +0200 Subject: [PATCH 03/32] chore(deps): update dependency ws to v7 (#1834) --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 569f7f0e4c..469e3b01f5 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,8 @@ "typescript": "^3.6.2", "url-loader": "^1.1.2", "webpack": "^4.39.3", - "webpack-cli": "^3.3.8" + "webpack-cli": "^3.3.8", + "ws": "^7.0.0" }, "peerDependencies": { "webpack": "^4.0.0" From b32f7a373afd169cf15a83b7dfcb9d575a4c3e95 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" Date: Wed, 5 Jun 2019 21:52:19 +0200 Subject: [PATCH 04/32] chore(deps): update dependency file-loader to v4 (#1971) --- package-lock.json | 21 ++++++++++++++++----- package.json | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index b85b554cfe..bbb111c520 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4446,7 +4446,18 @@ "is-path-cwd": "^2.0.0", "is-path-in-cwd": "^2.0.0", "p-map": "^2.0.0", - "pify": "^4.0.1" + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + } } }, "delayed-stream": { @@ -5732,12 +5743,12 @@ } }, "file-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", - "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.0.0.tgz", + "integrity": "sha512-roAbL6IdSGczwfXxhMi6Zq+jD4IfUpL0jWHD7fvmjdOVb7xBfdRUHe4LpBgO23VtVK5AW1OlWZo0p34Jvx3iWg==", "dev": true, "requires": { - "loader-utils": "^1.0.2", + "loader-utils": "^1.2.2", "schema-utils": "^1.0.0" } }, diff --git a/package.json b/package.json index 469e3b01f5..42ad3dc137 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "eslint-config-webpack": "^1.2.5", "eslint-plugin-import": "^2.18.2", "execa": "^1.0.0", - "file-loader": "^3.0.1", + "file-loader": "^4.0.0", "html-loader": "^0.5.5", "html-webpack-plugin": "^3.2.0", "husky": "^3.0.5", From 342fa6aa30d39a05b7c9da385d10da0978c8de2a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" Date: Wed, 5 Jun 2019 22:18:26 +0200 Subject: [PATCH 05/32] chore(deps): update dependency chokidar to v3 (#1902) --- package-lock.json | 296 ++++++++++++++++++++++++++++++++++++++++------ package.json | 2 +- 2 files changed, 261 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index bbb111c520..e7b108c7b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,58 @@ "output-file-sync": "^2.0.0", "slash": "^2.0.0", "source-map": "^0.5.0" + }, + "dependencies": { + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + } } }, "@babel/code-frame": { @@ -2219,6 +2271,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" @@ -2228,6 +2281,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -2424,7 +2478,8 @@ "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true }, "async-limiter": { "version": "1.0.0", @@ -2654,9 +2709,9 @@ "dev": true }, "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==" }, "bluebird": { "version": "3.5.5", @@ -3082,22 +3137,72 @@ "dev": true }, "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", + "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", + "anymatch": "^3.0.1", + "braces": "^3.0.2", + "fsevents": "^2.0.6", + "glob-parent": "^5.0.0", + "is-binary-path": "^2.1.0", + "is-glob": "^4.0.1", "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "readdirp": "^3.1.1" + }, + "dependencies": { + "anymatch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.0.tgz", + "integrity": "sha512-Ozz7l4ixzI7Oxj2+cw+p0tVUt27BpaJ+1+q1TCeANWxHpvyn2+Un+YamBdfKu0uh8xLodGhoa1v7595NhKDAuA==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", + "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "optional": true + }, + "glob-parent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + } } }, "chownr": { @@ -5987,6 +6092,7 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, "optional": true, "requires": { "nan": "^2.12.1", @@ -5996,21 +6102,25 @@ "abbrev": { "version": "1.1.1", "bundled": true, + "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", "bundled": true, + "dev": true, "optional": true }, "aproba": { "version": "1.2.0", "bundled": true, + "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", "bundled": true, + "dev": true, "optional": true, "requires": { "delegates": "^1.0.0", @@ -6020,11 +6130,13 @@ "balanced-match": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "dev": true, "optional": true, "requires": { "balanced-match": "^1.0.0", @@ -6034,31 +6146,37 @@ "chownr": { "version": "1.1.1", "bundled": true, + "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", "bundled": true, + "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, + "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, + "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "debug": { "version": "4.1.1", "bundled": true, + "dev": true, "optional": true, "requires": { "ms": "^2.1.1" @@ -6067,21 +6185,25 @@ "deep-extend": { "version": "0.6.0", "bundled": true, + "dev": true, "optional": true }, "delegates": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", "bundled": true, + "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", "bundled": true, + "dev": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -6090,11 +6212,13 @@ "fs.realpath": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true }, "gauge": { "version": "2.7.4", "bundled": true, + "dev": true, "optional": true, "requires": { "aproba": "^1.0.3", @@ -6110,6 +6234,7 @@ "glob": { "version": "7.1.3", "bundled": true, + "dev": true, "optional": true, "requires": { "fs.realpath": "^1.0.0", @@ -6123,11 +6248,13 @@ "has-unicode": { "version": "2.0.1", "bundled": true, + "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", "bundled": true, + "dev": true, "optional": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -6136,6 +6263,7 @@ "ignore-walk": { "version": "3.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "minimatch": "^3.0.4" @@ -6144,6 +6272,7 @@ "inflight": { "version": "1.0.6", "bundled": true, + "dev": true, "optional": true, "requires": { "once": "^1.3.0", @@ -6153,16 +6282,19 @@ "inherits": { "version": "2.0.3", "bundled": true, + "dev": true, "optional": true }, "ini": { "version": "1.3.5", "bundled": true, + "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true, "requires": { "number-is-nan": "^1.0.0" @@ -6171,11 +6303,13 @@ "isarray": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", "bundled": true, + "dev": true, "optional": true, "requires": { "brace-expansion": "^1.1.7" @@ -6184,11 +6318,13 @@ "minimist": { "version": "0.0.8", "bundled": true, + "dev": true, "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, + "dev": true, "optional": true, "requires": { "safe-buffer": "^5.1.2", @@ -6198,6 +6334,7 @@ "minizlib": { "version": "1.2.1", "bundled": true, + "dev": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -6206,6 +6343,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "dev": true, "optional": true, "requires": { "minimist": "0.0.8" @@ -6214,11 +6352,13 @@ "ms": { "version": "2.1.1", "bundled": true, + "dev": true, "optional": true }, "needle": { "version": "2.3.0", "bundled": true, + "dev": true, "optional": true, "requires": { "debug": "^4.1.0", @@ -6229,6 +6369,7 @@ "node-pre-gyp": { "version": "0.12.0", "bundled": true, + "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", @@ -6246,6 +6387,7 @@ "nopt": { "version": "4.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "abbrev": "1", @@ -6255,11 +6397,13 @@ "npm-bundled": { "version": "1.0.6", "bundled": true, + "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", "bundled": true, + "dev": true, "optional": true, "requires": { "ignore-walk": "^3.0.1", @@ -6269,6 +6413,7 @@ "npmlog": { "version": "4.1.2", "bundled": true, + "dev": true, "optional": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -6280,16 +6425,19 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, + "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", "bundled": true, + "dev": true, "optional": true }, "once": { "version": "1.4.0", "bundled": true, + "dev": true, "optional": true, "requires": { "wrappy": "1" @@ -6298,16 +6446,19 @@ "os-homedir": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "osenv": { "version": "0.1.5", "bundled": true, + "dev": true, "optional": true, "requires": { "os-homedir": "^1.0.0", @@ -6317,16 +6468,19 @@ "path-is-absolute": { "version": "1.0.1", "bundled": true, + "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", "bundled": true, + "dev": true, "optional": true }, "rc": { "version": "1.2.8", "bundled": true, + "dev": true, "optional": true, "requires": { "deep-extend": "^0.6.0", @@ -6338,6 +6492,7 @@ "minimist": { "version": "1.2.0", "bundled": true, + "dev": true, "optional": true } } @@ -6345,6 +6500,7 @@ "readable-stream": { "version": "2.3.6", "bundled": true, + "dev": true, "optional": true, "requires": { "core-util-is": "~1.0.0", @@ -6359,6 +6515,7 @@ "rimraf": { "version": "2.6.3", "bundled": true, + "dev": true, "optional": true, "requires": { "glob": "^7.1.3" @@ -6367,36 +6524,43 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, + "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", "bundled": true, + "dev": true, "optional": true }, "sax": { "version": "1.2.4", "bundled": true, + "dev": true, "optional": true }, "semver": { "version": "5.7.0", "bundled": true, + "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", "bundled": true, + "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", "bundled": true, + "dev": true, "optional": true }, "string-width": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true, "requires": { "code-point-at": "^1.0.0", @@ -6407,6 +6571,7 @@ "string_decoder": { "version": "1.1.1", "bundled": true, + "dev": true, "optional": true, "requires": { "safe-buffer": "~5.1.0" @@ -6415,6 +6580,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "ansi-regex": "^2.0.0" @@ -6423,11 +6589,13 @@ "strip-json-comments": { "version": "2.0.1", "bundled": true, + "dev": true, "optional": true }, "tar": { "version": "4.4.8", "bundled": true, + "dev": true, "optional": true, "requires": { "chownr": "^1.1.1", @@ -6442,11 +6610,13 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", "bundled": true, + "dev": true, "optional": true, "requires": { "string-width": "^1.0.2 || 2" @@ -6455,11 +6625,13 @@ "wrappy": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, + "dev": true, "optional": true } } @@ -6821,6 +6993,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -6830,6 +7003,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, "requires": { "is-extglob": "^2.1.0" } @@ -6908,7 +7082,8 @@ "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true }, "growly": { "version": "1.3.0", @@ -7608,11 +7783,11 @@ "dev": true }, "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "^2.0.0" } }, "is-buffer": { @@ -10406,6 +10581,7 @@ "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, "optional": true }, "nanomatch": { @@ -11012,7 +11188,8 @@ "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true }, "path-exists": { "version": "3.0.0", @@ -11090,8 +11267,7 @@ "picomatch": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", - "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", - "dev": true + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==" }, "pidtree": { "version": "0.3.0", @@ -11613,13 +11789,11 @@ } }, "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.2.tgz", + "integrity": "sha512-8rhl0xs2cxfVsqzreYCvs8EwBfn/DhVdqtoLmw19uI3SC5avYX9teCurlErfpPXGmYtMHReGaP2RsLnFvz/lnw==", "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "picomatch": "^2.0.4" } }, "realpath-native": { @@ -11758,7 +11932,8 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true }, "renderkid": { "version": "2.0.3", @@ -13640,9 +13815,10 @@ } }, "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true }, "upper-case": { "version": "1.1.3", @@ -13817,6 +13993,54 @@ "chokidar": "^2.0.2", "graceful-fs": "^4.1.2", "neo-async": "^2.5.0" + }, + "dependencies": { + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + } } }, "wbuf": { diff --git a/package.json b/package.json index 42ad3dc137..7274ef78bf 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "dependencies": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", - "chokidar": "^2.1.8", + "chokidar": "^3.0.1", "compression": "^1.7.4", "connect-history-api-fallback": "^1.6.0", "debug": "^4.1.1", From 7901428c26e21725925e655dba9599015826c5bc Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Wed, 5 Jun 2019 22:47:30 +0200 Subject: [PATCH 06/32] chore(deps): introduce open and remove opn (#1865) Because opn was renamed to open. --- lib/utils/runOpen.js | 2 +- package.json | 2 +- test/Server.test.js | 503 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 505 insertions(+), 2 deletions(-) create mode 100644 test/Server.test.js diff --git a/lib/utils/runOpen.js b/lib/utils/runOpen.js index a2757ab919..7f0b814ffe 100644 --- a/lib/utils/runOpen.js +++ b/lib/utils/runOpen.js @@ -1,6 +1,6 @@ 'use strict'; -const open = require('opn'); +const open = require('open'); const isAbsoluteUrl = require('is-absolute-url'); function runOpen(uri, options, log) { diff --git a/package.json b/package.json index 7274ef78bf..f721a7b876 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "is-absolute-url": "^3.0.1", "killable": "^1.0.1", "loglevel": "^1.6.4", - "opn": "^5.5.0", + "open": "^6.2.0", "p-retry": "^3.0.1", "portfinder": "^1.0.24", "schema-utils": "^1.0.0", diff --git a/test/Server.test.js b/test/Server.test.js new file mode 100644 index 0000000000..60ae05731e --- /dev/null +++ b/test/Server.test.js @@ -0,0 +1,503 @@ +'use strict'; + +const { relative, sep } = require('path'); +const webpack = require('webpack'); +const request = require('supertest'); +// Mock open before loading Server +jest.mock('open'); +// eslint-disable-next-line import/newline-after-import +const open = require('open'); +open.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(open.mock.calls[0]).toEqual(['http://localhost:8080/', {}]); + expect(open.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); + }); + }); +}); From 898461ab081f935d99a59ec98625493b30c2a8b8 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Sat, 8 Jun 2019 13:46:20 +0200 Subject: [PATCH 07/32] chore: fix tests (#1997) --- test/__snapshots__/Server.test.js.snap | 116 +++++++++++++++++++++++++ test/server/open-option.test.js | 4 +- test/server/utils/runOpen.test.js | 26 +++--- 3 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 test/__snapshots__/Server.test.js.snap diff --git a/test/__snapshots__/Server.test.js.snap b/test/__snapshots__/Server.test.js.snap new file mode 100644 index 0000000000..afd2139df5 --- /dev/null +++ b/test/__snapshots__/Server.test.js.snap @@ -0,0 +1,116 @@ +// 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/server/open-option.test.js b/test/server/open-option.test.js index 9eeb8d3cd8..01f7d88b8a 100644 --- a/test/server/open-option.test.js +++ b/test/server/open-option.test.js @@ -1,9 +1,9 @@ 'use strict'; -jest.mock('opn'); +jest.mock('open'); const webpack = require('webpack'); -const open = require('opn'); +const open = require('open'); const Server = require('../../lib/Server'); const config = require('../fixtures/simple-config/webpack.config'); const port = require('../ports-map')['open-option']; diff --git a/test/server/utils/runOpen.test.js b/test/server/utils/runOpen.test.js index e6fa3b155a..d8c258008d 100644 --- a/test/server/utils/runOpen.test.js +++ b/test/server/utils/runOpen.test.js @@ -1,23 +1,23 @@ 'use strict'; -const opn = require('opn'); +const open = require('open'); const runOpen = require('../../../lib/utils/runOpen'); -jest.mock('opn'); +jest.mock('open'); describe('runOpen util', () => { afterEach(() => { - opn.mockClear(); + open.mockClear(); }); describe('should open browser', () => { beforeEach(() => { - opn.mockImplementation(() => Promise.resolve()); + open.mockImplementation(() => Promise.resolve()); }); it('on specify URL', () => { return runOpen('https://example.com', {}, console).then(() => { - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -34,7 +34,7 @@ describe('runOpen util', () => { { openPage: '/index.html' }, console ).then(() => { - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -51,7 +51,7 @@ describe('runOpen util', () => { { open: 'Google Chrome' }, console ).then(() => { - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -69,7 +69,7 @@ describe('runOpen util', () => { { open: 'Google Chrome', openPage: '/index.html' }, console ).then(() => { - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -122,7 +122,7 @@ describe('runOpen util', () => { const logMock = { warn: jest.fn() }; beforeEach(() => { - opn.mockImplementation(() => Promise.reject()); + open.mockImplementation(() => Promise.reject()); }); afterEach(() => { @@ -134,7 +134,7 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open browser. If you are running in a headless environment, please do not use the --open flag"` ); - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -154,7 +154,7 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open browser. If you are running in a headless environment, please do not use the --open flag"` ); - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -174,7 +174,7 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open browser: Google Chrome. If you are running in a headless environment, please do not use the --open flag"` ); - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -195,7 +195,7 @@ describe('runOpen util', () => { expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"Unable to open browser: Google Chrome. If you are running in a headless environment, please do not use the --open flag"` ); - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { From 75266648ee48ce740e2bedfdffafc500344b20cf Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Mon, 10 Jun 2019 14:27:15 +0200 Subject: [PATCH 08/32] test: make use of async/await (#1996) --- package-lock.json | 16 +- test/Server.test.js | 503 ------------------ test/__snapshots__/Server.test.js.snap | 116 ---- test/cli/cli.test.js | 166 +++--- test/client/clients/SockJSClient.test.js | 21 +- test/helpers/fs.js | 15 + test/helpers/run-browser.js | 31 +- test/helpers/timer.js | 11 + test/integration/MultiCompiler.test.js | 6 +- test/integration/UniversalCompiler.test.js | 42 +- test/options.test.js | 126 ++--- test/server/after-option.test.js | 11 +- test/server/before-option.test.js | 11 +- test/server/compress-option.test.js | 18 +- test/server/contentBase-option.test.js | 106 ++-- test/server/headers-option.test.js | 13 +- test/server/historyApiFallback-option.test.js | 48 +- test/server/host-option.test.js | 20 +- test/server/hot-option.test.js | 20 +- test/server/hotOnly-option.test.js | 6 +- test/server/http2-option.test.js | 12 +- test/server/https-option.test.js | 16 +- test/server/inline-option.test.js | 16 +- test/server/mimeTypes-option.test.js | 6 +- test/server/port-option.test.js | 20 +- test/server/proxy-option.test.js | 65 ++- test/server/servers/SockJSServer.test.js | 43 +- test/server/sockPath-option.test.js | 8 +- test/server/stats-option.test.js | 27 +- test/server/utils/addEntries.test.js | 66 ++- test/server/utils/findPort.test.js | 133 ++--- test/server/utils/routes.test.js | 156 +++--- test/server/utils/runOpen.test.js | 136 +++-- 33 files changed, 646 insertions(+), 1364 deletions(-) delete mode 100644 test/Server.test.js delete mode 100644 test/__snapshots__/Server.test.js.snap create mode 100644 test/helpers/fs.js create mode 100644 test/helpers/timer.js diff --git a/package-lock.json b/package-lock.json index e7b108c7b8..c2a8b23118 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10941,20 +10941,20 @@ } } }, + "open": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.3.0.tgz", + "integrity": "sha512-6AHdrJxPvAXIowO/aIaeHZ8CeMdDf7qCyRNq8NwJpinmCdXhz+NZR7ie1Too94lpciCDsG+qHGO9Mt0svA4OqA==", + "requires": { + "is-wsl": "^1.1.0" + } + }, "opencollective-postinstall": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==", "dev": true }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "requires": { - "is-wsl": "^1.1.0" - } - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", diff --git a/test/Server.test.js b/test/Server.test.js deleted file mode 100644 index 60ae05731e..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 open before loading Server -jest.mock('open'); -// eslint-disable-next-line import/newline-after-import -const open = require('open'); -open.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(open.mock.calls[0]).toEqual(['http://localhost:8080/', {}]); - expect(open.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/cli.test.js b/test/cli/cli.test.js index 372a21afef..e4106217b2 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -1,8 +1,8 @@ 'use strict'; -const { unlink } = require('fs'); const { join, resolve } = require('path'); const execa = require('execa'); +const { unlinkAsync } = require('../helpers/fs'); const testBin = require('../helpers/test-bin'); const httpsCertificateDirectory = resolve( @@ -15,134 +15,90 @@ const keyPath = resolve(httpsCertificateDirectory, 'server.key'); const certPath = resolve(httpsCertificateDirectory, 'server.crt'); describe('CLI', () => { - it('--progress', (done) => { - testBin('--progress') - .then((output) => { - expect(output.code).toEqual(0); - expect(output.stderr.includes('0% compiling')).toBe(true); - // should not profile - expect( - output.stderr.includes('ms after chunk modules optimization') - ).toBe(false); - done(); - }) - .catch(done); + it('--progress', async () => { + const { code, stderr } = await testBin('--progress'); + expect(code).toEqual(0); + expect(stderr.includes('0% compiling')).toBe(true); }); - it('--progress --profile', (done) => { - testBin('--progress --profile') - .then((output) => { - expect(output.code).toEqual(0); - // should profile - expect(output.stderr.includes('after chunk modules optimization')).toBe( - true - ); - done(); - }) - .catch(done); + it('--progress --profile', async () => { + const { code, stderr } = await testBin('--progress --profile'); + expect(code).toEqual(0); + // should profile + expect(output.stderr.includes('after chunk modules optimization')).toBe( + true + ); }); - it('--bonjour', (done) => { - testBin('--bonjour') - .then((output) => { - expect(output.code).toEqual(0); - expect(output.stdout.includes('Bonjour')).toBe(true); - done(); - }) - .catch(done); + it('--bonjour', async () => { + const { code, stdout } = await testBin('--bonjour'); + expect(code).toEqual(0); + expect(stdout.includes('Bonjour')).toBe(true); }); - it('--https', (done) => { - testBin('--https') - .then((output) => { - expect(output.code).toEqual(0); - expect(output.stdout.includes('Project is running at')).toBe(true); - done(); - }) - .catch(done); + it('--https', async () => { + const { code, stdout } = await testBin('--https'); + expect(code).toEqual(0); + expect(stdout.includes('Project is running at')).toBe(true); }); - it('--https --cacert --pfx --key --cert --pfx-passphrase', (done) => { - testBin( + it('--https --cacert --pfx --key --cert --pfx-passphrase', async () => { + const { code, stdout } = await testBin( `--https --cacert ${caPath} --pfx ${pfxPath} --key ${keyPath} --cert ${certPath} --pfx-passphrase webpack-dev-server` - ) - .then((output) => { - expect(output.code).toEqual(0); - expect(output.stdout.includes('Project is running at')).toBe(true); - done(); - }) - .catch(done); + ); + expect(code).toEqual(0); + expect(stdout.includes('Project is running at')).toBe(true); }); - it('--sockPath', (done) => { - testBin('--sockPath /mysockPath') - .then((output) => { - expect( - /http:\/\/localhost:[0-9]+&sockPath=\/mysockPath/.test(output.stdout) - ).toEqual(true); - done(); - }) - .catch(done); + it('--sockPath', async () => { + const { stdout } = await testBin('--sockPath /mysockPath'); + expect( + /http:\/\/localhost:[0-9]+&sockPath=\/mysockPath/.test(stdout) + ).toEqual(true); }); - it('unspecified port', (done) => { - testBin('') - .then((output) => { - expect(/http:\/\/localhost:[0-9]+/.test(output.stdout)).toEqual(true); - done(); - }) - .catch(done); + it('unspecified port', async () => { + const { output } = await testBin(''); + expect(/http:\/\/localhost:[0-9]+/.test(output.stdout)).toEqual(true); }); - it('--color', (done) => { - testBin('--color') - .then((output) => { - // https://github.com/webpack/webpack-dev-server/blob/master/lib/utils/colors.js - expect( - output.stdout.includes('\u001b[39m \u001b[90mï½¢wdsï½£\u001b[39m:') - ).toEqual(true); - done(); - }) - .catch(done); + it('--color', async () => { + const { stdout } = await testBin('--color'); + // https://github.com/webpack/webpack-dev-server/blob/master/lib/utils/colors.js + expect(stdout.includes('\u001b[39m \u001b[90mï½¢wdsï½£\u001b[39m:')).toBe(true); }); // The Unix socket to listen to (instead of a host). - it('--socket', (done) => { + it('--socket', async () => { const socketPath = join('.', 'webpack.sock'); + const { code, stdout } = await testBin(`--socket ${socketPath}`); + expect(code).toEqual(0); + + if (process.platform !== 'win32') { + expect(stdout.includes(socketPath)).toBe(true); - testBin(`--socket ${socketPath}`) - .then((output) => { - expect(output.code).toEqual(0); - - if (process.platform === 'win32') { - done(); - } else { - expect(output.stdout.includes(socketPath)).toBe(true); - - unlink(socketPath, () => { - done(); - }); - } - }) - .catch(done); + await unlinkAsync(socketPath); + } }); - it('should accept the promise function of webpack.config.js', (done) => { - testBin( - false, - resolve(__dirname, '../fixtures/promise-config/webpack.config.js') - ) - .then((output) => { - expect(output.code).toEqual(0); - done(); - }) - .catch((err) => { - // for windows - expect(err.stdout.includes('Compiled successfully.')).toEqual(true); - done(); - }); + it('should accept the promise function of webpack.config.js', async () => { + try { + const { code } = await testBin( + false, + resolve(__dirname, '../fixtures/promise-config/webpack.config.js') + ); + expect(code).toEqual(0); + } catch (err) { + // for windows + if (process.platform === 'win32') { + expect(err.stdout.includes('Compiled successfully.')).toBe(true); + } else { + throw err; + } + } }); + // TODO: hiroppy 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'); diff --git a/test/client/clients/SockJSClient.test.js b/test/client/clients/SockJSClient.test.js index d6c1ec4745..02009a4512 100644 --- a/test/client/clients/SockJSClient.test.js +++ b/test/client/clients/SockJSClient.test.js @@ -4,6 +4,7 @@ const http = require('http'); const express = require('express'); const sockjs = require('sockjs'); const SockJSClient = require('../../../client-src/clients/SockJSClient'); +const timer = require('../../helpers/timer'); const port = require('../../ports-map').sockJSClient; describe('SockJSClient', () => { @@ -32,13 +33,12 @@ describe('SockJSClient', () => { }); describe('client', () => { - it('should open, receive message, and close', (done) => { - socketServer.on('connection', (connection) => { + it('should open, receive message, and close', async () => { + socketServer.on('connection', async (connection) => { connection.write('hello world'); - setTimeout(() => { - connection.close(); - }, 1000); + await timer(1000); + connection.close(); }); const client = new SockJSClient(`http://localhost:${port}/sockjs-node`); @@ -54,16 +54,13 @@ describe('SockJSClient', () => { data.push(msg); }); - setTimeout(() => { - expect(data).toMatchSnapshot(); - done(); - }, 3000); + await timer(3000); + + expect(data).toMatchSnapshot(); }); }); afterAll((done) => { - listeningApp.close(() => { - done(); - }); + listeningApp.close(done); }); }); diff --git a/test/helpers/fs.js b/test/helpers/fs.js new file mode 100644 index 0000000000..d715846748 --- /dev/null +++ b/test/helpers/fs.js @@ -0,0 +1,15 @@ +// we'll delete this file when Node8 is not supported. +// because we can use fs.promise + +'use strict'; + +const { promisify } = require('util'); +const { writeFile, unlink } = require('fs'); + +const unlinkAsync = promisify(unlink); +const writeAsync = promisify(writeFile); + +module.exports = { + unlinkAsync, + writeAsync, +}; diff --git a/test/helpers/run-browser.js b/test/helpers/run-browser.js index 74f63652c3..688b847db3 100644 --- a/test/helpers/run-browser.js +++ b/test/helpers/run-browser.js @@ -3,7 +3,7 @@ const puppeteer = require('puppeteer'); const { puppeteerArgs } = require('./puppeteer-constants'); -function runBrowser(config) { +async function runBrowser(config) { const options = { viewport: { width: 500, @@ -13,27 +13,16 @@ function runBrowser(config) { ...config, }; - return new Promise((resolve, reject) => { - let page; - let browser; - - puppeteer - .launch({ - headless: true, - // args come from: https://github.com/alixaxel/chrome-aws-lambda/blob/master/source/index.js - args: puppeteerArgs, - }) - .then((launchedBrowser) => { - browser = launchedBrowser; - return browser.newPage(); - }) - .then((newPage) => { - page = newPage; - page.emulate(options); - resolve({ page, browser }); - }) - .catch(reject); + const launchedBrowser = await puppeteer.launch({ + headless: true, + // args come from: https://github.com/alixaxel/chrome-aws-lambda/blob/master/source/index.js + args: puppeteerArgs, }); + const browser = launchedBrowser; + const page = await browser.newPage(); + page.emulate(options); + + return { page, browser }; } module.exports = runBrowser; diff --git a/test/helpers/timer.js b/test/helpers/timer.js new file mode 100644 index 0000000000..0608301ec8 --- /dev/null +++ b/test/helpers/timer.js @@ -0,0 +1,11 @@ +'use strict'; + +function timer(t) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, t); + }); +} + +module.exports = timer; diff --git a/test/integration/MultiCompiler.test.js b/test/integration/MultiCompiler.test.js index 5d9cc9c15b..d35fe9ba78 100644 --- a/test/integration/MultiCompiler.test.js +++ b/test/integration/MultiCompiler.test.js @@ -17,10 +17,10 @@ describe('multi compiler', () => { afterAll(testServer.close); // TODO: this is a very basic test, optimally it should test multiple configs etc. - it('should handle GET request to bundle', (done) => { - req + it('should handle GET request to bundle', async () => { + await req .get('/main.js') .expect('Content-Type', 'application/javascript; charset=UTF-8') - .expect(200, done); + .expect(200); }); }); diff --git a/test/integration/UniversalCompiler.test.js b/test/integration/UniversalCompiler.test.js index 81225c3ad1..3ae2c3bd7a 100644 --- a/test/integration/UniversalCompiler.test.js +++ b/test/integration/UniversalCompiler.test.js @@ -16,35 +16,33 @@ describe('universal compiler', () => { afterAll(testServer.close); - it('client bundle should have the inlined the client runtime', (done) => { - req + it('client bundle should have the inlined the client runtime', async () => { + const { res, err } = await req .get('/client.js') .expect('Content-Type', 'application/javascript; charset=UTF-8') - .expect(200) - .end((err, res) => { - if (err) { - return done(err); - } - expect(res.text).toContain('Hello from the client'); - expect(res.text).toContain('sockjs-client'); - done(); - }); + .expect(200); + + if (err) { + throw err; + } + + expect(res.text).toContain('Hello from the client'); + expect(res.text).toContain('sockjs-client'); }); - it('server bundle should NOT have the inlined the client runtime', (done) => { + it('server bundle should NOT have the inlined the client runtime', async () => { // we wouldn't normally request a server bundle // but we'll do it here to check the contents - req + const { res, err } = await req .get('/server.js') .expect('Content-Type', 'application/javascript; charset=UTF-8') - .expect(200) - .end((err, res) => { - if (err) { - return done(err); - } - expect(res.text).toContain('Hello from the server'); - expect(res.text).not.toContain('sockjs-client'); - done(); - }); + .expect(200); + + if (err) { + throw err; + } + + expect(res.text).toContain('Hello from the server'); + expect(res.text).not.toContain('sockjs-client'); }); }); diff --git a/test/options.test.js b/test/options.test.js index 409dc07bec..2c649d393b 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -33,75 +33,7 @@ describe('options', () => { expect(res).toEqual(true); }); - describe('validation', () => { - let server; - - afterAll((done) => { - if (server) { - server.close(() => { - done(); - }); - } - }); - - function validateOption(propertyName, cases) { - const successCount = cases.success.length; - const testCases = []; - - for (const key of Object.keys(cases)) { - testCases.push(...cases[key]); - } - - let current = 0; - - return testCases.reduce((p, value) => { - let compiler = webpack(config); - - return p - .then(() => { - const opts = - Object.prototype.toString.call(value) === '[object Object]' && - Object.keys(value).length !== 0 - ? value - : { - [propertyName]: value, - }; - - server = new Server(compiler, opts); - }) - .then(() => { - if (current < successCount) { - expect(true).toBeTruthy(); - } else { - expect(false).toBeTruthy(); - } - }) - .catch((err) => { - if (current >= successCount) { - expect(err).toBeInstanceOf(ValidationError); - } else { - expect(false).toBeTruthy(); - } - }) - .then(() => { - return new Promise((resolve) => { - if (server) { - server.close(() => { - compiler = null; - server = null; - resolve(); - }); - } else { - resolve(); - } - }); - }) - .then(() => { - current += 1; - }); - }, Promise.resolve()); - } - + { const memfs = createFsFromVolume(new Volume()); // We need to patch memfs // https://github.com/webpack/webpack-dev-middleware#fs @@ -476,10 +408,58 @@ describe('options', () => { }, }; - Object.keys(cases).forEach((key) => { - it(key, () => { - return validateOption(key, cases[key]); + for (const [key, values] of Object.entries(cases)) { + it(`should validate "${key}" option`, async () => { + const compiler = webpack(config); + const { success, failure } = values; + + for (const sample of success) { + let server; + + try { + server = new Server(compiler, createOptions(key, sample)); + expect(true).toBeTruthy(); + } catch (e) { + expect(false).toBeTruthy(); + } + + // eslint-disable-next-line no-await-in-loop + await closeServer(server); + } + + for (const sample of failure) { + let server; + + try { + server = new Server(compiler, createOptions(key, sample)); + expect(false).toBeTruthy(); + } catch (e) { + expect(e).toBeInstanceOf(ValidationError); + } + + // eslint-disable-next-line no-await-in-loop + await closeServer(server); + } }); + } + } + + function createOptions(key, value) { + return Object.prototype.toString.call(value) === '[object Object]' && + Object.keys(value).length !== 0 + ? value + : { + [key]: value, + }; + } + + async function closeServer(server) { + await new Promise((resolve) => { + if (server) { + server.close(resolve); + } else { + resolve(); + } }); - }); + } }); diff --git a/test/server/after-option.test.js b/test/server/after-option.test.js index b9d57616d0..07e7fd5545 100644 --- a/test/server/after-option.test.js +++ b/test/server/after-option.test.js @@ -39,13 +39,12 @@ describe('after option', () => { afterAll(testServer.close); - it('should handle after route', () => { - return req + it('should handle after route', async () => { + const res = await req .get('/after/some/path') .expect('Content-Type', 'text/html; charset=utf-8') - .expect(200) - .then((response) => { - expect(response.text).toBe('after'); - }); + .expect(200); + + expect(res.text).toBe('after'); }); }); diff --git a/test/server/before-option.test.js b/test/server/before-option.test.js index 3da0ecfd54..4e831133c2 100644 --- a/test/server/before-option.test.js +++ b/test/server/before-option.test.js @@ -39,13 +39,12 @@ describe('before option', () => { afterAll(testServer.close); - it('should handle before route', () => { - return req + it('should handle before route', async () => { + const res = await req .get('/before/some/path') .expect('Content-Type', 'text/html; charset=utf-8') - .expect(200) - .then((response) => { - expect(response.text).toBe('before'); - }); + .expect(200); + + expect(res.text).toBe('before'); }); }); diff --git a/test/server/compress-option.test.js b/test/server/compress-option.test.js index 0a04d1466f..644d40356f 100644 --- a/test/server/compress-option.test.js +++ b/test/server/compress-option.test.js @@ -22,15 +22,15 @@ describe('compress option', () => { afterAll(testServer.close); - it('request to bundle file', (done) => { - req + it('request to bundle file', async () => { + await req .get('/main.js') .expect((res) => { if (res.header['content-encoding']) { throw new Error('Expected `content-encoding` header is undefined.'); } }) - .expect(200, done); + .expect(200); }); }); @@ -49,11 +49,11 @@ describe('compress option', () => { afterAll(testServer.close); - it('request to bundle file', (done) => { - req + it('request to bundle file', async () => { + await req .get('/main.js') .expect('Content-Encoding', 'gzip') - .expect(200, done); + .expect(200); }); }); @@ -72,15 +72,15 @@ describe('compress option', () => { afterAll(testServer.close); - it('request to bundle file', (done) => { - req + it('request to bundle file', async () => { + await req .get('/main.js') .expect((res) => { if (res.header['content-encoding']) { throw new Error('Expected `content-encoding` header is undefined.'); } }) - .expect(200, done); + .expect(200); }); }); }); diff --git a/test/server/contentBase-option.test.js b/test/server/contentBase-option.test.js index 13acc53165..b6a679ad6f 100644 --- a/test/server/contentBase-option.test.js +++ b/test/server/contentBase-option.test.js @@ -37,19 +37,17 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); fs.truncateSync(nestedFile); }); - it('Request to index', (done) => { - req.get('/').expect(200, /Heyo/, done); + it('Request to index', async () => { + await req.get('/').expect(200, /Heyo/); }); - it('Request to other file', (done) => { - req.get('/other.html').expect(200, /Other html/, done); + it('Request to other file', async () => { + await req.get('/other.html').expect(200, /Other html/); }); it('Watches folder recursively', (done) => { @@ -108,12 +106,12 @@ describe('contentBase option', () => { }); }); - it("shouldn't list the files inside the assets folder (404)", (done) => { - req.get('/assets/').expect(404, done); + it("shouldn't list the files inside the assets folder (404)", async () => { + await req.get('/assets/').expect(404); }); - it('should show Heyo. because bar has index.html inside it (200)', (done) => { - req.get('/bar/').expect(200, /Heyo/, done); + it('should show Heyo. because bar has index.html inside it (200)', async () => { + await req.get('/bar/').expect(200, /Heyo/); }); }); @@ -133,17 +131,15 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('should list the files inside the assets folder (200)', (done) => { - req.get('/assets/').expect(200, done); + it('should list the files inside the assets folder (200)', async () => { + await req.get('/assets/').expect(200); }); - it('should show Heyo. because bar has index.html inside it (200)', (done) => { - req.get('/bar/').expect(200, /Heyo/, done); + it('should show Heyo. because bar has index.html inside it (200)', async () => { + await req.get('/bar/').expect(200, /Heyo/); }); }); @@ -162,17 +158,15 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('should list the files inside the assets folder (200)', (done) => { - req.get('/assets/').expect(200, done); + it('should list the files inside the assets folder (200)', async () => { + await req.get('/assets/').expect(200); }); - it('should show Heyo. because bar has index.html inside it (200)', (done) => { - req.get('/bar/').expect(200, /Heyo/, done); + it('should show Heyo. because bar has index.html inside it (200)', async () => { + await req.get('/bar/').expect(200, /Heyo/); }); }); @@ -190,17 +184,15 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('Request to first directory', (done) => { - req.get('/').expect(200, /Heyo/, done); + it('Request to first directory', async () => { + await req.get('/').expect(200, /Heyo/); }); - it('Request to second directory', (done) => { - req.get('/foo.html').expect(200, /Foo!/, done); + it('Request to second directory', async () => { + await req.get('/foo.html').expect(200, /Foo!/); }); }); @@ -218,16 +210,14 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('Request to page', (done) => { - req + it('Request to page', async () => { + await req .get('/other.html') .expect('Location', '//localhost:9099999/other.html') - .expect(302, done); + .expect(302); }); }); @@ -245,25 +235,23 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('Request to page', (done) => { - req + it('Request to page', async () => { + await req .get('/foo.html') // TODO: hmm, two slashes seems to be a bug? .expect('Location', 'http://example.com//foo.html') - .expect(302, done); + .expect(302); }); - it('Request to page with search params', (done) => { - req + it('Request to page with search params', async () => { + await req .get('/foo.html?space=ship') // TODO: hmm, two slashes seems to be a bug? .expect('Location', 'http://example.com//foo.html?space=ship') - .expect(302, done); + .expect(302); }); }); @@ -362,13 +350,11 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('Request to page', (done) => { - req.get('/other.html').expect(200, done); + it('Request to page', async () => { + await req.get('/other.html').expect(200); }); }); @@ -390,13 +376,11 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('Request to page', (done) => { - req.get('/other.html').expect(404, done); + it('Request to page', async () => { + await req.get('/other.html').expect(404); }); }); @@ -414,13 +398,11 @@ describe('contentBase option', () => { }); afterAll((done) => { - testServer.close(() => { - done(); - }); + testServer.close(done); }); - it('Request foo.wasm', (done) => { - req.get('/foo.wasm').expect('Content-Type', 'application/wasm', done); + it('Request foo.wasm', async () => { + await req.get('/foo.wasm').expect('Content-Type', 'application/wasm'); }); }); }); diff --git a/test/server/headers-option.test.js b/test/server/headers-option.test.js index 1f3f7ad6fa..1891fe01a2 100644 --- a/test/server/headers-option.test.js +++ b/test/server/headers-option.test.js @@ -24,11 +24,11 @@ describe('headers option', () => { afterAll(testServer.close); - it('GET request with headers', (done) => { - req + it('GET request with headers', async () => { + await req .get('/main') .expect('X-Foo', '1') - .expect(200, done); + .expect(200); }); }); @@ -47,17 +47,18 @@ describe('headers option', () => { afterAll(testServer.close); - it('GET request with headers as an array', (done) => { + it('GET request with headers as an array', async () => { // https://github.com/webpack/webpack-dev-server/pull/1650#discussion_r254217027 const expected = ['v7', 'v8', 'v9'].includes( process.version.split('.')[0] ) ? 'key1=value1,key2=value2' : 'key1=value1, key2=value2'; - req + + await req .get('/main') .expect('X-Bar', expected) - .expect(200, done); + .expect(200); }); }); }); diff --git a/test/server/historyApiFallback-option.test.js b/test/server/historyApiFallback-option.test.js index cc600e7a4a..460e9441fd 100644 --- a/test/server/historyApiFallback-option.test.js +++ b/test/server/historyApiFallback-option.test.js @@ -50,11 +50,11 @@ describe('historyApiFallback option', () => { req = request(server.app); }); - it('request to directory', (done) => { - req + it('request to directory', async () => { + await req .get('/foo') .accept('html') - .expect(200, /Foobar/, done); + .expect(200, /Foobar/); }); }); @@ -77,18 +77,18 @@ describe('historyApiFallback option', () => { req = request(server.app); }); - it('historyApiFallback should take preference above directory index', (done) => { - req + it('historyApiFallback should take preference above directory index', async () => { + await req .get('/') .accept('html') - .expect(200, /Foobar/, done); + .expect(200, /Foobar/); }); - it('request to directory', (done) => { - req + it('request to directory', async () => { + await req .get('/foo') .accept('html') - .expect(200, /Foobar/, done); + .expect(200, /Foobar/); }); it('contentBase file should take preference above historyApiFallback', (done) => { @@ -124,11 +124,11 @@ describe('historyApiFallback option', () => { req = request(server.app); }); - it('historyApiFallback should work and ignore static content', (done) => { - req + it('historyApiFallback should work and ignore static content', async () => { + await req .get('/index.html') .accept('html') - .expect(200, /In-memory file/, done); + .expect(200, /In-memory file/); }); }); @@ -160,25 +160,25 @@ describe('historyApiFallback option', () => { req = request(server.app); }); - it('historyApiFallback respect rewrites for index', (done) => { - req + it('historyApiFallback respect rewrites for index', async () => { + await req .get('/') .accept('html') - .expect(200, /Foobar/, done); + .expect(200, /Foobar/); }); - it('historyApiFallback respect rewrites and shows index for unknown urls', (done) => { - req + it('historyApiFallback respect rewrites and shows index for unknown urls', async () => { + await req .get('/acme') .accept('html') - .expect(200, /Foobar/, done); + .expect(200, /Foobar/); }); - it('historyApiFallback respect any other specified rewrites', (done) => { - req + it('historyApiFallback respect any other specified rewrites', async () => { + await req .get('/other') .accept('html') - .expect(200, /Other file/, done); + .expect(200, /Other file/); }); }); @@ -199,11 +199,11 @@ describe('historyApiFallback option', () => { req = request(server.app); }); - it('should take precedence over contentBase files', (done) => { - req + it('should take precedence over contentBase files', async () => { + await req .get('/foo') .accept('html') - .expect(200, /In-memory file/, done); + .expect(200, /In-memory file/); }); }); }); diff --git a/test/server/host-option.test.js b/test/server/host-option.test.js index 009379062a..667caabd9f 100644 --- a/test/server/host-option.test.js +++ b/test/server/host-option.test.js @@ -50,8 +50,8 @@ describe('host option', () => { expect(address.port).toBe(port); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -77,8 +77,8 @@ describe('host option', () => { expect(address.port).toBe(port); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -104,8 +104,8 @@ describe('host option', () => { expect(address.port).toBe(port); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -131,8 +131,8 @@ describe('host option', () => { expect(address.port).toBe(port); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -158,8 +158,8 @@ describe('host option', () => { expect(address.port).toBe(port); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); diff --git a/test/server/hot-option.test.js b/test/server/hot-option.test.js index 979bbad12c..e79679ff4b 100644 --- a/test/server/hot-option.test.js +++ b/test/server/hot-option.test.js @@ -26,8 +26,8 @@ describe('hot option', () => { afterAll(testServer.close); - it('should include hot script in the bundle', (done) => { - req.get('/main.js').expect(200, /webpack\/hot\/dev-server\.js/, done); + it('should include hot script in the bundle', async () => { + await req.get('/main.js').expect(200, /webpack\/hot\/dev-server\.js/); }); }); @@ -51,8 +51,8 @@ describe('hot option', () => { afterAll(testServer.close); - it('should include hot script in the bundle', (done) => { - req.get('/main.js').expect(200, /webpack\/hot\/dev-server\.js/, done); + it('should include hot script in the bundle', async () => { + await req.get('/main.js').expect(200, /webpack\/hot\/dev-server\.js/); }); }); @@ -72,14 +72,10 @@ describe('hot option', () => { afterAll(testServer.close); - it('should NOT include hot script in the bundle', (done) => { - req - .get('/main.js') - .expect(200) - .then(({ text }) => { - expect(text).not.toMatch(/webpack\/hot\/dev-server\.js/); - done(); - }); + it('should NOT include hot script in the bundle', async () => { + const { text } = await req.get('/main.js').expect(200); + + expect(text).not.toMatch(/webpack\/hot\/dev-server\.js/); }); }); diff --git a/test/server/hotOnly-option.test.js b/test/server/hotOnly-option.test.js index e601325fd3..61cba1eb88 100644 --- a/test/server/hotOnly-option.test.js +++ b/test/server/hotOnly-option.test.js @@ -25,10 +25,10 @@ describe('hotOnly options', () => { afterAll(testServer.close); - it('should include hotOnly script in the bundle', (done) => { - req + it('should include hotOnly script in the bundle', async () => { + await req .get('/main.js') - .expect(200, /webpack\/hot\/only-dev-server\.js/, done); + .expect(200, /webpack\/hot\/only-dev-server\.js/); }); }); diff --git a/test/server/http2-option.test.js b/test/server/http2-option.test.js index 4cf4cd9934..aff171d6fa 100644 --- a/test/server/http2-option.test.js +++ b/test/server/http2-option.test.js @@ -107,14 +107,10 @@ describe('http2 option', () => { req = request(server.app); }); - it('Request to index', (done) => { - req - .get('/') - .expect(200, /Heyo/) - .then(({ res }) => { - expect(res.httpVersion).not.toEqual('2.0'); - done(); - }); + it('Request to index', async () => { + const { res } = await req.get('/').expect(200, /Heyo/); + + expect(res.httpVersion).not.toEqual('2.0'); }); afterAll(testServer.close); diff --git a/test/server/https-option.test.js b/test/server/https-option.test.js index 719875a000..2c569ea5df 100644 --- a/test/server/https-option.test.js +++ b/test/server/https-option.test.js @@ -35,8 +35,8 @@ describe('https option', () => { req = request(server.app); }); - it('Request to index', (done) => { - req.get('/').expect(200, /Heyo/, done); + it('Request to index', async () => { + await req.get('/').expect(200, /Heyo/); }); afterAll(() => { @@ -70,8 +70,8 @@ describe('https option', () => { req = request(server.app); }); - it('Request to index', (done) => { - req.get('/').expect(200, /Heyo/, done); + it('Request to index', async () => { + await req.get('/').expect(200, /Heyo/); }); }); @@ -124,8 +124,8 @@ describe('https option', () => { req = request(server.app); }); - it('Request to index', (done) => { - req.get('/').expect(200, /Heyo/, done); + it('Request to index', async () => { + await req.get('/').expect(200, /Heyo/); }); afterAll(testServer.close); @@ -160,8 +160,8 @@ describe('https option', () => { req = request(server.app); }); - it('Request to index', (done) => { - req.get('/').expect(200, /Heyo/, done); + it('Request to index', async () => { + await req.get('/').expect(200, /Heyo/); }); }); diff --git a/test/server/inline-option.test.js b/test/server/inline-option.test.js index 78344621e6..7fc37ad994 100644 --- a/test/server/inline-option.test.js +++ b/test/server/inline-option.test.js @@ -26,10 +26,10 @@ describe('inline option', () => { afterAll(testServer.close); - it('should include inline client script in the bundle', (done) => { + it('should include inline client script in the bundle', async () => { const url = new RegExp(`client/index.js\\?http://0.0.0.0:${port}`); - req.get('/main.js').expect(200, url, done); + await req.get('/main.js').expect(200, url); }); }); @@ -76,14 +76,10 @@ describe('inline option', () => { afterAll(testServer.close); - it('should NOT include inline client script in the bundle', (done) => { - req - .get('/main.js') - .expect(200) - .then(({ text }) => { - expect(text.includes(`client/index.js?http://0.0.0.0:${port}`)); - done(); - }); + it('should NOT include inline client script in the bundle', async () => { + const { text } = await req.get('/main.js').expect(200); + + expect(text.includes(`client/index.js?http://0.0.0.0:${port}`)); }); }); }); diff --git a/test/server/mimeTypes-option.test.js b/test/server/mimeTypes-option.test.js index 662007dadd..5f2fef5e7a 100644 --- a/test/server/mimeTypes-option.test.js +++ b/test/server/mimeTypes-option.test.js @@ -54,11 +54,11 @@ describe('mimeTypes option', () => { afterAll(testServer.close); - it('request to bundle file with modified mime type', (done) => { - req + it('request to bundle file with modified mime type', async () => { + await req .get('/main.js') .expect('Content-Type', /application\/octet-stream/) - .expect(200, done); + .expect(200); }); }); }); diff --git a/test/server/port-option.test.js b/test/server/port-option.test.js index ff7488de80..d9fd6c2391 100644 --- a/test/server/port-option.test.js +++ b/test/server/port-option.test.js @@ -23,8 +23,8 @@ describe('port', () => { expect(address.port).toBeDefined(); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -51,8 +51,8 @@ describe('port', () => { expect(address.port).toBeDefined(); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -78,8 +78,8 @@ describe('port', () => { expect(address.port).toBeDefined(); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -104,8 +104,8 @@ describe('port', () => { expect(address.port).toBe(33333); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); @@ -130,8 +130,8 @@ describe('port', () => { expect(address.port).toBe(33333); }); - it('Request to index', (done) => { - req.get('/').expect(200, done); + it('Request to index', async () => { + await req.get('/').expect(200); }); afterAll(testServer.close); diff --git a/test/server/proxy-option.test.js b/test/server/proxy-option.test.js index 6f21967248..21917d9ab8 100644 --- a/test/server/proxy-option.test.js +++ b/test/server/proxy-option.test.js @@ -108,32 +108,32 @@ describe('proxy option', () => { }); describe('target', () => { - it('respects a proxy option when a request path is matched', (done) => { - req.get('/proxy1').expect(200, 'from proxy1', done); + it('respects a proxy option when a request path is matched', async () => { + await req.get('/proxy1').expect(200, 'from proxy1'); }); }); describe('pathRewrite', () => { - it('respects a pathRewrite option', (done) => { - req.get('/api/proxy2').expect(200, 'from proxy2', done); + it('respects a pathRewrite option', async () => { + await req.get('/api/proxy2').expect(200, 'from proxy2'); }); }); describe('bypass', () => { - it('can rewrite a request path', (done) => { - req.get('/foo/bar.html').expect(200, /Hello/, done); + it('can rewrite a request path', async () => { + await req.get('/foo/bar.html').expect(200, /Hello/); }); - it('can rewrite a request path regardless of the target defined a bypass option', (done) => { - req.get('/baz/hoge.html').expect(200, /Hello/, done); + it('can rewrite a request path regardless of the target defined a bypass option', async () => { + await req.get('/baz/hoge.html').expect(200, /Hello/); }); - it('should pass through a proxy when a bypass function returns null', (done) => { - req.get('/foo.js').expect(200, /Hey/, done); + it('should pass through a proxy when a bypass function returns null', async () => { + await req.get('/foo.js').expect(200, /Hey/); }); - it('should not pass through a proxy when a bypass function returns false', (done) => { - req.get('/proxyfalse').expect(404, done); + it('should not pass through a proxy when a bypass function returns false', async () => { + await req.get('/proxyfalse').expect(404); }); }); }); @@ -164,8 +164,8 @@ describe('proxy option', () => { }); }); - it('respects a proxy option', (done) => { - req.get('/proxy1').expect(200, 'from proxy1', done); + it('respects a proxy option', async () => { + await req.get('/proxy1').expect(200, 'from proxy1'); }); }); @@ -195,12 +195,12 @@ describe('proxy option', () => { }); }); - it('respects a proxy option', (done) => { - req.get('/proxy1').expect(200, 'from proxy1', done); + it('respects a proxy option', async () => { + await req.get('/proxy1').expect(200, 'from proxy1'); }); - it('respects a proxy option of function', (done) => { - req.get('/api/proxy2').expect(200, 'from proxy2', done); + it('respects a proxy option of function', async () => { + await req.get('/api/proxy2').expect(200, 'from proxy2'); }); }); @@ -243,12 +243,12 @@ describe('proxy option', () => { }); }); - it('respects proxy1 option', (done) => { - req.get('/proxy1').expect(200, 'from proxy', done); + it('respects proxy1 option', async () => { + await req.get('/proxy1').expect(200, 'from proxy'); }); - it('respects proxy2 option', (done) => { - req.get('/proxy2').expect(200, 'from proxy', done); + it('respects proxy2 option', async () => { + await req.get('/proxy2').expect(200, 'from proxy'); }); }); @@ -366,36 +366,35 @@ describe('proxy option', () => { }); }); - it('GET method', (done) => { - req.get('/get').expect(200, 'GET method from proxy', done); + it('GET method', async () => { + await req.get('/get').expect(200, 'GET method from proxy'); }); it('HEAD method', (done) => { req.head('/head').expect(200, done); }); - it('POST method (application/x-www-form-urlencoded)', (done) => { - req + it('POST method (application/x-www-form-urlencoded)', async () => { + await req .post('/post-x-www-form-urlencoded') .send('id=1') - .expect(200, 'POST method from proxy (id: 1)', done); + .expect(200, 'POST method from proxy (id: 1)'); }); - it('POST method (application/json)', (done) => { - req + it('POST method (application/json)', async () => { + await req .post('/post-application-json') .send({ id: '1' }) .set('Accept', 'application/json') .expect('Content-Type', /json/) .expect( 200, - JSON.stringify({ answer: 'POST method from proxy (id: 1)' }), - done + JSON.stringify({ answer: 'POST method from proxy (id: 1)' }) ); }); - it('DELETE method', (done) => { - req.delete('/delete').expect(200, 'DELETE method from proxy', done); + it('DELETE method', async () => { + await req.delete('/delete').expect(200, 'DELETE method from proxy'); }); }); }); diff --git a/test/server/servers/SockJSServer.test.js b/test/server/servers/SockJSServer.test.js index 48c535e98e..f78610806f 100644 --- a/test/server/servers/SockJSServer.test.js +++ b/test/server/servers/SockJSServer.test.js @@ -4,6 +4,7 @@ const http = require('http'); const express = require('express'); const SockJS = require('sockjs-client/dist/sockjs'); const SockJSServer = require('../../../lib/servers/SockJSServer'); +const timer = require('../../helpers/timer'); const port = require('../../ports-map').SockJSServer; describe('SockJSServer', () => { @@ -32,18 +33,18 @@ describe('SockJSServer', () => { }); describe('server', () => { - it('should recieve connection, send message, and close client', (done) => { + it('should recieve connection, send message, and close client', async () => { const data = []; - let headers; - socketServer.onConnection((connection, h) => { - headers = h; + + socketServer.onConnection(async (connection) => { data.push('open'); socketServer.send(connection, 'hello world'); - setTimeout(() => { - // the server closes the connection with the client - socketServer.close(connection); - }, 1000); + + await timer(1000); + + // the server closes the connection with the client + socketServer.close(connection); }); const client = new SockJS(`http://localhost:${port}/sockjs-node`); @@ -56,14 +57,13 @@ describe('SockJSServer', () => { data.push('close'); }; - setTimeout(() => { - expect(headers.host).toMatchSnapshot(); - expect(data).toMatchSnapshot(); - done(); - }, 3000); + await timer(3000); + + expect(headers.host).toMatchSnapshot(); + expect(data).toMatchSnapshot(); }); - it('should receive client close event', (done) => { + it('should receive client close event', async () => { let receivedClientClose = false; socketServer.onConnection((connection) => { socketServer.onConnectionClose(connection, () => { @@ -74,15 +74,14 @@ describe('SockJSServer', () => { // eslint-disable-next-line new-cap const client = new SockJS(`http://localhost:${port}/sockjs-node`); - setTimeout(() => { - // the client closes itself, the server does not close it - client.close(); - }, 1000); + await timer(1000); + + // the client closes itself, the server does not close it + client.close(); + + await timer(3000); - setTimeout(() => { - expect(receivedClientClose).toBeTruthy(); - done(); - }, 3000); + expect(receivedClientClose).toBeTruthy(); }); it('should not throw an exception when connection is null', () => { diff --git a/test/server/sockPath-option.test.js b/test/server/sockPath-option.test.js index b6840228b5..860e3818be 100644 --- a/test/server/sockPath-option.test.js +++ b/test/server/sockPath-option.test.js @@ -25,8 +25,8 @@ describe('sockPath options', () => { expect(!!server.sockPath.match(/\/[a-z0-9\-/]+[^/]$/)).toBeTruthy(); }); - it('responds with a 200', (done) => { - req.get('/sockjs-node').expect(200, done); + it('responds with a 200', async () => { + await req.get('/sockjs-node').expect(200); }); }); @@ -49,8 +49,8 @@ describe('sockPath options', () => { expect(server.sockPath).toEqual(path); }); - it('responds with a 200 second', (done) => { - req.get(path).expect(200, done); + it('responds with a 200 second', async () => { + await req.get(path).expect(200); }); }); }); diff --git a/test/server/stats-option.test.js b/test/server/stats-option.test.js index dc89702cc8..f6db78dcc3 100644 --- a/test/server/stats-option.test.js +++ b/test/server/stats-option.test.js @@ -6,7 +6,7 @@ const config = require('../fixtures/simple-config/webpack.config'); const port = require('../ports-map')['stats-option']; describe('stats option', () => { - it(`should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors')`, () => { + it(`should works with difference stats values (contains 'hash', 'assets', 'warnings' and 'errors')`, async () => { const allStats = [ {}, // eslint-disable-next-line no-undefined @@ -18,23 +18,22 @@ describe('stats option', () => { }, ]; - return allStats.reduce((p, stats) => { - return p.then(() => { - return new Promise((resolve) => { - const compiler = webpack(config); - const server = new Server(compiler, { stats, port, quiet: true }); + for (const stats of allStats) { + const compiler = webpack(config); + const server = new Server(compiler, { stats, port, quiet: true }); - compiler.hooks.done.tap('webpack-dev-server', (s) => { - expect(Object.keys(server.getStats(s))).toMatchSnapshot(); + // eslint-disable-next-line no-await-in-loop + await new Promise((resolve) => { + compiler.hooks.done.tap('webpack-dev-server', (s) => { + expect(Object.keys(server.getStats(s))).toMatchSnapshot(); - server.close(resolve); - }); - - compiler.run(() => {}); - server.listen(port, 'localhost'); + server.close(resolve); }); + + compiler.run(() => {}); + server.listen(port, 'localhost'); }); - }, Promise.resolve()); + } }); it('should respect warningsFilter', (done) => { diff --git a/test/server/utils/addEntries.test.js b/test/server/utils/addEntries.test.js index 1bc6a6cef6..c124c7c36c 100644 --- a/test/server/utils/addEntries.test.js +++ b/test/server/utils/addEntries.test.js @@ -17,7 +17,7 @@ describe('addEntries util', () => { expect(webpackOptions.entry.length).toEqual(2); expect( - normalize(webpackOptions.entry[0]).indexOf('client/index.js?') !== -1 + normalize(webpackOptions.entry[0]).includes('client/index.js?') ).toBeTruthy(); expect(normalize(webpackOptions.entry[1])).toEqual('./foo.js'); }); @@ -33,7 +33,7 @@ describe('addEntries util', () => { expect(webpackOptions.entry.length).toEqual(3); expect( - normalize(webpackOptions.entry[0]).indexOf('client/index.js?') !== -1 + normalize(webpackOptions.entry[0]).includes('client/index.js?') ).toBeTruthy(); expect(webpackOptions.entry[1]).toEqual('./foo.js'); expect(webpackOptions.entry[2]).toEqual('./bar.js'); @@ -54,7 +54,7 @@ describe('addEntries util', () => { expect(webpackOptions.entry.foo.length).toEqual(2); expect( - normalize(webpackOptions.entry.foo[0]).indexOf('client/index.js?') !== -1 + normalize(webpackOptions.entry.foo[0]).includes('client/index.js?') ).toBeTruthy(); expect(webpackOptions.entry.foo[1]).toEqual('./foo.js'); expect(webpackOptions.entry.bar[1]).toEqual('./bar.js'); @@ -70,7 +70,7 @@ describe('addEntries util', () => { expect(webpackOptions.entry[1]).toEqual('./src'); }); - it('should preserves dynamic entry points', (done) => { + it('should preserves dynamic entry points', async () => { let i = 0; const webpackOptions = { // simulate dynamic entry @@ -85,22 +85,21 @@ describe('addEntries util', () => { expect(typeof webpackOptions.entry).toEqual('function'); - webpackOptions - .entry() - .then((entryFirstRun) => - webpackOptions.entry().then((entrySecondRun) => { - expect(entryFirstRun.length).toEqual(2); - expect(entryFirstRun[1]).toEqual('./src-1.js'); - - expect(entrySecondRun.length).toEqual(2); - expect(entrySecondRun[1]).toEqual('./src-2.js'); - done(); - }) - ) - .catch(done); + { + const entry = await webpackOptions.entry(); + + expect(entry.length).toEqual(2); + expect(entry[1]).toEqual('./src-1.js'); + } + { + const entry = await webpackOptions.entry(); + + expect(entry.length).toEqual(2); + expect(entry[1]).toEqual('./src-2.js'); + } }); - it('should preserves asynchronous dynamic entry points', (done) => { + it('should preserves asynchronous dynamic entry points', async () => { let i = 0; const webpackOptions = { // simulate async dynamic entry @@ -117,19 +116,18 @@ describe('addEntries util', () => { expect(typeof webpackOptions.entry).toEqual('function'); - webpackOptions - .entry() - .then((entryFirstRun) => - webpackOptions.entry().then((entrySecondRun) => { - expect(entryFirstRun.length).toEqual(2); - expect(entryFirstRun[1]).toEqual('./src-1.js'); - - expect(entrySecondRun.length).toEqual(2); - expect(entrySecondRun[1]).toEqual('./src-2.js'); - done(); - }) - ) - .catch(done); + { + const entry = await webpackOptions.entry(); + + expect(entry.length).toEqual(2); + expect(entry[1]).toEqual('./src-1.js'); + } + { + const entry = await webpackOptions.entry(); + + expect(entry.length).toEqual(2); + expect(entry[1]).toEqual('./src-2.js'); + } }); it("should prepends webpack's hot reload client script", () => { @@ -312,7 +310,7 @@ describe('addEntries util', () => { if (expectInline) { expect( - normalize(webpackOptions.entry[0]).indexOf('client/index.js?') !== -1 + normalize(webpackOptions.entry[0]).includes('client/index.js?') ).toBeTruthy(); } @@ -344,7 +342,7 @@ describe('addEntries util', () => { if (expectInline) { expect( - normalize(webpackOptions.entry[0]).indexOf('client/index.js?') !== -1 + normalize(webpackOptions.entry[0]).includes('client/index.js?') ).toBeTruthy(); } @@ -400,7 +398,7 @@ describe('addEntries util', () => { expect(webWebpackOptions.entry.length).toEqual(2); expect( - normalize(webWebpackOptions.entry[0]).indexOf('client/index.js?') !== -1 + normalize(webWebpackOptions.entry[0]).includes('client/index.js?') ).toBeTruthy(); expect(normalize(webWebpackOptions.entry[1])).toEqual('./foo.js'); diff --git a/test/server/utils/findPort.test.js b/test/server/utils/findPort.test.js index 8914807a6e..cabfc832e0 100644 --- a/test/server/utils/findPort.test.js +++ b/test/server/utils/findPort.test.js @@ -7,106 +7,109 @@ const findPort = require('../../../lib/utils/findPort'); describe('findPort', () => { let dummyServers = []; - afterEach(() => { + afterEach(async () => { 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 = []; + async function close(server) { + return new Promise((resolve) => { + server.close(resolve); }); + } + + for (const server of dummyServers) { + // eslint-disable-next-line no-await-in-loop + await close(server); + } + + dummyServers = []; }); - function createDummyServers(n) { - return (Array.isArray(n) ? n : [...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); - }); + async function createDummyServers(n) { + async function create(i) { + return new Promise((resolve) => { + const server = http.createServer(); + dummyServers.push(server); + server.listen(8080 + i, resolve); }); - }, Promise.resolve()); + } + + const samples = [...new Array(n)].map((_, i) => i); + + for (const i of samples) { + // eslint-disable-next-line no-await-in-loop + await create(i); + } } - it('should returns the port when the port is specified', () => { + it('should returns the port when the port is specified', async () => { process.env.DEFAULT_PORT_RETRY = 5; - return findPort(8082).then((port) => { - expect(port).toEqual(8082); - }); + const port = await findPort(8082); + expect(port).toEqual(8082); }); - it.only('should returns the port when the port is null', () => { + it.only('should returns the port when the port is null', async () => { const retryCount = 2; process.env.DEFAULT_PORT_RETRY = 2; - return createDummyServers(retryCount) - .then(() => findPort(null)) - .then((port) => { - expect(port).toEqual(8080 + retryCount); - }); + await createDummyServers(retryCount); + + const port = await findPort(null); + + expect(port).toEqual(8080 + retryCount); }); - it('should returns the port when the port is undefined', () => { + it('should returns the port when the port is undefined', async () => { const retryCount = 2; process.env.DEFAULT_PORT_RETRY = 2; - return ( - createDummyServers(retryCount) - // eslint-disable-next-line no-undefined - .then(() => findPort(undefined)) - .then((port) => { - expect(port).toEqual(8080 + retryCount); - }) - ); + await createDummyServers(retryCount); + + // eslint-disable-next-line no-undefined + const port = findPort(undefined); + + expect(port).toEqual(8080 + retryCount); }); - it('should retry finding the port for up to defaultPortRetry times (number)', () => { + it('should retry finding the port for up to defaultPortRetry times (number)', async () => { const retryCount = 3; process.env.DEFAULT_PORT_RETRY = retryCount; - return createDummyServers(retryCount) - .then(() => findPort()) - .then((port) => { - expect(port).toEqual(8080 + retryCount); - }); + await createDummyServers(retryCount); + + const port = await findPort(); + + expect(port).toEqual(8080 + retryCount); }); - it('should retry finding the port for up to defaultPortRetry times (string)', () => { + it('should retry finding the port for up to defaultPortRetry times (string)', async () => { const retryCount = 3; process.env.DEFAULT_PORT_RETRY = `${retryCount}`; - return createDummyServers(retryCount) - .then(() => findPort()) - .then((port) => { - expect(port).toEqual(8080 + retryCount); - }); + await createDummyServers(retryCount); + + const port = await findPort(); + + expect(port).toEqual(8080 + retryCount); }); - it('should retry finding the port when serial ports are busy', () => { + it('should retry finding the port when serial ports are busy', async () => { const busyPorts = [8080, 8081, 8082, 8083]; process.env.DEFAULT_PORT_RETRY = 3; - return createDummyServers(busyPorts) - .then(() => findPort()) - .then((port) => { - expect(port).toEqual(8080 + busyPorts.length); - }); + await createDummyServers(busyPorts); + + const port = await findPort(); + + expect(port).toEqual(8080 + busyPorts.length); }); - it("should throws the error when the port isn't found", () => { + it("should throws the error when the port isn't found", async () => { expect.assertions(1); const spy = jest @@ -119,12 +122,14 @@ describe('findPort', () => { process.env.DEFAULT_PORT_RETRY = 0; - return createDummyServers(retryCount) - .then(() => findPort()) - .catch((err) => { - expect(err.message).toMatchSnapshot(); + await createDummyServers(retryCount); - spy.mockRestore(); - }); + try { + await findPort(); + } catch (err) { + expect(err.message).toMatchSnapshot(); + } + + spy.mockRestore(); }); }); diff --git a/test/server/utils/routes.test.js b/test/server/utils/routes.test.js index acc94eb8eb..f4b5030e3d 100644 --- a/test/server/utils/routes.test.js +++ b/test/server/utils/routes.test.js @@ -16,112 +16,106 @@ describe('routes util', () => { afterAll(testServer.close); - 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); - done(); - }); + it('should handles GET request to live bundle', async () => { + const { headers, statusCode } = await req.get( + '/__webpack_dev_server__/live.bundle.js' + ); + + expect(headers['content-type']).toEqual('application/javascript'); + expect(statusCode).toEqual(200); }); - 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); - done(); - }); + it('should handles HEAD request to live bundle', async () => { + const { headers, statusCode } = await req.head( + '/__webpack_dev_server__/live.bundle.js' + ); + + expect(headers['content-type']).toEqual('application/javascript'); + expect(statusCode).toEqual(200); }); - 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); - done(); - }); + it('should handles GET request to sockjs bundle', async () => { + const { headers, statusCode } = await req.get( + '/__webpack_dev_server__/sockjs.bundle.js' + ); + + expect(headers['content-type']).toEqual('application/javascript'); + expect(statusCode).toEqual(200); }); - 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); - done(); - }); + it('should handles HEAD request to sockjs bundle', async () => { + const { headers, statusCode } = await req.head( + '/__webpack_dev_server__/sockjs.bundle.js' + ); + + expect(headers['content-type']).toEqual('application/javascript'); + expect(statusCode).toEqual(200); }); - 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); - done(); - }); + it('should handles GET request to inline bundle', async () => { + const { headers, statusCode } = await req.get('/webpack-dev-server.js'); + + expect(headers['content-type']).toEqual('application/javascript'); + expect(statusCode).toEqual(200); }); - 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); - done(); - }); + it('should handles HEAD request to inline bundle', async () => { + const { headers, statusCode } = await req.head('/webpack-dev-server.js'); + + expect(headers['content-type']).toEqual('application/javascript'); + expect(statusCode).toEqual(200); }); - 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); - done(); - }); + it('should handles GET request to live html', async () => { + const { headers, statusCode } = await req.get('/webpack-dev-server/'); + + expect(headers['content-type']).toEqual('text/html'); + expect(statusCode).toEqual(200); }); - 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); - done(); - }); + it('should handles HEAD request to live html', async () => { + const { headers, statusCode } = await req.head('/webpack-dev-server/'); + + expect(headers['content-type']).toEqual('text/html'); + expect(statusCode).toEqual(200); }); - 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); - expect(res.text).toMatchSnapshot(); - done(); - }); + it('should handles GET request to directory index', async () => { + const { headers, statusCode, text } = await req.get('/webpack-dev-server'); + + expect(headers['content-type']).toEqual('text/html'); + expect(statusCode).toEqual(200); + expect(text).toMatchSnapshot(); }); - 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); - done(); - }); + it('should handles HEAD request to directory index', async () => { + const { headers, statusCode } = await req.head('/webpack-dev-server'); + + expect(headers['content-type']).toEqual('text/html'); + expect(statusCode).toEqual(200); }); - it('should handles GET request to magic html', (done) => { - req.get('/main').then(({ res }) => { - expect(res.statusCode).toEqual(200); - done(); - }); + it('should handles GET request to magic html', async () => { + const { statusCode } = await req.get('/main'); + + expect(statusCode).toEqual(200); }); - it('should handles HEAD request to magic html', (done) => { - req.head('/main').then(({ res }) => { - expect(res.statusCode).toEqual(200); - done(); - }); + it('should handles HEAD request to magic html', async () => { + const { statusCode } = await req.head('/main'); + + expect(statusCode).toEqual(200); }); - it('should handles GET request to main chunk', (done) => { - req.get('/main.js').then(({ res }) => { - expect(res.statusCode).toEqual(200); - done(); - }); + it('should handles GET request to main chunk', async () => { + const { statusCode } = await req.get('/main.js'); + + expect(statusCode).toEqual(200); }); - it('should handles HEAD request to main chunk', (done) => { - req.head('/main.js').then(({ res }) => { - expect(res.statusCode).toEqual(200); - done(); - }); + it('should handles HEAD request to main chunk', async () => { + const { statusCode } = await req.head('/main.js'); + + expect(statusCode).toEqual(200); }); }); diff --git a/test/server/utils/runOpen.test.js b/test/server/utils/runOpen.test.js index d8c258008d..0c37e488b0 100644 --- a/test/server/utils/runOpen.test.js +++ b/test/server/utils/runOpen.test.js @@ -15,9 +15,10 @@ describe('runOpen util', () => { open.mockImplementation(() => Promise.resolve()); }); - it('on specify URL', () => { - return runOpen('https://example.com', {}, console).then(() => { - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + it('on specify URL', async () => { + await runOpen('https://example.com', {}, console); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -25,16 +26,16 @@ describe('runOpen util', () => { }, ] `); - }); }); - it('on specify URL with page', () => { - return runOpen( + it('on specify URL with page', async () => { + await runOpen( 'https://example.com', { openPage: '/index.html' }, console - ).then(() => { - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + ); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -42,16 +43,12 @@ describe('runOpen util', () => { }, ] `); - }); }); - it('on specify URL in Google Chrome', () => { - return runOpen( - 'https://example.com', - { open: 'Google Chrome' }, - console - ).then(() => { - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + it('on specify URL in Google Chrome', async () => { + await runOpen('https://example.com', { open: 'Google Chrome' }, console); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -60,16 +57,16 @@ describe('runOpen util', () => { }, ] `); - }); }); - it('on specify URL with page in Google Chrome ', () => { - return runOpen( + it('on specify URL with page in Google Chrome ', async () => { + await runOpen( 'https://example.com', { open: 'Google Chrome', openPage: '/index.html' }, console - ).then(() => { - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + ); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -78,16 +75,16 @@ describe('runOpen util', () => { }, ] `); - }); }); + }); - it('on specify absolute https URL with page in Google Chrome ', () => { - return runOpen( - 'https://example.com', - { open: 'Google Chrome', openPage: 'https://example2.com' }, - console - ).then(() => { - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + it('on specify absolute https URL with page in Google Chrome ', () => { + return runOpen( + 'https://example.com', + { open: 'Google Chrome', openPage: 'https://example2.com' }, + console + ).then(() => { + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example2.com", Object { @@ -96,16 +93,16 @@ describe('runOpen util', () => { }, ] `); - }); }); + }); - it('on specify absolute http URL with page in Google Chrome ', () => { - return runOpen( - 'https://example.com', - { open: 'Google Chrome', openPage: 'http://example2.com' }, - console - ).then(() => { - expect(opn.mock.calls[0]).toMatchInlineSnapshot(` + it('on specify absolute http URL with page in Google Chrome ', () => { + return runOpen( + 'https://example.com', + { open: 'Google Chrome', openPage: 'http://example2.com' }, + console + ).then(() => { + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "http://example2.com", Object { @@ -114,7 +111,6 @@ describe('runOpen util', () => { }, ] `); - }); }); }); @@ -129,12 +125,13 @@ describe('runOpen util', () => { logMock.warn.mockClear(); }); - it('on specify URL and log error', () => { - return runOpen('https://example.com', {}, logMock).then(() => { - expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( - `"Unable to open browser. If you are running in a headless environment, please do not use the --open flag"` - ); - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + it('on specify URL and log error', async () => { + await runOpen('https://example.com', {}, logMock); + + expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( + `"Unable to open browser. If you are running in a headless environment, please do not use the --open flag"` + ); + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -142,19 +139,19 @@ describe('runOpen util', () => { }, ] `); - }); }); - it('on specify URL with page and log error', () => { - return runOpen( + it('on specify URL with page and log error', async () => { + await runOpen( 'https://example.com', { openPage: '/index.html' }, logMock - ).then(() => { - expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( - `"Unable to open browser. If you are running in a headless environment, please do not use the --open flag"` - ); - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + ); + + expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( + `"Unable to open browser. If you are running in a headless environment, please do not use the --open flag"` + ); + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -162,19 +159,15 @@ describe('runOpen util', () => { }, ] `); - }); }); - it('on specify URL in Google Chrome and log error', () => { - return runOpen( - 'https://example.com', - { open: 'Google Chrome' }, - logMock - ).then(() => { - expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( - `"Unable to open browser: Google Chrome. If you are running in a headless environment, please do not use the --open flag"` - ); - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + it('on specify URL in Google Chrome and log error', async () => { + await runOpen('https://example.com', { open: 'Google Chrome' }, logMock); + + expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( + `"Unable to open browser: Google Chrome. If you are running in a headless environment, please do not use the --open flag"` + ); + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com", Object { @@ -183,19 +176,19 @@ describe('runOpen util', () => { }, ] `); - }); }); - it('on specify URL with page in Google Chrome and log error ', () => { - return runOpen( + it('on specify URL with page in Google Chrome and log error ', async () => { + await runOpen( 'https://example.com', { open: 'Google Chrome', openPage: '/index.html' }, logMock - ).then(() => { - expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( - `"Unable to open browser: Google Chrome. If you are running in a headless environment, please do not use the --open flag"` - ); - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + ); + + expect(logMock.warn.mock.calls[0][0]).toMatchInlineSnapshot( + `"Unable to open browser: Google Chrome. If you are running in a headless environment, please do not use the --open flag"` + ); + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -204,7 +197,6 @@ describe('runOpen util', () => { }, ] `); - }); }); }); }); From ec863847fa8320450cc18c8c28ede1228f34df2e Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Mon, 10 Jun 2019 16:47:58 +0200 Subject: [PATCH 09/32] feat(client): delete `none` and `warning` from clientLogLevel (#1998) ISSUE: https://github.com/webpack/webpack-dev-server/pull/1901 --- client-src/default/utils/log.js | 12 ------------ lib/options.json | 11 +---------- test/client/utils/__snapshots__/log.test.js.snap | 3 --- test/client/utils/log.test.js | 10 ++++------ test/options.test.js | 15 ++------------- 5 files changed, 7 insertions(+), 44 deletions(-) diff --git a/client-src/default/utils/log.js b/client-src/default/utils/log.js index 6ae76e069b..db9301cad1 100644 --- a/client-src/default/utils/log.js +++ b/client-src/default/utils/log.js @@ -8,11 +8,6 @@ const ERROR = 'error'; const DEBUG = 'debug'; const TRACE = 'trace'; const SILENT = 'silent'; -// deprecated -// TODO: remove these at major released -// https://github.com/webpack/webpack-dev-server/pull/1825 -const WARNING = 'warning'; -const NONE = 'none'; // Set the default log level log.setDefaultLevel(INFO); @@ -26,13 +21,6 @@ export function setLogLevel(level) { case TRACE: log.setLevel(level); break; - // deprecated - case WARNING: - // loglevel's warning name is different from webpack's - log.setLevel('warn'); - break; - // deprecated - case NONE: case SILENT: log.disableAll(); break; diff --git a/lib/options.json b/lib/options.json index 217ee5a631..71fe65f929 100644 --- a/lib/options.json +++ b/lib/options.json @@ -37,16 +37,7 @@ ] }, "clientLogLevel": { - "enum": [ - "info", - "warn", - "error", - "debug", - "trace", - "silent", - "none", - "warning" - ] + "enum": ["info", "warn", "error", "debug", "trace", "silent"] }, "compress": { "type": "boolean" diff --git a/test/client/utils/__snapshots__/log.test.js.snap b/test/client/utils/__snapshots__/log.test.js.snap index a62894e923..8f120617a2 100644 --- a/test/client/utils/__snapshots__/log.test.js.snap +++ b/test/client/utils/__snapshots__/log.test.js.snap @@ -19,8 +19,5 @@ Array [ Array [ "trace", ], - Array [ - "warn", - ], ] `; diff --git a/test/client/utils/log.test.js b/test/client/utils/log.test.js index f1f857ae70..3165a5353d 100644 --- a/test/client/utils/log.test.js +++ b/test/client/utils/log.test.js @@ -33,7 +33,7 @@ describe('log', () => { }); test('should set log level via setLogLevel', () => { - ['info', 'warn', 'error', 'debug', 'trace', 'warning'].forEach((level) => { + ['info', 'warn', 'error', 'debug', 'trace'].forEach((level) => { setLogLevel(level); }); @@ -42,14 +42,12 @@ describe('log', () => { ).toMatchSnapshot(); }); - test('should set none and silent via setLogLevel', () => { - ['none', 'silent'].forEach((level) => { - setLogLevel(level); - }); + test('should set silent via setLogLevel', () => { + setLogLevel('silent'); expect( logMock.getLogger.mock.results[0].value.disableAll.mock.results - ).toHaveLength(2); + ).toHaveLength(1); }); test('should output exception log when the level is unknown', () => { diff --git a/test/options.test.js b/test/options.test.js index 2c649d393b..66d7703356 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -65,19 +65,8 @@ describe('options', () => { failure: [false], }, clientLogLevel: { - success: [ - 'silent', - 'info', - 'error', - 'warn', - 'trace', - 'debug', - // deprecated - 'none', - // deprecated - 'warning', - ], - failure: ['whoops!'], + success: ['silent', 'info', 'error', 'warn', 'trace', 'debug'], + failure: ['whoops!', 'none', 'warning'], }, compress: { success: [true], From 742aa136a0eb622654285d13df2e7bbda85c84ed Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Mon, 10 Jun 2019 17:44:06 +0200 Subject: [PATCH 10/32] chore: fix code from master --- globalSetupTest.js | 3 +-- test/ports-map.js | 4 +--- test/server/contentBase-option.test.js | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/globalSetupTest.js b/globalSetupTest.js index c82cbb1432..1e4123b5fa 100644 --- a/globalSetupTest.js +++ b/globalSetupTest.js @@ -7,8 +7,7 @@ const ports = require('./test/ports-map'); async function validatePorts() { const samples = []; - Object.keys(ports).forEach((key) => { - const value = ports[key]; + Object.entries(ports).forEach(([key, value]) => { const arr = Array.isArray(value) ? value : [value]; arr.forEach((port) => { diff --git a/test/ports-map.js b/test/ports-map.js index ac73aaa142..81133db921 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -48,9 +48,7 @@ const portsList = { let startPort = 8089; const ports = {}; -Object.keys(portsList).forEach((key) => { - const value = portsList[key]; - +Object.entries(portsList).forEach(([key, value]) => { ports[key] = value === 1 ? (startPort += 1) diff --git a/test/server/contentBase-option.test.js b/test/server/contentBase-option.test.js index b6a679ad6f..acaa46da02 100644 --- a/test/server/contentBase-option.test.js +++ b/test/server/contentBase-option.test.js @@ -345,7 +345,7 @@ describe('contentBase option', () => { beforeAll((done) => { jest.spyOn(process, 'cwd').mockImplementation(() => contentBasePublic); - server = testServer.start(config, {}, done); + server = testServer.start(config, { port }, done); req = request(server.app); }); From b136055c5915555074cbfbcf0845d471b1c6dfd2 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Mon, 10 Jun 2019 19:49:57 +0200 Subject: [PATCH 11/32] chore(deps): update dependency p-retry to v4 (#2009) --- package-lock.json | 29 ++++++++++++++++++++++------- package.json | 7 +++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index c2a8b23118..e65e270b5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1923,6 +1923,11 @@ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, "@types/semver": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.0.1.tgz", @@ -11080,10 +11085,11 @@ "dev": true }, "p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.1.0.tgz", + "integrity": "sha512-oepllyG9gX1qH4Sm20YAKxg1GA7L7puhvGnTfimi31P07zSIj7SDV6YtuAx9nbJF51DES+2CIIRkXs8GKqWJxA==", "requires": { + "@types/retry": "^0.12.0", "retry": "^0.12.0" } }, @@ -11624,6 +11630,15 @@ "requires": { "glob": "^7.1.3" } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } } } }, @@ -14409,11 +14424,11 @@ } }, "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz", + "integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==", "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "^1.0.0" } }, "xml": { diff --git a/package.json b/package.json index f721a7b876..59dcb86f07 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "killable": "^1.0.1", "loglevel": "^1.6.4", "open": "^6.2.0", - "p-retry": "^3.0.1", + "p-retry": "^4.1.0", "portfinder": "^1.0.24", "schema-utils": "^1.0.0", "selfsigned": "^1.10.6", @@ -67,7 +67,7 @@ "url": "^0.11.0", "webpack-dev-middleware": "^3.7.1", "webpack-log": "^2.0.0", - "ws": "^6.2.1", + "ws": "^7.1.1", "yargs": "12.0.5" }, "devDependencies": { @@ -111,8 +111,7 @@ "typescript": "^3.6.2", "url-loader": "^1.1.2", "webpack": "^4.39.3", - "webpack-cli": "^3.3.8", - "ws": "^7.0.0" + "webpack-cli": "^3.3.8" }, "peerDependencies": { "webpack": "^4.0.0" From 50b99b62104b4f8093d1f18e4ff5d46653b1c6f0 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Sat, 15 Jun 2019 14:09:42 +0100 Subject: [PATCH 12/32] fix(options): delete none and warning from optinos.json --- lib/options.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/options.json b/lib/options.json index 71fe65f929..f1b6556f4f 100644 --- a/lib/options.json +++ b/lib/options.json @@ -399,7 +399,7 @@ "bonjour": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverbonjour)", "ca": "should be {String|Buffer}", "cert": "should be {String|Buffer}", - "clientLogLevel": "should be {String} and equal to one of the allowed values\n\n [ 'none', 'silent', 'info', 'debug', 'trace', 'error', 'warning', 'warn' ]\n\n (https://webpack.js.org/configuration/dev-server/#devserverclientloglevel)", + "clientLogLevel": "should be {String} and equal to one of the allowed values\n\n [ 'silent', 'info', 'debug', 'trace', 'error', 'warn' ]\n\n (https://webpack.js.org/configuration/dev-server/#devserverclientloglevel)", "compress": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devservercompress)", "contentBase": "should be {Number|String|Array} (https://webpack.js.org/configuration/dev-server/#devservercontentbase)", "disableHostCheck": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverdisablehostcheck)", From 5c0dcedf38f28b79f3970e7485b9f7a5bb2ef535 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Mon, 5 Aug 2019 18:39:34 +0100 Subject: [PATCH 13/32] chore(deps): update url-loader to 2.1.0 --- package-lock.json | 46 +++++++++++++++++++++++++++++++++++++--------- package.json | 2 +- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index e65e270b5d..d7c9270a1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13871,21 +13871,49 @@ } }, "url-loader": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", - "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.1.0.tgz", + "integrity": "sha512-kVrp/8VfEm5fUt+fl2E0FQyrpmOYgMEkBsv8+UDP1wFhszECq5JyGF33I7cajlVY90zRZ6MyfgKXngLvHYZX8A==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "mime": "^2.0.3", - "schema-utils": "^1.0.0" + "loader-utils": "^1.2.3", + "mime": "^2.4.4", + "schema-utils": "^2.0.0" }, "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, "mime": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", - "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true + }, + "schema-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.2.0.tgz", + "integrity": "sha512-5EwsCNhfFTZvUreQhx/4vVQpJ/lnCAkgoIHLhSpp4ZirE+4hzFvdJi0FMub6hxbFVBJYSpeVVmon+2e7uEGRrA==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } } } }, diff --git a/package.json b/package.json index 59dcb86f07..0d17abcc71 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "supertest": "^4.0.2", "tcp-port-used": "^1.0.1", "typescript": "^3.6.2", - "url-loader": "^1.1.2", + "url-loader": "^2.1.0", "webpack": "^4.39.3", "webpack-cli": "^3.3.8" }, From 167979703b552cefe3dd574cffabc45aed84c5e2 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Mon, 5 Aug 2019 18:39:49 +0100 Subject: [PATCH 14/32] test: update syntax --- test/cli/cli.test.js | 8 +-- test/client/socket-helper.test.js | 4 +- test/e2e/ClientOptions.test.js | 86 ++++++++++-------------- test/options.test.js | 2 +- test/server/servers/SockJSServer.test.js | 3 +- test/server/utils/runOpen.test.js | 20 +++--- 6 files changed, 54 insertions(+), 69 deletions(-) diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index e4106217b2..60618eb544 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -25,9 +25,7 @@ describe('CLI', () => { const { code, stderr } = await testBin('--progress --profile'); expect(code).toEqual(0); // should profile - expect(output.stderr.includes('after chunk modules optimization')).toBe( - true - ); + expect(stderr.includes('after chunk modules optimization')).toBe(true); }); it('--bonjour', async () => { @@ -58,8 +56,8 @@ describe('CLI', () => { }); it('unspecified port', async () => { - const { output } = await testBin(''); - expect(/http:\/\/localhost:[0-9]+/.test(output.stdout)).toEqual(true); + const { stdout } = await testBin(''); + expect(/http:\/\/localhost:[0-9]+/.test(stdout)).toEqual(true); }); it('--color', async () => { diff --git a/test/client/socket-helper.test.js b/test/client/socket-helper.test.js index a40007aa49..b8074cebd5 100644 --- a/test/client/socket-helper.test.js +++ b/test/client/socket-helper.test.js @@ -8,7 +8,7 @@ describe('socket', () => { it('should default to SockJSClient when no __webpack_dev_server_client__ set', () => { jest.mock('../../client/clients/SockJSClient'); - const socket = require('../../client/socket'); + const { default: socket } = require('../../client/socket'); const SockJSClient = require('../../client/clients/SockJSClient'); const mockHandler = jest.fn(); @@ -36,7 +36,7 @@ describe('socket', () => { it('should use __webpack_dev_server_client__ when set', () => { jest.mock('../../client/clients/SockJSClient'); - const socket = require('../../client/socket'); + const { default: socket } = require('../../client/socket'); global.__webpack_dev_server_client__ = require('../../client/clients/SockJSClient'); const mockHandler = jest.fn(); diff --git a/test/e2e/ClientOptions.test.js b/test/e2e/ClientOptions.test.js index c1cd2fffe9..1d7f4aa6e8 100644 --- a/test/e2e/ClientOptions.test.js +++ b/test/e2e/ClientOptions.test.js @@ -50,19 +50,18 @@ describe('Client code', () => { }); afterAll((done) => { - proxy.close(() => { - done(); - }); - }); - - it('responds with a 200 on proxy port', (done) => { - const req = request(`http://localhost:${port2}`); - req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n', done); + proxy.close(done); }); - it('responds with a 200 on non-proxy port', (done) => { - const req = request(`http://localhost:${port1}`); - req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n', done); + it('responds with a 200', async () => { + { + const req = request(`http://localhost:${port2}`); + await req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n'); + } + { + const req = request(`http://localhost:${port1}`); + await req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n'); + } }); it('requests websocket through the proxy with proper port number', (done) => { @@ -296,47 +295,34 @@ describe('Client console.log', () => { }, ]; - cases.forEach(({ title, options }) => { - it(title, (done) => { + for (const { title, options } of cases) { + it(title, async () => { const res = []; const testOptions = Object.assign({}, baseOptions, options); - // TODO: use async/await when Node.js v6 support is dropped - Promise.resolve() - .then(() => { - return new Promise((resolve) => { - testServer.startAwaitingCompilation(config, testOptions, resolve); - }); - }) - .then(() => { - // make sure the previous Promise is not passing along strange arguments to runBrowser - return runBrowser(); - }) - .then(({ page, browser }) => { - return new Promise((resolve) => { - page.goto(`http://localhost:${port2}/main`); - page.on('console', ({ _text }) => { - res.push(_text); - }); - // wait for load before closing the browser - page.waitForNavigation({ waitUntil: 'load' }).then(() => { - page.waitFor(beforeBrowserCloseDelay).then(() => { - browser.close().then(() => { - resolve(); - }); - }); - }); - }); - }) - .then(() => { - return new Promise((resolve) => { - testServer.close(resolve); - }); - }) - .then(() => { - expect(res).toMatchSnapshot(); - done(); - }); + // TODO: refactor(hiroppy) + await new Promise((resolve) => { + testServer.startAwaitingCompilation(config, testOptions, resolve); + }); + + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port2}/main`); + page.on('console', ({ _text }) => { + res.push(_text); + }); + + // wait for load before closing the browser + await page.waitForNavigation({ waitUntil: 'load' }); + await page.waitFor(beforeBrowserCloseDelay); + await browser.close(); + + expect(res).toMatchSnapshot(); + + // TODO: refactor(hiroppy) + await new Promise((resolve) => { + testServer.close(resolve); + }); }); - }); + } }); diff --git a/test/options.test.js b/test/options.test.js index 66d7703356..8044c49bf7 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -26,7 +26,7 @@ describe('options', () => { const properties = Object.keys(options.properties); const messages = Object.keys(options.errorMessage.properties); - expect(properties.length).toEqual(messages.length); + expect(properties).toEqual(messages); const res = properties.every((name) => messages.includes(name)); diff --git a/test/server/servers/SockJSServer.test.js b/test/server/servers/SockJSServer.test.js index f78610806f..14aaf04d73 100644 --- a/test/server/servers/SockJSServer.test.js +++ b/test/server/servers/SockJSServer.test.js @@ -37,7 +37,8 @@ describe('SockJSServer', () => { const data = []; let headers; - socketServer.onConnection(async (connection) => { + socketServer.onConnection(async (connection, h) => { + headers = h; data.push('open'); socketServer.send(connection, 'hello world'); diff --git a/test/server/utils/runOpen.test.js b/test/server/utils/runOpen.test.js index 0c37e488b0..1ae6b092d1 100644 --- a/test/server/utils/runOpen.test.js +++ b/test/server/utils/runOpen.test.js @@ -78,13 +78,14 @@ describe('runOpen util', () => { }); }); - it('on specify absolute https URL with page in Google Chrome ', () => { - return runOpen( + it('on specify absolute https URL with page in Google Chrome ', async () => { + await runOpen( 'https://example.com', { open: 'Google Chrome', openPage: 'https://example2.com' }, console - ).then(() => { - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + ); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example2.com", Object { @@ -93,16 +94,16 @@ describe('runOpen util', () => { }, ] `); - }); }); - it('on specify absolute http URL with page in Google Chrome ', () => { - return runOpen( + it('on specify absolute http URL with page in Google Chrome ', async () => { + runOpen( 'https://example.com', { open: 'Google Chrome', openPage: 'http://example2.com' }, console - ).then(() => { - expect(open.mock.calls[0]).toMatchInlineSnapshot(` + ); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "http://example2.com", Object { @@ -111,7 +112,6 @@ describe('runOpen util', () => { }, ] `); - }); }); describe('should not open browser', () => { From c600b0eefea5d6fe6a66881937c04cd8bdb38fa2 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Mon, 5 Aug 2019 19:04:22 +0100 Subject: [PATCH 15/32] refactor(server): remove some variables of options (#2175) --- lib/Server.js | 61 +++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 809b214f24..cc2d9488cf 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -83,21 +83,7 @@ class Server { this.sockets = []; this.contentBaseWatchers = []; - - // TODO this. is deprecated (remove them in next major release.) in favor this.options. this.hot = this.options.hot || this.options.hotOnly; - this.headers = this.options.headers; - this.progress = this.options.progress; - - this.serveIndex = this.options.serveIndex; - - this.clientOverlay = this.options.overlay; - this.clientLogLevel = this.options.clientLogLevel; - - this.publicHost = this.options.public; - this.allowedHosts = this.options.allowedHosts; - this.disableHostCheck = !!this.options.disableHostCheck; - this.watchOptions = options.watchOptions || {}; // Replace leading and trailing slashes to normalize path @@ -107,7 +93,7 @@ class Server { : 'sockjs-node' }`; - if (this.progress) { + if (this.options.progress) { this.setupProgressPlugin(); } @@ -530,9 +516,10 @@ class Server { } // checking if it's set to true or not set (Default : undefined => true) - this.serveIndex = this.serveIndex || this.serveIndex === undefined; + this.options.serveIndex = + this.options.serveIndex || this.options.serveIndex === undefined; - if (this.options.contentBase && this.serveIndex) { + if (this.options.contentBase && this.options.serveIndex) { runnableFeatures.push('contentBaseIndex'); } @@ -689,8 +676,8 @@ class Server { } }); - if (this.clientLogLevel) { - this.sockWrite([connection], 'log-level', this.clientLogLevel); + if (this.options.clientLogLevel) { + this.sockWrite([connection], 'log-level', this.options.clientLogLevel); } if (this.hot) { @@ -702,12 +689,12 @@ class Server { this.sockWrite([connection], 'liveReload', this.options.liveReload); } - if (this.progress) { - this.sockWrite([connection], 'progress', this.progress); + if (this.options.progress) { + this.sockWrite([connection], 'progress', this.options.progress); } - if (this.clientOverlay) { - this.sockWrite([connection], 'overlay', this.clientOverlay); + if (this.options.overlay) { + this.sockWrite([connection], 'overlay', this.options.overlay); } if (!this._stats) { @@ -800,10 +787,10 @@ class Server { } setContentHeaders(req, res, next) { - if (this.headers) { + if (this.options.headers) { // eslint-disable-next-line - for (const name in this.headers) { - res.setHeader(name, this.headers[name]); + for (const name in this.options.headers) { + res.setHeader(name, this.options.headers[name]); } } @@ -819,8 +806,10 @@ class Server { } checkHeaders(headers, headerToCheck) { + const optionsDisableHostCheck = !!this.options.disableHostCheck; + // allow user to opt-out this security check, at own risk - if (this.disableHostCheck) { + if (optionsDisableHostCheck) { return true; } @@ -862,9 +851,13 @@ class Server { } // always allow localhost host, for convenience // allow if hostname is in allowedHosts - if (this.allowedHosts && this.allowedHosts.length) { - for (let hostIdx = 0; hostIdx < this.allowedHosts.length; hostIdx++) { - const allowedHost = this.allowedHosts[hostIdx]; + if (this.options.allowedHosts && this.options.allowedHosts.length) { + for ( + let hostIdx = 0; + hostIdx < this.options.allowedHosts.length; + hostIdx++ + ) { + const allowedHost = this.options.allowedHosts[hostIdx]; if (allowedHost === hostname) { return true; @@ -886,10 +879,12 @@ class Server { } // also allow public hostname if provided - if (typeof this.publicHost === 'string') { - const idxPublic = this.publicHost.indexOf(':'); + if (typeof this.options.public === 'string') { + const idxPublic = this.options.public.indexOf(':'); const publicHostname = - idxPublic >= 0 ? this.publicHost.substr(0, idxPublic) : this.publicHost; + idxPublic >= 0 + ? this.options.public.substr(0, idxPublic) + : this.options.public; if (hostname === publicHostname) { return true; From 27b1913efea1b9694e85f16594f20deab3b41045 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Tue, 6 Aug 2019 10:24:18 +0100 Subject: [PATCH 16/32] chore(deps): update del, supports-color, import-local and execa (#2178) --- package-lock.json | 853 ++++++++++++++++++++++++++++++------------- package.json | 8 +- test/cli/cli.test.js | 39 +- 3 files changed, 624 insertions(+), 276 deletions(-) diff --git a/package-lock.json b/package-lock.json index d7c9270a1f..7f143226c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1460,6 +1460,66 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, "jest-get-type": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", @@ -1486,6 +1546,21 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, "pretty-format": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", @@ -1795,7 +1870,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz", "integrity": "sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.1", "run-parallel": "^1.1.9" @@ -1804,14 +1878,12 @@ "@nodelib/fs.stat": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz", - "integrity": "sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw==", - "dev": true + "integrity": "sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw==" }, "@nodelib/fs.walk": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz", "integrity": "sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.1", "fastq": "^1.6.0" @@ -2378,6 +2450,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, "requires": { "array-uniq": "^1.0.1" } @@ -2385,7 +2458,8 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true }, "array-unique": { "version": "0.3.2", @@ -3426,6 +3500,47 @@ "dev": true, "requires": { "execa": "^1.0.0" + }, + "dependencies": { + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + } } }, "commondir": { @@ -4498,6 +4613,43 @@ "requires": { "execa": "^1.0.0", "ip-regex": "^2.1.0" + }, + "dependencies": { + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + } } }, "define-properties": { @@ -4547,16 +4699,14 @@ } }, "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-5.0.0.tgz", + "integrity": "sha512-TfU3nUY0WDIhN18eq+pgpbLY9AfL5RfiE9czKaTSolc6aK7qASXfDErvYgjV1UqCR4sNXDoxO0/idPmhDUt2Sg==", "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", + "globby": "^10.0.0", "is-path-cwd": "^2.0.0", "is-path-in-cwd": "^2.0.0", "p-map": "^2.0.0", - "pify": "^4.0.1", "rimraf": "^2.6.3" }, "dependencies": { @@ -5411,17 +5561,43 @@ "dev": true }, "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-2.0.3.tgz", + "integrity": "sha512-iM124nlyGSrXmuyZF1EMe83ESY2chIYVyDRZKgmcDynid2Q2v/+GuE7gNMl6Sy9Niwf4MC0DDxagOxeMPjuLsw==", + "dev": true, "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "cross-spawn": "^6.0.5", + "get-stream": "^5.0.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^3.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + } } }, "exit": { @@ -5712,7 +5888,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.0.4.tgz", "integrity": "sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg==", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.1", "@nodelib/fs.walk": "^1.2.1", @@ -5726,7 +5901,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -5735,7 +5909,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -5744,7 +5917,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -5752,14 +5924,12 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "micromatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.0.5" @@ -5769,7 +5939,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -5797,7 +5966,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", - "dev": true, "requires": { "reusify": "^1.0.0" } @@ -6860,9 +7028,10 @@ "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, "requires": { "pump": "^3.0.0" } @@ -7066,21 +7235,47 @@ "dev": true }, "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" }, "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "ignore": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.2.tgz", + "integrity": "sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" } } }, @@ -7158,7 +7353,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "has-symbols": { "version": "1.0.0", @@ -7482,6 +7678,21 @@ "slash": "^3.0.0" }, "dependencies": { + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7492,6 +7703,15 @@ "path-exists": "^4.0.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -7501,6 +7721,21 @@ "p-locate": "^4.1.0" } }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -7624,12 +7859,52 @@ } }, "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + } } }, "imurmurhash": { @@ -8102,6 +8377,17 @@ "istanbul-lib-coverage": "^2.0.5", "make-dir": "^2.1.0", "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "istanbul-lib-source-maps": { @@ -8153,26 +8439,6 @@ "jest-cli": "^24.9.0" }, "dependencies": { - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@types/yargs": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.2.tgz", - "integrity": "sha512-lwwgizwk/bIIU+3ELORkyuOgDjCh7zuWDFqRtPPhhVgq9N1F7CvLNKg1TX4f2duwtKQ0p044Au9r1PLIXHrIzQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -8196,6 +8462,16 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, "jest-cli": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", @@ -8217,42 +8493,29 @@ "yargs": "^13.3.0" } }, - "jest-get-type": { + "jest-config": { "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", "dev": true, "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", + "babel-jest": "^24.9.0", "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" } }, "require-main-filename": { @@ -8261,6 +8524,15 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -8322,130 +8594,6 @@ } } }, - "jest-changed-files": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", - "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "execa": "^1.0.0", - "throat": "^4.0.0" - }, - "dependencies": { - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@types/yargs": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.2.tgz", - "integrity": "sha512-lwwgizwk/bIIU+3ELORkyuOgDjCh7zuWDFqRtPPhhVgq9N1F7CvLNKg1TX4f2duwtKQ0p044Au9r1PLIXHrIzQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - } - } - }, - "jest-config": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", - "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^24.9.0", - "@jest/types": "^24.9.0", - "babel-jest": "^24.9.0", - "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^24.9.0", - "jest-environment-node": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "micromatch": "^3.1.10", - "pretty-format": "^24.9.0", - "realpath-native": "^1.1.0" - }, - "dependencies": { - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@types/yargs": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.2.tgz", - "integrity": "sha512-lwwgizwk/bIIU+3ELORkyuOgDjCh7zuWDFqRtPPhhVgq9N1F7CvLNKg1TX4f2duwtKQ0p044Au9r1PLIXHrIzQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - } - } - } - }, "jest-diff": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", @@ -9093,6 +9241,31 @@ "requires": { "@types/yargs-parser": "*" } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } } } }, @@ -9170,6 +9343,31 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, "jest-get-type": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", @@ -9455,6 +9653,17 @@ "requires": { "merge-stream": "^2.0.0", "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "jquery": { @@ -10384,10 +10593,9 @@ "dev": true }, "merge2": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.4.tgz", - "integrity": "sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A==", - "dev": true + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", + "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==" }, "methods": { "version": "1.1.2", @@ -10775,11 +10983,20 @@ } }, "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", + "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", + "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "^3.0.0" + }, + "dependencies": { + "path-key": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz", + "integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==", + "dev": true + } } }, "nth-check": { @@ -10817,7 +11034,8 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-copy": { "version": "0.1.0", @@ -11014,6 +11232,43 @@ "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" + }, + "dependencies": { + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + } } }, "os-tmpdir": { @@ -11048,9 +11303,10 @@ } }, "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true }, "p-is-promise": { "version": "2.1.0", @@ -11284,17 +11540,20 @@ "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, "requires": { "pinkie": "^2.0.0" } @@ -11312,6 +11571,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, "requires": { "find-up": "^3.0.0" } @@ -11372,6 +11632,15 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -12079,11 +12348,18 @@ } }, "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "requires": { - "resolve-from": "^3.0.0" + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } } }, "resolve-dir": { @@ -12112,7 +12388,8 @@ "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true }, "resolve-global": { "version": "1.0.0", @@ -12151,8 +12428,7 @@ "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "rimraf": { "version": "3.0.0", @@ -12197,8 +12473,7 @@ "run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, "run-queue": { "version": "1.0.3", @@ -12253,11 +12528,50 @@ "walker": "~1.0.5" }, "dependencies": { + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true } } }, @@ -13299,11 +13613,18 @@ } }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.0.0.tgz", + "integrity": "sha512-WRt32iTpYEZWYOpcetGm0NPeSvaebccx7hhS/5M6sAiqnhedtFCHFxkjzZlJvFNCPowiKSFGiZk5USQDFy83vQ==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + } } }, "symbol-observable": { @@ -14209,12 +14530,31 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -14235,6 +14575,15 @@ "ansi-regex": "^4.1.0" } }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, "v8-compile-cache": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", diff --git a/package.json b/package.json index 0d17abcc71..ea094b14c3 100644 --- a/package.json +++ b/package.json @@ -42,11 +42,11 @@ "compression": "^1.7.4", "connect-history-api-fallback": "^1.6.0", "debug": "^4.1.1", - "del": "^4.1.1", + "del": "^5.0.0", "express": "^4.17.1", "html-entities": "^1.2.1", "http-proxy-middleware": "^0.19.1", - "import-local": "^2.0.0", + "import-local": "^3.0.2", "internal-ip": "^4.3.0", "ip": "^1.1.5", "is-absolute-url": "^3.0.1", @@ -63,7 +63,7 @@ "sockjs-client": "1.4.0", "spdy": "^4.0.1", "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", + "supports-color": "^7.0.0", "url": "^0.11.0", "webpack-dev-middleware": "^3.7.1", "webpack-log": "^2.0.0", @@ -87,7 +87,7 @@ "eslint-config-prettier": "^6.1.0", "eslint-config-webpack": "^1.2.5", "eslint-plugin-import": "^2.18.2", - "execa": "^1.0.0", + "execa": "^2.0.3", "file-loader": "^4.0.0", "html-loader": "^0.5.5", "html-webpack-plugin": "^3.2.0", diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index 60618eb544..4a47075952 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -1,3 +1,7 @@ +/** + * @jest-environment node + */ + 'use strict'; const { join, resolve } = require('path'); @@ -16,35 +20,35 @@ const certPath = resolve(httpsCertificateDirectory, 'server.crt'); describe('CLI', () => { it('--progress', async () => { - const { code, stderr } = await testBin('--progress'); - expect(code).toEqual(0); + const { exitCode, stderr } = await testBin('--progress'); + expect(exitCode).toEqual(0); expect(stderr.includes('0% compiling')).toBe(true); }); it('--progress --profile', async () => { - const { code, stderr } = await testBin('--progress --profile'); - expect(code).toEqual(0); + const { exitCode, stderr } = await testBin('--progress --profile'); + expect(exitCode).toEqual(0); // should profile expect(stderr.includes('after chunk modules optimization')).toBe(true); }); it('--bonjour', async () => { - const { code, stdout } = await testBin('--bonjour'); - expect(code).toEqual(0); + const { exitCode, stdout } = await testBin('--bonjour'); + expect(exitCode).toEqual(0); expect(stdout.includes('Bonjour')).toBe(true); }); it('--https', async () => { - const { code, stdout } = await testBin('--https'); - expect(code).toEqual(0); + const { exitCode, stdout } = await testBin('--https'); + expect(exitCode).toEqual(0); expect(stdout.includes('Project is running at')).toBe(true); }); it('--https --cacert --pfx --key --cert --pfx-passphrase', async () => { - const { code, stdout } = await testBin( + const { exitCode, stdout } = await testBin( `--https --cacert ${caPath} --pfx ${pfxPath} --key ${keyPath} --cert ${certPath} --pfx-passphrase webpack-dev-server` ); - expect(code).toEqual(0); + expect(exitCode).toEqual(0); expect(stdout.includes('Project is running at')).toBe(true); }); @@ -69,8 +73,8 @@ describe('CLI', () => { // The Unix socket to listen to (instead of a host). it('--socket', async () => { const socketPath = join('.', 'webpack.sock'); - const { code, stdout } = await testBin(`--socket ${socketPath}`); - expect(code).toEqual(0); + const { exitCode, stdout } = await testBin(`--socket ${socketPath}`); + expect(exitCode).toEqual(0); if (process.platform !== 'win32') { expect(stdout.includes(socketPath)).toBe(true); @@ -81,18 +85,13 @@ describe('CLI', () => { it('should accept the promise function of webpack.config.js', async () => { try { - const { code } = await testBin( + const { exitCode } = await testBin( false, resolve(__dirname, '../fixtures/promise-config/webpack.config.js') ); - expect(code).toEqual(0); + expect(exitCode).toEqual(0); } catch (err) { - // for windows - if (process.platform === 'win32') { - expect(err.stdout.includes('Compiled successfully.')).toBe(true); - } else { - throw err; - } + expect(err.stdout.includes('Compiled successfully.')).toBe(true); } }); From e819cfe3dea79464fae48b9449522679918097b9 Mon Sep 17 00:00:00 2001 From: Loonride Date: Sat, 10 Aug 2019 13:35:24 -0500 Subject: [PATCH 17/32] feat(server): add stdin option to API (#2186) * feat(server): add stdin for api * test(stdin): switch to async await tests for stdin * test(cli): use await timer --- lib/Server.js | 3 ++ lib/options.json | 4 ++ lib/utils/createConfig.js | 7 +-- lib/utils/handleStdin.js | 16 +++++++ test/cli/cli.test.js | 42 ++++++++++++++++++ test/helpers/test-bin.js | 19 ++++++-- test/options.test.js | 4 ++ test/ports-map.js | 1 + test/server/stdin-option.test.js | 62 +++++++++++++++++++++++++++ test/server/utils/handleStdin.test.js | 41 ++++++++++++++++++ 10 files changed, 190 insertions(+), 9 deletions(-) create mode 100644 lib/utils/handleStdin.js create mode 100644 test/server/stdin-option.test.js create mode 100644 test/server/utils/handleStdin.test.js diff --git a/lib/Server.js b/lib/Server.js index cc2d9488cf..f260e75919 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -33,6 +33,7 @@ const createDomain = require('./utils/createDomain'); const runBonjour = require('./utils/runBonjour'); const routes = require('./utils/routes'); const getSocketServerImplementation = require('./utils/getSocketServerImplementation'); +const handleStdin = require('./utils/handleStdin'); const schema = require('./options.json'); // Workaround for node ^8.6.0, ^9.0.0 @@ -69,6 +70,8 @@ class Server { normalizeOptions(this.compiler, this.options); + handleStdin(this.options); + updateCompiler(this.compiler, this.options); // this.SocketServerImplementation is a class, so it must be instantiated before use diff --git a/lib/options.json b/lib/options.json index f1b6556f4f..87319af51c 100644 --- a/lib/options.json +++ b/lib/options.json @@ -368,6 +368,9 @@ } ] }, + "stdin": { + "type": "boolean" + }, "useLocalIp": { "type": "boolean" }, @@ -450,6 +453,7 @@ "staticOptions": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devserverstaticoptions)", "stats": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverstats-)", "transportMode": "should be {String|Object} (https://webpack.js.org/configuration/dev-server/#devservertransportmode)", + "stdin": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverstdin)", "useLocalIp": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserveruselocalip)", "warn": "should be {Function}", "watchContentBase": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverwatchcontentbase)", diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index 0211561235..d5a3e1db99 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -81,12 +81,7 @@ function createConfig(config, argv, { port }) { } if (argv.stdin) { - process.stdin.on('end', () => { - // eslint-disable-next-line no-process-exit - process.exit(0); - }); - - process.stdin.resume(); + options.stdin = true; } // TODO https://github.com/webpack/webpack-dev-server/issues/616 (v4) diff --git a/lib/utils/handleStdin.js b/lib/utils/handleStdin.js new file mode 100644 index 0000000000..c26431300c --- /dev/null +++ b/lib/utils/handleStdin.js @@ -0,0 +1,16 @@ +'use strict'; + +function handleStdin(options) { + if (options.stdin) { + // listening for this event only once makes testing easier, + // since it prevents event listeners from hanging open + process.stdin.once('end', () => { + // eslint-disable-next-line no-process-exit + process.exit(0); + }); + + process.stdin.resume(); + } +} + +module.exports = handleStdin; diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index 4a47075952..c29bad439f 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -8,6 +8,7 @@ const { join, resolve } = require('path'); const execa = require('execa'); const { unlinkAsync } = require('../helpers/fs'); const testBin = require('../helpers/test-bin'); +const timer = require('../helpers/timer'); const httpsCertificateDirectory = resolve( __dirname, @@ -83,6 +84,47 @@ describe('CLI', () => { } }); + it('without --stdin, with stdin "end" event should time out', async (done) => { + const configPath = resolve( + __dirname, + '../fixtures/simple-config/webpack.config.js' + ); + const childProcess = testBin(false, configPath, true); + + childProcess.once('exit', () => { + expect(childProcess.killed).toBeTruthy(); + done(); + }); + + await timer(500); + // this is meant to confirm that it does not have any effect on the running process + // since options.stdin is not enabled + childProcess.stdin.emit('end'); + childProcess.stdin.pause(); + + await timer(500); + + childProcess.kill(); + }); + + it('--stdin, with "end" event should exit without time out', async () => { + const configPath = resolve( + __dirname, + '../fixtures/simple-config/webpack.config.js' + ); + const childProcess = testBin('--stdin', configPath); + + await timer(500); + + childProcess.stdin.emit('end'); + childProcess.stdin.pause(); + + const { exitCode, timedOut, killed } = await childProcess; + expect(exitCode).toEqual(0); + expect(timedOut).toBeFalsy(); + expect(killed).toBeFalsy(); + }); + it('should accept the promise function of webpack.config.js', async () => { try { const { exitCode } = await testBin( diff --git a/test/helpers/test-bin.js b/test/helpers/test-bin.js index 25e3af020a..39f38f0b16 100644 --- a/test/helpers/test-bin.js +++ b/test/helpers/test-bin.js @@ -1,6 +1,7 @@ 'use strict'; const path = require('path'); +const { spawn } = require('child_process'); const execa = require('execa'); const webpackDevServerPath = path.resolve( @@ -12,9 +13,12 @@ const basicConfigPath = path.resolve( '../fixtures/cli/webpack.config.js' ); -function testBin(testArgs, configPath) { +function testBin(testArgs, configPath, useSpawn) { const cwd = process.cwd(); - const env = process.env.NODE_ENV; + const env = { + NODE_ENV: process.env.NODE_ENV, + PATH: process.env.PATH, + }; if (!configPath) { configPath = basicConfigPath; @@ -28,7 +32,16 @@ function testBin(testArgs, configPath) { const args = [webpackDevServerPath, '--config', configPath].concat(testArgs); - return execa('node', args, { cwd, env, timeout: 10000 }); + const opts = { cwd, env, timeout: 10000 }; + let execLib = execa; + // use Node's spawn as a workaround for execa issues + // https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options + if (useSpawn) { + execLib = spawn; + delete opts.timeout; + } + + return execLib('node', args, opts); } module.exports = testBin; diff --git a/test/options.test.js b/test/options.test.js index 8044c49bf7..8f41f4b65f 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -375,6 +375,10 @@ describe('options', () => { }, ], }, + stdin: { + success: [false], + failure: [''], + }, useLocalIp: { success: [false], failure: [''], diff --git a/test/ports-map.js b/test/ports-map.js index 81133db921..07ebee36a0 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -43,6 +43,7 @@ const portsList = { 'progress-option': 1, 'profile-option': 1, Iframe: 1, + 'stdin-option': 1, }; let startPort = 8089; diff --git a/test/server/stdin-option.test.js b/test/server/stdin-option.test.js new file mode 100644 index 0000000000..da742ffff8 --- /dev/null +++ b/test/server/stdin-option.test.js @@ -0,0 +1,62 @@ +'use strict'; + +const config = require('../fixtures/simple-config/webpack.config'); +const testServer = require('../helpers/test-server'); +const timer = require('../helpers/timer'); +const port = require('../ports-map')['stdin-option']; + +describe('stdin', () => { + // eslint-disable-next-line no-unused-vars + let server; + let exitSpy; + + beforeAll(() => { + exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {}); + }); + + afterEach((done) => { + server = null; + exitSpy.mockReset(); + process.stdin.removeAllListeners('end'); + testServer.close(done); + }); + + describe('enabled', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + port, + stdin: true, + }, + done + ); + }); + + it('should exit process', async () => { + process.stdin.emit('end'); + await timer(1000); + process.stdin.pause(); + expect(exitSpy.mock.calls[0]).toEqual([0]); + }); + }); + + describe('disabled (default)', () => { + beforeAll((done) => { + server = testServer.start( + config, + { + port, + }, + done + ); + }); + + it('should not exit process', async () => { + process.stdin.emit('end'); + await timer(1000); + process.stdin.pause(); + expect(exitSpy.mock.calls.length).toEqual(0); + }); + }); +}); diff --git a/test/server/utils/handleStdin.test.js b/test/server/utils/handleStdin.test.js new file mode 100644 index 0000000000..5d44e0dc06 --- /dev/null +++ b/test/server/utils/handleStdin.test.js @@ -0,0 +1,41 @@ +'use strict'; + +const timer = require('../../helpers/timer'); +const handleStdin = require('../../../lib/utils/handleStdin'); + +describe('handleStdin', () => { + let exitSpy; + + beforeAll(() => { + exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {}); + }); + + afterEach(() => { + process.stdin.removeAllListeners('end'); + exitSpy.mockReset(); + }); + + describe('enabled', () => { + it('should exit process', async () => { + handleStdin({ + stdin: true, + }); + process.stdin.emit('end'); + + await timer(1000); + process.stdin.pause(); + expect(exitSpy.mock.calls[0]).toEqual([0]); + }); + }); + + describe('disabled (default)', () => { + it('should not exit process', async () => { + handleStdin({}); + process.stdin.emit('end'); + + await timer(1000); + process.stdin.pause(); + expect(exitSpy.mock.calls.length).toEqual(0); + }); + }); +}); From 64036a0f501cc3e6667fddb01a0108a2d56fc929 Mon Sep 17 00:00:00 2001 From: Loonride Date: Thu, 22 Aug 2019 05:49:47 -0500 Subject: [PATCH 18/32] refactor(server): move socket handling into server.listen (#2061) --- bin/webpack-dev-server.js | 34 ----- lib/Server.js | 39 +++++- lib/utils/startUnixSocket.js | 62 +++++++++ test/cli/cli.test.js | 26 ++-- test/helpers/test-server.js | 22 +++- test/helpers/test-unix-socket.js | 30 +++++ test/server/onListening-option.test.js | 77 ++++++++--- test/server/socket-option.test.js | 149 ++++++++++++++++++++++ test/server/utils/startUnixSocket.test.js | 124 ++++++++++++++++++ 9 files changed, 493 insertions(+), 70 deletions(-) create mode 100644 lib/utils/startUnixSocket.js create mode 100644 test/helpers/test-unix-socket.js create mode 100644 test/server/socket-option.test.js create mode 100644 test/server/utils/startUnixSocket.test.js diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index 286cad93b9..224a69d978 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -4,8 +4,6 @@ /* eslint-disable no-shadow, no-console */ -const fs = require('fs'); -const net = require('net'); const debug = require('debug')('webpack-dev-server'); const importLocal = require('import-local'); const yargs = require('yargs'); @@ -116,42 +114,10 @@ function startDevServer(config, options) { } if (options.socket) { - server.listeningApp.on('error', (e) => { - if (e.code === 'EADDRINUSE') { - const clientSocket = new net.Socket(); - - clientSocket.on('error', (err) => { - if (err.code === 'ECONNREFUSED') { - // No other server listening on this socket so it can be safely removed - fs.unlinkSync(options.socket); - - server.listen(options.socket, options.host, (error) => { - if (error) { - throw error; - } - }); - } - }); - - clientSocket.connect({ path: options.socket }, () => { - throw new Error('This socket is already used'); - }); - } - }); - server.listen(options.socket, options.host, (err) => { if (err) { throw err; } - - // chmod 666 (rw rw rw) - const READ_WRITE = 438; - - fs.chmod(options.socket, READ_WRITE, (err) => { - if (err) { - throw err; - } - }); }); } else { server.listen(options.port, options.host, (err) => { diff --git a/lib/Server.js b/lib/Server.js index f260e75919..1a8f83ea60 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -34,6 +34,8 @@ const runBonjour = require('./utils/runBonjour'); const routes = require('./utils/routes'); const getSocketServerImplementation = require('./utils/getSocketServerImplementation'); const handleStdin = require('./utils/handleStdin'); +const tryParseInt = require('./utils/tryParseInt'); +const startUnixSocket = require('./utils/startUnixSocket'); const schema = require('./options.json'); // Workaround for node ^8.6.0, ^9.0.0 @@ -726,7 +728,7 @@ class Server { listen(port, hostname, fn) { this.hostname = hostname; - return this.listeningApp.listen(port, hostname, (err) => { + const setupCallback = () => { this.createSocketServer(); if (this.options.bonjour) { @@ -734,15 +736,46 @@ class Server { } this.showStatus(); + }; - if (fn) { + // between setupCallback and userCallback should be any other needed handling, + // specifically so that things are done in the right order to prevent + // backwards compatability issues + let userCallbackCalled = false; + const userCallback = (err) => { + if (fn && !userCallbackCalled) { + userCallbackCalled = true; fn.call(this.listeningApp, err); } + }; + const onListeningCallback = () => { if (typeof this.options.onListening === 'function') { this.options.onListening(this); } - }); + }; + + const fullCallback = (err) => { + setupCallback(); + userCallback(err); + onListeningCallback(); + }; + + // try to follow the Node standard in terms of deciding + // whether this is a socket or a port that we will listen on: + // https://github.com/nodejs/node/blob/64219741218aa87e259cf8257596073b8e747f0a/lib/net.js#L196 + if (typeof port === 'string' && tryParseInt(port) === null) { + // in this case the "port" argument is actually a socket path + const socket = port; + // set this so that status helper can identify how the project is being run correctly + this.options.socket = socket; + + startUnixSocket(this.listeningApp, socket, fullCallback); + } else { + this.listeningApp.listen(port, hostname, fullCallback); + } + + return this.listeningApp; } close(cb) { diff --git a/lib/utils/startUnixSocket.js b/lib/utils/startUnixSocket.js new file mode 100644 index 0000000000..9bf850c2ec --- /dev/null +++ b/lib/utils/startUnixSocket.js @@ -0,0 +1,62 @@ +'use strict'; + +const fs = require('fs'); +const net = require('net'); +const { promisify } = require('util'); + +const accessAsync = promisify(fs.access); + +async function startUnixSocket(listeningApp, socket, cb) { + const chmodSocket = (done) => { + // chmod 666 (rw rw rw) - octal + const READ_WRITE = 438; + fs.chmod(socket, READ_WRITE, done); + }; + + const startSocket = () => { + listeningApp.on('error', (err) => { + cb(err); + }); + + // 511 is the default value for the server.listen backlog parameter + // https://nodejs.org/api/net.html#net_server_listen + listeningApp.listen(socket, 511, (err) => { + if (err) { + cb(err); + } else { + chmodSocket(cb); + } + }); + }; + + try { + await accessAsync(socket, fs.constants.F_OK); + } catch (e) { + // file does not exist + startSocket(); + return; + } + + // file exists + + const clientSocket = new net.Socket(); + + clientSocket.on('error', (err) => { + if (err.code === 'ECONNREFUSED' || err.code === 'ENOTSOCK') { + // No other server listening on this socket so it can be safely removed + fs.unlinkSync(socket); + + startSocket(); + } + }); + + clientSocket.connect({ path: socket }, () => { + // if a client socket successfully connects to the given socket path, + // it means that the socket is in use + const err = new Error('This socket is already used'); + clientSocket.destroy(); + cb(err); + }); +} + +module.exports = startUnixSocket; diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index c29bad439f..72a5443ad6 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -9,6 +9,7 @@ const execa = require('execa'); const { unlinkAsync } = require('../helpers/fs'); const testBin = require('../helpers/test-bin'); const timer = require('../helpers/timer'); +const { skipTestOnWindows } = require('../helpers/conditional-test'); const httpsCertificateDirectory = resolve( __dirname, @@ -71,17 +72,24 @@ describe('CLI', () => { expect(stdout.includes('\u001b[39m \u001b[90mï½¢wdsï½£\u001b[39m:')).toBe(true); }); - // The Unix socket to listen to (instead of a host). - it('--socket', async () => { - const socketPath = join('.', 'webpack.sock'); - const { exitCode, stdout } = await testBin(`--socket ${socketPath}`); - expect(exitCode).toEqual(0); + describe('Unix socket', () => { + if (skipTestOnWindows('Unix sockets are not supported on Windows')) { + return; + } - if (process.platform !== 'win32') { - expect(stdout.includes(socketPath)).toBe(true); + // The Unix socket to listen to (instead of a host). + it('--socket', async () => { + const socketPath = join('.', 'webpack.sock'); - await unlinkAsync(socketPath); - } + const { exitCode, stdout } = await testBin(`--socket ${socketPath}`); + expect(exitCode).toEqual(0); + + if (process.platform !== 'win32') { + expect(stdout.includes(socketPath)).toBe(true); + + await unlinkAsync(socketPath); + } + }); }); it('without --stdin, with stdin "end" event should time out', async (done) => { diff --git a/test/helpers/test-server.js b/test/helpers/test-server.js index f9284c4fca..85de3777f7 100644 --- a/test/helpers/test-server.js +++ b/test/helpers/test-server.js @@ -40,9 +40,19 @@ function startFullSetup(config, options, done) { server = new Server(compiler, options); - const port = Object.prototype.hasOwnProperty.call(options, 'port') - ? options.port - : 8080; + // originally the fallback default was 8080, but it should be + // undefined so that the server.listen method can choose it for us, + // and thus prevent port mapping collision between tests + let port; + if (Object.prototype.hasOwnProperty.call(options, 'port')) { + port = options.port; + } else if (Object.prototype.hasOwnProperty.call(options, 'socket')) { + port = options.socket; + } else { + // TODO: remove this when findPort is implemented in the server.listen method + port = 8080; + } + const host = Object.prototype.hasOwnProperty.call(options, 'host') ? options.host : 'localhost'; @@ -65,10 +75,12 @@ function startFullSetup(config, options, done) { function startAwaitingCompilationFullSetup(config, options, done) { let readyCount = 0; - const ready = () => { + let err; + const ready = (e) => { + err = e instanceof Error || (typeof e === 'object' && e.code) ? e : err; readyCount += 1; if (readyCount === 2) { - done(); + done(err); } }; diff --git a/test/helpers/test-unix-socket.js b/test/helpers/test-unix-socket.js new file mode 100644 index 0000000000..d2c504b62f --- /dev/null +++ b/test/helpers/test-unix-socket.js @@ -0,0 +1,30 @@ +'use strict'; + +const http = require('http'); + +const TestUnixSocket = class TestUnixSocket { + constructor() { + this.server = http.createServer(); + this.sockets = new Set(); + this.server.on('connection', (socket) => { + this.sockets.add(socket); + socket.on('close', () => { + this.sockets.delete(socket); + }); + }); + } + + close(done) { + if (this.server.listening) { + // get rid of connected sockets + for (const socket of this.sockets.values()) { + socket.destroy(); + } + this.server.close(done); + } else { + done(); + } + } +}; + +module.exports = TestUnixSocket; diff --git a/test/server/onListening-option.test.js b/test/server/onListening-option.test.js index d6d66b1565..2d8b86dc3e 100644 --- a/test/server/onListening-option.test.js +++ b/test/server/onListening-option.test.js @@ -1,32 +1,71 @@ 'use strict'; +const { unlink } = require('fs'); +const { join } = require('path'); const testServer = require('../helpers/test-server'); const config = require('../fixtures/simple-config/webpack.config'); const port = require('../ports-map')['onListening-option']; +const { skipTestOnWindows } = require('../helpers/conditional-test'); describe('onListening option', () => { - let onListeningIsRunning = false; - - beforeAll((done) => { - testServer.start( - config, - { - onListening: (devServer) => { - if (!devServer) { - throw new Error('webpack-dev-server is not defined'); - } - - onListeningIsRunning = true; + describe('with host and port', () => { + let onListeningIsRunning = false; + + beforeAll((done) => { + testServer.start( + config, + { + onListening: (devServer) => { + if (!devServer) { + throw new Error('webpack-dev-server is not defined'); + } + + onListeningIsRunning = true; + }, + port, }, - port, - }, - done - ); + done + ); + }); + + afterAll(testServer.close); + + it('should run onListening callback', () => { + expect(onListeningIsRunning).toBe(true); + }); }); - afterAll(testServer.close); + describe('with Unix socket', () => { + if (skipTestOnWindows('Unix sockets are not supported on Windows')) { + return; + } + + const socketPath = join('.', 'onListening.webpack.sock'); + let onListeningIsRunning = false; + + beforeAll((done) => { + testServer.start( + config, + { + onListening: (devServer) => { + if (!devServer) { + throw new Error('webpack-dev-server is not defined'); + } + + onListeningIsRunning = true; + }, + socket: socketPath, + }, + done + ); + }); + + afterAll(testServer.close); + + it('should run onListening callback', (done) => { + expect(onListeningIsRunning).toBe(true); - it('should runs onListening callback', () => { - expect(onListeningIsRunning).toBe(true); + unlink(socketPath, done); + }); }); }); diff --git a/test/server/socket-option.test.js b/test/server/socket-option.test.js new file mode 100644 index 0000000000..a933097bb1 --- /dev/null +++ b/test/server/socket-option.test.js @@ -0,0 +1,149 @@ +'use strict'; + +const net = require('net'); +const fs = require('fs'); +const path = require('path'); +const webpack = require('webpack'); +const testServer = require('../helpers/test-server'); +const TestUnixSocket = require('../helpers/test-unix-socket'); +const { skipTestOnWindows } = require('../helpers/conditional-test'); +const config = require('../fixtures/simple-config/webpack.config'); +const Server = require('../../lib/Server'); + +describe('socket', () => { + const socketPath = path.join('.', 'socket-option.webpack.sock'); + let server = null; + + describe('path to a non-existent file', () => { + let err; + beforeAll((done) => { + server = testServer.start( + config, + { + socket: socketPath, + }, + (e) => { + err = e; + done(); + } + ); + }); + + it('should work as Unix socket or error on windows', (done) => { + if (process.platform === 'win32') { + expect(err.code).toEqual('EACCES'); + done(); + } else { + const clientSocket = new net.Socket(); + clientSocket.connect({ path: socketPath }, () => { + // this means the connection was made successfully + expect(true).toBeTruthy(); + done(); + }); + } + }); + + afterAll((done) => { + testServer.close(() => { + fs.unlink(socketPath, done); + }); + }); + }); + + describe('path to existent, unused file', () => { + if (skipTestOnWindows('Unix sockets are not supported on Windows')) { + return; + } + + beforeAll((done) => { + fs.writeFileSync(socketPath, ''); + server = testServer.start( + config, + { + socket: socketPath, + }, + done + ); + }); + + it('should work as Unix socket', (done) => { + const clientSocket = new net.Socket(); + clientSocket.connect({ path: socketPath }, () => { + // this means the connection was made successfully + expect(true).toBeTruthy(); + done(); + }); + }); + + afterAll((done) => { + testServer.close(() => { + fs.unlink(socketPath, done); + }); + }); + }); + + describe('path to existent file with listening server', () => { + if (skipTestOnWindows('Unix sockets are not supported on Windows')) { + return; + } + + let testUnixSocket; + beforeAll((done) => { + testUnixSocket = new TestUnixSocket(); + testUnixSocket.server.listen(socketPath, 511, () => { + done(); + }); + }); + + it('should throw already used error', (done) => { + server = testServer.start( + config, + { + socket: socketPath, + }, + (err) => { + expect(err).not.toBeNull(); + expect(err).not.toBeUndefined(); + expect(err.message).toEqual('This socket is already used'); + server.close(done); + } + ); + }); + + afterAll((done) => { + testUnixSocket.close(() => { + fs.unlink(socketPath, done); + }); + }); + }); + + describe('path to existent, unused file', () => { + let devServer; + const options = { + socket: socketPath, + }; + beforeAll(() => { + fs.writeFileSync(socketPath, ''); + }); + + // this test is significant because previously the callback was called + // twice if a file at the given socket path already existed, but + // could be removed + it('should only call server.listen callback once', (done) => { + const compiler = webpack(config); + + devServer = new Server(compiler, options); + const onListen = jest.fn(); + // eslint-disable-next-line no-undefined + devServer.listen(options.socket, undefined, onListen); + setTimeout(() => { + expect(onListen).toBeCalledTimes(1); + done(); + }, 10000); + }); + + afterAll((done) => { + devServer.close(done); + }); + }); +}); diff --git a/test/server/utils/startUnixSocket.test.js b/test/server/utils/startUnixSocket.test.js new file mode 100644 index 0000000000..e0ab7b899a --- /dev/null +++ b/test/server/utils/startUnixSocket.test.js @@ -0,0 +1,124 @@ +'use strict'; + +const net = require('net'); +const fs = require('fs'); +const path = require('path'); +const TestUnixSocket = require('../../helpers/test-unix-socket'); +const { skipTestOnWindows } = require('../../helpers/conditional-test'); +const startUnixSocket = require('../../../lib/utils/startUnixSocket'); + +describe('startUnixSocket', () => { + const socketPath = path.join('.', 'startUnixSocket.webpack.sock'); + let testUnixSocket = null; + + describe('path to a non-existent file', () => { + let err; + beforeAll((done) => { + testUnixSocket = new TestUnixSocket(); + startUnixSocket(testUnixSocket.server, socketPath, (e) => { + err = e; + done(); + }); + }); + + it('should work as Unix socket or error on windows', (done) => { + if (process.platform === 'win32') { + expect(err.code).toEqual('EACCES'); + done(); + } else { + const clientSocket = new net.Socket(); + clientSocket.connect({ path: socketPath }, () => { + // this means the connection was made successfully + expect(true).toBeTruthy(); + done(); + }); + } + }); + + afterAll((done) => { + testUnixSocket.close(() => { + fs.unlink(socketPath, done); + }); + }); + }); + + describe('path to existent, unused file', () => { + if (skipTestOnWindows('Unix sockets are not supported on Windows')) { + return; + } + + beforeAll((done) => { + fs.writeFileSync(socketPath, ''); + testUnixSocket = new TestUnixSocket(); + startUnixSocket(testUnixSocket.server, socketPath, done); + }); + + it('should work as Unix socket', (done) => { + const clientSocket = new net.Socket(); + clientSocket.connect({ path: socketPath }, () => { + // this means the connection was made successfully + expect(true).toBeTruthy(); + done(); + }); + }); + + afterAll((done) => { + testUnixSocket.close(() => { + fs.unlink(socketPath, done); + }); + }); + }); + + describe('path to existent file with listening server', () => { + if (skipTestOnWindows('Unix sockets are not supported on Windows')) { + return; + } + + let dummyUnixSocket; + beforeAll((done) => { + dummyUnixSocket = new TestUnixSocket(); + dummyUnixSocket.server.listen(socketPath, 511, () => { + done(); + }); + }); + + it('should throw already used error', (done) => { + testUnixSocket = new TestUnixSocket(); + startUnixSocket(testUnixSocket.server, socketPath, (err) => { + expect(err).not.toBeNull(); + expect(err).not.toBeUndefined(); + expect(err.message).toEqual('This socket is already used'); + testUnixSocket.close(done); + }); + }); + + afterAll((done) => { + dummyUnixSocket.close(() => { + fs.unlink(socketPath, done); + }); + }); + }); + + describe('path to existent, unused file', () => { + beforeAll(() => { + fs.writeFileSync(socketPath, ''); + testUnixSocket = new TestUnixSocket(); + }); + + // this test is significant because previously the callback was called + // twice if a file at the given socket path already existed, but + // could be removed + it('should only call server.listen callback once', (done) => { + const userCallback = jest.fn(); + startUnixSocket(testUnixSocket.server, socketPath, userCallback); + setTimeout(() => { + expect(userCallback).toBeCalledTimes(1); + done(); + }, 3000); + }); + + afterAll((done) => { + testUnixSocket.close(done); + }); + }); +}); From 97bf13378dd393c6b415240d79994a6727ef1057 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Fri, 2 Aug 2019 23:53:48 -0500 Subject: [PATCH 19/32] refactor(options): wip moving options between helpers --- lib/utils/createConfig.js | 65 +-------------------- lib/utils/normalizeOptions.js | 103 ++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 63 deletions(-) diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index d5a3e1db99..ffdcd8b790 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -1,16 +1,13 @@ 'use strict'; -const path = require('path'); -const isAbsoluteUrl = require('is-absolute-url'); +// const path = require('path'); +// const isAbsoluteUrl = require('is-absolute-url'); const defaultTo = require('./defaultTo'); function createConfig(config, argv, { port }) { const firstWpOpt = Array.isArray(config) ? config[0] : config; const options = firstWpOpt.devServer || {}; - // This updates both config and firstWpOpt - firstWpOpt.mode = defaultTo(firstWpOpt.mode, 'development'); - if (argv.bonjour) { options.bonjour = true; } @@ -59,27 +56,6 @@ function createConfig(config, argv, { port }) { options.overlay = argv.overlay; } - if (!options.publicPath) { - // eslint-disable-next-line - options.publicPath = - (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; - - if ( - !isAbsoluteUrl(String(options.publicPath)) && - options.publicPath[0] !== '/' - ) { - options.publicPath = `/${options.publicPath}`; - } - } - - if (!options.filename && firstWpOpt.output && firstWpOpt.output.filename) { - options.filename = firstWpOpt.output && firstWpOpt.output.filename; - } - - if (!options.watchOptions && firstWpOpt.watchOptions) { - options.watchOptions = firstWpOpt.watchOptions; - } - if (argv.stdin) { options.stdin = true; } @@ -102,34 +78,10 @@ function createConfig(config, argv, { port }) { options.clientLogLevel = argv.clientLogLevel; } - if (argv.contentBase) { - options.contentBase = argv.contentBase; - - if (Array.isArray(options.contentBase)) { - options.contentBase = options.contentBase.map((p) => path.resolve(p)); - } else if (/^[0-9]$/.test(options.contentBase)) { - options.contentBase = +options.contentBase; - } else if (!isAbsoluteUrl(String(options.contentBase))) { - options.contentBase = path.resolve(options.contentBase); - } - } - // It is possible to disable the contentBase by using - // `--no-content-base`, which results in arg["content-base"] = false - else if (argv.contentBase === false) { - options.contentBase = false; - } - if (argv.watchContentBase) { options.watchContentBase = true; } - if (!options.stats) { - options.stats = defaultTo(firstWpOpt.stats, { - cached: false, - cachedAssets: false, - }); - } - if ( typeof options.stats === 'object' && typeof options.stats.colors === 'undefined' && @@ -196,19 +148,6 @@ function createConfig(config, argv, { port }) { options.disableHostCheck = true; } - if (argv.openPage) { - options.open = true; - options.openPage = argv.openPage; - } - - if (typeof argv.open !== 'undefined') { - options.open = argv.open !== '' ? argv.open : true; - } - - if (options.open && !options.openPage) { - options.openPage = ''; - } - if (argv.useLocalIp) { options.useLocalIp = true; } diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 885f365687..77ec861259 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -4,7 +4,110 @@ no-undefined */ +const path = require('path'); +const isAbsoluteUrl = require('is-absolute-url'); +const defaultTo = require('./defaultTo'); + function normalizeOptions(compiler, options) { + const firstWpOpt = compiler.compilers + ? compiler.compilers[0].options + : compiler.options; + + // defaultTo only returns the second parameter if the first is null or undefined + firstWpOpt.mode = defaultTo(firstWpOpt.mode, 'development'); + + const devServerOptions = firstWpOpt.devServer || {}; + + // webpackOptions.devServer has the lowest priority here. + // This is a breaking change for CLI, but a desired one. + + // For the API, it did not use webpackOptions.devServer in previous versions. + // With these changes, API users, optimally, should do 1 of 3 things: + // 1. Put all config in webpackOptions.devServer, then call: new Server(compiler, {}); + // 2. Put all config in webpackOptions.devServer, then call: new Server(compiler, webpackOptions.devServer); + // 3. Put no config in webpackOptions.devServer, then call: new Server(compiler, options); + + // These are the recommended usage practices, + // because it will cause no collision between webpackOptions.devServer and normal options + + // not using Object.assign because we want the current options object to remain, + // but populate it with data from devServer if it does not already exist + Object.keys(devServerOptions).forEach((key) => { + if (options[key] === undefined) { + options[key] = devServerOptions[key]; + } + }); + + if (!options.publicPath) { + // eslint-disable-next-line + options.publicPath = + (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; + + if ( + !isAbsoluteUrl(String(options.publicPath)) && + options.publicPath[0] !== '/' + ) { + options.publicPath = `/${options.publicPath}`; + } + } + + if (!options.filename && firstWpOpt.output && firstWpOpt.output.filename) { + options.filename = firstWpOpt.output && firstWpOpt.output.filename; + } + + if (!options.watchOptions && firstWpOpt.watchOptions) { + options.watchOptions = firstWpOpt.watchOptions; + } + + // resolve paths if this is an array + if (Array.isArray(options.contentBase)) { + options.contentBase = options.contentBase.map((p) => path.resolve(p)); + // string that should be a number + } else if ( + typeof options.contentBase === 'string' && + /^[0-9]$/.test(options.contentBase) + ) { + options.contentBase = +options.contentBase; + // resolve path if it is not absolute + } else if ( + typeof options.contentBase === 'string' && + !isAbsoluteUrl(String(options.contentBase)) + ) { + options.contentBase = path.resolve(options.contentBase); + } + + if (!options.stats) { + options.stats = defaultTo(firstWpOpt.stats, { + cached: false, + cachedAssets: false, + }); + } + + // consider retrieving the webpack config's color option, and remove the dev server + // CLI color option entirely. + + if (options.openPage) { + options.open = true; + } + + if (options.open !== undefined) { + options.open = options.open !== '' ? options.open : true; + } + + if (options.open && !options.openPage) { + options.openPage = ''; + } + + // options that default to true: + if (options.liveReload === undefined) { + options.liveReload = true; + } + if (options.inline === undefined) { + options.inline = true; + } + + // ---- The options below were already here, they are not breaking changes ---- // + // Setup default value options.contentBase = options.contentBase !== undefined ? options.contentBase : process.cwd(); From 1135766a0b2a08dd6ea8362617fd30b71b31e092 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Mon, 5 Aug 2019 15:47:22 -0500 Subject: [PATCH 20/32] fix(cli): move back some options that must be in createConfig --- lib/utils/createConfig.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index ffdcd8b790..c415babfe8 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -148,6 +148,15 @@ function createConfig(config, argv, { port }) { options.disableHostCheck = true; } + if (argv.openPage) { + options.openPage = argv.openPage; + } + + // eslint-disable-next-line no-undefined + if (argv.open !== undefined) { + options.open = argv.open; + } + if (argv.useLocalIp) { options.useLocalIp = true; } From 9c087e533011a21f9ec8cb8a23ee26f678d67227 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Mon, 5 Aug 2019 16:39:03 -0500 Subject: [PATCH 21/32] fix(options): only map to absolute paths if not urls --- lib/utils/normalizeOptions.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 77ec861259..7fd13bc284 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -61,8 +61,15 @@ function normalizeOptions(compiler, options) { // resolve paths if this is an array if (Array.isArray(options.contentBase)) { - options.contentBase = options.contentBase.map((p) => path.resolve(p)); + options.contentBase = options.contentBase.map((p) => { + if (isAbsoluteUrl(p)) { + return p; + } + + return path.resolve(p); + }); // string that should be a number + // TODO: remove ability to make contentBase a number } else if ( typeof options.contentBase === 'string' && /^[0-9]$/.test(options.contentBase) @@ -71,7 +78,7 @@ function normalizeOptions(compiler, options) { // resolve path if it is not absolute } else if ( typeof options.contentBase === 'string' && - !isAbsoluteUrl(String(options.contentBase)) + !isAbsoluteUrl(options.contentBase) ) { options.contentBase = path.resolve(options.contentBase); } From 46a5b6cf245fefddd7ecab0d3e5450e5bf8f90e2 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Mon, 5 Aug 2019 17:16:10 -0500 Subject: [PATCH 22/32] test(options): fixed existing normalize opts tests --- .../normalizeOptions.test.js.snap | 229 +++++++++++++++++- test/server/utils/normalizeOptions.test.js | 149 +++++++++++- 2 files changed, 360 insertions(+), 18 deletions(-) diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap index 5741d85d9a..444e4fb3da 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap @@ -2,10 +2,14 @@ exports[`normalizeOptions contentBase array should set correct options 1`] = ` Object { - "contentBase": Array [ - "/path/to/dist1", - "/path/to/dist2", - ], + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "sockjs", "server": "sockjs", @@ -16,7 +20,158 @@ Object { exports[`normalizeOptions contentBase string should set correct options 1`] = ` Object { - "contentBase": "/path/to/dist", + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions existing devServer.filename, existing compiler filename should set correct options 1`] = ` +Object { + "filename": "devserver-bundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions existing devServer.filename, no compiler filename should set correct options 1`] = ` +Object { + "filename": "devserver-bundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions multi compiler, existing devServer.filename, existing compiler filename should set correct options 1`] = ` +Object { + "filename": "devserver-bundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions multi compiler, existing devServer.filename, no compiler filename should set correct options 1`] = ` +Object { + "filename": "devserver-bundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions multi compiler, no devServer.filename, existing compiler filename should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions multi compiler, no devServer.filename, no compiler filename should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no devServer.filename, existing compiler filename should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no devServer.filename, no compiler filename should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "sockjs", "server": "sockjs", @@ -27,6 +182,14 @@ Object { exports[`normalizeOptions no options should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "sockjs", "server": "sockjs", @@ -37,6 +200,14 @@ Object { exports[`normalizeOptions transportMode custom client path should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "/path/to/custom/client/", "server": "sockjs", @@ -47,6 +218,14 @@ Object { exports[`normalizeOptions transportMode custom server class should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "sockjs", "server": [Function], @@ -57,6 +236,14 @@ Object { exports[`normalizeOptions transportMode custom server path should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "sockjs", "server": "/path/to/custom/server/", @@ -67,6 +254,14 @@ Object { exports[`normalizeOptions transportMode sockjs string should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "sockjs", "server": "sockjs", @@ -77,6 +272,14 @@ Object { exports[`normalizeOptions transportMode ws object should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "ws", "server": "ws", @@ -87,6 +290,14 @@ Object { exports[`normalizeOptions transportMode ws string should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "ws", "server": "ws", @@ -97,6 +308,14 @@ Object { exports[`normalizeOptions watchOptions should set correct options 1`] = ` Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, "transportMode": Object { "client": "sockjs", "server": "sockjs", diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index 1490b36088..10d473e43c 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -1,5 +1,6 @@ 'use strict'; +const path = require('path'); const webpack = require('webpack'); const normalizeOptions = require('../../../lib/utils/normalizeOptions'); @@ -15,17 +16,24 @@ describe('normalizeOptions', () => { title: 'contentBase string', multiCompiler: false, options: { - contentBase: '/path/to/dist', + contentBase: 'path/to/dist', + }, + optionsResults: { + contentBase: path.resolve('path/to/dist'), }, - optionsResults: null, }, { title: 'contentBase array', multiCompiler: false, options: { - contentBase: ['/path/to/dist1', '/path/to/dist2'], + contentBase: ['path/to/dist1', 'path/to/dist2'], + }, + optionsResults: { + contentBase: [ + path.resolve('path/to/dist1'), + path.resolve('path/to/dist2'), + ], }, - optionsResults: null, }, { title: 'watchOptions', @@ -37,6 +45,7 @@ describe('normalizeOptions', () => { }, optionsResults: null, }, + { title: 'transportMode sockjs string', multiCompiler: false, @@ -94,12 +103,113 @@ describe('normalizeOptions', () => { }, optionsResults: null, }, + + { + title: 'no devServer.filename, no compiler filename', + webpackConfig: null, + multiCompiler: false, + options: {}, + optionsResults: null, + }, + { + title: 'no devServer.filename, existing compiler filename', + webpackConfig: { + output: { + filename: 'mybundle.js', + }, + }, + multiCompiler: false, + options: {}, + optionsResults: null, + }, + { + title: 'existing devServer.filename, no compiler filename', + webpackConfig: null, + multiCompiler: false, + options: { + filename: 'devserver-bundle.js', + }, + optionsResults: null, + }, + { + title: 'existing devServer.filename, existing compiler filename', + webpackConfig: { + output: { + filename: 'mybundle.js', + }, + }, + multiCompiler: false, + options: { + filename: 'devserver-bundle.js', + }, + optionsResults: null, + }, + { + title: 'multi compiler, no devServer.filename, no compiler filename', + webpackConfig: null, + multiCompiler: true, + options: {}, + optionsResults: null, + }, + { + title: + 'multi compiler, no devServer.filename, existing compiler filename', + webpackConfig: { + output: { + filename: 'mybundle.js', + }, + }, + multiCompiler: true, + options: {}, + optionsResults: null, + }, + { + title: + 'multi compiler, existing devServer.filename, no compiler filename', + webpackConfig: null, + multiCompiler: true, + options: { + filename: 'devserver-bundle.js', + }, + optionsResults: null, + }, + { + title: + 'multi compiler, existing devServer.filename, existing compiler filename', + webpackConfig: { + output: { + filename: 'mybundle.js', + }, + }, + multiCompiler: true, + options: { + filename: 'devserver-bundle.js', + }, + optionsResults: null, + }, ]; cases.forEach((data) => { describe(data.title, () => { let compiler; beforeAll(() => { + // this will merge webpack configs through a depth of one layer of objects, + // specifically so that the webpack config output object can be merged + const mergeConfigs = (baseConfig, config) => { + Object.keys(config).forEach((key1) => { + if (typeof config[key1] === 'object') { + Object.keys(config[key1]).forEach((key2) => { + if (!baseConfig[key1]) { + baseConfig[key1] = {}; + } + baseConfig[key1][key2] = config[key1][key2]; + }); + } else { + baseConfig[key1] = config[key1]; + } + }); + }; + let webpackConfig; if (data.multiCompiler) { webpackConfig = require('../../fixtures/multi-compiler-config/webpack.config'); @@ -107,6 +217,13 @@ describe('normalizeOptions', () => { webpackConfig = require('../../fixtures/simple-config/webpack.config'); } + if (data.webpackConfig) { + mergeConfigs( + data.multiCompiler ? webpackConfig[0] : webpackConfig, + data.webpackConfig + ); + } + compiler = webpack(webpackConfig); }); @@ -114,16 +231,22 @@ describe('normalizeOptions', () => { const originalContentBase = data.options.contentBase; normalizeOptions(compiler, data.options); if (data.optionsResults) { - expect(data.options).toEqual(data.optionsResults); - } else { - if (data.options.contentBase !== originalContentBase) { - // we don't want this in the snapshot, because it is - // the current working directory - expect(data.options.contentBase).toEqual(process.cwd()); - delete data.options.contentBase; - } - expect(data.options).toMatchSnapshot(); + Object.keys(data.optionsResults).forEach((key) => { + expect(data.options[key]).toEqual(data.optionsResults[key]); + delete data.options[key]; + }); + } + + if ( + data.options.contentBase && + data.options.contentBase !== originalContentBase + ) { + // we don't want this in the snapshot, because it is + // the current working directory + expect(data.options.contentBase).toEqual(process.cwd()); + delete data.options.contentBase; } + expect(data.options).toMatchSnapshot(); }); }); }); From a54897bce03f523ccaf49885e62117592a0c19fd Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Mon, 5 Aug 2019 18:37:11 -0500 Subject: [PATCH 23/32] test(server): add public path option tests to normalize tests --- lib/utils/normalizeOptions.js | 14 +- .../normalizeOptions.test.js.snap | 252 +++++++++++++++++- test/server/utils/normalizeOptions.test.js | 150 ++++++++++- 3 files changed, 391 insertions(+), 25 deletions(-) diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 7fd13bc284..59f3dba878 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -42,13 +42,15 @@ function normalizeOptions(compiler, options) { // eslint-disable-next-line options.publicPath = (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; + } - if ( - !isAbsoluteUrl(String(options.publicPath)) && - options.publicPath[0] !== '/' - ) { - options.publicPath = `/${options.publicPath}`; - } + // moving this block out of the above (!options.publicPath) if statement + // is a minor breaking change, but I think will make for better UX all around + if ( + !isAbsoluteUrl(String(options.publicPath)) && + options.publicPath[0] !== '/' + ) { + options.publicPath = `/${options.publicPath}`; } if (!options.filename && firstWpOpt.output && firstWpOpt.output.filename) { diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap index 444e4fb3da..3cfe7f6e7f 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap @@ -1,5 +1,41 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`normalizeOptions absolute options.publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "http://localhost:8080/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions bad relative options.publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + exports[`normalizeOptions contentBase array should set correct options 1`] = ` Object { "filename": "[name].js", @@ -36,7 +72,7 @@ Object { } `; -exports[`normalizeOptions existing devServer.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions existing options.filename, existing compiler filename should set correct options 1`] = ` Object { "filename": "devserver-bundle.js", "inline": true, @@ -54,7 +90,7 @@ Object { } `; -exports[`normalizeOptions existing devServer.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions existing options.filename, no compiler filename should set correct options 1`] = ` Object { "filename": "devserver-bundle.js", "inline": true, @@ -72,7 +108,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, existing devServer.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions multi compiler, existing options.filename, existing compiler filename should set correct options 1`] = ` Object { "filename": "devserver-bundle.js", "inline": true, @@ -90,7 +126,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, existing devServer.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions multi compiler, existing options.filename, no compiler filename should set correct options 1`] = ` Object { "filename": "devserver-bundle.js", "inline": true, @@ -108,7 +144,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, no devServer.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions multi compiler, no options.filename, existing compiler filename should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, @@ -126,7 +162,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, no devServer.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions multi compiler, no options.filename, no compiler filename should set correct options 1`] = ` Object { "filename": "[name].js", "inline": true, @@ -144,7 +180,7 @@ Object { } `; -exports[`normalizeOptions no devServer.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions multi compiler, no options.publicPath, / compiler publicPath should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, @@ -162,9 +198,45 @@ Object { } `; -exports[`normalizeOptions no devServer.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions multi compiler, no options.publicPath, absolute url compiler publicPath should set correct options 1`] = ` Object { - "filename": "[name].js", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "http://localhost:8080/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions multi compiler, no options.publicPath, bad relative compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions multi compiler, no options.publicPath, no compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", @@ -180,6 +252,24 @@ Object { } `; +exports[`normalizeOptions multi compiler, no options.publicPath, relative compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + exports[`normalizeOptions no options should set correct options 1`] = ` Object { "filename": "[name].js", @@ -198,6 +288,150 @@ Object { } `; +exports[`normalizeOptions no options.filename, existing compiler filename should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no options.filename, no compiler filename should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no options.publicPath, / compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no options.publicPath, absolute url compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "http://localhost:8080/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no options.publicPath, bad relative compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no options.publicPath, no compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions no options.publicPath, relative compiler publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions relative options.publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + exports[`normalizeOptions transportMode custom client path should set correct options 1`] = ` Object { "filename": "[name].js", diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index 10d473e43c..cd4449512b 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -105,14 +105,14 @@ describe('normalizeOptions', () => { }, { - title: 'no devServer.filename, no compiler filename', + title: 'no options.filename, no compiler filename', webpackConfig: null, multiCompiler: false, options: {}, optionsResults: null, }, { - title: 'no devServer.filename, existing compiler filename', + title: 'no options.filename, existing compiler filename', webpackConfig: { output: { filename: 'mybundle.js', @@ -123,7 +123,7 @@ describe('normalizeOptions', () => { optionsResults: null, }, { - title: 'existing devServer.filename, no compiler filename', + title: 'existing options.filename, no compiler filename', webpackConfig: null, multiCompiler: false, options: { @@ -132,7 +132,7 @@ describe('normalizeOptions', () => { optionsResults: null, }, { - title: 'existing devServer.filename, existing compiler filename', + title: 'existing options.filename, existing compiler filename', webpackConfig: { output: { filename: 'mybundle.js', @@ -145,15 +145,14 @@ describe('normalizeOptions', () => { optionsResults: null, }, { - title: 'multi compiler, no devServer.filename, no compiler filename', + title: 'multi compiler, no options.filename, no compiler filename', webpackConfig: null, multiCompiler: true, options: {}, optionsResults: null, }, { - title: - 'multi compiler, no devServer.filename, existing compiler filename', + title: 'multi compiler, no options.filename, existing compiler filename', webpackConfig: { output: { filename: 'mybundle.js', @@ -164,8 +163,7 @@ describe('normalizeOptions', () => { optionsResults: null, }, { - title: - 'multi compiler, existing devServer.filename, no compiler filename', + title: 'multi compiler, existing options.filename, no compiler filename', webpackConfig: null, multiCompiler: true, options: { @@ -175,7 +173,7 @@ describe('normalizeOptions', () => { }, { title: - 'multi compiler, existing devServer.filename, existing compiler filename', + 'multi compiler, existing options.filename, existing compiler filename', webpackConfig: { output: { filename: 'mybundle.js', @@ -187,6 +185,138 @@ describe('normalizeOptions', () => { }, optionsResults: null, }, + + { + title: 'no options.publicPath, no compiler publicPath', + webpackConfig: null, + multiCompiler: false, + options: {}, + }, + { + title: 'no options.publicPath, relative compiler publicPath', + webpackConfig: { + output: { + publicPath: '/assets/', + }, + }, + multiCompiler: false, + options: {}, + }, + { + title: 'no options.publicPath, bad relative compiler publicPath', + webpackConfig: { + output: { + publicPath: 'assets/', + }, + }, + multiCompiler: false, + options: {}, + }, + { + title: 'no options.publicPath, / compiler publicPath', + webpackConfig: { + output: { + publicPath: '/', + }, + }, + multiCompiler: false, + options: {}, + }, + { + title: 'no options.publicPath, absolute url compiler publicPath', + webpackConfig: { + output: { + publicPath: 'http://localhost:8080/assets/', + }, + }, + multiCompiler: false, + options: {}, + }, + { + title: 'multi compiler, no options.publicPath, no compiler publicPath', + webpackConfig: null, + multiCompiler: true, + options: {}, + }, + { + title: + 'multi compiler, no options.publicPath, relative compiler publicPath', + webpackConfig: { + output: { + publicPath: '/assets/', + }, + }, + multiCompiler: true, + options: {}, + }, + { + title: + 'multi compiler, no options.publicPath, bad relative compiler publicPath', + webpackConfig: { + output: { + publicPath: 'assets/', + }, + }, + multiCompiler: true, + options: {}, + }, + { + title: 'multi compiler, no options.publicPath, / compiler publicPath', + webpackConfig: { + output: { + publicPath: '/', + }, + }, + multiCompiler: true, + options: {}, + }, + { + title: + 'multi compiler, no options.publicPath, absolute url compiler publicPath', + webpackConfig: { + output: { + publicPath: 'http://localhost:8080/assets/', + }, + }, + multiCompiler: true, + options: {}, + }, + { + title: 'relative options.publicPath', + webpackConfig: { + output: { + publicPath: '/', + }, + }, + multiCompiler: false, + options: { + publicPath: '/assets/', + }, + }, + { + title: 'bad relative options.publicPath', + webpackConfig: { + output: { + publicPath: '/', + }, + }, + multiCompiler: false, + options: { + publicPath: 'assets/', + }, + }, + { + title: 'absolute options.publicPath', + webpackConfig: { + output: { + publicPath: '/', + }, + }, + multiCompiler: false, + options: { + publicPath: 'http://localhost:8080/assets/', + }, + }, ]; cases.forEach((data) => { From 5d6502eee08718d413a8630a094020b71ba9f410 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Mon, 5 Aug 2019 22:20:09 -0500 Subject: [PATCH 24/32] test(options): add normalize options tests, remove create config tests --- .../__snapshots__/createConfig.test.js.snap | 614 ------------------ .../normalizeOptions.test.js.snap | 534 +++++++++++++-- test/server/utils/createConfig.test.js | 177 +---- test/server/utils/normalizeOptions.test.js | 331 ++++++---- 4 files changed, 712 insertions(+), 944 deletions(-) diff --git a/test/server/utils/__snapshots__/createConfig.test.js.snap b/test/server/utils/__snapshots__/createConfig.test.js.snap index 585d74105c..5514400d5d 100644 --- a/test/server/utils/__snapshots__/createConfig.test.js.snap +++ b/test/server/utils/__snapshots__/createConfig.test.js.snap @@ -10,11 +10,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -28,11 +23,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -43,11 +33,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -58,11 +43,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -74,11 +54,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -90,11 +65,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -106,11 +76,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -122,11 +87,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -137,11 +97,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -152,11 +107,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -167,11 +117,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -182,74 +127,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig contentBase option (array) 1`] = ` -Object { - "contentBase": Array [ - "assets", - "static", - ], - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig contentBase option (boolean) 1`] = ` -Object { - "contentBase": false, - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig contentBase option (string) (in devServer config) 1`] = ` -Object { - "contentBase": "assets", - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig contentBase option (string) 1`] = ` -Object { - "contentBase": "assets", - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -260,11 +137,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -275,56 +147,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig filename option (in devServer config) 1`] = ` -Object { - "filename": "[name]-dev-server-bundle.js", - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig filename option (in output config) 1`] = ` -Object { - "filename": "[name]-output-bundle.js", - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig filename option (in webpack config) 1`] = ` -Object { - "filename": "[name]-bundle.js", - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -335,11 +157,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -350,11 +167,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -365,11 +177,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -380,11 +187,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -394,11 +196,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -409,11 +206,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -423,11 +215,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -438,11 +225,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -452,11 +234,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -466,11 +243,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -480,11 +252,6 @@ Object { "hotOnly": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -494,11 +261,6 @@ Object { "hotOnly": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -510,11 +272,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -526,11 +283,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -541,11 +293,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -556,11 +303,6 @@ Object { "noInfo": true, "pfxPassphrase": "passphrase", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -571,11 +313,6 @@ Object { "https": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -585,11 +322,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -599,11 +331,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -614,11 +341,6 @@ Object { "inline": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -629,11 +351,6 @@ Object { "inline": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -645,11 +362,6 @@ Object { "key": "/path/to/server.key", "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -661,11 +373,6 @@ Object { "key": "/path/to/server.key", "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -676,11 +383,6 @@ Object { "lazy": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -691,11 +393,6 @@ Object { "lazy": true, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -706,11 +403,6 @@ Object { "liveReload": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -728,11 +420,6 @@ Object { }, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -747,11 +434,6 @@ Object { }, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -762,11 +444,6 @@ Object { "noInfo": true, "onListening": [Function], "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -776,13 +453,7 @@ Object { "hotOnly": false, "noInfo": true, "open": true, - "openPage": "", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -792,13 +463,7 @@ Object { "hotOnly": false, "noInfo": true, "open": true, - "openPage": "", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -808,13 +473,7 @@ Object { "hotOnly": false, "noInfo": true, "open": "Google Chrome", - "openPage": "", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -826,11 +485,6 @@ Object { "open": true, "openPage": "/different/page", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -839,14 +493,8 @@ Object { "hot": true, "hotOnly": false, "noInfo": true, - "open": true, "openPage": "/different/page", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -857,11 +505,6 @@ Object { "noInfo": true, "overlay": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -872,11 +515,6 @@ Object { "noInfo": true, "overlay": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -888,11 +526,6 @@ Object { "noInfo": true, "pfx": "/path/to/file.pfx", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -904,11 +537,6 @@ Object { "noInfo": true, "pfx": "/path/to/file.pfx", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -919,11 +547,6 @@ Object { "noInfo": true, "pfxPassphrase": "passphrase", "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -933,11 +556,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 7070, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -947,11 +565,6 @@ Object { "hotOnly": false, "noInfo": true, "port": null, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -961,11 +574,6 @@ Object { "hotOnly": false, "noInfo": true, "port": "9090", - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -975,11 +583,6 @@ Object { "hotOnly": false, "noInfo": true, "port": undefined, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -989,11 +592,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 9090, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1004,11 +602,6 @@ Object { "noInfo": true, "port": 8080, "profile": "profile", - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1019,11 +612,6 @@ Object { "noInfo": true, "port": 8080, "progress": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1034,11 +622,6 @@ Object { "noInfo": true, "port": 8080, "progress": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1049,11 +632,6 @@ Object { "noInfo": true, "port": 8080, "public": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1064,95 +642,6 @@ Object { "noInfo": true, "port": 8080, "public": true, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig publicPath option (not specify) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig publicPath option (path in devServer option) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig publicPath option (path in output option) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig publicPath option (path without starting slash in output option) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig publicPath option (url in devServer option) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "http://localhost:8080/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, -} -`; - -exports[`createConfig publicPath option (url in output option) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "http://localhost:8080/assets/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1162,12 +651,7 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "quiet": true, - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1177,12 +661,7 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "quiet": true, - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1192,11 +671,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1206,12 +680,7 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "sockHost": true, - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1221,12 +690,7 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "sockPath": "path", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1236,12 +700,7 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "sockPort": "port", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1251,12 +710,7 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "socket": "socket", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1266,12 +720,7 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "socket": "socket", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, } `; @@ -1281,7 +730,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "stats": Object { "colors": true, "errors": true, @@ -1295,7 +743,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", "stats": "errors-only", } `; @@ -1324,9 +771,6 @@ Object { "publicPath": "_publicPath", "quiet": "_quiet", "socket": "_socket", - "stats": Object { - "assetsSort": "size", - }, "useLocalIp": "_useLocalIp", "watchContentBase": "_watchContentBase", } @@ -1357,14 +801,10 @@ Object { "publicPath": "_publicPath", "quiet": "_quiet", "socket": "_socket", - "stats": Object { - "assetsSort": "size", - }, "useLocalIp": "_useLocalIp", "watchContentBase": "_watchContentBase", }, "entry": "./app.js", - "mode": "development", "stats": Object { "assetsSort": "size", }, @@ -1377,11 +817,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "useLocalIp": true, } `; @@ -1392,11 +827,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "useLocalIp": true, } `; @@ -1407,11 +837,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "watchContentBase": true, } `; @@ -1422,45 +847,6 @@ Object { "hotOnly": false, "noInfo": true, "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, "watchContentBase": true, } `; - -exports[`createConfig watchOptions option (in devServer config) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, - "watchOptions": Object { - "poll": true, - }, -} -`; - -exports[`createConfig watchOptions option (in output config) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, - "publicPath": "/", - "stats": Object { - "cached": false, - "cachedAssets": false, - }, - "watchOptions": Object { - "poll": true, - }, -} -`; diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap index 3cfe7f6e7f..b3b43f6cdf 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap @@ -1,5 +1,23 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`normalizeOptions absolute options.publicPath (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "http://localhost:8080/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + exports[`normalizeOptions absolute options.publicPath should set correct options 1`] = ` Object { "filename": "mybundle.js", @@ -18,6 +36,24 @@ Object { } `; +exports[`normalizeOptions bad relative options.publicPath (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + exports[`normalizeOptions bad relative options.publicPath should set correct options 1`] = ` Object { "filename": "mybundle.js", @@ -36,9 +72,10 @@ Object { } `; -exports[`normalizeOptions contentBase array should set correct options 1`] = ` +exports[`normalizeOptions compiler options.devServer (multi compiler) should set correct options 1`] = ` Object { "filename": "[name].js", + "hot": true, "inline": true, "liveReload": true, "publicPath": "/", @@ -54,9 +91,10 @@ Object { } `; -exports[`normalizeOptions contentBase string should set correct options 1`] = ` +exports[`normalizeOptions compiler options.devServer should set correct options 1`] = ` Object { "filename": "[name].js", + "hot": true, "inline": true, "liveReload": true, "publicPath": "/", @@ -72,9 +110,63 @@ Object { } `; -exports[`normalizeOptions existing options.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions compiler stats (multi compiler) should set correct options 1`] = ` Object { - "filename": "devserver-bundle.js", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "errors": true, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler stats should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "errors": true, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler watchOptions (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object { + "poll": true, + }, +} +`; + +exports[`normalizeOptions compiler watchOptions should set correct options 1`] = ` +Object { + "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", @@ -86,13 +178,108 @@ Object { "client": "sockjs", "server": "sockjs", }, + "watchOptions": Object { + "poll": true, + }, +} +`; + +exports[`normalizeOptions complex compiler options.devServer (multi compiler) should set correct options 1`] = ` +Object { + "clientLogLevel": "_clientLogLevel", + "compress": "_compress", + "disableHostCheck": "_disableHostCheck", + "filename": "_filename", + "historyApiFallback": "_historyApiFallback", + "host": "_foo", + "hot": "_hot", + "hotOnly": "_hotOnly", + "https": "_https", + "inline": "_inline", + "lazy": "_lazy", + "liveReload": true, + "noInfo": "_noInfo", + "open": true, + "openPage": "_openPage", + "pfxPassphrase": "_pfxPassphrase", + "port": "_port", + "progress": "_progress", + "public": "_public", + "publicPath": "/_publicPath", + "quiet": "_quiet", + "socket": "_socket", + "stats": Object { + "assetsSort": "size", + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "useLocalIp": "_useLocalIp", + "watchContentBase": "_watchContentBase", "watchOptions": Object {}, } `; -exports[`normalizeOptions existing options.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions complex compiler options.devServer should set correct options 1`] = ` Object { - "filename": "devserver-bundle.js", + "clientLogLevel": "_clientLogLevel", + "compress": "_compress", + "disableHostCheck": "_disableHostCheck", + "filename": "_filename", + "historyApiFallback": "_historyApiFallback", + "host": "_foo", + "hot": "_hot", + "hotOnly": "_hotOnly", + "https": "_https", + "inline": "_inline", + "lazy": "_lazy", + "liveReload": true, + "noInfo": "_noInfo", + "open": true, + "openPage": "_openPage", + "pfxPassphrase": "_pfxPassphrase", + "port": "_port", + "progress": "_progress", + "public": "_public", + "publicPath": "/_publicPath", + "quiet": "_quiet", + "socket": "_socket", + "stats": Object { + "assetsSort": "size", + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "useLocalIp": "_useLocalIp", + "watchContentBase": "_watchContentBase", + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions contentBase (array) should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions contentBase (boolean) should set correct options 1`] = ` +Object { + "contentBase": false, + "filename": "[name].js", "inline": true, "liveReload": true, "publicPath": "/", @@ -108,7 +295,25 @@ Object { } `; -exports[`normalizeOptions multi compiler, existing options.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions contentBase (string) should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions existing options.filename, existing compiler filename (multi compiler) should set correct options 1`] = ` Object { "filename": "devserver-bundle.js", "inline": true, @@ -126,7 +331,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, existing options.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions existing options.filename, existing compiler filename should set correct options 1`] = ` Object { "filename": "devserver-bundle.js", "inline": true, @@ -144,9 +349,9 @@ Object { } `; -exports[`normalizeOptions multi compiler, no options.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions existing options.filename, no compiler filename should set correct options 1`] = ` Object { - "filename": "mybundle.js", + "filename": "devserver-bundle.js", "inline": true, "liveReload": true, "publicPath": "/", @@ -162,7 +367,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, no options.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions no options should set correct options 1`] = ` Object { "filename": "[name].js", "inline": true, @@ -180,7 +385,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, no options.publicPath, / compiler publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.filename, existing compiler filename (multi compiler) should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, @@ -198,12 +403,12 @@ Object { } `; -exports[`normalizeOptions multi compiler, no options.publicPath, absolute url compiler publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.filename, existing compiler filename (multi compiler) should set correct options 2`] = ` Object { "filename": "mybundle.js", "inline": true, "liveReload": true, - "publicPath": "http://localhost:8080/assets/", + "publicPath": "/", "stats": Object { "cached": false, "cachedAssets": false, @@ -216,12 +421,12 @@ Object { } `; -exports[`normalizeOptions multi compiler, no options.publicPath, bad relative compiler publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.filename, existing compiler filename should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, "liveReload": true, - "publicPath": "/assets/", + "publicPath": "/", "stats": Object { "cached": false, "cachedAssets": false, @@ -234,7 +439,7 @@ Object { } `; -exports[`normalizeOptions multi compiler, no options.publicPath, no compiler publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.filename, existing compiler filename should set correct options 2`] = ` Object { "filename": "mybundle.js", "inline": true, @@ -252,12 +457,12 @@ Object { } `; -exports[`normalizeOptions multi compiler, no options.publicPath, relative compiler publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.filename, no compiler filename should set correct options 1`] = ` Object { - "filename": "mybundle.js", + "filename": "[name].js", "inline": true, "liveReload": true, - "publicPath": "/assets/", + "publicPath": "/", "stats": Object { "cached": false, "cachedAssets": false, @@ -270,7 +475,7 @@ Object { } `; -exports[`normalizeOptions no options should set correct options 1`] = ` +exports[`normalizeOptions no options.filename, no compiler filename should set correct options 2`] = ` Object { "filename": "[name].js", "inline": true, @@ -288,7 +493,7 @@ Object { } `; -exports[`normalizeOptions no options.filename, existing compiler filename should set correct options 1`] = ` +exports[`normalizeOptions no options.publicPath, / compiler publicPath (multi compiler) should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, @@ -306,9 +511,9 @@ Object { } `; -exports[`normalizeOptions no options.filename, no compiler filename should set correct options 1`] = ` +exports[`normalizeOptions no options.publicPath, / compiler publicPath should set correct options 1`] = ` Object { - "filename": "[name].js", + "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", @@ -324,12 +529,12 @@ Object { } `; -exports[`normalizeOptions no options.publicPath, / compiler publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.publicPath, absolute url compiler publicPath (multi compiler) should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, "liveReload": true, - "publicPath": "/", + "publicPath": "http://localhost:8080/assets/", "stats": Object { "cached": false, "cachedAssets": false, @@ -360,6 +565,24 @@ Object { } `; +exports[`normalizeOptions no options.publicPath, bad relative compiler publicPath (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + exports[`normalizeOptions no options.publicPath, bad relative compiler publicPath should set correct options 1`] = ` Object { "filename": "mybundle.js", @@ -380,7 +603,7 @@ Object { exports[`normalizeOptions no options.publicPath, no compiler publicPath should set correct options 1`] = ` Object { - "filename": "mybundle.js", + "filename": "[name].js", "inline": true, "liveReload": true, "publicPath": "/", @@ -396,7 +619,7 @@ Object { } `; -exports[`normalizeOptions no options.publicPath, relative compiler publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.publicPath, relative compiler publicPath (multi compiler) should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, @@ -414,7 +637,7 @@ Object { } `; -exports[`normalizeOptions relative options.publicPath should set correct options 1`] = ` +exports[`normalizeOptions no options.publicPath, relative compiler publicPath should set correct options 1`] = ` Object { "filename": "mybundle.js", "inline": true, @@ -432,9 +655,10 @@ Object { } `; -exports[`normalizeOptions transportMode custom client path should set correct options 1`] = ` +exports[`normalizeOptions normal options override compiler options.devServer (multi compiler) should set correct options 1`] = ` Object { "filename": "[name].js", + "hot": false, "inline": true, "liveReload": true, "publicPath": "/", @@ -443,16 +667,17 @@ Object { "cachedAssets": false, }, "transportMode": Object { - "client": "/path/to/custom/client/", + "client": "sockjs", "server": "sockjs", }, "watchOptions": Object {}, } `; -exports[`normalizeOptions transportMode custom server class should set correct options 1`] = ` +exports[`normalizeOptions normal options override compiler options.devServer should set correct options 1`] = ` Object { "filename": "[name].js", + "hot": false, "inline": true, "liveReload": true, "publicPath": "/", @@ -462,17 +687,55 @@ Object { }, "transportMode": Object { "client": "sockjs", - "server": [Function], + "server": "sockjs", }, "watchOptions": Object {}, } `; -exports[`normalizeOptions transportMode custom server path should set correct options 1`] = ` +exports[`normalizeOptions options.inline should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": false, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.liveReload should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": false, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.open (boolean) should set correct options 1`] = ` Object { "filename": "[name].js", "inline": true, "liveReload": true, + "open": true, + "openPage": "", "publicPath": "/", "stats": Object { "cached": false, @@ -480,17 +743,19 @@ Object { }, "transportMode": Object { "client": "sockjs", - "server": "/path/to/custom/server/", + "server": "sockjs", }, "watchOptions": Object {}, } `; -exports[`normalizeOptions transportMode sockjs string should set correct options 1`] = ` +exports[`normalizeOptions options.open (empty string) should set correct options 1`] = ` Object { "filename": "[name].js", "inline": true, "liveReload": true, + "open": true, + "openPage": "", "publicPath": "/", "stats": Object { "cached": false, @@ -504,43 +769,82 @@ Object { } `; -exports[`normalizeOptions transportMode ws object should set correct options 1`] = ` +exports[`normalizeOptions options.open (string) should set correct options 1`] = ` Object { "filename": "[name].js", "inline": true, "liveReload": true, + "open": "Google Chrome", + "openPage": "", "publicPath": "/", "stats": Object { "cached": false, "cachedAssets": false, }, "transportMode": Object { - "client": "ws", - "server": "ws", + "client": "sockjs", + "server": "sockjs", }, "watchOptions": Object {}, } `; -exports[`normalizeOptions transportMode ws string should set correct options 1`] = ` +exports[`normalizeOptions options.openPage, no options.open should set correct options 1`] = ` Object { "filename": "[name].js", "inline": true, "liveReload": true, + "open": true, + "openPage": "/different/page", "publicPath": "/", "stats": Object { "cached": false, "cachedAssets": false, }, "transportMode": Object { - "client": "ws", - "server": "ws", + "client": "sockjs", + "server": "sockjs", }, "watchOptions": Object {}, } `; -exports[`normalizeOptions watchOptions should set correct options 1`] = ` +exports[`normalizeOptions options.openPage, options.open should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "open": true, + "openPage": "/different/page", + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.stats should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": "errors-only", + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.watchOptions should set correct options 1`] = ` Object { "filename": "[name].js", "inline": true, @@ -559,3 +863,147 @@ Object { }, } `; + +exports[`normalizeOptions relative options.publicPath (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions relative options.publicPath should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/assets/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions transportMode custom client path should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "/path/to/custom/client/", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions transportMode custom server class should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": [Function], + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions transportMode custom server path should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "/path/to/custom/server/", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions transportMode sockjs string should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions transportMode ws object should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "ws", + "server": "ws", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions transportMode ws string should set correct options 1`] = ` +Object { + "filename": "[name].js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "ws", + "server": "ws", + }, + "watchOptions": Object {}, +} +`; diff --git a/test/server/utils/createConfig.test.js b/test/server/utils/createConfig.test.js index 685941ef56..5422fc94f4 100644 --- a/test/server/utils/createConfig.test.js +++ b/test/server/utils/createConfig.test.js @@ -1,6 +1,5 @@ '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'); @@ -210,131 +209,11 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - it('publicPath option (not specify)', () => { - const config = createConfig(webpackConfig, argv, { port: 8080 }); + // removed: publicPath tests - expect(config).toMatchSnapshot(); - }); - - it('publicPath option (path in devServer option)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { publicPath: '/assets/' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('publicPath option (url in devServer option)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { publicPath: 'http://localhost:8080/assets/' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('publicPath option (url in output option)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - output: { publicPath: 'http://localhost:8080/assets/' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('publicPath option (path in output option)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - output: { publicPath: '/assets/' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('publicPath option (path without starting slash in output option)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - output: { publicPath: 'assets/' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('filename option (in webpack config)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - output: { filename: '[name]-bundle.js' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('filename option (in output config)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - output: { filename: '[name]-output-bundle.js' }, - }), - argv, - { port: 8080 } - ); + // removed: filename tests - expect(config).toMatchSnapshot(); - }); - - it('filename option (in devServer config)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { filename: '[name]-dev-server-bundle.js' }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('watchOptions option (in output config)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - watchOptions: { poll: true }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('watchOptions option (in devServer config)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { watchOptions: { poll: true } }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); + // removed: watchOptions tests it('hot option', () => { const config = createConfig( @@ -402,55 +281,7 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - it('contentBase option (string)', () => { - const config = createConfig( - webpackConfig, - Object.assign({}, argv, { contentBase: 'assets' }), - { port: 8080 } - ); - - config.contentBase = path.relative(process.cwd(), config.contentBase); - - expect(config).toMatchSnapshot(); - }); - - it('contentBase option (array)', () => { - const config = createConfig( - webpackConfig, - Object.assign({}, argv, { contentBase: ['assets', 'static'] }), - { port: 8080 } - ); - - config.contentBase = config.contentBase.map((item) => - path.relative(process.cwd(), item) - ); - - expect(config).toMatchSnapshot(); - }); - - it('contentBase option (boolean)', () => { - const config = createConfig( - webpackConfig, - Object.assign({}, argv, { contentBase: false }), - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('contentBase option (string) (in devServer config)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { contentBase: 'assets' }, - }), - argv, - { port: 8080 } - ); - - config.contentBase = path.relative(process.cwd(), config.contentBase); - - expect(config).toMatchSnapshot(); - }); + // removed: contentBase tests it('watchContentBase option', () => { const config = createConfig( diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index cd4449512b..d24ca30bfc 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -3,6 +3,9 @@ const path = require('path'); const webpack = require('webpack'); const normalizeOptions = require('../../../lib/utils/normalizeOptions'); +const multiWebpackConfig = require('../../fixtures/multi-compiler-config/webpack.config'); +const simpleWebpackConfig = require('../../fixtures/simple-config/webpack.config'); +const webpackConfigNoStats = require('../../fixtures/schema/webpack.config.no-dev-stats'); describe('normalizeOptions', () => { const cases = [ @@ -12,8 +15,50 @@ describe('normalizeOptions', () => { options: {}, optionsResults: null, }, + + // ------- compiler's options.devServer works ------- // + + { + title: 'compiler options.devServer', + webpackConfig: { + devServer: { + hot: true, + }, + }, + multiCompiler: false, + options: {}, + optionsResults: null, + }, + + { + title: 'complex compiler options.devServer', + webpackConfig: webpackConfigNoStats, + multiCompiler: false, + options: {}, + optionsResults: { + contentBase: path.resolve('_contentBase'), + }, + }, + + // ---- normal options override compiler's options.devServer ---- // + + { + title: 'normal options override compiler options.devServer', + webpackConfig: { + devServer: { + hot: true, + }, + }, + multiCompiler: false, + options: { + hot: false, + }, + optionsResults: null, + }, + + // ------------------ contentBase ------------------ // { - title: 'contentBase string', + title: 'contentBase (string)', multiCompiler: false, options: { contentBase: 'path/to/dist', @@ -23,7 +68,7 @@ describe('normalizeOptions', () => { }, }, { - title: 'contentBase array', + title: 'contentBase (array)', multiCompiler: false, options: { contentBase: ['path/to/dist1', 'path/to/dist2'], @@ -36,16 +81,16 @@ describe('normalizeOptions', () => { }, }, { - title: 'watchOptions', + title: 'contentBase (boolean)', multiCompiler: false, options: { - watchOptions: { - poll: true, - }, + contentBase: false, }, optionsResults: null, }, + // ------------------ watchOptions ------------------ // + { title: 'transportMode sockjs string', multiCompiler: false, @@ -123,69 +168,73 @@ describe('normalizeOptions', () => { optionsResults: null, }, { - title: 'existing options.filename, no compiler filename', + title: 'options.watchOptions', webpackConfig: null, multiCompiler: false, options: { - filename: 'devserver-bundle.js', + watchOptions: { + poll: true, + }, }, optionsResults: null, }, { - title: 'existing options.filename, existing compiler filename', + title: 'compiler watchOptions', webpackConfig: { - output: { - filename: 'mybundle.js', + watchOptions: { + poll: true, }, }, multiCompiler: false, - options: { - filename: 'devserver-bundle.js', - }, + options: {}, optionsResults: null, }, + + // ------------------ filename ------------------ // + { - title: 'multi compiler, no options.filename, no compiler filename', + title: 'no options.filename, no compiler filename', webpackConfig: null, - multiCompiler: true, + multiCompiler: false, options: {}, optionsResults: null, }, { - title: 'multi compiler, no options.filename, existing compiler filename', + title: 'no options.filename, existing compiler filename', webpackConfig: { output: { filename: 'mybundle.js', }, }, - multiCompiler: true, + multiCompiler: false, options: {}, optionsResults: null, }, { - title: 'multi compiler, existing options.filename, no compiler filename', + title: 'existing options.filename, no compiler filename', webpackConfig: null, - multiCompiler: true, + multiCompiler: false, options: { filename: 'devserver-bundle.js', }, optionsResults: null, }, { - title: - 'multi compiler, existing options.filename, existing compiler filename', + title: 'existing options.filename, existing compiler filename', webpackConfig: { output: { filename: 'mybundle.js', }, }, - multiCompiler: true, + multiCompiler: false, options: { filename: 'devserver-bundle.js', }, optionsResults: null, }, + // ------------------ publicPath ------------------ // + { title: 'no options.publicPath, no compiler publicPath', webpackConfig: null, @@ -233,151 +282,205 @@ describe('normalizeOptions', () => { options: {}, }, { - title: 'multi compiler, no options.publicPath, no compiler publicPath', - webpackConfig: null, - multiCompiler: true, - options: {}, - }, - { - title: - 'multi compiler, no options.publicPath, relative compiler publicPath', + title: 'relative options.publicPath', webpackConfig: { output: { - publicPath: '/assets/', + publicPath: '/', }, }, - multiCompiler: true, - options: {}, + multiCompiler: false, + options: { + publicPath: '/assets/', + }, }, { - title: - 'multi compiler, no options.publicPath, bad relative compiler publicPath', + title: 'bad relative options.publicPath', webpackConfig: { output: { - publicPath: 'assets/', + publicPath: '/', }, }, - multiCompiler: true, - options: {}, + multiCompiler: false, + options: { + publicPath: 'assets/', + }, }, { - title: 'multi compiler, no options.publicPath, / compiler publicPath', + title: 'absolute options.publicPath', webpackConfig: { output: { publicPath: '/', }, }, - multiCompiler: true, - options: {}, + multiCompiler: false, + options: { + publicPath: 'http://localhost:8080/assets/', + }, + }, + + // ------------------ stats ------------------ // + + { + title: 'options.stats', + webpackConfig: null, + multiCompiler: false, + options: { + stats: 'errors-only', + }, }, { - title: - 'multi compiler, no options.publicPath, absolute url compiler publicPath', + title: 'compiler stats', webpackConfig: { - output: { - publicPath: 'http://localhost:8080/assets/', - }, + stats: { errors: true }, }, - multiCompiler: true, + multiCompiler: false, options: {}, }, + + // ------------------ inline ------------------ // + { - title: 'relative options.publicPath', - webpackConfig: { - output: { - publicPath: '/', - }, + title: 'options.inline', + webpackConfig: null, + multiCompiler: false, + options: { + inline: false, }, + }, + + // ------------------ liveReload ------------------ // + + { + title: 'options.liveReload', + webpackConfig: null, multiCompiler: false, options: { - publicPath: '/assets/', + liveReload: false, }, }, + + // ------------------ open/openPage ------------------ // + { - title: 'bad relative options.publicPath', - webpackConfig: { - output: { - publicPath: '/', - }, + title: 'options.open (boolean)', + webpackConfig: null, + multiCompiler: false, + options: { + open: true, }, + }, + { + title: 'options.open (string)', + webpackConfig: null, multiCompiler: false, options: { - publicPath: 'assets/', + open: 'Google Chrome', }, }, { - title: 'absolute options.publicPath', - webpackConfig: { - output: { - publicPath: '/', - }, + title: 'options.open (empty string)', + webpackConfig: null, + multiCompiler: false, + options: { + open: '', }, + }, + { + title: 'options.openPage, no options.open', + webpackConfig: null, multiCompiler: false, options: { - publicPath: 'http://localhost:8080/assets/', + openPage: '/different/page', + }, + }, + { + title: 'options.openPage, options.open', + webpackConfig: null, + multiCompiler: false, + options: { + open: true, + openPage: '/different/page', }, }, ]; cases.forEach((data) => { - describe(data.title, () => { - let compiler; - beforeAll(() => { - // this will merge webpack configs through a depth of one layer of objects, - // specifically so that the webpack config output object can be merged - const mergeConfigs = (baseConfig, config) => { - Object.keys(config).forEach((key1) => { - if (typeof config[key1] === 'object') { - Object.keys(config[key1]).forEach((key2) => { - if (!baseConfig[key1]) { - baseConfig[key1] = {}; + let repeatWithMultiCompiler = false; + if (data.webpackConfig) { + repeatWithMultiCompiler = true; + } + + const useMultiCompiler = [false]; + + if (repeatWithMultiCompiler) { + useMultiCompiler.push(true); + } + + useMultiCompiler.forEach((multi) => { + data.multiCompiler = multi; + describe( + data.title + (data.multiCompiler ? ' (multi compiler)' : ''), + () => { + let compiler; + beforeAll(() => { + // this will merge webpack configs through a depth of one layer of objects, + // specifically so that the webpack config output object can be merged + const mergeConfigs = (baseConfig, config) => { + Object.keys(config).forEach((key1) => { + if (typeof config[key1] === 'object') { + Object.keys(config[key1]).forEach((key2) => { + if (!baseConfig[key1]) { + baseConfig[key1] = {}; + } + baseConfig[key1][key2] = config[key1][key2]; + }); + } else { + baseConfig[key1] = config[key1]; } - baseConfig[key1][key2] = config[key1][key2]; }); + }; + + let webpackConfig; + if (data.multiCompiler) { + webpackConfig = [Object.assign({}, multiWebpackConfig[0])]; } else { - baseConfig[key1] = config[key1]; + webpackConfig = Object.assign({}, simpleWebpackConfig); } - }); - }; - let webpackConfig; - if (data.multiCompiler) { - webpackConfig = require('../../fixtures/multi-compiler-config/webpack.config'); - } else { - webpackConfig = require('../../fixtures/simple-config/webpack.config'); - } + if (data.webpackConfig) { + mergeConfigs( + data.multiCompiler ? webpackConfig[0] : webpackConfig, + data.webpackConfig + ); + } - if (data.webpackConfig) { - mergeConfigs( - data.multiCompiler ? webpackConfig[0] : webpackConfig, - data.webpackConfig - ); - } + compiler = webpack(webpackConfig); + }); - compiler = webpack(webpackConfig); - }); + it('should set correct options', () => { + const optionsClone = Object.assign({}, data.options); + const originalContentBase = optionsClone.contentBase; + normalizeOptions(compiler, optionsClone); + if (data.optionsResults) { + Object.keys(data.optionsResults).forEach((key) => { + expect(optionsClone[key]).toEqual(data.optionsResults[key]); + delete optionsClone[key]; + }); + } - it('should set correct options', () => { - const originalContentBase = data.options.contentBase; - normalizeOptions(compiler, data.options); - if (data.optionsResults) { - Object.keys(data.optionsResults).forEach((key) => { - expect(data.options[key]).toEqual(data.optionsResults[key]); - delete data.options[key]; + if ( + optionsClone.contentBase && + optionsClone.contentBase !== originalContentBase + ) { + // we don't want this in the snapshot, because it is + // the current working directory + expect(optionsClone.contentBase).toEqual(process.cwd()); + delete optionsClone.contentBase; + } + expect(optionsClone).toMatchSnapshot(); }); } - - if ( - data.options.contentBase && - data.options.contentBase !== originalContentBase - ) { - // we don't want this in the snapshot, because it is - // the current working directory - expect(data.options.contentBase).toEqual(process.cwd()); - delete data.options.contentBase; - } - expect(data.options).toMatchSnapshot(); - }); + ); }); }); }); From 2f5f3b368da0ef518152cb094e70d3f83ece7a7b Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Wed, 7 Aug 2019 11:55:14 -0500 Subject: [PATCH 25/32] refactor(options): removed comments, changed eslint slightly --- lib/utils/createConfig.js | 7 ++++--- lib/utils/normalizeOptions.js | 4 +--- test/server/utils/createConfig.test.js | 8 -------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index c415babfe8..88bc8db9c6 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -1,7 +1,9 @@ 'use strict'; -// const path = require('path'); -// const isAbsoluteUrl = require('is-absolute-url'); +/* eslint-disable + no-undefined +*/ + const defaultTo = require('./defaultTo'); function createConfig(config, argv, { port }) { @@ -152,7 +154,6 @@ function createConfig(config, argv, { port }) { options.openPage = argv.openPage; } - // eslint-disable-next-line no-undefined if (argv.open !== undefined) { options.open = argv.open; } diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 59f3dba878..6c8c43c74f 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -39,7 +39,6 @@ function normalizeOptions(compiler, options) { }); if (!options.publicPath) { - // eslint-disable-next-line options.publicPath = (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; } @@ -114,8 +113,7 @@ function normalizeOptions(compiler, options) { if (options.inline === undefined) { options.inline = true; } - - // ---- The options below were already here, they are not breaking changes ---- // + // Setup default value options.contentBase = diff --git a/test/server/utils/createConfig.test.js b/test/server/utils/createConfig.test.js index 5422fc94f4..92db0b3a54 100644 --- a/test/server/utils/createConfig.test.js +++ b/test/server/utils/createConfig.test.js @@ -209,12 +209,6 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - // removed: publicPath tests - - // removed: filename tests - - // removed: watchOptions tests - it('hot option', () => { const config = createConfig( webpackConfig, @@ -281,8 +275,6 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - // removed: contentBase tests - it('watchContentBase option', () => { const config = createConfig( webpackConfig, From 80f1f33bc9e389b6f3fd2617c479909d6d268537 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Wed, 7 Aug 2019 12:02:21 -0500 Subject: [PATCH 26/32] refactor(options): move public path option setting to single line --- lib/utils/normalizeOptions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 6c8c43c74f..17a2c25fdb 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -39,8 +39,7 @@ function normalizeOptions(compiler, options) { }); if (!options.publicPath) { - options.publicPath = - (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; + options.publicPath = (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; } // moving this block out of the above (!options.publicPath) if statement From d94237384b0604fe1c315a451d4027e433e21541 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Wed, 7 Aug 2019 12:10:00 -0500 Subject: [PATCH 27/32] refactor(options): fix eslint double empty line, public path two lines --- lib/utils/normalizeOptions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 17a2c25fdb..23d2e65d6c 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -39,7 +39,8 @@ function normalizeOptions(compiler, options) { }); if (!options.publicPath) { - options.publicPath = (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; + options.publicPath = + (firstWpOpt.output && firstWpOpt.output.publicPath) || ''; } // moving this block out of the above (!options.publicPath) if statement @@ -112,7 +113,6 @@ function normalizeOptions(compiler, options) { if (options.inline === undefined) { options.inline = true; } - // Setup default value options.contentBase = From 0e5ede928b161d0e8a4d4c3f19d3c2dea5111061 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Tue, 20 Aug 2019 00:18:08 -0500 Subject: [PATCH 28/32] refactor(cli): move over more options from create config --- lib/utils/createConfig.js | 18 +- .../__snapshots__/createConfig.test.js.snap | 95 +--------- .../normalizeOptions.test.js.snap | 175 ++++++++++++++++++ test/server/utils/createConfig.test.js | 22 --- test/server/utils/normalizeOptions.test.js | 95 +++++++++- 5 files changed, 268 insertions(+), 137 deletions(-) diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index 88bc8db9c6..77f83c23ed 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -14,7 +14,7 @@ function createConfig(config, argv, { port }) { options.bonjour = true; } - if (argv.host && (argv.host !== 'localhost' || !options.host)) { + if (argv.host) { options.host = argv.host; } @@ -62,21 +62,15 @@ function createConfig(config, argv, { port }) { options.stdin = true; } - // TODO https://github.com/webpack/webpack-dev-server/issues/616 (v4) - // We should prefer CLI arg under config, now we always prefer `hot` from `devServer` - if (!options.hot) { - options.hot = argv.hot; + if (argv.hot) { + options.hot = true; } - // TODO https://github.com/webpack/webpack-dev-server/issues/616 (v4) - // We should prefer CLI arg under config, now we always prefer `hotOnly` from `devServer` - if (!options.hotOnly) { - options.hotOnly = argv.hotOnly; + if (argv.hotOnly) { + options.hotOnly = true; } - // TODO https://github.com/webpack/webpack-dev-server/issues/616 (v4) - // We should prefer CLI arg under config, now we always prefer `clientLogLevel` from `devServer` - if (!options.clientLogLevel && argv.clientLogLevel) { + if (argv.clientLogLevel) { options.clientLogLevel = argv.clientLogLevel; } diff --git a/test/server/utils/__snapshots__/createConfig.test.js.snap b/test/server/utils/__snapshots__/createConfig.test.js.snap index 5514400d5d..72ebc3679f 100644 --- a/test/server/utils/__snapshots__/createConfig.test.js.snap +++ b/test/server/utils/__snapshots__/createConfig.test.js.snap @@ -7,7 +7,6 @@ Object { "host2.com", ], "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -20,7 +19,6 @@ Object { "host2.com", ], "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -30,7 +28,6 @@ exports[`createConfig bonjour option (devServer config) 1`] = ` Object { "bonjour": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -40,7 +37,6 @@ exports[`createConfig bonjour option 1`] = ` Object { "bonjour": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -50,7 +46,6 @@ exports[`createConfig cacert option (in devServer config) 1`] = ` Object { "ca": "/path/to/ca.pem", "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "port": 8080, @@ -61,7 +56,6 @@ exports[`createConfig cacert option 1`] = ` Object { "ca": "/path/to/ca.pem", "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "port": 8080, @@ -72,7 +66,6 @@ exports[`createConfig cert option (in devServer config) 1`] = ` Object { "cert": "/path/to/server.crt", "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "port": 8080, @@ -83,7 +76,6 @@ exports[`createConfig cert option 1`] = ` Object { "cert": "/path/to/server.crt", "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "port": 8080, @@ -94,7 +86,6 @@ exports[`createConfig clientLogLevel option (in devServer config) 1`] = ` Object { "clientLogLevel": "none", "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -104,7 +95,6 @@ exports[`createConfig clientLogLevel option 1`] = ` Object { "clientLogLevel": "none", "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -114,7 +104,6 @@ exports[`createConfig compress option (in devServer config) 1`] = ` Object { "compress": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -124,7 +113,6 @@ exports[`createConfig compress option 1`] = ` Object { "compress": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -134,7 +122,6 @@ exports[`createConfig disableHostCheck option (in devServer config) 1`] = ` Object { "disableHostCheck": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -144,7 +131,6 @@ exports[`createConfig disableHostCheck option 1`] = ` Object { "disableHostCheck": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -154,7 +140,6 @@ exports[`createConfig historyApiFallback option (in devServer config) 1`] = ` Object { "historyApiFallback": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -164,7 +149,6 @@ exports[`createConfig historyApiFallback option 1`] = ` Object { "historyApiFallback": true, "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -174,7 +158,6 @@ exports[`createConfig host option (devServer config) 1`] = ` Object { "host": "example.dev", "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -184,7 +167,6 @@ exports[`createConfig host option (localhost) 1`] = ` Object { "host": "localhost", "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -193,7 +175,6 @@ Object { exports[`createConfig host option (null) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -203,7 +184,6 @@ exports[`createConfig host option (specify for CLI and devServer config) 1`] = ` Object { "host": "other.dev", "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -212,7 +192,6 @@ Object { exports[`createConfig host option (undefined) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -222,25 +201,6 @@ exports[`createConfig host option 1`] = ` Object { "host": "example.dev", "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, -} -`; - -exports[`createConfig hot option (in devServer config) 1`] = ` -Object { - "hot": true, - "hotOnly": false, - "noInfo": true, - "port": 8080, -} -`; - -exports[`createConfig hot option 1`] = ` -Object { - "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -267,7 +227,6 @@ Object { exports[`createConfig http2 option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "http2": true, "https": true, "noInfo": true, @@ -278,7 +237,6 @@ Object { exports[`createConfig http2 option 1`] = ` Object { "hot": true, - "hotOnly": false, "http2": true, "https": true, "noInfo": true, @@ -289,7 +247,6 @@ Object { exports[`createConfig https option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "port": 8080, @@ -299,7 +256,6 @@ Object { exports[`createConfig https option (in devServer config) 2`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "pfxPassphrase": "passphrase", "port": 8080, @@ -309,7 +265,6 @@ Object { exports[`createConfig https option 1`] = ` Object { "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "port": 8080, @@ -319,7 +274,6 @@ Object { exports[`createConfig info option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -328,7 +282,6 @@ Object { exports[`createConfig info option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -337,7 +290,6 @@ Object { exports[`createConfig inline option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "inline": false, "noInfo": true, "port": 8080, @@ -347,7 +299,6 @@ Object { exports[`createConfig inline option 1`] = ` Object { "hot": true, - "hotOnly": false, "inline": false, "noInfo": true, "port": 8080, @@ -357,7 +308,6 @@ Object { exports[`createConfig key option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "https": true, "key": "/path/to/server.key", "noInfo": true, @@ -368,7 +318,6 @@ Object { exports[`createConfig key option 1`] = ` Object { "hot": true, - "hotOnly": false, "https": true, "key": "/path/to/server.key", "noInfo": true, @@ -379,7 +328,6 @@ Object { exports[`createConfig lazy option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "lazy": true, "noInfo": true, "port": 8080, @@ -389,7 +337,6 @@ Object { exports[`createConfig lazy option 1`] = ` Object { "hot": true, - "hotOnly": false, "lazy": true, "noInfo": true, "port": 8080, @@ -399,7 +346,6 @@ Object { exports[`createConfig liveReload option 1`] = ` Object { "hot": true, - "hotOnly": false, "liveReload": false, "noInfo": true, "port": 8080, @@ -409,7 +355,6 @@ Object { exports[`createConfig mimeTypes option - with force 1`] = ` Object { "hot": true, - "hotOnly": false, "mimeTypes": Object { "force": true, "typeMap": Object { @@ -426,7 +371,6 @@ Object { exports[`createConfig mimeTypes option 1`] = ` Object { "hot": true, - "hotOnly": false, "mimeTypes": Object { "text/html": Array [ "phtml", @@ -440,7 +384,6 @@ Object { exports[`createConfig onListening option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "onListening": [Function], "port": 8080, @@ -450,7 +393,6 @@ Object { exports[`createConfig open option (boolean) (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "open": true, "port": 8080, @@ -460,7 +402,6 @@ Object { exports[`createConfig open option (boolean) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "open": true, "port": 8080, @@ -470,7 +411,6 @@ Object { exports[`createConfig open option (browser) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "open": "Google Chrome", "port": 8080, @@ -480,7 +420,6 @@ Object { exports[`createConfig openPage option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "open": true, "openPage": "/different/page", @@ -491,7 +430,6 @@ Object { exports[`createConfig openPage option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "openPage": "/different/page", "port": 8080, @@ -501,7 +439,6 @@ Object { exports[`createConfig overlay option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "overlay": true, "port": 8080, @@ -511,7 +448,6 @@ Object { exports[`createConfig overlay option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "overlay": true, "port": 8080, @@ -521,7 +457,6 @@ Object { exports[`createConfig pfx option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "pfx": "/path/to/file.pfx", @@ -532,7 +467,6 @@ Object { exports[`createConfig pfx option 1`] = ` Object { "hot": true, - "hotOnly": false, "https": true, "noInfo": true, "pfx": "/path/to/file.pfx", @@ -543,7 +477,6 @@ Object { exports[`createConfig pfxPassphrase option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "pfxPassphrase": "passphrase", "port": 8080, @@ -553,7 +486,6 @@ Object { exports[`createConfig port option (difference) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 7070, } @@ -562,7 +494,6 @@ Object { exports[`createConfig port option (same) (null) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": null, } @@ -571,7 +502,6 @@ Object { exports[`createConfig port option (same) (string) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": "9090", } @@ -580,7 +510,6 @@ Object { exports[`createConfig port option (same) (undefined) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": undefined, } @@ -589,7 +518,6 @@ Object { exports[`createConfig port option (same) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 9090, } @@ -598,7 +526,6 @@ Object { exports[`createConfig profile option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "profile": "profile", @@ -608,7 +535,6 @@ Object { exports[`createConfig progress option (devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "progress": true, @@ -618,7 +544,6 @@ Object { exports[`createConfig progress option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "progress": true, @@ -628,7 +553,6 @@ Object { exports[`createConfig public option (devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "public": true, @@ -638,7 +562,6 @@ Object { exports[`createConfig public option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "public": true, @@ -648,7 +571,6 @@ Object { exports[`createConfig quiet option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "quiet": true, @@ -658,7 +580,6 @@ Object { exports[`createConfig quiet option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "quiet": true, @@ -668,7 +589,6 @@ Object { exports[`createConfig simple 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, } @@ -677,7 +597,6 @@ Object { exports[`createConfig sockHost option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "sockHost": true, @@ -687,7 +606,6 @@ Object { exports[`createConfig sockPath option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "sockPath": "path", @@ -697,7 +615,6 @@ Object { exports[`createConfig sockPort option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "sockPort": "port", @@ -707,7 +624,6 @@ Object { exports[`createConfig socket option (devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "socket": "socket", @@ -717,7 +633,6 @@ Object { exports[`createConfig socket option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "socket": "socket", @@ -727,7 +642,6 @@ Object { exports[`createConfig stats option (colors) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "stats": Object { @@ -740,7 +654,6 @@ Object { exports[`createConfig stats option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "stats": "errors-only", @@ -756,7 +669,7 @@ Object { "filename": "_filename", "historyApiFallback": "_historyApiFallback", "host": "_foo", - "hot": "_hot", + "hot": true, "hotOnly": "_hotOnly", "https": "_https", "inline": "_inline", @@ -786,7 +699,7 @@ Object { "filename": "_filename", "historyApiFallback": "_historyApiFallback", "host": "_foo", - "hot": "_hot", + "hot": true, "hotOnly": "_hotOnly", "https": "_https", "inline": "_inline", @@ -814,7 +727,6 @@ Object { exports[`createConfig useLocalIp option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "useLocalIp": true, @@ -824,7 +736,6 @@ Object { exports[`createConfig useLocalIp option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "useLocalIp": true, @@ -834,7 +745,6 @@ Object { exports[`createConfig watchContentBase option (in devServer config) 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "watchContentBase": true, @@ -844,7 +754,6 @@ Object { exports[`createConfig watchContentBase option 1`] = ` Object { "hot": true, - "hotOnly": false, "noInfo": true, "port": 8080, "watchContentBase": true, diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap index b3b43f6cdf..a9afdf5846 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap @@ -74,6 +74,7 @@ Object { exports[`normalizeOptions compiler options.devServer (multi compiler) should set correct options 1`] = ` Object { + "clientLogLevel": "silent", "filename": "[name].js", "hot": true, "inline": true, @@ -93,6 +94,7 @@ Object { exports[`normalizeOptions compiler options.devServer should set correct options 1`] = ` Object { + "clientLogLevel": "silent", "filename": "[name].js", "hot": true, "inline": true, @@ -657,6 +659,7 @@ Object { exports[`normalizeOptions normal options override compiler options.devServer (multi compiler) should set correct options 1`] = ` Object { + "clientLogLevel": "debug", "filename": "[name].js", "hot": false, "inline": true, @@ -676,6 +679,7 @@ Object { exports[`normalizeOptions normal options override compiler options.devServer should set correct options 1`] = ` Object { + "clientLogLevel": "debug", "filename": "[name].js", "hot": false, "inline": true, @@ -693,6 +697,177 @@ Object { } `; +exports[`normalizeOptions options.clientLogLevel overrides compiler options.devServer.clientLogLevel (multi compiler) should set correct options 1`] = ` +Object { + "clientLogLevel": "debug", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.clientLogLevel overrides compiler options.devServer.clientLogLevel should set correct options 1`] = ` +Object { + "clientLogLevel": "debug", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.host localhost overrides compiler options.devServer.host (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "host": "localhost", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.host localhost overrides compiler options.devServer.host should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "host": "localhost", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.host should set correct options 1`] = ` +Object { + "filename": "[name].js", + "host": "0.0.0.0", + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.hot overrides compiler options.devServer.hot (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "hot": false, + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.hot overrides compiler options.devServer.hot should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "hot": false, + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.hotOnly overrides compiler options.devServer.hotOnly (multi compiler) should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "hotOnly": false, + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.hotOnly overrides compiler options.devServer.hotOnly should set correct options 1`] = ` +Object { + "filename": "mybundle.js", + "hotOnly": false, + "inline": true, + "liveReload": true, + "publicPath": "/", + "stats": Object { + "cached": false, + "cachedAssets": false, + }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, + "watchOptions": Object {}, +} +`; + exports[`normalizeOptions options.inline should set correct options 1`] = ` Object { "filename": "[name].js", diff --git a/test/server/utils/createConfig.test.js b/test/server/utils/createConfig.test.js index 92db0b3a54..7dee1abb50 100644 --- a/test/server/utils/createConfig.test.js +++ b/test/server/utils/createConfig.test.js @@ -209,28 +209,6 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - it('hot option', () => { - const config = createConfig( - webpackConfig, - Object.assign({}, argv, { hot: true }), - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - - it('hot option (in devServer config)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { hot: true }, - }), - argv, - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - it('hotOnly option', () => { const config = createConfig( webpackConfig, diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index d24ca30bfc..7abf134f2a 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -16,13 +16,14 @@ describe('normalizeOptions', () => { optionsResults: null, }, - // ------- compiler's options.devServer works ------- // + // compiler's options.devServer works { title: 'compiler options.devServer', webpackConfig: { devServer: { hot: true, + clientLogLevel: 'silent', }, }, multiCompiler: false, @@ -40,23 +41,25 @@ describe('normalizeOptions', () => { }, }, - // ---- normal options override compiler's options.devServer ---- // + // normal options override compiler's options.devServer { title: 'normal options override compiler options.devServer', webpackConfig: { devServer: { hot: true, + clientLogLevel: 'silent', }, }, multiCompiler: false, options: { hot: false, + clientLogLevel: 'debug', }, optionsResults: null, }, - // ------------------ contentBase ------------------ // + // contentBase { title: 'contentBase (string)', multiCompiler: false, @@ -89,7 +92,7 @@ describe('normalizeOptions', () => { optionsResults: null, }, - // ------------------ watchOptions ------------------ // + // watchOptions { title: 'transportMode sockjs string', @@ -190,7 +193,7 @@ describe('normalizeOptions', () => { optionsResults: null, }, - // ------------------ filename ------------------ // + // filename { title: 'no options.filename, no compiler filename', @@ -233,7 +236,7 @@ describe('normalizeOptions', () => { optionsResults: null, }, - // ------------------ publicPath ------------------ // + // publicPath { title: 'no options.publicPath, no compiler publicPath', @@ -318,7 +321,7 @@ describe('normalizeOptions', () => { }, }, - // ------------------ stats ------------------ // + // stats { title: 'options.stats', @@ -337,7 +340,7 @@ describe('normalizeOptions', () => { options: {}, }, - // ------------------ inline ------------------ // + // inline { title: 'options.inline', @@ -348,7 +351,7 @@ describe('normalizeOptions', () => { }, }, - // ------------------ liveReload ------------------ // + // liveReload { title: 'options.liveReload', @@ -359,7 +362,7 @@ describe('normalizeOptions', () => { }, }, - // ------------------ open/openPage ------------------ // + // open/openPage { title: 'options.open (boolean)', @@ -402,6 +405,78 @@ describe('normalizeOptions', () => { openPage: '/different/page', }, }, + + // host + + // this test is here because previously devServer.host would override CLI host option + // only if CLI's options.host was localhost. Since we want a firm stance that + // normal/CLI options always override the compiler's devServer options, this is no + // longer the case. + { + title: 'options.host localhost overrides compiler options.devServer.host', + webpackConfig: { + devServer: { + host: '0.0.0.0', + }, + }, + multiCompiler: false, + options: { + host: 'localhost', + }, + optionsResults: null, + }, + { + title: 'options.host', + webpackConfig: null, + multiCompiler: false, + options: { + host: '0.0.0.0', + }, + optionsResults: null, + }, + + { + title: 'options.hot overrides compiler options.devServer.hot', + webpackConfig: { + devServer: { + hot: true, + }, + }, + multiCompiler: false, + options: { + hot: false, + }, + optionsResults: null, + }, + + { + title: 'options.hotOnly overrides compiler options.devServer.hotOnly', + webpackConfig: { + devServer: { + hotOnly: true, + }, + }, + multiCompiler: false, + options: { + hotOnly: false, + }, + optionsResults: null, + }, + + { + title: + 'options.clientLogLevel overrides compiler options.devServer.clientLogLevel', + webpackConfig: { + devServer: { + clientLogLevel: 'silent', + }, + }, + multiCompiler: false, + options: { + clientLogLevel: 'debug', + }, + optionsResults: null, + }, ]; cases.forEach((data) => { From e7ab9f141c1af4647d5b41482025a78daadc8379 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Thu, 22 Aug 2019 13:11:24 -0500 Subject: [PATCH 29/32] style(cli): add eslint no undefined for single line only --- lib/utils/createConfig.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index 77f83c23ed..8bdde50afe 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -1,9 +1,5 @@ 'use strict'; -/* eslint-disable - no-undefined -*/ - const defaultTo = require('./defaultTo'); function createConfig(config, argv, { port }) { @@ -148,6 +144,7 @@ function createConfig(config, argv, { port }) { options.openPage = argv.openPage; } + // eslint-disable-next-line no-undefined if (argv.open !== undefined) { options.open = argv.open; } From c674e8783d435705d1c5757b1558a00187a2589d Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Tue, 10 Sep 2019 12:06:22 -0500 Subject: [PATCH 30/32] refactor(stats): moved stats and colors handling to normalize options --- lib/utils/createConfig.js | 8 - lib/utils/normalizeOptions.js | 17 +- .../__snapshots__/createConfig.test.js.snap | 12 - .../normalizeOptions.test.js.snap | 234 ++++++++++++++++++ test/server/utils/createConfig.test.js | 12 - test/server/utils/normalizeOptions.test.js | 94 +++++++ 6 files changed, 343 insertions(+), 34 deletions(-) diff --git a/lib/utils/createConfig.js b/lib/utils/createConfig.js index 8bdde50afe..b5e7eedc68 100644 --- a/lib/utils/createConfig.js +++ b/lib/utils/createConfig.js @@ -74,14 +74,6 @@ function createConfig(config, argv, { port }) { options.watchContentBase = true; } - if ( - typeof options.stats === 'object' && - typeof options.stats.colors === 'undefined' && - argv.color - ) { - options.stats = Object.assign({}, options.stats, { colors: argv.color }); - } - if (argv.lazy) { options.lazy = true; } diff --git a/lib/utils/normalizeOptions.js b/lib/utils/normalizeOptions.js index 23d2e65d6c..466fb670be 100644 --- a/lib/utils/normalizeOptions.js +++ b/lib/utils/normalizeOptions.js @@ -6,6 +6,7 @@ const path = require('path'); const isAbsoluteUrl = require('is-absolute-url'); +const supportsColor = require('supports-color').stdout; const defaultTo = require('./defaultTo'); function normalizeOptions(compiler, options) { @@ -91,8 +92,20 @@ function normalizeOptions(compiler, options) { }); } - // consider retrieving the webpack config's color option, and remove the dev server - // CLI color option entirely. + // the fallback for the color value is whether or not the user's console + // supports color, so usually true (supportsColor is an object but we just want a boolean) + let colors = !!supportsColor; + if ( + typeof firstWpOpt.stats === 'object' && + firstWpOpt.stats.colors !== undefined + ) { + // firstWpOpt.stats.colors could be an object but we just want a boolean + colors = !!firstWpOpt.stats.colors; + } + + if (typeof options.stats === 'object' && options.stats.colors === undefined) { + options.stats = Object.assign({}, options.stats, { colors }); + } if (options.openPage) { options.open = true; diff --git a/test/server/utils/__snapshots__/createConfig.test.js.snap b/test/server/utils/__snapshots__/createConfig.test.js.snap index 72ebc3679f..b95e10e224 100644 --- a/test/server/utils/__snapshots__/createConfig.test.js.snap +++ b/test/server/utils/__snapshots__/createConfig.test.js.snap @@ -639,18 +639,6 @@ Object { } `; -exports[`createConfig stats option (colors) 1`] = ` -Object { - "hot": true, - "noInfo": true, - "port": 8080, - "stats": Object { - "colors": true, - "errors": true, - }, -} -`; - exports[`createConfig stats option 1`] = ` Object { "hot": true, diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap index a9afdf5846..4330e42bce 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap @@ -9,6 +9,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -27,6 +28,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -45,6 +47,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -63,6 +66,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -83,6 +87,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -103,6 +108,157 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.devServer.stats (multi compiler) should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.devServer.stats overrides compiler options.stats (multi compiler) should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.devServer.stats overrides compiler options.stats should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.devServer.stats should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.stats (multi compiler) should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": "none", + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.stats should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": "none", + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.stats.colors does not override options.stats.colors (multi compiler) should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "cached": true, + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.stats.colors does not override options.stats.colors should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "cached": true, + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.stats.colors used (multi compiler) should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "cached": true, + "colors": false, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions compiler options.stats.colors used should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "cached": true, + "colors": false, }, "transportMode": Object { "client": "sockjs", @@ -119,6 +275,7 @@ Object { "liveReload": true, "publicPath": "/", "stats": Object { + "colors": true, "errors": true, }, "transportMode": Object { @@ -136,6 +293,7 @@ Object { "liveReload": true, "publicPath": "/", "stats": Object { + "colors": true, "errors": true, }, "transportMode": Object { @@ -155,6 +313,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -175,6 +334,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -212,6 +372,7 @@ Object { "socket": "_socket", "stats": Object { "assetsSort": "size", + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -249,6 +410,7 @@ Object { "socket": "_socket", "stats": Object { "assetsSort": "size", + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -269,6 +431,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -288,6 +451,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -306,6 +470,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -324,6 +489,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -342,6 +508,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -360,6 +527,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -378,6 +546,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -396,6 +565,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -432,6 +602,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -468,6 +639,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -504,6 +676,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -522,6 +695,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -540,6 +714,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -558,6 +733,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -576,6 +752,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -594,6 +771,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -612,6 +790,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -630,6 +809,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -648,6 +828,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -668,6 +849,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -688,6 +870,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -707,6 +890,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -726,6 +910,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -745,6 +930,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -764,6 +950,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -783,6 +970,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -802,6 +990,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -821,6 +1010,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -840,6 +1030,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -859,6 +1050,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -877,6 +1069,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -895,6 +1088,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -915,6 +1109,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -935,6 +1130,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -955,6 +1151,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -975,6 +1172,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -995,6 +1193,39 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.stats overrides compiler options.devServer.stats (multi compiler) should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "cached": true, + "colors": true, + }, + "watchOptions": Object {}, +} +`; + +exports[`normalizeOptions options.stats overrides compiler options.devServer.stats should set correct options 1`] = ` +Object { + "clientMode": "sockjs", + "filename": "mybundle.js", + "inline": true, + "liveReload": true, + "publicPath": "/", + "serverMode": "sockjs", + "stats": Object { + "cached": true, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -1028,6 +1259,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -1048,6 +1280,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -1066,6 +1299,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", diff --git a/test/server/utils/createConfig.test.js b/test/server/utils/createConfig.test.js index 7dee1abb50..cc9342419a 100644 --- a/test/server/utils/createConfig.test.js +++ b/test/server/utils/createConfig.test.js @@ -287,18 +287,6 @@ describe('createConfig', () => { expect(config).toMatchSnapshot(); }); - it('stats option (colors)', () => { - const config = createConfig( - Object.assign({}, webpackConfig, { - devServer: { stats: { errors: true } }, - }), - Object.assign({}, argv, { color: true }), - { port: 8080 } - ); - - expect(config).toMatchSnapshot(); - }); - it('lazy option', () => { const config = createConfig( webpackConfig, diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index 7abf134f2a..fc362a8422 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -477,6 +477,100 @@ describe('normalizeOptions', () => { }, optionsResults: null, }, + + { + title: 'compiler options.devServer.stats', + webpackConfig: { + devServer: { + stats: { + colors: true, + }, + }, + }, + multiCompiler: false, + options: {}, + optionsResults: null, + }, + { + title: 'options.stats overrides compiler options.devServer.stats', + webpackConfig: { + devServer: { + // this stats object should not be used + stats: { + colors: true, + }, + }, + }, + multiCompiler: false, + options: { + stats: { + cached: true, + }, + }, + optionsResults: null, + }, + { + title: + 'compiler options.devServer.stats overrides compiler options.stats', + webpackConfig: { + devServer: { + stats: { + colors: true, + }, + }, + // this stats object should not be used for the dev server + stats: 'none', + }, + multiCompiler: false, + options: {}, + optionsResults: null, + }, + { + title: 'compiler options.stats', + webpackConfig: { + stats: 'none', + }, + multiCompiler: false, + options: {}, + optionsResults: null, + }, + + { + title: + 'compiler options.stats.colors does not override options.stats.colors', + webpackConfig: { + stats: { + // colors for the dev server will be true, because the main options object + // explicitly sets colors to true below + colors: false, + }, + }, + multiCompiler: false, + options: { + stats: { + colors: true, + cached: true, + }, + }, + optionsResults: null, + }, + { + title: 'compiler options.stats.colors used', + webpackConfig: { + stats: { + // colors for the dev server will be false, because the main options object + // does not set colors below + colors: false, + }, + }, + multiCompiler: false, + options: { + stats: { + cached: true, + }, + }, + optionsResults: null, + }, ]; cases.forEach((data) => { From 3e8d32c74fb4c86d66e8d29e45bbdae4967ab45b Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Tue, 10 Sep 2019 20:35:28 -0500 Subject: [PATCH 31/32] test(options): update normalize options snapshot --- .../normalizeOptions.test.js.snap | 81 +++++++++++++------ 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap index 4330e42bce..5561d85c86 100644 --- a/test/server/utils/__snapshots__/normalizeOptions.test.js.snap +++ b/test/server/utils/__snapshots__/normalizeOptions.test.js.snap @@ -110,152 +110,172 @@ Object { "cachedAssets": false, "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.devServer.stats (multi compiler) should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.devServer.stats overrides compiler options.stats (multi compiler) should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.devServer.stats overrides compiler options.stats should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.devServer.stats should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.stats (multi compiler) should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": "none", + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.stats should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": "none", + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.stats.colors does not override options.stats.colors (multi compiler) should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "cached": true, "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.stats.colors does not override options.stats.colors should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "cached": true, "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.stats.colors used (multi compiler) should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "cached": true, "colors": false, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions compiler options.stats.colors used should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "cached": true, "colors": false, @@ -584,6 +604,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -621,6 +642,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -658,6 +680,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -1195,34 +1218,38 @@ Object { "cachedAssets": false, "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions options.stats overrides compiler options.devServer.stats (multi compiler) should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "cached": true, "colors": true, }, + "transportMode": Object { + "client": "sockjs", + "server": "sockjs", + }, "watchOptions": Object {}, } `; exports[`normalizeOptions options.stats overrides compiler options.devServer.stats should set correct options 1`] = ` Object { - "clientMode": "sockjs", "filename": "mybundle.js", "inline": true, "liveReload": true, "publicPath": "/", - "serverMode": "sockjs", "stats": Object { "cached": true, "colors": true, @@ -1318,6 +1345,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "/path/to/custom/client/", @@ -1336,6 +1364,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -1354,6 +1383,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -1372,6 +1402,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "sockjs", @@ -1390,6 +1421,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "ws", @@ -1408,6 +1440,7 @@ Object { "stats": Object { "cached": false, "cachedAssets": false, + "colors": true, }, "transportMode": Object { "client": "ws", From 69aa91162af37396aabd2fd1139dda210150dd94 Mon Sep 17 00:00:00 2001 From: Kirill Nagaitsev Date: Tue, 10 Sep 2019 21:09:55 -0500 Subject: [PATCH 32/32] test(options): mock supports color and fix transport mode --- test/server/__snapshots__/transportMode-option.test.js.snap | 2 +- test/server/utils/normalizeOptions.test.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/server/__snapshots__/transportMode-option.test.js.snap b/test/server/__snapshots__/transportMode-option.test.js.snap index 0a07287ada..baf012714c 100644 --- a/test/server/__snapshots__/transportMode-option.test.js.snap +++ b/test/server/__snapshots__/transportMode-option.test.js.snap @@ -87,7 +87,7 @@ Array [ Object { "foo": "bar", }, - "{\\"type\\":\\"liveReload\\"}", + "{\\"type\\":\\"liveReload\\",\\"data\\":true}", ] `; diff --git a/test/server/utils/normalizeOptions.test.js b/test/server/utils/normalizeOptions.test.js index fc362a8422..d3c27bc5fb 100644 --- a/test/server/utils/normalizeOptions.test.js +++ b/test/server/utils/normalizeOptions.test.js @@ -2,12 +2,16 @@ const path = require('path'); const webpack = require('webpack'); -const normalizeOptions = require('../../../lib/utils/normalizeOptions'); const multiWebpackConfig = require('../../fixtures/multi-compiler-config/webpack.config'); const simpleWebpackConfig = require('../../fixtures/simple-config/webpack.config'); const webpackConfigNoStats = require('../../fixtures/schema/webpack.config.no-dev-stats'); describe('normalizeOptions', () => { + jest.setMock('supports-color', { + stdout: true, + }); + const normalizeOptions = require('../../../lib/utils/normalizeOptions'); + const cases = [ { title: 'no options',