diff --git a/.eslintrc b/.eslintrc index e1337ccf95..096f7c8ab0 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/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/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 388c25fef1..5824bc9af9 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 1ae8ecf2fb..6b4e5acf91 100644 --- a/client-src/clients/WebsocketClient.js +++ b/client-src/clients/WebsocketClient.js @@ -1,5 +1,3 @@ -'use strict'; - const BaseClient = require('./BaseClient'); module.exports = class WebsocketClient extends BaseClient {}; 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..39963a246b 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', @@ -96,7 +94,7 @@ function ensureOverlayDivExists(onOverlayDivReady) { } // Successful compilation. -function clear() { +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 = `= 2.1.2 < 3" @@ -5424,6 +5693,7 @@ "ignore-walk": { "version": "3.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "minimatch": "^3.0.4" @@ -5432,6 +5702,7 @@ "inflight": { "version": "1.0.6", "bundled": true, + "dev": true, "optional": true, "requires": { "once": "^1.3.0", @@ -5441,16 +5712,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" @@ -5459,11 +5733,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" @@ -5472,11 +5748,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", @@ -5486,6 +5764,7 @@ "minizlib": { "version": "1.2.1", "bundled": true, + "dev": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -5494,6 +5773,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "dev": true, "optional": true, "requires": { "minimist": "0.0.8" @@ -5502,11 +5782,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", @@ -5517,6 +5799,7 @@ "node-pre-gyp": { "version": "0.12.0", "bundled": true, + "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", @@ -5534,6 +5817,7 @@ "nopt": { "version": "4.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "abbrev": "1", @@ -5543,11 +5827,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", @@ -5557,6 +5843,7 @@ "npmlog": { "version": "4.1.2", "bundled": true, + "dev": true, "optional": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -5568,16 +5855,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" @@ -5586,16 +5876,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", @@ -5605,16 +5898,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", @@ -5626,6 +5922,7 @@ "minimist": { "version": "1.2.0", "bundled": true, + "dev": true, "optional": true } } @@ -5633,6 +5930,7 @@ "readable-stream": { "version": "2.3.6", "bundled": true, + "dev": true, "optional": true, "requires": { "core-util-is": "~1.0.0", @@ -5647,6 +5945,7 @@ "rimraf": { "version": "2.6.3", "bundled": true, + "dev": true, "optional": true, "requires": { "glob": "^7.1.3" @@ -5655,36 +5954,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", @@ -5695,6 +6001,7 @@ "string_decoder": { "version": "1.1.1", "bundled": true, + "dev": true, "optional": true, "requires": { "safe-buffer": "~5.1.0" @@ -5703,6 +6010,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "ansi-regex": "^2.0.0" @@ -5711,11 +6019,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", @@ -5730,11 +6040,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" @@ -5743,11 +6055,13 @@ "wrappy": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, + "dev": true, "optional": true } } @@ -6126,6 +6440,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" @@ -6135,6 +6450,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" } @@ -6195,6 +6511,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, "requires": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -6206,14 +6523,16 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, "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", @@ -6893,11 +7212,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": { @@ -8499,6 +8818,11 @@ "readable-stream": "^2.0.1" } }, + "merge2": { + "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", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -8685,6 +9009,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": { @@ -8935,7 +9260,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", @@ -9040,10 +9366,10 @@ } } }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "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" } @@ -9173,10 +9499,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" } }, @@ -9281,7 +9608,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", @@ -9356,6 +9684,11 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==" + }, "pidtree": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", @@ -9365,17 +9698,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" } @@ -9708,6 +10044,15 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true + }, + "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" + } } } }, @@ -9873,13 +10218,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.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.0.2.tgz", + "integrity": "sha512-LbyJYv48eywrhOlScq16H/VkCiGKGPC2TpOdZCJ7QXnYEjn3NN/Oblh8QEU3vqfSRBB7OGvh5x45NKiVeNujIQ==", "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "picomatch": "^2.0.4" } }, "realpath-native": { @@ -10018,7 +10361,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", @@ -10218,6 +10562,11 @@ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -10257,6 +10606,11 @@ "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", "dev": true }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", @@ -11811,7 +12165,8 @@ "upath": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==" + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "dev": true }, "upper-case": { "version": "1.1.3", @@ -11849,9 +12204,9 @@ } }, "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.0.0", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.0.0.tgz", + "integrity": "sha512-RT3cz+Lw+kFMCKLabMyogFrc/aRoAMJHmY5os1VDBlav+4t5vxUxKDn47zCSFAYAl+hM8YLg4TZwG4TkJaafkg==", "dev": true, "requires": { "loader-utils": "^1.1.0", @@ -11860,9 +12215,9 @@ }, "dependencies": { "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 } } @@ -11986,6 +12341,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.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", + "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": { @@ -12312,12 +12715,12 @@ } }, "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.0.1.tgz", + "integrity": "sha512-ILHfMbuqLJvnSgYXLgy4kMntroJpe8hT41dOVWM8bxRuw6TK4mgMp9VJUNsZTEc5Bh+Mbs0DJT4M0N+wBG9l9A==", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "^1.0.0" } }, "xml": { diff --git a/package.json b/package.json index f34c3ddf83..b3fe1355b0 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", @@ -37,11 +37,11 @@ "dependencies": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", - "chokidar": "^2.1.6", + "chokidar": "^3.0.1", "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", @@ -51,8 +51,8 @@ "is-absolute-url": "^3.0.0", "killable": "^1.0.1", "loglevel": "^1.6.3", - "opn": "^5.5.0", - "p-retry": "^3.0.1", + "open": "^6.2.0", + "p-retry": "^4.1.0", "portfinder": "^1.0.20", "schema-utils": "^1.0.0", "selfsigned": "^1.10.4", @@ -85,7 +85,7 @@ "eslint-config-webpack": "^1.2.5", "eslint-plugin-import": "^2.17.3", "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": "^2.5.0", @@ -105,10 +105,10 @@ "style-loader": "^0.23.1", "supertest": "^4.0.2", "tcp-port-used": "^1.0.1", - "url-loader": "^1.1.2", "webpack": "^4.35.0", "webpack-cli": "^3.3.5", - "ws": "^6.2.1" + "url-loader": "^2.0.0", + "ws": "^7.0.0" }, "peerDependencies": { "webpack": "^4.0.0" diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index 8bd1e04ddd..404cff789c 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,108 +15,74 @@ 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); - done(); - }) - .catch(done); + it('--progress', async () => { + const { code, stderr } = await testBin('--progress'); + expect(code).toEqual(0); + expect(stderr.includes('0% compiling')).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( - output.stdout.includes('http://localhost&sockPath=/mysockPath') - ).toEqual(true); - done(); - }) - .catch(done); + it('--sockPath', async () => { + const { stdout } = await testBin('--sockPath /mysockPath'); + expect(stdout.includes('http://localhost&sockPath=/mysockPath')).toBe(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); - 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); + if (process.platform !== 'win32') { + expect(stdout.includes(socketPath)).toBe(true); + + 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 a5b667c03a..62817459da 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', () => { @@ -25,13 +26,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`); @@ -47,19 +47,16 @@ describe('SockJSClient', () => { data.push(msg); }); - setTimeout(() => { - expect(data.length).toEqual(3); - expect(data[0]).toEqual('open'); - expect(data[1]).toEqual('hello world'); - expect(data[2]).toEqual('close'); - done(); - }, 3000); + await timer(3000); + + expect(data.length).toEqual(3); + expect(data[0]).toEqual('open'); + expect(data[1]).toEqual('hello world'); + expect(data[2]).toEqual('close'); }); }); afterAll((done) => { - listeningApp.close(() => { - done(); - }); + listeningApp.close(done); }); }); 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/createSocketUrl.test.js b/test/client/utils/createSocketUrl.test.js index 892e8204eb..b521242c76 100644 --- a/test/client/utils/createSocketUrl.test.js +++ b/test/client/utils/createSocketUrl.test.js @@ -21,8 +21,10 @@ describe('createSocketUrl', () => { () => () => url ); - // eslint-disable-next-line global-require - const createSocketUrl = require('../../../client-src/default/utils/createSocketUrl'); + const { + default: createSocketUrl, + // eslint-disable-next-line global-require + } = require('../../../client-src/default/utils/createSocketUrl'); test(`should return the url when __resourceQuery is ${url}`, () => { expect(createSocketUrl(url)).toMatchSnapshot(); diff --git a/test/client/utils/getCurrentScriptSource.test.js b/test/client/utils/getCurrentScriptSource.test.js index 8fb953b1f3..b6c4f4d017 100644 --- a/test/client/utils/getCurrentScriptSource.test.js +++ b/test/client/utils/getCurrentScriptSource.test.js @@ -1,6 +1,8 @@ 'use strict'; -const getCurrentScriptSource = require('../../../client-src/default/utils/getCurrentScriptSource'); +const { + default: getCurrentScriptSource, +} = require('../../../client-src/default/utils/getCurrentScriptSource'); describe('getCurrentScriptSource', () => { afterEach(() => { diff --git a/test/client/utils/log.test.js b/test/client/utils/log.test.js index 79021d13d7..f72c6486b7 100644 --- a/test/client/utils/log.test.js +++ b/test/client/utils/log.test.js @@ -35,7 +35,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); }); @@ -44,14 +44,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/client/utils/reloadApp.test.js b/test/client/utils/reloadApp.test.js index 13a392b117..9686dddf70 100644 --- a/test/client/utils/reloadApp.test.js +++ b/test/client/utils/reloadApp.test.js @@ -25,7 +25,7 @@ describe('reloadApp', () => { }); // eslint-disable-next-line global-require - reloadApp = require('../../../client-src/default/utils/reloadApp'); + reloadApp = require('../../../client-src/default/utils/reloadApp').default; }); afterEach(() => { diff --git a/test/client/utils/sendMessage.test.js b/test/client/utils/sendMessage.test.js index a60f2548bc..17cbb4ea61 100644 --- a/test/client/utils/sendMessage.test.js +++ b/test/client/utils/sendMessage.test.js @@ -2,7 +2,9 @@ /* global self */ -const sendMessage = require('../../../client-src/default/utils/sendMessage'); +const { + default: sendMessage, +} = require('../../../client-src/default/utils/sendMessage'); describe('sendMessage', () => { afterEach(() => { diff --git a/test/e2e/Client.test.js b/test/e2e/Client.test.js index 90eb2ffe5a..3995fec5a6 100644 --- a/test/e2e/Client.test.js +++ b/test/e2e/Client.test.js @@ -37,56 +37,50 @@ describe('reload', () => { }); describe('on browser client', () => { - it('should hot reload without page refresh', (done) => { - runBrowser().then(({ page, browser }) => { - let refreshed = false; - page.waitForNavigation({ waitUntil: 'load' }).then(() => { - page - .evaluate(() => { - const body = document.body; - const bgColor = getComputedStyle(body)['background-color']; - return bgColor; - }) - .then((color) => { - page.setRequestInterception(true).then(() => { - page.on('request', (req) => { - if ( - req.isNavigationRequest() && - req.frame() === page.mainFrame() && - req.url() === `http://localhost:${port}/main` - ) { - refreshed = true; - } - req.continue(); - }); - fs.writeFileSync( - cssFilePath, - 'body { background-color: rgb(255, 0, 0); }' - ); - page.waitFor(10000).then(() => { - page - .evaluate(() => { - const body = document.body; - const bgColor = getComputedStyle(body)[ - 'background-color' - ]; - return bgColor; - }) - .then((color2) => { - browser.close().then(() => { - expect(color).toEqual('rgb(0, 0, 255)'); - expect(color2).toEqual('rgb(255, 0, 0)'); - expect(refreshed).toBeFalsy(); - done(); - }); - }); - }); - }); - }); - }); - - page.goto(`http://localhost:${port}/main`); + it('should hot reload without page refresh', async () => { + let refreshed = false; + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port}/main`); + + await page.waitForNavigation({ waitUntil: 'load' }); + + const color = await page.evaluate(() => { + const body = document.body; + const bgColor = getComputedStyle(body)['background-color']; + return bgColor; + }); + + await page.setRequestInterception(true); + + page.on('request', (req) => { + if ( + req.isNavigationRequest() && + req.frame() === page.mainFrame() && + req.url() === `http://localhost:${port}/main` + ) { + refreshed = true; + } + req.continue(); }); + fs.writeFileSync( + cssFilePath, + 'body { background-color: rgb(255, 0, 0); }' + ); + + await page.waitFor(10000); + + const color2 = await page.evaluate(() => { + const body = document.body; + const bgColor = getComputedStyle(body)['background-color']; + return bgColor; + }); + + await browser.close(); + + expect(color).toEqual('rgb(0, 0, 255)'); + expect(color2).toEqual('rgb(255, 0, 0)'); + expect(refreshed).toBeFalsy(); }); }); }); @@ -115,56 +109,50 @@ describe('reload', () => { }); describe('on browser client', () => { - it('should reload with page refresh', (done) => { - runBrowser().then(({ page, browser }) => { - let refreshed = false; - page.waitForNavigation({ waitUntil: 'load' }).then(() => { - page - .evaluate(() => { - const body = document.body; - const bgColor = getComputedStyle(body)['background-color']; - return bgColor; - }) - .then((color) => { - page.setRequestInterception(true).then(() => { - page.on('request', (req) => { - if ( - req.isNavigationRequest() && - req.frame() === page.mainFrame() && - req.url() === `http://localhost:${port}/main` - ) { - refreshed = true; - } - req.continue(); - }); - fs.writeFileSync( - cssFilePath, - 'body { background-color: rgb(255, 0, 0); }' - ); - page.waitFor(10000).then(() => { - page - .evaluate(() => { - const body = document.body; - const bgColor = getComputedStyle(body)[ - 'background-color' - ]; - return bgColor; - }) - .then((color2) => { - browser.close().then(() => { - expect(color).toEqual('rgb(0, 0, 255)'); - expect(color2).toEqual('rgb(255, 0, 0)'); - expect(refreshed).toBeTruthy(); - done(); - }); - }); - }); - }); - }); - }); - - page.goto(`http://localhost:${port}/main`); + it('should reload with page refresh', async () => { + let refreshed = false; + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port}/main`); + + await page.waitForNavigation({ waitUntil: 'load' }); + + const color = await page.evaluate(() => { + const body = document.body; + const bgColor = getComputedStyle(body)['background-color']; + return bgColor; + }); + + await page.setRequestInterception(true); + + page.on('request', (req) => { + if ( + req.isNavigationRequest() && + req.frame() === page.mainFrame() && + req.url() === `http://localhost:${port}/main` + ) { + refreshed = true; + } + req.continue(); }); + fs.writeFileSync( + cssFilePath, + 'body { background-color: rgb(255, 0, 0); }' + ); + + await page.waitFor(10000); + + const color2 = await page.evaluate(() => { + const body = document.body; + const bgColor = getComputedStyle(body)['background-color']; + return bgColor; + }); + + await browser.close(); + + expect(color).toEqual('rgb(0, 0, 255)'); + expect(color2).toEqual('rgb(255, 0, 0)'); + expect(refreshed).toBeTruthy(); }); }); }); diff --git a/test/e2e/ClientOptions.test.js b/test/e2e/ClientOptions.test.js index 07d3bba8d9..9c7f119a48 100644 --- a/test/e2e/ClientOptions.test.js +++ b/test/e2e/ClientOptions.test.js @@ -7,6 +7,7 @@ const testServer = require('../helpers/test-server'); const config = require('../fixtures/client-config/webpack.config'); const runBrowser = require('../helpers/run-browser'); const [port1, port2, port3] = require('../ports-map').ClientOptions; +const timer = require('../helpers/timer'); describe('Client code', () => { function startProxy(port) { @@ -48,38 +49,33 @@ describe('Client code', () => { }); afterAll((done) => { - proxy.close(() => { - done(); - }); + proxy.close(done); }); - it('responds with a 200', (done) => { + it('responds with a 200', async () => { { const req = request(`http://localhost:${port2}`); - req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n', done); + await req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n'); } { const req = request(`http://localhost:${port1}`); - req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n', done); + await req.get('/sockjs-node').expect(200, 'Welcome to SockJS!\n'); } }); - it('requests websocket through the proxy with proper port number', (done) => { - runBrowser().then(({ page, browser }) => { - page - .waitForRequest((requestObj) => requestObj.url().match(/sockjs-node/)) - .then((requestObj) => { - browser.close().then(() => { - expect( - requestObj - .url() - .includes(`http://localhost:${port1}/sockjs-node`) - ).toBeTruthy(); - done(); - }); - }); - page.goto(`http://localhost:${port2}/main`); - }); + it('requests websocket through the proxy with proper port number', async () => { + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port2}/main`); + const req = await page.waitForRequest((requestObj) => + requestObj.url().match(/sockjs-node/) + ); + + await browser.close(); + + expect( + req.url().includes(`http://localhost:${port1}/sockjs-node`) + ).toBeTruthy(); }); }); }); @@ -102,24 +98,20 @@ describe('Client complex inline script path', () => { afterAll(testServer.close); describe('browser client', () => { - it('uses the correct public hostname and sockPath', (done) => { - runBrowser().then(({ page, browser }) => { - page - .waitForRequest((requestObj) => - requestObj.url().match(/foo\/test\/bar/) - ) - .then((requestObj) => { - browser.close().then(() => { - expect( - requestObj - .url() - .includes(`http://myhost.test:${port2}/foo/test/bar/`) - ).toBeTruthy(); - done(); - }); - }); - page.goto(`http://localhost:${port2}/main`); - }); + it('uses the correct public hostname and sockPath', async () => { + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port2}/main`); + + const req = await page.waitForRequest((requestObj) => + requestObj.url().match(/foo\/test\/bar/) + ); + + await browser.close(); + + expect( + req.url().includes(`http://myhost.test:${port2}/foo/test/bar/`) + ).toBeTruthy(); }); }); }); @@ -142,25 +134,20 @@ describe('Client complex inline script path with sockPort', () => { afterAll(testServer.close); describe('browser client', () => { - it('uses the correct sockPort', (done) => { - runBrowser().then(({ page, browser }) => { - page - .waitForRequest((requestObj) => - requestObj.url().match(/foo\/test\/bar/) - ) - .then((requestObj) => { - browser.close().then(() => { - expect( - requestObj - .url() - .includes(`http://localhost:${port3}/foo/test/bar`) - ).toBeTruthy(); - done(); - }); - }); - - page.goto(`http://localhost:${port2}/main`); - }); + it('uses the correct sockPort', async () => { + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port2}/main`); + + const req = await page.waitForRequest((requestObj) => + requestObj.url().match(/foo\/test\/bar/) + ); + + await browser.close(); + + expect( + req.url().includes(`http://localhost:${port3}/foo/test/bar`) + ).toBeTruthy(); }); }); }); @@ -185,22 +172,19 @@ describe('Client complex inline script path with sockPort, no sockPath', () => { afterAll(testServer.close); describe('browser client', () => { - it('uses the correct sockPort and sockPath', (done) => { - runBrowser().then(({ page, browser }) => { - page - .waitForRequest((requestObj) => requestObj.url().match(/sockjs-node/)) - .then((requestObj) => { - browser.close().then(() => { - expect( - requestObj - .url() - .includes(`http://localhost:${port3}/sockjs-node`) - ).toBeTruthy(); - done(); - }); - }); - page.goto(`http://localhost:${port2}/main`); - }); + it('uses the correct sockPort and sockPath', async () => { + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port2}/main`); + const req = await page.waitForRequest((requestObj) => + requestObj.url().match(/sockjs-node/) + ); + + await browser.close(); + + expect( + req.url().includes(`http://localhost:${port3}/sockjs-node`) + ).toBeTruthy(); }); }); }); @@ -222,22 +206,19 @@ describe('Client complex inline script path with sockHost', () => { afterAll(testServer.close); describe('browser client', () => { - it('uses the correct sockHost', (done) => { - runBrowser().then(({ page, browser }) => { - page - .waitForRequest((requestObj) => requestObj.url().match(/sockjs-node/)) - .then((requestObj) => { - browser.close().then(() => { - expect( - requestObj - .url() - .includes(`http://myhost.test:${port2}/sockjs-node`) - ).toBeTruthy(); - done(); - }); - }); - page.goto(`http://localhost:${port2}/main`); - }); + it('uses the correct sockHost', async () => { + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port2}/main`); + + const req = await page.waitForRequest((requestObj) => + requestObj.url().match(/sockjs-node/) + ); + await browser.close(); + + expect( + req.url().includes(`http://myhost.test:${port2}/sockjs-node`) + ).toBeTruthy(); }); }); }); @@ -281,37 +262,31 @@ describe('Client console.log', () => { ]; for (const { title, options } of cases) { - it(title, () => { + it(title, async () => { const res = []; const testOptions = Object.assign({}, baseOptions, options); - // TODO: use async/await when Node.js v6 support is dropped - return Promise.resolve() - .then(() => { - return new Promise((resolve) => { - testServer.startAwaitingCompilation(config, testOptions, resolve); - }); - }) - .then(runBrowser) - .then(({ page, browser }) => { - return new Promise((resolve) => { - page.goto(`http://localhost:${port2}/main`); - page.on('console', ({ _text }) => { - res.push(_text); - }); - setTimeout(() => { - browser.close().then(() => { - expect(res).toMatchSnapshot(); - resolve(); - }); - }, 1000); - }); - }) - .then(() => { - return new Promise((resolve) => { - testServer.close(resolve); - }); - }); + // 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); + }); + + await timer(3000); + + expect(res).toMatchSnapshot(); + await browser.close(); + + // TODO: refactor(hiroppy) + await new Promise((resolve) => { + testServer.close(resolve); + }); }); } }); diff --git a/test/e2e/ProvidePlugin.test.js b/test/e2e/ProvidePlugin.test.js index 99d44cf910..38eaa089dd 100644 --- a/test/e2e/ProvidePlugin.test.js +++ b/test/e2e/ProvidePlugin.test.js @@ -22,22 +22,19 @@ describe('ProvidePlugin', () => { afterAll(testServer.close); describe('on browser client', () => { - it('should inject SockJS client implementation', (done) => { - runBrowser().then(({ page, browser }) => { - page.waitForNavigation({ waitUntil: 'load' }).then(() => { - page - .evaluate(() => { - return window.injectedClient === window.expectedClient; - }) - .then((isCorrectClient) => { - browser.close().then(() => { - expect(isCorrectClient).toBeTruthy(); - done(); - }); - }); - }); - page.goto(`http://localhost:${port}/main`); + it('should inject SockJS client implementation', async () => { + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port}/main`); + await page.waitForNavigation({ waitUntil: 'load' }); + + const isCorrectClient = await page.evaluate(() => { + return window.injectedClient === window.expectedClient; }); + + await browser.close(); + + expect(isCorrectClient).toBeTruthy(); }); }); }); @@ -58,23 +55,21 @@ describe('ProvidePlugin', () => { afterAll(testServer.close); describe('on browser client', () => { - it('should not inject client implementation', (done) => { - runBrowser().then(({ page, browser }) => { - page.waitForNavigation({ waitUntil: 'load' }).then(() => { - page - .evaluate(() => { - // eslint-disable-next-line no-undefined - return window.injectedClient === undefined; - }) - .then((isCorrectClient) => { - browser.close().then(() => { - expect(isCorrectClient).toBeTruthy(); - done(); - }); - }); - }); - page.goto(`http://localhost:${port}/main`); + it('should not inject client implementation', async () => { + const { page, browser } = await runBrowser(); + + page.goto(`http://localhost:${port}/main`); + + await page.waitForNavigation({ waitUntil: 'load' }); + + const isCorrectClient = await page.evaluate(() => { + // eslint-disable-next-line no-undefined + return window.injectedClient === undefined; }); + + await browser.close(); + + expect(isCorrectClient).toBeTruthy(); }); }); }); 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 53993d88d1..9e36ca5d11 100644 --- a/test/helpers/run-browser.js +++ b/test/helpers/run-browser.js @@ -2,7 +2,7 @@ const puppeteer = require('puppeteer'); -function runBrowser(config) { +async function runBrowser(config) { const options = { viewport: { width: 500, @@ -12,26 +12,15 @@ function runBrowser(config) { ...config, }; - return new Promise((resolve, reject) => { - let page; - let browser; - - puppeteer - .launch({ - headless: true, - args: ['--no-sandbox', '--disable-setuid-sandbox'], - }) - .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: ['--no-sandbox', '--disable-setuid-sandbox'], }); + 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 7e59879bb0..d63827cc56 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -23,75 +23,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 @@ -123,19 +55,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], @@ -414,10 +335,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/ports-map.js b/test/ports-map.js index eee60008e4..94559e3b6d 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -40,9 +40,7 @@ const portsList = { let startPort = 8079; 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/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 baa4111124..00619a657a 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); }); }); @@ -271,18 +259,16 @@ 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); }); 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); }); }); @@ -304,13 +290,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); }); }); @@ -328,13 +312,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 3e5506558a..eee2862848 100644 --- a/test/server/http2-option.test.js +++ b/test/server/http2-option.test.js @@ -109,14 +109,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/open-option.test.js b/test/server/open-option.test.js index b33d0a834c..6417a97ddd 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/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/serverMode-option.test.js b/test/server/serverMode-option.test.js index b0ef7357fb..1cd89e76da 100644 --- a/test/server/serverMode-option.test.js +++ b/test/server/serverMode-option.test.js @@ -34,8 +34,8 @@ describe('serverMode option', () => { req = request(`http://localhost:${port}`); }); - it('sockjs path responds with a 200', (done) => { - req.get('/sockjs-node').expect(200, done); + it('sockjs path responds with a 200', async () => { + await req.get('/sockjs-node').expect(200); }); }); @@ -52,8 +52,8 @@ describe('serverMode option', () => { req = request(`http://localhost:${port}`); }); - it('sockjs path responds with a 200', (done) => { - req.get('/sockjs-node').expect(200, done); + it('sockjs path responds with a 200', async () => { + await req.get('/sockjs-node').expect(200); }); }); @@ -70,8 +70,8 @@ describe('serverMode option', () => { req = request(`http://localhost:${port}`); }); - it('sockjs path responds with a 200', (done) => { - req.get('/sockjs-node').expect(200, done); + it('sockjs path responds with a 200', async () => { + await req.get('/sockjs-node').expect(200); }); }); diff --git a/test/server/servers/SockJSServer.test.js b/test/server/servers/SockJSServer.test.js index d1024c5910..a099f16e0c 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,15 +33,16 @@ 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 = []; - socketServer.onConnection((connection) => { + socketServer.onConnection(async (connection) => { data.push('open'); socketServer.send(connection, 'hello world'); - setTimeout(() => { - socketServer.close(connection); - }, 1000); + + await timer(1000); + + socketServer.close(connection); }); const client = new SockJS(`http://localhost:${port}/sockjs-node`); @@ -53,13 +55,12 @@ describe('SockJSServer', () => { data.push('close'); }; - setTimeout(() => { - expect(data.length).toEqual(3); - expect(data[0]).toEqual('open'); - expect(data[1]).toEqual('hello world'); - expect(data[2]).toEqual('close'); - done(); - }, 3000); + await timer(3000); + + expect(data.length).toEqual(3); + expect(data[0]).toEqual('open'); + expect(data[1]).toEqual('hello world'); + expect(data[2]).toEqual('close'); }); }); 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 82d58fd233..45e7cc3035 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 }); + for (const stats of allStats) { + const compiler = webpack(config); + const server = new Server(compiler, { stats, port }); - 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 608bd61a30..026298e923 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", () => { @@ -292,7 +290,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(); } @@ -324,7 +322,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(); } @@ -380,7 +378,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 92ccc36e22..9ab59edd5e 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 util', () => { 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 util', () => { 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 c5f0d7369e..27115a9d4b 100644 --- a/test/server/utils/routes.test.js +++ b/test/server/utils/routes.test.js @@ -16,111 +16,105 @@ 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); - done(); - }); + it('should handles GET request to directory index', 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 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 e6fa3b155a..1ae6b092d1 100644 --- a/test/server/utils/runOpen.test.js +++ b/test/server/utils/runOpen.test.js @@ -1,23 +1,24 @@ '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(` + 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(opn.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(opn.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(opn.mock.calls[0]).toMatchInlineSnapshot(` + ); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example.com/index.html", Object { @@ -78,16 +75,17 @@ 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 ', async () => { + await runOpen( + 'https://example.com', + { open: 'Google Chrome', openPage: 'https://example2.com' }, + console + ); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "https://example2.com", Object { @@ -96,16 +94,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 ', async () => { + runOpen( + 'https://example.com', + { open: 'Google Chrome', openPage: 'http://example2.com' }, + console + ); + + expect(open.mock.calls[0]).toMatchInlineSnapshot(` Array [ "http://example2.com", Object { @@ -114,27 +112,26 @@ describe('runOpen util', () => { }, ] `); - }); - }); }); describe('should not open browser', () => { const logMock = { warn: jest.fn() }; beforeEach(() => { - opn.mockImplementation(() => Promise.reject()); + open.mockImplementation(() => Promise.reject()); }); afterEach(() => { 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(opn.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(opn.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(opn.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(opn.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', () => { }, ] `); - }); }); }); });