From 4fb3484285d174ac23a1da4432af4de5a87928ba Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Thu, 8 Mar 2018 17:02:54 -0800 Subject: [PATCH 01/50] fix(common): Proxy function toString does not contain Proxy. Recent change (https://www.chromestatus.com/feature/5666372071718912) means Proxied functions no longer throw TypeError. Change the test to conform to the new reality. --- common/stringify.js | 4 ++-- test/client/stringify.spec.js | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/common/stringify.js b/common/stringify.js index 6df1d3e97..192a4847a 100644 --- a/common/stringify.js +++ b/common/stringify.js @@ -25,8 +25,8 @@ var stringify = function stringify (obj, depth) { return obj.toString().replace(/\{[\s\S]*\}/, '{ ... }') } catch (err) { if (err instanceof TypeError) { - // Proxy(function abc(...) { ... }) - return 'Proxy(function ' + (obj.name || '') + '(...) { ... })' + // Support older browsers + return 'function ' + (obj.name || '') + '() { ... }' } else { throw err } diff --git a/test/client/stringify.spec.js b/test/client/stringify.spec.js index 603c2df03..e51c85d37 100644 --- a/test/client/stringify.spec.js +++ b/test/client/stringify.spec.js @@ -40,11 +40,8 @@ describe('stringify', function () { // http://caniuse.com/#feat=proxy if (window.Proxy) { it('should serialize proxied functions', function () { - var abcProxy = new Proxy(function abc (a, b, c) { return 'whatever' }, {}) var defProxy = new Proxy(function (d, e, f) { return 'whatever' }, {}) - - assert.deepEqual(stringify(abcProxy), 'Proxy(function abc(...) { ... })') - assert.deepEqual(stringify(defProxy), 'Proxy(function (...) { ... })') + assert.deepEqual(stringify(defProxy), 'function () { ... }') }) } From 0b2c6904f12ca3cf3b41a24eb9ff31ebae572d2c Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Mon, 23 Apr 2018 09:15:41 -0700 Subject: [PATCH 02/50] docs: Outline the basic workflow. (#2974) This short narative also helps introduce 'client' and 'context' terminology. --- docs/intro/03-how-it-works.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/intro/03-how-it-works.md b/docs/intro/03-how-it-works.md index 61a1ce111..eafdec9da 100644 --- a/docs/intro/03-how-it-works.md +++ b/docs/intro/03-how-it-works.md @@ -14,7 +14,28 @@ The server collects the results from all of the captured browsers and presents t This is only a very brief overview, as the internals of how Karma works aren't entirely necessary when using Karma. -However, if you are interested in learning more, Karma itself originates from a university thesis, which goes into detail about the design +## Outline of workflow. + +Here is roughly how Karma works: + +After starting up, Karma loads plugins and the configuration file, then starts its local web server which listens for connections. +Any browser already waiting on websockets from the server will reconnect immediately. As part of loading the plugins, test reporters +register for 'browser' events so they are ready for test results. + +Then karma launches zero, one, or more browsers, setting their start page the Karma server URL. + +When the browsers connect, Karma serves a 'client.html' page; when this page runs in the browser it connects back to the server via websockets. + +Once the server sees the websocket connection, it instructs the client -- over the websocket -- to execute tests. The client page opens an iframe with a 'context.html' page from the server. The server generates this context.html page using the configuration. This page includes the test framework adapter, the code to be tested, and the test code. + +When the browser loads this context page, the onload event handler connects the context page to the client page via postMessage. The framework adapter is in charge at this point: it runs the test, reporting errors or success by messaging through the client page. + +Messages sent to the client page are forwarded through the websocket to the Karma server. The server re-dispatches these messages as 'browser' events. The reporters listening to 'browser' events get the data; they may print it, save it to files, or forward the data to another service. +Since the data is sent by the test framework adapter to the reporter, adapters and reporters almost always come in pairs, like karma-jasmine and karma-jasmine-reporter. The detailed content of test-result data is of no concern to other parts of karma: only the reporter needs to know it format. + +Karma has many variations and options that may cause different workflow with different configurations. + +If you are interested in learning more about the design, Karma itself originates from a university thesis, which goes into detail about the design and implementation, and it is available to read [right here]. [right here]: https://github.com/karma-runner/karma/raw/master/thesis.pdf From a3ff6c84481271c0578ca2b7b4396b804b02e76a Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Mon, 23 Apr 2018 09:23:15 -0700 Subject: [PATCH 03/50] feat(grunt): run check_clean before starting release. (#2978) * fix(package.json): sinon-chai 2.13 is not compatible with sinon 4.x * feat(grunt): run check_clean before starting release. By checking early we avoid pushing a new version to github that is not then published to npm. --- gruntfile.js | 2 ++ package.json | 1 + 2 files changed, 3 insertions(+) diff --git a/gruntfile.js b/gruntfile.js index 0a1b6f1ce..3ae8f22bc 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -131,6 +131,7 @@ module.exports = function (grunt) { } }) + grunt.loadNpmTasks('grunt-check-clean') grunt.loadTasks('tasks') require('load-grunt-tasks')(grunt) @@ -141,6 +142,7 @@ module.exports = function (grunt) { grunt.registerTask('release', 'Build, bump and publish to NPM.', function (type) { grunt.task.run([ + 'check_clean', 'npm-contributors', 'bump:' + (type || 'patch') + ':bump-only', 'build', diff --git a/package.json b/package.json index 0ffdcc382..fe3fd7087 100644 --- a/package.json +++ b/package.json @@ -397,6 +397,7 @@ "grunt-browserify": "^5.0.0", "grunt-bump": "^0.8.0", "grunt-cli": "^1.1.0", + "grunt-check-clean": "^0.1.2", "grunt-contrib-watch": "^1.0.0", "grunt-conventional-changelog": "^6.0.1", "grunt-conventional-github-releaser": "^1.0.0", From bc1453e3198faa53dd6b02a23b1d3b3911d6b467 Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Mon, 30 Apr 2018 08:34:56 -0700 Subject: [PATCH 04/50] fix(build): pin npm version in appveyor to v3, compat with node 4 (#2983) --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 150f49eb8..40cf08a0d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,8 +13,8 @@ install: # Install Node.js - ps: Install-Product node $env:nodejs_version - # Upgrade npm - - npm install -g npm + # Install npm compat with node 4 + - npm install -g npm@3 # Output our current versions for debugging - node --version From c3f05ef25de93e40d5a58920c495c48703f9ebfa Mon Sep 17 00:00:00 2001 From: Brian Di Palma Date: Mon, 23 Apr 2018 10:33:56 +0100 Subject: [PATCH 05/50] fix(server): Remove Socket.IO listeners Not removing Socket.IO listeners can cause memory issues in long running processes that spawn many Karma instance. Fixes #2980 --- lib/server.js | 4 ++++ test/unit/server.spec.js | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/server.js b/lib/server.js index dd015aca2..c9ddbe71e 100644 --- a/lib/server.js +++ b/lib/server.js @@ -425,6 +425,10 @@ Server.prototype._start = function (config, launcher, preprocess, fileList, } self.emitAsync('exit').then(function () { + // Remove Socket.IO listeners. `connection` callback closes over `Server` + // instance so it leaks Plugin state e.g. Webpack compilations. + socketServer.sockets.removeAllListeners() + socketServer.close() // don't wait forever on webServer.close() because // pending client connections prevent it from closing. var closeTimeout = setTimeout(removeAllListeners, webServerCloseTimeout) diff --git a/test/unit/server.spec.js b/test/unit/server.spec.js index 2274355db..a16a8ad83 100644 --- a/test/unit/server.spec.js +++ b/test/unit/server.spec.js @@ -65,13 +65,15 @@ describe('server', () => { } mockSocketServer = { + close: () => {}, flashPolicyServer: { close: () => {} }, sockets: { sockets: {}, on: () => {}, - emit: () => {} + emit: () => {}, + removeAllListeners: () => {} } } From b4fddd2ca10582ad7b0e880bf7e24172d5c99526 Mon Sep 17 00:00:00 2001 From: Brian Di Palma Date: Thu, 26 Apr 2018 07:24:50 +0100 Subject: [PATCH 06/50] chore(appveyor): Remove npm upgrade step from AppVeyor script Upgrading npm can cause build failures in older node.js versions see https://github.com/karma-runner/karma/pull/2981 for details. --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 40cf08a0d..8e212bd91 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,9 +13,6 @@ install: # Install Node.js - ps: Install-Product node $env:nodejs_version - # Install npm compat with node 4 - - npm install -g npm@3 - # Output our current versions for debugging - node --version - npm --version From af9c84a379d3b02de03d0fc2d0402ea56a0a0462 Mon Sep 17 00:00:00 2001 From: Brian Di Palma Date: Thu, 26 Apr 2018 09:18:03 +0100 Subject: [PATCH 07/50] fix(UTs): Correct proxy listeners expectation Expectations added in https://github.com/karma-runner/karma/pull/2596 didn't match `EventEmitter` API for `listeners`. --- test/unit/middleware/proxy.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/middleware/proxy.spec.js b/test/unit/middleware/proxy.spec.js index 73bb0f9f9..d1047ac35 100644 --- a/test/unit/middleware/proxy.spec.js +++ b/test/unit/middleware/proxy.spec.js @@ -346,8 +346,8 @@ describe('middleware.proxy', () => { } var parsedProxyConfig = m.parseProxyConfig(proxy, config) expect(parsedProxyConfig).to.have.length(1) - expect(parsedProxyConfig[0].proxy.listeners('proxyReq', true)).to.equal(true) - expect(parsedProxyConfig[0].proxy.listeners('proxyRes', true)).to.equal(true) + expect(parsedProxyConfig[0].proxy.listeners('proxyReq')[0]).to.equal(config.proxyReq) + expect(parsedProxyConfig[0].proxy.listeners('proxyRes')[0]).to.equal(config.proxyRes) }) it('should handle empty proxy config', () => { From a5f75c07698f609e8085fc98a2d87e1090d6852d Mon Sep 17 00:00:00 2001 From: Pieter Mees Date: Fri, 4 May 2018 11:21:27 -0400 Subject: [PATCH 08/50] chore(chokidar): Update chokidar to fix install issue on Node 10 / OSX --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fe3fd7087..cca0ea8b1 100644 --- a/package.json +++ b/package.json @@ -350,7 +350,7 @@ "dependencies": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "chokidar": "^1.4.1", + "chokidar": "^2.0.3", "colors": "^1.1.0", "combine-lists": "^1.0.0", "connect": "^3.6.0", From 80cf39c4f2a327921d3d4d3d2edbb10448425bf2 Mon Sep 17 00:00:00 2001 From: Pieter Mees Date: Fri, 4 May 2018 11:29:31 -0400 Subject: [PATCH 09/50] chore(appveyor): Add Node 10 to appveyor --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 8e212bd91..12f756f1c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,6 +5,7 @@ environment: - nodejs_version: "4" - nodejs_version: "6" - nodejs_version: "8" + - nodejs_version: "10" matrix: fast_finish: true From 3add635f4efd183e91b6e36714c64d0c8b941a54 Mon Sep 17 00:00:00 2001 From: Pieter Mees Date: Fri, 4 May 2018 11:29:58 -0400 Subject: [PATCH 10/50] chore(travis): Add Node 10 to Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 95c0c269f..7dfc3ae9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ node_js: - 6 - 8 - 9 + - 10 env: global: From 6c355f1fd3aae733e5d1fd221b876aafbea4076a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Usarz?= Date: Fri, 4 May 2018 18:33:57 +0200 Subject: [PATCH 11/50] refactor(watcher): refactor lib/watcher.js to ES2015 --- lib/watcher.js | 130 ++++++++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 78 deletions(-) diff --git a/lib/watcher.js b/lib/watcher.js index 284a45088..0af95c0e5 100644 --- a/lib/watcher.js +++ b/lib/watcher.js @@ -1,118 +1,92 @@ -var chokidar = require('chokidar') -var mm = require('minimatch') -var expandBraces = require('expand-braces') +'use strict' -var helper = require('./helper') -var log = require('./logger').create('watcher') +const chokidar = require('chokidar') +const mm = require('minimatch') +const expandBraces = require('expand-braces') -var DIR_SEP = require('path').sep +const helper = require('./helper') +const log = require('./logger').create('watcher') -// Get parent folder, that be watched (does not contain any special globbing character) -var baseDirFromPattern = function (pattern) { +const DIR_SEP = require('path').sep + +function baseDirFromPattern (pattern) { return pattern - .replace(/[/\\][^/\\]*\*.*$/, '') // remove parts with * - .replace(/[/\\][^/\\]*[!+]\(.*$/, '') // remove parts with !(...) and +(...) + .replace(/[/\\][^/\\]*\*.*$/, '') // remove parts with * + .replace(/[/\\][^/\\]*[!+]\(.*$/, '') // remove parts with !(...) and +(...) .replace(/[/\\][^/\\]*\)\?.*$/, '') || DIR_SEP // remove parts with (...)? } -var watchPatterns = function (patterns, watcher) { - // filter only unique non url patterns paths - var pathsToWatch = [] - var uniqueMap = {} - var path +function watchPatterns (patterns, watcher) { + let pathsToWatch = new Set() // expand ['a/{b,c}'] to ['a/b', 'a/c'] - patterns = expandBraces(patterns) - - patterns.forEach(function (pattern) { - path = baseDirFromPattern(pattern) - if (!uniqueMap[path]) { - uniqueMap[path] = true - pathsToWatch.push(path) - } - }) + expandBraces(patterns) + .forEach(path => pathsToWatch.add(baseDirFromPattern(path))) + pathsToWatch = Array.from(pathsToWatch) // watch only common parents, no sub paths - pathsToWatch.forEach(function (path) { - if (!pathsToWatch.some(function (p) { - return p !== path && path.substr(0, p.length + 1) === p + DIR_SEP - })) { + pathsToWatch.forEach(path => { + if (!pathsToWatch.some(p => p !== path && path.substr(0, p.length + 1) === p + DIR_SEP)) { watcher.add(path) log.debug('Watching "%s"', path) } }) } -// Function to test if a path should be ignored by chokidar. -var createIgnore = function (patterns, excludes) { +function checkAnyPathMatch (patterns, path) { + return patterns.some(pattern => mm(path, pattern, {dot: true})) +} + +function createIgnore (patterns, excludes) { return function (path, stat) { if (!stat || stat.isDirectory()) { return false } - // Check if the path matches any of the watched patterns. - if (!patterns.some(function (pattern) { - return mm(path, pattern, {dot: true}) - })) { - return true - } - - // Check if the path matches any of the exclude patterns. - if (excludes.some(function (pattern) { - return mm(path, pattern, {dot: true}) - })) { - return true - } - - return false + return !checkAnyPathMatch(patterns, path) || checkAnyPathMatch(excludes, path) } } -var onlyWatchedTrue = function (pattern) { - return pattern.watched -} - -var getWatchedPatterns = function (patternObjects) { - return patternObjects.filter(onlyWatchedTrue).map(function (patternObject) { - return patternObject.pattern - }) +function getWatchedPatterns (patterns) { + return patterns + .reduce((array, pattern) => { + if (pattern.watched) { + array.push(pattern.pattern) + } + return array + }, []) } exports.watch = function (patterns, excludes, fileList, usePolling, emitter) { - var watchedPatterns = getWatchedPatterns(patterns) - var options = { + const watchedPatterns = getWatchedPatterns(patterns) + + const watcher = new chokidar.FSWatcher({ usePolling: usePolling, ignorePermissionErrors: true, ignoreInitial: true, ignored: createIgnore(watchedPatterns, excludes) - } - var chokidarWatcher = new chokidar.FSWatcher(options) + }) - watchPatterns(watchedPatterns, chokidarWatcher) + watchPatterns(watchedPatterns, watcher) - var bind = function (fn) { - return function (path) { - return fn.call(fileList, helper.normalizeWinPath(path)) - } - } + watcher + .on('add', path => fileList.addFile(helper.normalizeWinPath(path))) + .on('change', path => fileList.changeFile(helper.normalizeWinPath(path))) + .on('unlink', path => fileList.removeFile(helper.normalizeWinPath(path))) + .on('error', log.debug.bind(log)) - // register events - chokidarWatcher.on('add', bind(fileList.addFile)) - .on('change', bind(fileList.changeFile)) - .on('unlink', bind(fileList.removeFile)) - // If we don't subscribe; unhandled errors from Chokidar will bring Karma down - // (see GH Issue #959) - .on('error', function (e) { - log.debug(e) - }) - - emitter.on('exit', function (done) { - chokidarWatcher.close() + emitter.on('exit', done => { + watcher.close() done() }) - return chokidarWatcher + return watcher } -exports.watch.$inject = ['config.files', 'config.exclude', 'fileList', 'config.usePolling', - 'emitter'] +exports.watch.$inject = [ + 'config.files', + 'config.exclude', + 'fileList', + 'config.usePolling', + 'emitter' +] From a328150d686cd622899200e71db4aa3a16394366 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 4 May 2018 18:38:50 +0200 Subject: [PATCH 12/50] chore(deps): update yarn.lock --- yarn.lock | 1037 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 994 insertions(+), 43 deletions(-) diff --git a/yarn.lock b/yarn.lock index afff03b87..6ac0cdf3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,19 @@ # yarn lockfile v1 +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + +JSONStream@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.10.0.tgz#74349d0d89522b71f30f0a03ff9bd20ca6f12ac0" + dependencies: + jsonparse "0.0.5" + through ">=2.2.7 <3" + JSONStream@^1.0.3, JSONStream@^1.0.4: version "1.3.2" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" @@ -43,6 +56,13 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" +acorn-node@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.3.0.tgz#5f86d73346743810ef1269b901dbcbded020861b" + dependencies: + acorn "^5.4.1" + xtend "^4.0.1" + acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" @@ -55,6 +75,10 @@ acorn@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7" +acorn@^5.4.1: + version "5.5.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" + addressparser@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" @@ -139,6 +163,13 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -187,10 +218,18 @@ arr-diff@^2.0.0: dependencies: arr-flatten "^1.0.1" -arr-flatten@^1.0.1: +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" @@ -240,6 +279,10 @@ array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + arraybuffer.slice@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" @@ -290,6 +333,10 @@ assertion-error@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + ast-types@0.x.x: version "0.10.1" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd" @@ -308,7 +355,7 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async@1.x, async@^1.4.0, async@^1.5.0, async@~1.5.2: +async@1.x, async@^1.4.0, async@^1.5.0, async@^1.5.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -318,7 +365,7 @@ async@2.0.1: dependencies: lodash "^4.8.0" -async@^2.0.0, async@^2.1.2: +async@^2.0.0, async@^2.1.2, async@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" dependencies: @@ -328,6 +375,10 @@ async@~0.2.9: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" +async@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" + async@~2.1.2: version "2.1.5" resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc" @@ -338,6 +389,10 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +atob@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -490,6 +545,18 @@ base64id@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" @@ -616,6 +683,21 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -651,6 +733,14 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: inherits "^2.0.1" safe-buffer "^5.0.1" +browserify-cache-api@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/browserify-cache-api/-/browserify-cache-api-3.0.1.tgz#96247e853f068fd6e0d45cc73f0bb2cd9778ef02" + dependencies: + async "^1.5.2" + through2 "^2.0.0" + xtend "^4.0.0" + browserify-cipher@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" @@ -667,6 +757,15 @@ browserify-des@^1.0.0: des.js "^1.0.0" inherits "^2.0.1" +browserify-incremental@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/browserify-incremental/-/browserify-incremental-3.1.1.tgz#0713cb7587247a632a9f08cf1bd169b878b62a8a" + dependencies: + JSONStream "^0.10.0" + browserify-cache-api "^3.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" @@ -744,6 +843,59 @@ browserify@^14.5.0: vm-browserify "~0.0.1" xtend "^4.0.0" +browserify@^16.0.0, browserify@^16.1.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.2.0.tgz#04ba47c4150555532978453818160666aa3bd8a7" + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^1.11.0" + browserify-zlib "~0.2.0" + buffer "^5.0.2" + cached-path-relative "^1.0.0" + concat-stream "^1.6.0" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "^1.2.0" + duplexer2 "~0.1.2" + events "^2.0.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "^1.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + mkdirp "^0.5.0" + module-deps "^6.0.0" + os-browserify "~0.3.0" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^2.0.0" + string_decoder "^1.1.1" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "0.0.1" + url "~0.11.0" + util "~0.10.1" + vm-browserify "^1.0.0" + xtend "^4.0.0" + browserstack@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.5.0.tgz#b565425ad62ed72c1082a1eb979d5313c7d4754f" @@ -761,6 +913,10 @@ buffer-crc32@^0.2.1: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" +buffer-from@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -776,6 +932,21 @@ buffers@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" +build@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/build/-/build-0.1.4.tgz#707fe026ffceddcacbfdcdf356eafda64f151046" + dependencies: + cssmin "0.3.x" + jsmin "1.x" + jxLoader "*" + moo-server "*" + promised-io "*" + timespan "2.x" + uglify-js "1.x" + walker "1.x" + winston "*" + wrench "1.3.x" + buildmail@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/buildmail/-/buildmail-4.0.1.tgz#877f7738b78729871c9a105e3b837d2be11a7a72" @@ -808,6 +979,20 @@ bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + cached-path-relative@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" @@ -924,7 +1109,7 @@ chokidar@1.6.1: optionalDependencies: fsevents "^1.0.0" -chokidar@^1.4.1: +chokidar@^1.0.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -939,6 +1124,28 @@ chokidar@^1.4.1: optionalDependencies: fsevents "^1.0.0" +chokidar@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176" + dependencies: + anymatch "^2.0.0" + async-each "^1.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^2.1.1" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + upath "^1.0.0" + optionalDependencies: + fsevents "^1.1.2" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + ci-info@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.2.tgz#03561259db48d0474c8bdc90f5b47b068b6bbfb4" @@ -958,6 +1165,15 @@ circular-json@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.4.0.tgz#c448ea998b7fe31ecf472ec29c6b608e2e2a62fd" +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -1006,6 +1222,13 @@ coffeescript@^1.12.7: version "1.12.7" resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.12.7.tgz#e57ee4c4867cf7f606bfc4a0f2d550c0981ddd27" +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + color-convert@^1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" @@ -1016,7 +1239,7 @@ color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" -colors@1.0.3: +colors@1.0.3, colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" @@ -1078,7 +1301,7 @@ component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" -component-emitter@1.2.1, component-emitter@^1.2.0: +component-emitter@1.2.1, component-emitter@^1.2.0, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -1115,6 +1338,15 @@ concat-stream@~1.5.0, concat-stream@~1.5.1: readable-stream "~2.0.0" typedarray "~0.0.5" +concat-stream@~1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + connect@^3.6.0: version "3.6.5" resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.5.tgz#fb8dde7ba0763877d0ec9df9dac0b4b40e72c7da" @@ -1305,6 +1537,10 @@ cookiejar@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" @@ -1391,6 +1627,10 @@ crypto-browserify@^3.0.0: randombytes "^2.0.0" randomfill "^1.0.3" +cssmin@0.3.x: + version "0.3.2" + resolved "https://registry.yarnpkg.com/cssmin/-/cssmin-0.3.2.tgz#ddce4c547b510ae0d594a8f1fbf8aaf8e2c5c00d" + cucumber-expressions@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cucumber-expressions/-/cucumber-expressions-3.0.0.tgz#4cf424813dae396cc9dab714b8104b459befc32c" @@ -1502,6 +1742,10 @@ custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" +cycle@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" @@ -1545,7 +1789,7 @@ dateformat@^1.0.11, dateformat@^1.0.12, dateformat@^1.0.6, dateformat@~1.0.12: get-stdin "^4.0.1" meow "^3.3.0" -debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9: +debug@2, debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6, debug@~2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -1567,6 +1811,10 @@ decamelize@^1.0.0, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + deep-eql@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" @@ -1588,6 +1836,25 @@ define-properties@^1.1.2: foreach "^2.0.5" object-keys "^1.0.8" +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -1663,6 +1930,14 @@ detective@^4.0.0: acorn "^5.2.1" defined "^1.0.0" +detective@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.1.0.tgz#7a20d89236d7b331ccea65832e7123b5551bb7cb" + dependencies: + acorn-node "^1.3.0" + defined "^1.0.0" + minimist "^1.1.1" + di@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" @@ -1705,6 +1980,10 @@ dom-serialize@^2.2.0: extend "^3.0.0" void-elements "^2.0.0" +domain-browser@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + domain-browser@~1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" @@ -2071,6 +2350,10 @@ events@^1.1.1, events@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" +events@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/events/-/events-2.0.0.tgz#cbbb56bf3ab1ac18d71c43bb32c86255062769f2" + evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -2100,6 +2383,18 @@ expand-brackets@^0.1.4: dependencies: is-posix-bracket "^0.1.0" +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + expand-range@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" @@ -2119,6 +2414,19 @@ expand-tilde@^1.2.2: dependencies: os-homedir "^1.0.1" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -2137,6 +2445,19 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + extract-zip@^1.6.5: version "1.6.6" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" @@ -2154,6 +2475,10 @@ extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" +eyes@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" @@ -2232,6 +2557,15 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + finalhandler@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.6.tgz#007aea33d1a4d3e42017f624848ad58d212f814f" @@ -2304,7 +2638,7 @@ follow-redirects@1.0.0: dependencies: debug "^2.2.0" -for-in@^1.0.1: +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2346,7 +2680,7 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -formatio@1.2.0, formatio@^1.2.0: +formatio@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" dependencies: @@ -2356,6 +2690,12 @@ formidable@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9" +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + fs-access@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" @@ -2392,6 +2732,12 @@ fs-finder@^1.8.1: operator-compare "~1.0.1" q "~1.0.0" +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2403,6 +2749,13 @@ fsevents@^1.0.0: nan "^2.3.0" node-pre-gyp "^0.6.39" +fsevents@^1.1.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.3.tgz#08292982e7059f6674c93d8b829c1e8604979ac0" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.9.0" + fstream-ignore@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" @@ -2502,6 +2855,10 @@ get-uri@2: ftp "~0.3.10" readable-stream "2" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + getobject@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c" @@ -2569,6 +2926,13 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -2670,12 +3034,28 @@ grunt-auto-release@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/grunt-auto-release/-/grunt-auto-release-0.0.7.tgz#4a1be3254b10a17b341e402f51b85191e86cf4d1" +grunt-browserify@^5.0.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/grunt-browserify/-/grunt-browserify-5.3.0.tgz#47fd8cf8bac58fe2de683afdc57f7f3a80ca792d" + dependencies: + async "^2.5.0" + browserify "^16.0.0" + browserify-incremental "^3.1.1" + glob "^7.1.2" + lodash "^4.17.4" + resolve "^1.1.6" + watchify "^3.6.1" + grunt-bump@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/grunt-bump/-/grunt-bump-0.8.0.tgz#d3ffe0cf3cf0b38e09607b78538f42a531eafe55" dependencies: semver "^5.1.0" +grunt-check-clean@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/grunt-check-clean/-/grunt-check-clean-0.1.2.tgz#02bb10f7e9f2878782120de1966d36649f2cb414" + grunt-cli@^1.1.0, grunt-cli@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8" @@ -2863,6 +3243,33 @@ has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + has@^1.0.0, has@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" @@ -3068,10 +3475,22 @@ iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@^0.4.4: + version "0.4.21" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.21.tgz#c47f8733d02171189ebc4a400f3218d348094798" + dependencies: + safer-buffer "^2.1.0" + ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + ignore@^3.3.3, ignore@^3.3.6: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" @@ -3177,6 +3596,18 @@ irregular-plurals@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-1.4.0.tgz#2ca9b033651111855412f16be5d77c62a458a766" +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3207,10 +3638,38 @@ is-ci@^1.0.10: dependencies: ci-info "^1.0.0" +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -3221,14 +3680,24 @@ is-equal-shallow@^0.1.3: dependencies: is-primitive "^2.0.0" -is-extendable@^0.1.1: +is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" @@ -3255,6 +3724,18 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" + is-my-json-valid@^2.12.4: version "2.17.1" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" @@ -3280,6 +3761,10 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -3288,6 +3773,12 @@ is-object@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" +is-odd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" + dependencies: + is-number "^4.0.0" + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -3304,6 +3795,12 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -3360,6 +3857,10 @@ is-windows@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + isarray@0.0.1, isarray@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -3386,6 +3887,10 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + isomorphic-fetch@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -3393,7 +3898,7 @@ isomorphic-fetch@^2.1.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -isstream@~0.1.2: +isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -3436,6 +3941,10 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +js-yaml@0.3.x: + version "0.3.7" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-0.3.7.tgz#d739d8ee86461e54b354d6a7d7d1f2ad9a167f62" + js-yaml@3.x, js-yaml@^3.9.1: version "3.10.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" @@ -3458,6 +3967,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsmin@1.x: + version "1.0.1" + resolved "https://registry.yarnpkg.com/jsmin/-/jsmin-1.0.1.tgz#e7bd0dcd6496c3bf4863235bf461a3d98aa3b98c" + json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" @@ -3510,6 +4023,10 @@ jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" +jsonparse@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64" + jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -3533,10 +4050,19 @@ jsx-ast-utils@^2.0.0: dependencies: array-includes "^3.0.3" -just-extend@^1.1.26: +just-extend@^1.1.27: version "1.1.27" resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" +jxLoader@*: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jxLoader/-/jxLoader-0.1.1.tgz#0134ea5144e533b594fc1ff25ff194e235c53ecd" + dependencies: + js-yaml "0.3.x" + moo-server "1.3.x" + promised-io "*" + walker "1.x" + karma-browserify@^5.0.1: version "5.1.2" resolved "https://registry.yarnpkg.com/karma-browserify/-/karma-browserify-5.1.2.tgz#48016359d722312a3530aa1dbbab7663e022d779" @@ -3669,7 +4195,7 @@ kew@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" -kind-of@^3.0.2: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -3681,6 +4207,14 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -3865,13 +4399,9 @@ loggly@^1.1.0: request "2.75.x" timespan "2.3.x" -lolex@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" - -lolex@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.1.tgz#3d2319894471ea0950ef64692ead2a5318cff362" +lolex@^2.1.2, lolex@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.2.tgz#85f9450425103bf9e7a60668ea25dc43274ca807" longest@^1.0.1: version "1.0.1" @@ -3930,10 +4460,26 @@ mailgun-js@^0.7.0: q "~1.4.0" tsscmp "~1.0.0" +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + dependencies: + tmpl "1.0.x" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + "match-stream@>= 0.0.2 < 1": version "0.0.2" resolved "https://registry.yarnpkg.com/match-stream/-/match-stream-0.0.2.tgz#99eb050093b34dffade421b9ac0b410a9cfa17cf" @@ -3999,6 +4545,24 @@ micromatch@^2.1.5, micromatch@^2.3.7: parse-glob "^3.0.4" regex-cache "^0.4.2" +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -4042,7 +4606,7 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: +minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -4050,6 +4614,26 @@ minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" +minipass@^2.2.1, minipass@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.2.4.tgz#03c824d84551ec38a8d1bb5bc350a5a30a354a40" + dependencies: + safe-buffer "^5.1.1" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + mkdirp@0.5, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -4105,6 +4689,26 @@ module-deps@^4.0.8: through2 "^2.0.0" xtend "^4.0.0" +module-deps@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.0.2.tgz#660217d1602b863ac8d4d16951a3720dd9aa4c80" + dependencies: + JSONStream "^1.0.3" + browser-resolve "^1.7.0" + cached-path-relative "^1.0.0" + concat-stream "~1.6.0" + defined "^1.0.0" + detective "^5.0.2" + duplexer2 "^0.1.2" + inherits "^2.0.1" + parents "^1.0.0" + readable-stream "^2.0.2" + resolve "^1.4.0" + stream-combiner2 "^1.1.1" + subarg "^1.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + module-not-found-error@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0" @@ -4113,6 +4717,10 @@ moment@~2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.5.1.tgz#7146a3900533064ca799d5e792f4e480ee0e82bc" +moo-server@*, moo-server@1.3.x: + version "1.3.0" + resolved "https://registry.yarnpkg.com/moo-server/-/moo-server-1.3.0.tgz#5dc79569565a10d6efed5439491e69d2392e58f1" + ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" @@ -4146,6 +4754,31 @@ nan@^2.3.0: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-odd "^2.0.0" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +native-promise-only@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" + natives@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.1.tgz#011acce1f7cbd87f7ba6b3093d6cd9392be1c574" @@ -4154,6 +4787,14 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +needle@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -4162,13 +4803,13 @@ netmask@~1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" -nise@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/nise/-/nise-1.2.0.tgz#079d6cadbbcb12ba30e38f1c999f36ad4d6baa53" +nise@^1.0.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.3.3.tgz#c17a850066a8a1dfeb37f921da02441afc4a82ba" dependencies: - formatio "^1.2.0" - just-extend "^1.1.26" - lolex "^1.6.0" + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" path-to-regexp "^1.7.0" text-encoding "^0.6.4" @@ -4205,6 +4846,21 @@ node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" +node-pre-gyp@^0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz#f11c07516dd92f87199dbc7e1838eab7cd56c9e0" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.0" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.1.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + node-uuid@~1.4.7: version "1.4.8" resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" @@ -4284,12 +4940,23 @@ normalize-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" -normalize-path@^2.0.0, normalize-path@^2.0.1: +normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: remove-trailing-separator "^1.0.1" +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.10" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -4319,10 +4986,24 @@ object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -4330,6 +5011,12 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -4408,6 +5095,12 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +outpipe@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/outpipe/-/outpipe-1.1.1.tgz#50cf8616365e87e031e29a5ec9339a3da4725fa2" + dependencies: + shell-quote "^1.4.2" + "over@>= 0.0.5 < 1": version "0.0.5" resolved "https://registry.yarnpkg.com/over/-/over-0.0.5.tgz#f29852e70fd7e25f360e013a8ec44c82aedb5708" @@ -4511,10 +5204,18 @@ parseurl@~1.3.0, parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" @@ -4643,6 +5344,10 @@ pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + prelude-ls@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.0.3.tgz#443920ce8940a8294b993fbfcee63b9a8920dce0" @@ -4681,6 +5386,10 @@ promise@^7.1.1: dependencies: asap "~2.0.3" +promised-io@*: + version "0.3.5" + resolved "https://registry.yarnpkg.com/promised-io/-/promised-io-0.3.5.tgz#4ad217bb3658bcaae9946b17a8668ecd851e1356" + prop-types@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" @@ -4974,6 +5683,13 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -5152,6 +5868,10 @@ resolve-pkg@^0.1.0: dependencies: resolve-from "^2.0.0" +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + resolve@1.1.7, resolve@1.1.x, resolve@~1.1.0, resolve@~1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -5168,6 +5888,12 @@ resolve@^1.1.3, resolve@^1.1.4, resolve@^1.2.0, resolve@^1.3.3: dependencies: path-parse "^1.0.5" +resolve@^1.1.6, resolve@^1.4.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + dependencies: + path-parse "^1.0.5" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -5175,6 +5901,10 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -5218,7 +5948,21 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -samsam@1.x: +safe-buffer@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +samsam@1.3.0, samsam@1.x, samsam@^1.1.3: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" @@ -5238,6 +5982,10 @@ saucelabs@^1.4.0: dependencies: https-proxy-agent "^1.0.0" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + semver-regex@1.0.0, semver-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9" @@ -5262,6 +6010,24 @@ set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + "setimmediate@>= 1.0.1 < 2", "setimmediate@>= 1.0.2 < 2", setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -5294,7 +6060,7 @@ shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" -shell-quote@^1.6.1: +shell-quote@^1.4.2, shell-quote@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" dependencies: @@ -5311,17 +6077,21 @@ sinon-chai@^2.7.0: version "2.14.0" resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d" -sinon@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.1.3.tgz#fc599eda47ed9f1a694ce774b94ab44260bd7ac5" +sinon@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-3.3.0.tgz#9132111b4bbe13c749c2848210864250165069b1" dependencies: + build "^0.1.4" diff "^3.1.0" formatio "1.2.0" lodash.get "^4.4.2" - lolex "^2.2.0" - nise "^1.2.0" - supports-color "^4.4.0" - type-detect "^4.0.5" + lolex "^2.1.2" + native-promise-only "^0.8.1" + nise "^1.0.1" + path-to-regexp "^1.7.0" + samsam "^1.1.3" + text-encoding "0.6.4" + type-detect "^4.0.0" slack-node@~0.2.0: version "0.2.0" @@ -5356,6 +6126,33 @@ smtp-connection@2.12.0: httpntlm "1.6.1" nodemailer-shared "1.1.0" +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -5431,12 +6228,26 @@ socks@~1.1.5: ip "^1.1.4" smart-buffer "^1.0.13" +source-map-resolve@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" + dependencies: + atob "^2.0.0" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: source-map "^0.5.6" +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" @@ -5475,6 +6286,12 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + split2@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" @@ -5523,6 +6340,10 @@ stack-generator@^2.0.1: dependencies: stackframe "^1.0.4" +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + stackframe@^1.0.3, stackframe@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" @@ -5542,6 +6363,13 @@ stacktrace-js@^2.0.0: stack-generator "^2.0.1" stacktrace-gps "^3.0.1" +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + statuses@1, "statuses@>= 1.3.1 < 2": version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" @@ -5609,6 +6437,12 @@ string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string_decoder@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -5703,7 +6537,7 @@ supports-color@^3.1.0: dependencies: has-flag "^1.0.0" -supports-color@^4.0.0, supports-color@^4.4.0: +supports-color@^4.0.0: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" dependencies: @@ -5756,7 +6590,19 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" -text-encoding@^0.6.4: +tar@^4: + version "4.4.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.2.tgz#60685211ba46b38847b1ae7ee1a24d744a2cd462" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.2.4" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +text-encoding@0.6.4, text-encoding@^0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" @@ -5811,7 +6657,7 @@ timers-browserify@^1.0.1: dependencies: process "~0.11.0" -timespan@2.3.x: +timespan@2.3.x, timespan@2.x: version "2.3.0" resolved "https://registry.yarnpkg.com/timespan/-/timespan-2.3.0.tgz#4902ce040bd13d845c8f59b27e9d59bad6f39929" @@ -5839,6 +6685,10 @@ tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" @@ -5851,6 +6701,28 @@ to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" @@ -5881,6 +6753,10 @@ tsscmp@~1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" +tty-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + tty-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -5905,7 +6781,7 @@ type-check@~0.3.1, type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@^4.0.0, type-detect@^4.0.5: +type-detect@^4.0.0: version "4.0.5" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.5.tgz#d70e5bc81db6de2a381bcaca0c6e0cbdc7635de2" @@ -5924,6 +6800,10 @@ ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" +uglify-js@1.x: + version "1.3.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-1.3.5.tgz#4b5bfff9186effbaa888e4c9e94bd9fc4c94929d" + uglify-js@^2.6: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" @@ -5964,6 +6844,15 @@ underscore@~1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + universalify@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" @@ -5972,6 +6861,13 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + unzip@~0.1.9: version "0.1.11" resolved "https://registry.yarnpkg.com/unzip/-/unzip-0.1.11.tgz#89749c63b058d7d90d619f86b98aa1535d3b97f0" @@ -5983,6 +6879,10 @@ unzip@~0.1.9: readable-stream "~1.0.31" setimmediate ">= 1.0.1 < 2" +upath@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.5.tgz#02cab9ecebe95bbec6d5fc2566325725ab6d1a73" + upper-case-first@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115" @@ -5993,6 +6893,10 @@ upper-case@^1.0.3, upper-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + url@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -6000,7 +6904,13 @@ url@~0.11.0: punycode "1.3.2" querystring "0.2.0" -useragent@^2.1.12: +use@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" + dependencies: + kind-of "^6.0.2" + +useragent@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" dependencies: @@ -6061,6 +6971,10 @@ verror@1.10.0, verror@^1.9.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vm-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.0.1.tgz#a15d7762c4c48fa6bf9f3309a21340f00ed23063" + vm-browserify@~0.0.1: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -6082,6 +6996,24 @@ walkdir@^0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.11.tgz#a16d025eb931bd03b52f308caed0f40fcebe9532" +walker@1.x: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + dependencies: + makeerror "1.0.x" + +watchify@^3.6.1: + version "3.11.0" + resolved "https://registry.yarnpkg.com/watchify/-/watchify-3.11.0.tgz#03f1355c643955e7ab8dcbf399f624644221330f" + dependencies: + anymatch "^1.3.0" + browserify "^16.1.0" + chokidar "^1.0.0" + defined "^1.0.0" + outpipe "^1.1.0" + through2 "^2.0.0" + xtend "^4.0.0" + wd@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/wd/-/wd-1.5.0.tgz#45c96a16ff9f8c0f9e7ca90f806a8b48bd0034d6" @@ -6136,6 +7068,17 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" +winston@*: + version "2.4.2" + resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.2.tgz#3ca01f763116fc48db61053b7544e750431f8db0" + dependencies: + async "~1.0.0" + colors "1.0.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + stack-trace "0.0.x" + wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" @@ -6152,6 +7095,10 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" +wrench@1.3.x: + version "1.3.9" + resolved "https://registry.yarnpkg.com/wrench/-/wrench-1.3.9.tgz#6f13ec35145317eb292ca5f6531391b244111411" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" @@ -6178,7 +7125,7 @@ xregexp@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -6186,6 +7133,10 @@ yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" From 095fc7e04cc7abb3f44a275a6c7a8b693a260f28 Mon Sep 17 00:00:00 2001 From: lukasz Date: Tue, 1 May 2018 17:10:53 +0200 Subject: [PATCH 13/50] refactor(formatters): refactor formatters.js --- config.tpl.coffee | 3 +- config.tpl.js | 3 +- config.tpl.ls | 4 +- config.tpl.ts | 3 +- lib/init/formatters.js | 166 ++++++++++++------------------ lib/utils/file-utils.js | 19 ++++ test/unit/init/formatters.spec.js | 4 +- 7 files changed, 96 insertions(+), 106 deletions(-) create mode 100644 lib/utils/file-utils.js diff --git a/config.tpl.coffee b/config.tpl.coffee index 7b340dcc2..c7f15de80 100644 --- a/config.tpl.coffee +++ b/config.tpl.coffee @@ -25,7 +25,8 @@ module.exports = (config) -> # preprocess matching files before serving them to the browser # available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: %PREPROCESSORS% + preprocessors: {%PREPROCESSORS% + } # test results reporter to use diff --git a/config.tpl.js b/config.tpl.js index ede8f4c22..d50e11359 100644 --- a/config.tpl.js +++ b/config.tpl.js @@ -25,7 +25,8 @@ module.exports = function(config) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: %PREPROCESSORS%, + preprocessors: {%PREPROCESSORS% + }, // test results reporter to use diff --git a/config.tpl.ls b/config.tpl.ls index abca7e0b3..c185ae4dd 100644 --- a/config.tpl.ls +++ b/config.tpl.ls @@ -25,8 +25,8 @@ module.exports = (config) -> # preprocess matching files before serving them to the browser # available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: %PREPROCESSORS% - + preprocessors: {%PREPROCESSORS% + } # test results reporter to use # possible values: 'dots', 'progress' diff --git a/config.tpl.ts b/config.tpl.ts index 918889aba..1a90a3284 100644 --- a/config.tpl.ts +++ b/config.tpl.ts @@ -25,7 +25,8 @@ module.exports = (config) => { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: %PREPROCESSORS%, + preprocessors: {%PREPROCESSORS% + }, // test results reporter to use diff --git a/lib/init/formatters.js b/lib/init/formatters.js index f479e09a2..3c7231370 100644 --- a/lib/init/formatters.js +++ b/lib/init/formatters.js @@ -1,129 +1,97 @@ -var fs = require('graceful-fs') -var util = require('util') -var path = require('path') - -var JS_TEMPLATE_PATH = path.join(__dirname, '/../../config.tpl.js') -var COFFEE_TEMPLATE_PATH = path.join(__dirname, '/../../config.tpl.coffee') -var JS_REQUIREJS_TEMPLATE_PATH = path.join(__dirname, '/../../requirejs.config.tpl.js') -var COFFEE_REQUIREJS_TEMPLATE_PATH = path.join(__dirname, '/../../requirejs.config.tpl.coffee') -var COFFEE_REGEXP = /\.coffee$/ -var LIVE_TEMPLATE_PATH = path.join(__dirname, '/../../config.tpl.ls') -var LIVE_REGEXP = /\.ls$/ -var TYPE_TEMPLATE_PATH = path.join(__dirname, '/../../config.tpl.ts') -var TYPE_REGEXP = /\.ts$/ - -var isCoffeeFile = function (filename) { - return COFFEE_REGEXP.test(filename) -} +'use strict' -var isLiveFile = function (filename) { - return LIVE_REGEXP.test(filename) -} +const path = require('path') +const FileUtils = require('../utils/file-utils') -var isTypeFile = function (filename) { - return TYPE_REGEXP.test(filename) +function quote (value) { + return `'${value}'` } -var JavaScriptFormatter = function () { - var quote = function (value) { - return "'" + value + "'" - } +function formatLine (items) { + return items.map(quote).join(', ') +} - var quoteNonIncludedPattern = function (value) { - return util.format('{pattern: %s, included: false}', quote(value)) - } +function formatMultiLines (items) { + return items + .map(file => '\n ' + file) + .join(',') +} - var pad = function (str, pad) { - return str.replace(/\n/g, '\n' + pad).replace(/\s+$/gm, '') - } +function formatFiles (includedFiles, onlyServedFiles) { + const lines = [] + .concat(includedFiles.map(quote)) + .concat(onlyServedFiles.map(file => `{ pattern: ${quote(file)}, included: false }`)) - var formatQuottedList = function (list) { - return list.map(quote).join(', ') - } - - this.TEMPLATE_FILE_PATH = JS_TEMPLATE_PATH - this.REQUIREJS_TEMPLATE_FILE = JS_REQUIREJS_TEMPLATE_PATH + return formatMultiLines(lines) +} - this.formatFiles = function (includedFiles, onlyServedFiles) { - var files = includedFiles.map(quote) +function formatPreprocessors (preprocessors) { + const lines = Object.keys(preprocessors) + .map(pattern => `${quote(pattern)}: [${formatLine(preprocessors[pattern])}]`) - onlyServedFiles.forEach(function (onlyServedFile) { - files.push(quoteNonIncludedPattern(onlyServedFile)) - }) + return formatMultiLines(lines) +} - files = files.map(function (file) { - return '\n ' + file - }) +function getConfigPath (file) { + return path.join(__dirname, `/../../${file}`) +} - return files.join(',') +class JavaScriptFormatter { + constructor () { + this.TEMPLATE_FILE_PATH = getConfigPath('config.tpl.js') + this.REQUIREJS_TEMPLATE_FILE = getConfigPath('requirejs.config.tpl.js') } - this.formatPreprocessors = function (preprocessors) { - var lines = [] - Object.keys(preprocessors).forEach(function (pattern) { - lines.push(' ' + quote(pattern) + ': [' + formatQuottedList(preprocessors[pattern]) + ']') - }) + generateConfigFile (answers) { + const replacements = this.formatAnswers(answers) - return pad('{\n' + lines.join(',\n') + '\n}', ' ') + return FileUtils + .readFile(this.TEMPLATE_FILE_PATH) + .replace(/%(.*)%/g, (a, key) => replacements[key]) } - this.formatFrameworks = formatQuottedList + writeConfigFile (path, answers) { + FileUtils.saveFile(path, this.generateConfigFile(answers)) + } - this.formatBrowsers = formatQuottedList + writeRequirejsConfigFile (path) { + FileUtils.copyFile(this.REQUIREJS_TEMPLATE_FILE, path) + } - this.formatAnswers = function (answers) { + formatAnswers (answers) { return { DATE: new Date(), BASE_PATH: answers.basePath, - FRAMEWORKS: this.formatFrameworks(answers.frameworks), - FILES: this.formatFiles(answers.files, answers.onlyServedFiles), - EXCLUDE: this.formatFiles(answers.exclude, []), + FRAMEWORKS: formatLine(answers.frameworks), + FILES: formatFiles(answers.files, answers.onlyServedFiles), + EXCLUDE: formatFiles(answers.exclude, []), AUTO_WATCH: answers.autoWatch ? 'true' : 'false', - BROWSERS: this.formatBrowsers(answers.browsers), - PREPROCESSORS: this.formatPreprocessors(answers.preprocessors) + BROWSERS: formatLine(answers.browsers), + PREPROCESSORS: formatPreprocessors(answers.preprocessors) } } - - this.generateConfigFile = function (answers) { - var template = fs.readFileSync(this.TEMPLATE_FILE_PATH).toString() - var replacements = this.formatAnswers(answers) - - return template.replace(/%(.*)%/g, function (a, key) { - return replacements[key] - }) - } - - this.writeConfigFile = function (path, answers) { - fs.writeFileSync(path, this.generateConfigFile(answers)) - } - - this.generateRequirejsConfigFile = function () { - var template = fs.readFileSync(this.REQUIREJS_TEMPLATE_FILE).toString() - return template - } - - this.writeRequirejsConfigFile = function (path) { - fs.writeFileSync(path, this.generateRequirejsConfigFile()) - } } -var CoffeeFormatter = function () { - JavaScriptFormatter.call(this) - - this.TEMPLATE_FILE_PATH = COFFEE_TEMPLATE_PATH - this.REQUIREJS_TEMPLATE_FILE = COFFEE_REQUIREJS_TEMPLATE_PATH +class CoffeeFormatter extends JavaScriptFormatter { + constructor () { + super() + this.TEMPLATE_FILE_PATH = getConfigPath('config.tpl.coffee') + this.REQUIREJS_TEMPLATE_FILE = getConfigPath('requirejs.config.tpl.coffee') + } } -var LiveFormatter = function () { - JavaScriptFormatter.call(this) - - this.TEMPLATE_FILE_PATH = LIVE_TEMPLATE_PATH +class LiveFormatter extends JavaScriptFormatter { + constructor () { + super() + this.TEMPLATE_FILE_PATH = getConfigPath('config.tpl.ls') + } } -var TypeFormatter = function () { - JavaScriptFormatter.call(this) - - this.TEMPLATE_FILE_PATH = TYPE_TEMPLATE_PATH +class TypeFormatter extends JavaScriptFormatter { + constructor () { + super() + this.TEMPLATE_FILE_PATH = getConfigPath('config.tpl.ts') + } } exports.JavaScript = JavaScriptFormatter @@ -132,15 +100,15 @@ exports.Live = LiveFormatter exports.Type = TypeFormatter exports.createForPath = function (path) { - if (isCoffeeFile(path)) { + if (/\.coffee$/.test(path)) { return new CoffeeFormatter() } - if (isLiveFile(path)) { + if (/\.ls$/.test(path)) { return new LiveFormatter() } - if (isTypeFile(path)) { + if (/\.ts$/.test(path)) { return new TypeFormatter() } diff --git a/lib/utils/file-utils.js b/lib/utils/file-utils.js new file mode 100644 index 000000000..7cec11c25 --- /dev/null +++ b/lib/utils/file-utils.js @@ -0,0 +1,19 @@ +'use strict' + +const fs = require('graceful-fs') + +const FileUtils = { + readFile (path) { + return fs.readFileSync(path).toString() + }, + + saveFile (path, content) { + fs.writeFileSync(path, content) + }, + + copyFile (src, dest) { + FileUtils.saveFile(dest, FileUtils.readFile(src)) + } +} + +module.exports = FileUtils diff --git a/test/unit/init/formatters.spec.js b/test/unit/init/formatters.spec.js index 3a46667ca..2d45b1006 100644 --- a/test/unit/init/formatters.spec.js +++ b/test/unit/init/formatters.spec.js @@ -55,7 +55,7 @@ describe('init/formatters', () => { })) expect(replacements.FILES).to.equal( - "\n 'test-main.js',\n {pattern: 'src/*.js', included: false}" + "\n 'test-main.js',\n { pattern: 'src/*.js', included: false }" ) }) @@ -63,7 +63,7 @@ describe('init/formatters', () => { var replacements = formatter.formatAnswers(createAnswers({preprocessors: {'*.coffee': ['coffee']}})) expect(replacements.PREPROCESSORS).to.equal( - "{\n '*.coffee': ['coffee']\n }" + "\n '*.coffee': ['coffee']" ) }) }) From 57b7938bae658ac00d4fc31470050fc57269ee85 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Tue, 15 May 2018 03:47:32 +0300 Subject: [PATCH 14/50] docs(Files): Increase the discoverability of the custom middleware feature. (#2999) Also minor content improvements. --- docs/config/02-files.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/config/02-files.md b/docs/config/02-files.md index 141fe36df..7cd632082 100644 --- a/docs/config/02-files.md +++ b/docs/config/02-files.md @@ -17,12 +17,12 @@ ## Included, served, watched -Each pattern is either a simple string or an object with four properties: +Each pattern is either a simple string or an object with the following properties: ### `pattern` * **Type.** String -* **No Default.** -* **Description.** The pattern to use for matching. This property is mandatory. +* **No Default.** This property is mandatory. +* **Description.** The pattern to use for matching. ### `type` * **Type.** String @@ -143,6 +143,7 @@ proxies: { * In-memory caching of files. * Watching for updates in the files. * Proxies to alter file paths. +* Support for custom middlewares (the `middleware` configuration option). [glob]: https://github.com/isaacs/node-glob From 2bb4e3691cc79ea7d46096c6cf154e5f3acc82af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Usarz?= Date: Tue, 15 May 2018 18:01:28 +0200 Subject: [PATCH 15/50] fix: remove support of jsVersion configuration property (#3002) Fixes #2911 --- docs/config/01-configuration-file.md | 12 ------------ lib/middleware/karma.js | 26 -------------------------- test/client/karma.conf.js | 2 -- test/e2e/tag.feature | 3 --- 4 files changed, 43 deletions(-) diff --git a/docs/config/01-configuration-file.md b/docs/config/01-configuration-file.md index 8b40bbc49..a2bb5f5bb 100644 --- a/docs/config/01-configuration-file.md +++ b/docs/config/01-configuration-file.md @@ -794,18 +794,6 @@ All of Karma's urls get prefixed with the `urlRoot`. This is helpful when using sometimes you might want to proxy a url that is already taken by Karma. -## jsVersion -**Type:** Number - -**Default:** `0` - -**Description:** The JavaScript version to use in the Firefox browser. - -If `> 0`, Karma will add a JavaScript version tag to the included JavaScript files. - -Note: This will only be applied to the Firefox browser up to version 58. Support for JavaScript version was [removed](https://bugzilla.mozilla.org/show_bug.cgi?id=1428745) in Firefox 59. This property is deprecated and will be removed in the next major release of Karma. - - [plugins]: plugins.html [config/files]: files.html [config/browsers]: browsers.html diff --git a/lib/middleware/karma.js b/lib/middleware/karma.js index 4d8d0ea3a..b9d06fcfc 100644 --- a/lib/middleware/karma.js +++ b/lib/middleware/karma.js @@ -14,7 +14,6 @@ var path = require('path') var util = require('util') var url = require('url') -var useragent = require('useragent') var _ = require('lodash') var log = require('../logger').create('middleware:karma') @@ -72,17 +71,6 @@ var getXUACompatibleUrl = function (url) { return value } -var isFirefox = function (req) { - if (!(req && req.headers)) { - return false - } - - // Browser check - var firefox = useragent.is(req.headers['user-agent']).firefox - - return firefox -} - var createKarmaMiddleware = function ( filesPromise, serveStaticFile, @@ -99,7 +87,6 @@ var createKarmaMiddleware = function ( var customContextFile = injector.get('config.customContextFile') var customDebugFile = injector.get('config.customDebugFile') var customClientContextFile = injector.get('config.customClientContextFile') - var jsVersion = injector.get('config.jsVersion') var includeCrossOriginAttribute = injector.get('config.crossOriginAttribute') var requestUrl = request.normalizedUrl.replace(/\?.*/, '') @@ -221,19 +208,6 @@ var createKarmaMiddleware = function ( var scriptFileType = (fileType || fileExt.substring(1)) var scriptType = (SCRIPT_TYPE[scriptFileType] || 'text/javascript') - // In case there is a JavaScript version specified and this is a Firefox browser - if (jsVersion && jsVersion > 0 && isFirefox(request)) { - var agent = useragent.parse(request.headers['user-agent']) - - log.warn('jsVersion configuration property is deprecated and will be removed in the next major release of Karma.') - - if (agent.major < 59) { - scriptType += ';version=' + jsVersion - } else { - log.warn('jsVersion is not supported in Firefox 59+ (see https://bugzilla.mozilla.org/show_bug.cgi?id=1428745 for more details). Ignoring.') - } - } - var crossOriginAttribute = includeCrossOriginAttribute ? CROSSORIGIN_ATTRIBUTE : '' scriptTags.push(util.format(SCRIPT_TAG, scriptType, filePath, crossOriginAttribute)) } diff --git a/test/client/karma.conf.js b/test/client/karma.conf.js index 1ffff3041..4422ca7cb 100644 --- a/test/client/karma.conf.js +++ b/test/client/karma.conf.js @@ -156,8 +156,6 @@ module.exports = function (config) { forceJSONP: true, - jsVersion: 0, - browserStack: { project: 'Karma' } diff --git a/test/e2e/tag.feature b/test/e2e/tag.feature index 63c3ff35a..960fa0f10 100644 --- a/test/e2e/tag.feature +++ b/test/e2e/tag.feature @@ -8,7 +8,6 @@ Feature: JavaScript Tag """ files = ['tag/tag.js', 'tag/test-with-version.js']; browsers = ['Firefox'] - jsVersion = 1.8 plugins = [ 'karma-jasmine', 'karma-firefox-launcher' @@ -26,7 +25,6 @@ Feature: JavaScript Tag """ files = ['tag/tag.js', 'tag/test-with-version.js']; browsers = ['Chrome']; - jsVersion = 1.8; plugins = [ 'karma-jasmine', 'karma-chrome-launcher' @@ -72,4 +70,3 @@ Feature: JavaScript Tag . Chrome """ - \ No newline at end of file From e1fbdcbdfdf7e8beb4925416219ea28ffdee4c89 Mon Sep 17 00:00:00 2001 From: Yaroslav Admin Date: Thu, 17 May 2018 18:50:44 +0200 Subject: [PATCH 16/50] refactor: migrate Executor to ES2015 (#3003) --- lib/executor.js | 76 +++++++++++++++++++++----------------- lib/server.js | 2 +- test/unit/executor.spec.js | 20 +++++----- 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/lib/executor.js b/lib/executor.js index a20451b1b..55694c4b8 100644 --- a/lib/executor.js +++ b/lib/executor.js @@ -1,60 +1,70 @@ -var log = require('./logger').create() +'use strict' -var Executor = function (capturedBrowsers, config, emitter) { - var self = this - var executionScheduled = false - var pendingCount = 0 - var runningBrowsers +const log = require('./logger').create() - var schedule = function () { - var nonReady = [] +class Executor { + constructor (capturedBrowsers, config, emitter) { + this.capturedBrowsers = capturedBrowsers + this.config = config + this.emitter = emitter - if (!capturedBrowsers.length) { - log.warn('No captured browser, open %s//%s:%s%s', config.protocol, config.hostname, - config.port, config.urlRoot) + this.executionScheduled = false + this.pendingCount = 0 + this.runningBrowsers = null + + // bind all the events + this.emitter.on('run_complete', () => this.onRunComplete()) + this.emitter.on('browser_complete', () => this.onBrowserComplete()) + } + + schedule () { + const nonReady = [] + + if (!this.capturedBrowsers.length) { + log.warn('No captured browser, open %s//%s:%s%s', this.config.protocol, this.config.hostname, + this.config.port, this.config.urlRoot) return false } - if (capturedBrowsers.areAllReady(nonReady)) { + if (this.capturedBrowsers.areAllReady(nonReady)) { log.debug('All browsers are ready, executing') - log.debug('Captured %s browsers', capturedBrowsers.length) - executionScheduled = false - capturedBrowsers.clearResults() - capturedBrowsers.setAllToExecuting() - pendingCount = capturedBrowsers.length - runningBrowsers = capturedBrowsers.clone() - emitter.emit('run_start', runningBrowsers) - self.socketIoSockets.emit('execute', config.client) + log.debug('Captured %s browsers', this.capturedBrowsers.length) + this.executionScheduled = false + this.capturedBrowsers.clearResults() + this.capturedBrowsers.setAllToExecuting() + this.pendingCount = this.capturedBrowsers.length + this.runningBrowsers = this.capturedBrowsers.clone() + this.emitter.emit('run_start', this.runningBrowsers) + this.socketIoSockets.emit('execute', this.config.client) return true } log.info('Delaying execution, these browsers are not ready: ' + nonReady.join(', ')) - executionScheduled = true + this.executionScheduled = true return false } - this.schedule = schedule - - this.onRunComplete = function () { - if (executionScheduled) { - schedule() + onRunComplete () { + if (this.executionScheduled) { + this.schedule() } } - this.onBrowserComplete = function () { - pendingCount-- + onBrowserComplete () { + this.pendingCount-- - if (!pendingCount) { + if (!this.pendingCount) { // Ensure run_complete is emitted in the next tick // so it is never emitted before browser_complete - setTimeout(function () { - emitter.emit('run_complete', runningBrowsers, runningBrowsers.getResults()) + setTimeout(() => { + this.emitter.emit('run_complete', this.runningBrowsers, this.runningBrowsers.getResults()) }, 0) } } +} - // bind all the events - emitter.bind(this) +Executor.factory = function (capturedBrowsers, config, emitter) { + return new Executor(capturedBrowsers, config, emitter) } module.exports = Executor diff --git a/lib/server.js b/lib/server.js index c9ddbe71e..160a8130f 100644 --- a/lib/server.js +++ b/lib/server.js @@ -93,7 +93,7 @@ var Server = function (cliOptions, done) { fileList: ['type', FileList], webServer: ['factory', ws.create], socketServer: ['factory', createSocketIoServer], - executor: ['type', Executor], + executor: ['factory', Executor.factory], // TODO(vojta): remove customFileHandlers: ['value', []], // TODO(vojta): remove, once karma-dart does not rely on it diff --git a/test/unit/executor.spec.js b/test/unit/executor.spec.js index 21279aa18..a09382c4f 100644 --- a/test/unit/executor.spec.js +++ b/test/unit/executor.spec.js @@ -1,14 +1,16 @@ -var Browser = require('../../lib/browser') -var BrowserCollection = require('../../lib/browser_collection') -var EventEmitter = require('../../lib/events').EventEmitter -var Executor = require('../../lib/executor') +'use strict' + +const Browser = require('../../lib/browser') +const BrowserCollection = require('../../lib/browser_collection') +const EventEmitter = require('../../lib/events').EventEmitter +const Executor = require('../../lib/executor') describe('executor', () => { - var emitter - var capturedBrowsers - var config - var spy - var executor + let emitter + let capturedBrowsers + let config + let spy + let executor beforeEach(() => { config = {client: {}} From 639cd272870285aba72d5c319066ce9134e6b9f0 Mon Sep 17 00:00:00 2001 From: Yaroslav Admin Date: Thu, 17 May 2018 20:58:02 +0200 Subject: [PATCH 17/50] refactor: migrate helper to ES2015 (#3005) --- lib/helper.js | 103 ++++++++++++++++++++------------------- test/unit/helper.spec.js | 48 +++++++++--------- 2 files changed, 78 insertions(+), 73 deletions(-) diff --git a/lib/helper.js b/lib/helper.js index e0b32c8ac..cdf051f01 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -1,26 +1,29 @@ -var fs = require('graceful-fs') -var path = require('path') -var _ = require('lodash') -var useragent = require('useragent') -var Promise = require('bluebird') -var mm = require('minimatch') - -exports.browserFullNameToShort = function (fullName) { - var agent = useragent.parse(fullName) - var isKnown = agent.family !== 'Other' && agent.os.family !== 'Other' +'use strict' + +const fs = require('graceful-fs') +const path = require('path') +const _ = require('lodash') +const useragent = require('useragent') +const Promise = require('bluebird') +const mm = require('minimatch') + +exports.browserFullNameToShort = (fullName) => { + const agent = useragent.parse(fullName) + const isKnown = agent.family !== 'Other' && agent.os.family !== 'Other' return isKnown ? agent.toAgent() + ' (' + agent.os + ')' : fullName } -exports.isDefined = function (value) { +exports.isDefined = (value) => { return !_.isUndefined(value) } -var parser = function (pattern, out) { + +const parser = (pattern, out) => { if (pattern.length === 0) return out - var p = /^(\[[^\]]*\]|[*+@?]\((.+?)\))/g - var matches = p.exec(pattern) + const p = /^(\[[^\]]*\]|[*+@?]\((.+?)\))/g + const matches = p.exec(pattern) if (!matches) { - var c = pattern[0] - var t = 'word' + const c = pattern[0] + let t = 'word' if (c === '*') { t = 'star' } else if (c === '?') { @@ -38,7 +41,7 @@ var parser = function (pattern, out) { return parser(pattern.substring(matches[0].length), out) } -var gsParser = function (pattern, out) { +const gsParser = (pattern, out) => { if (pattern === '**') { out.glob_star++ return out @@ -46,18 +49,18 @@ var gsParser = function (pattern, out) { return parser(pattern, out) } -var compareWeightObject = function (w1, w2) { +const compareWeightObject = (w1, w2) => { return exports.mmComparePatternWeights( [w1.glob_star, w1.star, w1.ext_glob, w1.range, w1.optional], [w2.glob_star, w2.star, w2.ext_glob, w2.range, w2.optional] ) } -exports.mmPatternWeight = function (pattern) { - var m = new mm.Minimatch(pattern) +exports.mmPatternWeight = (pattern) => { + const m = new mm.Minimatch(pattern) if (!m.globParts) return [0, 0, 0, 0, 0, 0] - var result = m.globParts.reduce(function (prev, p) { - var r = p.reduce(function (prev, p) { + const result = m.globParts.reduce((prev, p) => { + const r = p.reduce((prev, p) => { return gsParser(p, prev) }, {glob_star: 0, ext_glob: 0, word: 0, star: 0, optional: 0, range: 0}) if (prev === undefined) return r @@ -67,8 +70,8 @@ exports.mmPatternWeight = function (pattern) { return [result.glob_sets, result.glob_star, result.star, result.ext_glob, result.range, result.optional] } -exports.mmComparePatternWeights = function (weight1, weight2) { - var n1, n2, diff +exports.mmComparePatternWeights = (weight1, weight2) => { + let n1, n2, diff n1 = weight1[0] n2 = weight2[0] diff = n1 - n2 @@ -82,28 +85,28 @@ exports.isObject = _.isObject exports.isArray = _.isArray exports.isNumber = _.isNumber -var ABS_URL = /^https?:\/\// -exports.isUrlAbsolute = function (url) { +const ABS_URL = /^https?:\/\// +exports.isUrlAbsolute = (url) => { return ABS_URL.test(url) } -exports.camelToSnake = function (camelCase) { - return camelCase.replace(/[A-Z]/g, function (match, pos) { +exports.camelToSnake = (camelCase) => { + return camelCase.replace(/[A-Z]/g, (match, pos) => { return (pos > 0 ? '_' : '') + match.toLowerCase() }) } -exports.ucFirst = function (word) { +exports.ucFirst = (word) => { return word.charAt(0).toUpperCase() + word.substr(1) } -exports.dashToCamel = function (dash) { - var words = dash.split('-') +exports.dashToCamel = (dash) => { + const words = dash.split('-') return words.shift() + words.map(exports.ucFirst).join('') } -exports.arrayRemove = function (collection, item) { - var idx = collection.indexOf(item) +exports.arrayRemove = (collection, item) => { + const idx = collection.indexOf(item) if (idx !== -1) { collection.splice(idx, 1) @@ -114,15 +117,15 @@ exports.arrayRemove = function (collection, item) { } exports.merge = function () { - var args = Array.prototype.slice.call(arguments, 0) + const args = Array.prototype.slice.call(arguments, 0) args.unshift({}) return _.merge.apply({}, args) } -exports.formatTimeInterval = function (time) { - var mins = Math.floor(time / 60000) - var secs = (time - mins * 60000) / 1000 - var str = secs + (secs === 1 ? ' sec' : ' secs') +exports.formatTimeInterval = (time) => { + const mins = Math.floor(time / 60000) + const secs = (time - mins * 60000) / 1000 + let str = secs + (secs === 1 ? ' sec' : ' secs') if (mins) { str = mins + (mins === 1 ? ' min ' : ' mins ') + str @@ -131,20 +134,20 @@ exports.formatTimeInterval = function (time) { return str } -var replaceWinPath = function (path) { +const replaceWinPath = (path) => { return _.isString(path) ? path.replace(/\\/g, '/') : path } exports.normalizeWinPath = process.platform === 'win32' ? replaceWinPath : _.identity -exports.mkdirIfNotExists = function mkdir (directory, done) { +exports.mkdirIfNotExists = (directory, done) => { // TODO(vojta): handle if it's a file /* eslint-disable handle-callback-err */ - fs.stat(directory, function (err, stat) { + fs.stat(directory, (err, stat) => { if (stat && stat.isDirectory()) { done() } else { - mkdir(path.dirname(directory), function () { + exports.mkdirIfNotExists(path.dirname(directory), () => { fs.mkdir(directory, done) }) } @@ -152,17 +155,17 @@ exports.mkdirIfNotExists = function mkdir (directory, done) { /* eslint-enable handle-callback-err */ } -exports.defer = function () { - var resolve - var reject - var promise = new Promise(function () { - resolve = arguments[0] - reject = arguments[1] +exports.defer = () => { + let res + let rej + const promise = new Promise((resolve, reject) => { + res = resolve + rej = reject }) return { - resolve: resolve, - reject: reject, + resolve: res, + reject: rej, promise: promise } } diff --git a/test/unit/helper.spec.js b/test/unit/helper.spec.js index c937bb95d..1cf286c07 100644 --- a/test/unit/helper.spec.js +++ b/test/unit/helper.spec.js @@ -1,11 +1,13 @@ -var path = require('path') +'use strict' + +const path = require('path') describe('helper', () => { - var helper = require('../../lib/helper') + const helper = require('../../lib/helper') describe('browserFullNameToShort', () => { // helper function - var expecting = (name) => expect(helper.browserFullNameToShort(name)) + const expecting = (name) => expect(helper.browserFullNameToShort(name)) it('should parse iOS', () => { expecting( @@ -119,7 +121,7 @@ describe('helper', () => { }) describe('isDefined', () => { - var isDefined = helper.isDefined + const isDefined = helper.isDefined it('should return true if defined', () => { expect(isDefined()).to.equal(false) @@ -133,7 +135,7 @@ describe('helper', () => { }) describe('camelToSnake', () => { - var camelToSnake = helper.camelToSnake + const camelToSnake = helper.camelToSnake it('should convert camelCase string to snake_case', () => { expect(camelToSnake('OneMoreThing')).to.equal('one_more_thing') @@ -141,7 +143,7 @@ describe('helper', () => { }) describe('dashToCamel', () => { - var dashToCamel = helper.dashToCamel + const dashToCamel = helper.dashToCamel it('should convert dash-case to camelCase', () => { expect(dashToCamel('one-more-thing')).to.equal('oneMoreThing') @@ -150,14 +152,14 @@ describe('helper', () => { }) describe('arrayRemove', () => { - var arrayRemove = helper.arrayRemove + const arrayRemove = helper.arrayRemove it('should remove object from array', () => { - var a = 'one' - var b = [] - var c = {} - var d = () => null - var collection = [a, b, c, d] + const a = 'one' + const b = [] + const c = {} + const d = () => null + const collection = [a, b, c, d] expect(arrayRemove(collection, b)).to.equal(true) expect(collection).to.deep.equal([a, c, d]) @@ -175,8 +177,8 @@ describe('helper', () => { describe('merge', () => { it('should copy properties to first argument', () => { - var destination = {a: 1, b: 2} - var result = helper.merge(destination, {a: 4, c: 5}) + const destination = {a: 1, b: 2} + const result = helper.merge(destination, {a: 4, c: 5}) expect(destination.a).to.equal(1) expect(result).to.deep.equal({a: 4, b: 2, c: 5}) @@ -211,17 +213,17 @@ describe('helper', () => { }) describe('mkdirIfNotExists', () => { - var fsMock = require('mocks').fs - var loadFile = require('mocks').loadFile + const fsMock = require('mocks').fs + const loadFile = require('mocks').loadFile - var fs = fsMock.create({ + const fs = fsMock.create({ home: {'some.js': fsMock.file()} }) // load file under test - var m = loadFile(path.join(__dirname, '/../../lib/helper.js'), {'graceful-fs': fs, lodash: require('lodash')}) + const m = loadFile(path.join(__dirname, '/../../lib/helper.js'), {'graceful-fs': fs, lodash: require('lodash')}) - var mkdirIfNotExists = m.exports.mkdirIfNotExists + const mkdirIfNotExists = m.exports.mkdirIfNotExists it('should not do anything, if dir already exists', (done) => { mkdirIfNotExists('/home', done) @@ -229,7 +231,7 @@ describe('helper', () => { it('should create directory if it does not exist', (done) => { mkdirIfNotExists('/home/new', () => { - var stat = fs.statSync('/home/new') + const stat = fs.statSync('/home/new') expect(stat).to.exist expect(stat.isDirectory()).to.equal(true) done() @@ -238,7 +240,7 @@ describe('helper', () => { it('should create even parent directories if it does not exist', (done) => { mkdirIfNotExists('/home/new/parent/child', () => { - var stat = fs.statSync('/home/new/parent/child') + const stat = fs.statSync('/home/new/parent/child') expect(stat).to.exist expect(stat.isDirectory()).to.equal(true) done() @@ -247,7 +249,7 @@ describe('helper', () => { }) describe('mmComparePatternWeights', () => { - var helper = require('../../lib/helper') + const helper = require('../../lib/helper') it('should compare right on equal', () => { helper.mmComparePatternWeights([1, 2, 3], [1, 2, 3]).should.be.equal(0) }) @@ -266,7 +268,7 @@ describe('helper', () => { }) describe('mmPatternWeight', () => { - var helper = require('../../lib/helper') + const helper = require('../../lib/helper') it('should calculate right weight of empty', () => { helper.mmPatternWeight('').should.be.deep.equal([0, 0, 0, 0, 0, 0]) }) From 582f96f3124a2640fa1884a3e101e87338285986 Mon Sep 17 00:00:00 2001 From: Yaroslav Admin Date: Fri, 18 May 2018 01:28:28 +0200 Subject: [PATCH 18/50] refactor: migrate File and FileList to ES2015 (#3004) --- lib/file-list.js | 612 ++++++++++++++--------------- lib/file.js | 45 +-- lib/server.js | 2 +- test/unit/file-list.spec.js | 114 +++--- test/unit/middleware/karma.spec.js | 10 +- 5 files changed, 384 insertions(+), 399 deletions(-) diff --git a/lib/file-list.js b/lib/file-list.js index 070e65189..b3b27b866 100644 --- a/lib/file-list.js +++ b/lib/file-list.js @@ -1,29 +1,25 @@ -// File List -// ========= -// -// The List is an object for tracking all files that karma knows about -// currently. +'use strict' // Dependencies // ------------ -var Promise = require('bluebird') -var mm = require('minimatch') -var Glob = require('glob').Glob -var fs = Promise.promisifyAll(require('graceful-fs')) -var pathLib = require('path') -var _ = require('lodash') +const Promise = require('bluebird') +const mm = require('minimatch') +const Glob = require('glob').Glob +const fs = Promise.promisifyAll(require('graceful-fs')) +const pathLib = require('path') +const _ = require('lodash') -var File = require('./file') -var Url = require('./url') -var helper = require('./helper') -var log = require('./logger').create('watcher') -var createPatternObject = require('./config').createPatternObject +const File = require('./file') +const Url = require('./url') +const helper = require('./helper') +const log = require('./logger').create('watcher') +const createPatternObject = require('./config').createPatternObject // Constants // --------- -var GLOB_OPTS = { +const GLOB_OPTS = { cwd: '/', follow: true, nodir: true, @@ -33,211 +29,203 @@ var GLOB_OPTS = { // Helper Functions // ---------------- -function byPath (a, b) { +const byPath = (a, b) => { if (a.path > b.path) return 1 if (a.path < b.path) return -1 return 0 } -// Constructor -// -// patterns - Array -// excludes - Array -// emitter - EventEmitter -// preprocess - Function -// batchInterval - Number -var List = function (patterns, excludes, emitter, preprocess, autoWatchBatchDelay) { - // Store options - this._patterns = patterns - this._excludes = excludes - this._emitter = emitter - this._preprocess = Promise.promisify(preprocess) - this._autoWatchBatchDelay = autoWatchBatchDelay - - // The actual list of files - this.buckets = new Map() - - // Internal tracker if we are refreshing. - // When a refresh is triggered this gets set - // to the promise that `this._refresh` returns. - // So we know we are refreshing when this promise - // is still pending, and we are done when it's either - // resolved or rejected. - this._refreshing = Promise.resolve() - - var self = this - - // Emit the `file_list_modified` event. - // This function is debounced to the value of `autoWatchBatchDelay` - // to avoid reloading while files are still being modified. - function emit () { - self._emitter.emit('file_list_modified', self.files) - } - var debouncedEmit = _.debounce(emit, self._autoWatchBatchDelay) - self._emitModified = function (immediate) { - immediate ? emit() : debouncedEmit() - } -} - -// Private Interface -// ----------------- - -// Is the given path matched by any exclusion filter -// -// path - String -// -// Returns `undefined` if no match, otherwise the matching -// pattern. -List.prototype._isExcluded = function (path) { - return _.find(this._excludes, function (pattern) { - return mm(path, pattern) - }) -} +/** + * The List is an object for tracking all files that karma knows about + * currently. + */ +class FileList { + /** + * @param {Array} patterns + * @param {Array} excludes + * @param {EventEmitter} emitter + * @param {Function} preprocess + * @param {number} autoWatchBatchDelay + */ + constructor (patterns, excludes, emitter, preprocess, autoWatchBatchDelay) { + // Store options + this._patterns = patterns + this._excludes = excludes + this._emitter = emitter + this._preprocess = Promise.promisify(preprocess) + this._autoWatchBatchDelay = autoWatchBatchDelay + + // The actual list of files + this.buckets = new Map() + + // Internal tracker if we are refreshing. + // When a refresh is triggered this gets set + // to the promise that `this._refresh` returns. + // So we know we are refreshing when this promise + // is still pending, and we are done when it's either + // resolved or rejected. + this._refreshing = Promise.resolve() + + // Emit the `file_list_modified` event. + // This function is debounced to the value of `autoWatchBatchDelay` + // to avoid reloading while files are still being modified. + const emit = () => { + this._emitter.emit('file_list_modified', this.files) + } -// Find the matching include pattern for the given path. -// -// path - String -// -// Returns the match or `undefined` if none found. -List.prototype._isIncluded = function (path) { - return _.find(this._patterns, function (pattern) { - return mm(path, pattern.pattern) - }) -} + const debouncedEmit = _.debounce(emit, this._autoWatchBatchDelay) + this._emitModified = (immediate) => { + immediate ? emit() : debouncedEmit() + } + } -// Find the given path in the bucket corresponding -// to the given pattern. -// -// path - String -// pattern - Object -// -// Returns a File or undefined -List.prototype._findFile = function (path, pattern) { - if (!path || !pattern) return - if (!this.buckets.has(pattern.pattern)) return - - return _.find(Array.from(this.buckets.get(pattern.pattern)), function (file) { - return file.originalPath === path - }) -} + // Private Interface + // ----------------- + + // Is the given path matched by any exclusion filter + // + // path - String + // + // Returns `undefined` if no match, otherwise the matching + // pattern. + _isExcluded (path) { + return _.find(this._excludes, (pattern) => mm(path, pattern)) + } -// Is the given path already in the files list. -// -// path - String -// -// Returns a boolean. -List.prototype._exists = function (path) { - var self = this - - var patterns = this._patterns.filter(function (pattern) { - return mm(path, pattern.pattern) - }) - - return !!_.find(patterns, function (pattern) { - return self._findFile(path, pattern) - }) -} + // Find the matching include pattern for the given path. + // + // path - String + // + // Returns the match or `undefined` if none found. + _isIncluded (path) { + return _.find(this._patterns, (pattern) => mm(path, pattern.pattern)) + } -// Check if we are currently refreshing -List.prototype._isRefreshing = function () { - return this._refreshing.isPending() -} + // Find the given path in the bucket corresponding + // to the given pattern. + // + // path - String + // pattern - Object + // + // Returns a File or undefined + _findFile (path, pattern) { + if (!path || !pattern) return + if (!this.buckets.has(pattern.pattern)) return + + return _.find(Array.from(this.buckets.get(pattern.pattern)), (file) => { + return file.originalPath === path + }) + } -// Do the actual work of refreshing -List.prototype._refresh = function () { - var self = this - var buckets = this.buckets - var matchedFiles = new Set() + // Is the given path already in the files list. + // + // path - String + // + // Returns a boolean. + _exists (path) { + const patterns = this._patterns.filter((pattern) => mm(path, pattern.pattern)) - var promise = Promise.map(this._patterns, function (patternObject) { - var pattern = patternObject.pattern - var type = patternObject.type + return !!_.find(patterns, (pattern) => this._findFile(path, pattern)) + } - if (helper.isUrlAbsolute(pattern)) { - buckets.set(pattern, new Set([new Url(pattern, type)])) - return Promise.resolve() - } + // Check if we are currently refreshing + _isRefreshing () { + return this._refreshing.isPending() + } - var mg = new Glob(pathLib.normalize(pattern), GLOB_OPTS) - var files = mg.found - buckets.set(pattern, new Set()) + // Do the actual work of refreshing + _refresh () { + const buckets = this.buckets + const matchedFiles = new Set() - if (_.isEmpty(files)) { - log.warn('Pattern "%s" does not match any file.', pattern) - return - } + let promise + promise = Promise.map(this._patterns, (patternObject) => { + const pattern = patternObject.pattern + const type = patternObject.type - return Promise.map(files, function (path) { - if (self._isExcluded(path)) { - log.debug('Excluded file "%s"', path) + if (helper.isUrlAbsolute(pattern)) { + buckets.set(pattern, new Set([new Url(pattern, type)])) return Promise.resolve() } - if (matchedFiles.has(path)) { - return Promise.resolve() + const mg = new Glob(pathLib.normalize(pattern), GLOB_OPTS) + const files = mg.found + buckets.set(pattern, new Set()) + + if (_.isEmpty(files)) { + log.warn('Pattern "%s" does not match any file.', pattern) + return } - matchedFiles.add(path) + return Promise.map(files, (path) => { + if (this._isExcluded(path)) { + log.debug('Excluded file "%s"', path) + return Promise.resolve() + } + + if (matchedFiles.has(path)) { + return Promise.resolve() + } - var mtime = mg.statCache[path].mtime - var doNotCache = patternObject.nocache - var type = patternObject.type - var file = new File(path, mtime, doNotCache, type) + matchedFiles.add(path) - if (file.doNotCache) { - log.debug('Not preprocessing "%s" due to nocache') - return Promise.resolve(file) - } + const mtime = mg.statCache[path].mtime + const doNotCache = patternObject.nocache + const type = patternObject.type + const file = new File(path, mtime, doNotCache, type) - return self._preprocess(file).then(function () { - return file - }) - }) - .then(function (files) { - files = _.compact(files) + if (file.doNotCache) { + log.debug('Not preprocessing "%s" due to nocache') + return Promise.resolve(file) + } - if (_.isEmpty(files)) { - log.warn('All files matched by "%s" were excluded or matched by prior matchers.', pattern) - } else { - buckets.set(pattern, new Set(files)) - } + return this._preprocess(file).then(() => { + return file + }) + }) + .then((files) => { + files = _.compact(files) + + if (_.isEmpty(files)) { + log.warn('All files matched by "%s" were excluded or matched by prior matchers.', pattern) + } else { + buckets.set(pattern, new Set(files)) + } + }) }) - }) - .then(function () { - if (self._refreshing !== promise) { - return self._refreshing - } - self.buckets = buckets - self._emitModified(true) - return self.files - }) + .then(() => { + if (this._refreshing !== promise) { + return this._refreshing + } + this.buckets = buckets + this._emitModified(true) + return this.files + }) - return promise -} + return promise + } -// Public Interface -// ---------------- + // Public Interface + // ---------------- -Object.defineProperty(List.prototype, 'files', { - get: function () { - var self = this - var uniqueFlat = function (list) { + get files () { + const uniqueFlat = (list) => { return _.uniq(_.flatten(list), 'path') } - var expandPattern = function (p) { - return Array.from(self.buckets.get(p.pattern) || []).sort(byPath) + const expandPattern = (p) => { + return Array.from(this.buckets.get(p.pattern) || []).sort(byPath) } - var served = this._patterns.filter(function (pattern) { + const served = this._patterns.filter((pattern) => { return pattern.served }) - .map(expandPattern) + .map(expandPattern) - var lookup = {} - var included = {} - this._patterns.forEach(function (p) { + const lookup = {} + const included = {} + this._patterns.forEach((p) => { // This needs to be here sadly, as plugins are modifiying // the _patterns directly resulting in elements not being // instantiated properly @@ -245,9 +233,9 @@ Object.defineProperty(List.prototype, 'files', { p = createPatternObject(p) } - var bucket = expandPattern(p) - bucket.forEach(function (file) { - var other = lookup[file.path] + const bucket = expandPattern(p) + bucket.forEach((file) => { + const other = lookup[file.path] if (other && other.compare(p) < 0) return lookup[file.path] = p if (p.included) { @@ -263,148 +251,144 @@ Object.defineProperty(List.prototype, 'files', { included: _.values(included) } } -}) - -// Reglob all patterns to update the list. -// -// Returns a promise that is resolved when the refresh -// is completed. -List.prototype.refresh = function () { - this._refreshing = this._refresh() - return this._refreshing -} - -// Set new patterns and excludes and update -// the list accordingly -// -// patterns - Array, the new patterns. -// excludes - Array, the new exclude patterns. -// -// Returns a promise that is resolved when the refresh -// is completed. -List.prototype.reload = function (patterns, excludes) { - this._patterns = patterns - this._excludes = excludes - - // Wait until the current refresh is done and then do a - // refresh to ensure a refresh actually happens - return this.refresh() -} -// Add a new file from the list. -// This is called by the watcher -// -// path - String, the path of the file to update. -// -// Returns a promise that is resolved when the update -// is completed. -List.prototype.addFile = function (path) { - var self = this - - // Ensure we are not adding a file that should be excluded - var excluded = this._isExcluded(path) - if (excluded) { - log.debug('Add file "%s" ignored. Excluded by "%s".', path, excluded) - - return Promise.resolve(this.files) + // Reglob all patterns to update the list. + // + // Returns a promise that is resolved when the refresh + // is completed. + refresh () { + this._refreshing = this._refresh() + return this._refreshing } - var pattern = this._isIncluded(path) - - if (!pattern) { - log.debug('Add file "%s" ignored. Does not match any pattern.', path) - return Promise.resolve(this.files) + // Set new patterns and excludes and update + // the list accordingly + // + // patterns - Array, the new patterns. + // excludes - Array, the new exclude patterns. + // + // Returns a promise that is resolved when the refresh + // is completed. + reload (patterns, excludes) { + this._patterns = patterns + this._excludes = excludes + + // Wait until the current refresh is done and then do a + // refresh to ensure a refresh actually happens + return this.refresh() } - if (this._exists(path)) { - log.debug('Add file "%s" ignored. Already in the list.', path) - return Promise.resolve(this.files) - } + // Add a new file from the list. + // This is called by the watcher + // + // path - String, the path of the file to update. + // + // Returns a promise that is resolved when the update + // is completed. + addFile (path) { + // Ensure we are not adding a file that should be excluded + const excluded = this._isExcluded(path) + if (excluded) { + log.debug('Add file "%s" ignored. Excluded by "%s".', path, excluded) + + return Promise.resolve(this.files) + } - var file = new File(path) - this.buckets.get(pattern.pattern).add(file) - - return Promise.all([ - fs.statAsync(path), - this._refreshing - ]).spread(function (stat) { - file.mtime = stat.mtime - return self._preprocess(file) - }) - .then(function () { - log.info('Added file "%s".', path) - self._emitModified() - return self.files - }) -} + const pattern = this._isIncluded(path) -// Update the `mtime` of a file. -// This is called by the watcher -// -// path - String, the path of the file to update. -// -// Returns a promise that is resolved when the update -// is completed. -List.prototype.changeFile = function (path) { - var self = this - - var pattern = this._isIncluded(path) - var file = this._findFile(path, pattern) - - if (!pattern || !file) { - log.debug('Changed file "%s" ignored. Does not match any file in the list.', path) - return Promise.resolve(this.files) - } + if (!pattern) { + log.debug('Add file "%s" ignored. Does not match any pattern.', path) + return Promise.resolve(this.files) + } - return Promise.all([ - fs.statAsync(path), - this._refreshing - ]).spread(function (stat) { - if (stat.mtime <= file.mtime) throw new Promise.CancellationError() - - file.mtime = stat.mtime - return self._preprocess(file) - }) - .then(function () { - log.info('Changed file "%s".', path) - self._emitModified() - return self.files - }) - .catch(Promise.CancellationError, function () { - return self.files - }) -} + if (this._exists(path)) { + log.debug('Add file "%s" ignored. Already in the list.', path) + return Promise.resolve(this.files) + } -// Remove a file from the list. -// This is called by the watcher -// -// path - String, the path of the file to update. -// -// Returns a promise that is resolved when the update -// is completed. -List.prototype.removeFile = function (path) { - var self = this + const file = new File(path) + this.buckets.get(pattern.pattern).add(file) - return Promise.try(function () { - var pattern = self._isIncluded(path) - var file = self._findFile(path, pattern) + return Promise.all([ + fs.statAsync(path), + this._refreshing + ]).spread((stat) => { + file.mtime = stat.mtime + return this._preprocess(file) + }) + .then(() => { + log.info('Added file "%s".', path) + this._emitModified() + return this.files + }) + } + + // Update the `mtime` of a file. + // This is called by the watcher + // + // path - String, the path of the file to update. + // + // Returns a promise that is resolved when the update + // is completed. + changeFile (path) { + const pattern = this._isIncluded(path) + const file = this._findFile(path, pattern) if (!pattern || !file) { - log.debug('Removed file "%s" ignored. Does not match any file in the list.', path) - return self.files + log.debug('Changed file "%s" ignored. Does not match any file in the list.', path) + return Promise.resolve(this.files) } - self.buckets.get(pattern.pattern).delete(file) + return Promise.all([ + fs.statAsync(path), + this._refreshing + ]).spread((stat) => { + if (stat.mtime <= file.mtime) throw new Promise.CancellationError() + + file.mtime = stat.mtime + return this._preprocess(file) + }) + .then(() => { + log.info('Changed file "%s".', path) + this._emitModified() + return this.files + }) + .catch(Promise.CancellationError, () => { + return this.files + }) + } + + // Remove a file from the list. + // This is called by the watcher + // + // path - String, the path of the file to update. + // + // Returns a promise that is resolved when the update + // is completed. + removeFile (path) { + return Promise.try(() => { + const pattern = this._isIncluded(path) + const file = this._findFile(path, pattern) + + if (!pattern || !file) { + log.debug('Removed file "%s" ignored. Does not match any file in the list.', path) + return this.files + } + + this.buckets.get(pattern.pattern).delete(file) + + log.info('Removed file "%s".', path) + this._emitModified() + return this.files + }) + } +} - log.info('Removed file "%s".', path) - self._emitModified() - return self.files - }) +FileList.factory = function (patterns, excludes, emitter, preprocess, autoWatchBatchDelay) { + return new FileList(patterns, excludes, emitter, preprocess, autoWatchBatchDelay) } -// Inject dependencies -List.$inject = ['config.files', 'config.exclude', 'emitter', 'preprocess', +FileList.factory.$inject = ['config.files', 'config.exclude', 'emitter', 'preprocess', 'config.autoWatchBatchDelay'] -// PUBLIC -module.exports = List +module.exports = FileList diff --git a/lib/file.js b/lib/file.js index 0dd0a4827..094df9e0e 100644 --- a/lib/file.js +++ b/lib/file.js @@ -1,35 +1,30 @@ -// File -// ==== -// -// File object used for tracking files in `file-list.js` +'use strict' -// Dependencies -// ------------ +/** + * File object used for tracking files in `file-list.js`. + */ +class File { + constructor (path, mtime, doNotCache, type) { + // used for serving (processed path, eg some/file.coffee -> some/file.coffee.js) + this.path = path -var _ = require('lodash') + // original absolute path, id of the file + this.originalPath = path -// Constructor -var File = function (path, mtime, doNotCache, type) { - // used for serving (processed path, eg some/file.coffee -> some/file.coffee.js) - this.path = path + // where the content is stored (processed) + this.contentPath = path - // original absolute path, id of the file - this.originalPath = path + this.mtime = mtime + this.isUrl = false - // where the content is stored (processed) - this.contentPath = path + this.doNotCache = doNotCache === undefined ? false : doNotCache - this.mtime = mtime - this.isUrl = false + this.type = type + } - this.doNotCache = _.isUndefined(doNotCache) ? false : doNotCache - - this.type = type -} - -File.prototype.toString = function () { - return this.path + toString () { + return this.path + } } -// PUBLIC module.exports = File diff --git a/lib/server.js b/lib/server.js index 160a8130f..9b6c861df 100644 --- a/lib/server.js +++ b/lib/server.js @@ -90,7 +90,7 @@ var Server = function (cliOptions, done) { launcher: ['type', Launcher], config: ['value', config], preprocess: ['factory', preprocessor.createPreprocessor], - fileList: ['type', FileList], + fileList: ['factory', FileList.factory], webServer: ['factory', ws.create], socketServer: ['factory', createSocketIoServer], executor: ['factory', Executor.factory], diff --git a/test/unit/file-list.spec.js b/test/unit/file-list.spec.js index 9a6ad1af0..42a61a6e1 100644 --- a/test/unit/file-list.spec.js +++ b/test/unit/file-list.spec.js @@ -1,33 +1,35 @@ -var Promise = require('bluebird') -var EventEmitter = require('events').EventEmitter -var mocks = require('mocks') -var proxyquire = require('proxyquire') -var pathLib = require('path') -var _ = require('lodash') +'use strict' -var helper = require('../../lib/helper') -var config = require('../../lib/config') +const Promise = require('bluebird') +const EventEmitter = require('events').EventEmitter +const mocks = require('mocks') +const proxyquire = require('proxyquire') +const pathLib = require('path') +const _ = require('lodash') + +const helper = require('../../lib/helper') +const config = require('../../lib/config') // create an array of pattern objects from given strings -var patterns = function () { +const patterns = function () { return Array.from(arguments).map((str) => new config.Pattern(str)) } -function pathsFrom (files) { +const pathsFrom = (files) => { return _.map(Array.from(files), 'path') } -function findFile (path, files) { +const findFile = (path, files) => { return Array.from(files).find((file) => file.path === path) } -var PATTERN_LIST = { +const PATTERN_LIST = { '/some/*.js': ['/some/a.js', '/some/b.js'], '*.txt': ['/c.txt', '/a.txt', '/b.txt'], '/a.*': ['/a.txt'] } -var MG = { +const MG = { statCache: { '/some/a.js': {mtime: new Date()}, '/some/b.js': {mtime: new Date()}, @@ -36,7 +38,7 @@ var MG = { '/c.txt': {mtime: new Date()} } } -var mockFs = mocks.fs.create({ +const mockFs = mocks.fs.create({ some: { '0.js': mocks.fs.file('2012-04-04'), 'a.js': mocks.fs.file('2012-04-04'), @@ -53,14 +55,14 @@ var mockFs = mocks.fs.create({ }) describe('FileList', () => { - var list - var emitter - var preprocess - var patternList - var mg - var modified - var glob - var List = list = emitter = preprocess = patternList = mg = modified = glob = null + let list + let emitter + let preprocess + let patternList + let mg + let modified + let glob + let List = list = emitter = preprocess = patternList = mg = modified = glob = null beforeEach(() => {}) @@ -106,7 +108,7 @@ describe('FileList', () => { }) it('returns only served files', () => { - var files = [ + const files = [ new config.Pattern('/a.*', true), // served: true new config.Pattern('/some/*.js', false) // served: false ] @@ -119,7 +121,7 @@ describe('FileList', () => { }) it('marks no cache files', () => { - var files = [ + const files = [ new config.Pattern('/a.*'), // nocach: false new config.Pattern('/some/*.js', true, true, true, true) // nocache: true ] @@ -140,7 +142,7 @@ describe('FileList', () => { }) it('returns a flat array of included files', () => { - var files = [ + const files = [ new config.Pattern('/a.*', true, false), // included: false new config.Pattern('/some/*.js') // included: true ] @@ -265,8 +267,8 @@ describe('FileList', () => { return list.refresh().then((files) => { expect(list.buckets.size).to.equal(2) - var first = pathsFrom(list.buckets.get('/some/*.js')) - var second = pathsFrom(list.buckets.get('*.txt')) + const first = pathsFrom(list.buckets.get('/some/*.js')) + const second = pathsFrom(list.buckets.get('*.txt')) expect(first).to.contain('/some/a.js', '/some/b.js') expect(second).to.contain('/a.txt', '/b.txt', '/c.txt') @@ -276,8 +278,8 @@ describe('FileList', () => { it('uses the file from the first matcher if two matchers match the same file', () => { list = new List(patterns('/a.*', '*.txt'), [], emitter, preprocess, 100) return list.refresh().then(() => { - var first = pathsFrom(list.buckets.get('/a.*')) - var second = pathsFrom(list.buckets.get('*.txt')) + const first = pathsFrom(list.buckets.get('/a.*')) + const second = pathsFrom(list.buckets.get('*.txt')) expect(first).to.contain('/a.txt') expect(second).not.to.contain('/a.txt') @@ -285,16 +287,16 @@ describe('FileList', () => { }) it('cancels refreshs', () => { - var checkResult = (files) => { + const checkResult = (files) => { expect(_.map(files.served, 'path')).to.contain('/some/a.js', '/some/b.js', '/some/c.js') } - var p1 = list.refresh().then(checkResult) + const p1 = list.refresh().then(checkResult) patternList['/some/*.js'].push('/some/c.js') mg.statCache['/some/c.js'] = {mtime: new Date(Date.now() + 5000)} - var p2 = list.refresh().then(checkResult) - var called = false - var callback = (data) => { + const p2 = list.refresh().then(checkResult) + let called = false + const callback = (data) => { expect(called).to.be.false expect(data.served[0].mtime.toString()).to.not.equal(data.served[2].mtime.toString()) expect(data.served[0].mtime.toString()).to.equal(data.served[1].mtime.toString()) @@ -309,10 +311,10 @@ describe('FileList', () => { it('sets the mtime for all files', () => { return list.refresh().then((files) => { - var bucket = list.buckets.get('/some/*.js') + const bucket = list.buckets.get('/some/*.js') - var file1 = findFile('/some/a.js', bucket) - var file2 = findFile('/some/b.js', bucket) + const file1 = findFile('/some/a.js', bucket) + const file2 = findFile('/some/b.js', bucket) expect(file1.mtime).to.be.eql(mg.statCache['/some/a.js'].mtime) expect(file2.mtime).to.be.eql(mg.statCache['/some/b.js'].mtime) @@ -323,10 +325,10 @@ describe('FileList', () => { list = new List(patterns('/some/world/../*.js', '*.txt'), [], emitter, preprocess) return list.refresh().then((files) => { - var bucket = list.buckets.get('/some/world/../*.js') + const bucket = list.buckets.get('/some/world/../*.js') - var file1 = findFile('/some/a.js', bucket) - var file2 = findFile('/some/b.js', bucket) + const file1 = findFile('/some/a.js', bucket) + const file2 = findFile('/some/b.js', bucket) expect(file1.mtime).to.be.eql(mg.statCache['/some/a.js'].mtime) expect(file2.mtime).to.be.eql(mg.statCache['/some/b.js'].mtime) @@ -353,7 +355,7 @@ describe('FileList', () => { list = new List(patterns('*.txt'), ['/a.*', '**/b.txt'], emitter, preprocess) return list.refresh().then((files) => { - var bucket = pathsFrom(list.buckets.get('*.txt')) + const bucket = pathsFrom(list.buckets.get('*.txt')) expect(bucket).to.contain('/c.txt') expect(bucket).not.to.contain('/a.txt') @@ -366,8 +368,8 @@ describe('FileList', () => { return list.refresh() .then((files) => { - var bucket = list.buckets.get('http://some.com') - var file = findFile('http://some.com', bucket) + const bucket = list.buckets.get('http://some.com') + const file = findFile('http://some.com', bucket) expect(file).to.have.property('isUrl', true) }) @@ -392,7 +394,7 @@ describe('FileList', () => { }) it('fires modified before resolving promise after subsequent calls', () => { - var modified = sinon.stub() + const modified = sinon.stub() emitter.on('file_list_modified', modified) return list.refresh().then(() => { @@ -427,7 +429,7 @@ describe('FileList', () => { }) describe('addFile', () => { - var clock = null + let clock = null beforeEach(() => { patternList = PATTERN_LIST @@ -493,14 +495,14 @@ describe('FileList', () => { return list.refresh().then((before) => { return list.addFile('/some/d.js').then((files) => { expect(pathsFrom(files.served)).to.contain('/some/d.js') - var bucket = list.buckets.get('/some/*.js') + const bucket = list.buckets.get('/some/*.js') expect(pathsFrom(bucket)).to.contain('/some/d.js') }) }) }) it('fires "file_list_modified"', () => { - var modified = sinon.stub() + const modified = sinon.stub() emitter.on('file_list_modified', modified) return list.refresh().then(() => { @@ -555,7 +557,7 @@ describe('FileList', () => { }) describe('changeFile', () => { - var clock = null + let clock = null beforeEach(() => { patternList = PATTERN_LIST @@ -598,7 +600,7 @@ describe('FileList', () => { it('updates mtime and fires "file_list_modified"', () => { // MATCH: /some/a.js, /some/b.js list = new List(patterns('/some/*.js', '/a.*'), [], emitter, preprocess, 100) - var modified = sinon.stub() + const modified = sinon.stub() emitter.on('file_list_modified', modified) return list.refresh().then((files) => { @@ -617,7 +619,7 @@ describe('FileList', () => { // MATCH: /some/a.js list = new List(patterns('/some/*.js', '/a.*'), ['/some/b.js'], emitter, preprocess) - var modified = sinon.stub() + const modified = sinon.stub() emitter.on('file_list_modified', modified) return list.refresh().then((files) => { @@ -635,7 +637,7 @@ describe('FileList', () => { // MATCH: /some/a.js, /some/b.js, /a.txt list = new List(patterns('/some/*.js', '/a.*'), [], emitter, preprocess) - var modified = sinon.stub() + const modified = sinon.stub() emitter.on('file_list_modified', modified) return list.refresh().then((files) => { @@ -664,7 +666,7 @@ describe('FileList', () => { }) describe('removeFile', () => { - var clock = null + let clock = null beforeEach(() => { patternList = PATTERN_LIST @@ -708,7 +710,7 @@ describe('FileList', () => { // MATCH: /some/a.js, /some/b.js, /a.txt list = new List(patterns('/some/*.js', '/a.*'), [], emitter, preprocess, 100) - var modified = sinon.stub() + const modified = sinon.stub() emitter.on('file_list_modified', modified) return list.refresh().then((files) => { @@ -747,12 +749,12 @@ describe('FileList', () => { // Rule of thumb: Always wait on the promises returned by list.addFile, list.changeFile, // and list.removeFile. - var clock = null + let clock = null beforeEach(() => { patternList = PATTERN_LIST mg = MG - Promise.setScheduler(function (fn) { fn() }) + Promise.setScheduler((fn) => { fn() }) preprocess = sinon.spy((file, done) => process.nextTick(done)) emitter = new EventEmitter() @@ -929,7 +931,7 @@ describe('FileList', () => { expect(preprocess).to.not.have.been.called - var promise = new Promise((resolve) => { + const promise = new Promise((resolve) => { emitter.once('file_list_modified', () => _.defer(() => { resolve() })) diff --git a/test/unit/middleware/karma.spec.js b/test/unit/middleware/karma.spec.js index edb29293c..ae76de2b2 100644 --- a/test/unit/middleware/karma.spec.js +++ b/test/unit/middleware/karma.spec.js @@ -1,3 +1,5 @@ +'use strict' + var mocks = require('mocks') var helper = require('../../../lib/helper') @@ -14,9 +16,11 @@ describe('middleware.karma', () => { var nextSpy var response - var MockFile = function (path, sha, type) { - File.call(this, path, undefined, undefined, type) - this.sha = sha || 'sha-default' + class MockFile extends File { + constructor (path, sha, type) { + super(path, undefined, undefined, type) + this.sha = sha || 'sha-default' + } } var fsMock = mocks.fs.create({ From adaefd5c3e99b416bf75acdbb88531af9ec6c7f1 Mon Sep 17 00:00:00 2001 From: Yaroslav Admin Date: Fri, 18 May 2018 01:29:22 +0200 Subject: [PATCH 19/50] refactor: migrate index to ES2015 (#3006) --- lib/index.js | 18 +++++++++--------- test/unit/index.spec.js | 6 ++++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/index.js b/lib/index.js index 9d09178b0..4d906a437 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,20 +1,20 @@ -// index module +'use strict' -var constants = require('./constants') -var Server = require('./server') -var runner = require('./runner') -var stopper = require('./stopper') -var launcher = require('./launcher') -var cfg = require('./config') +const constants = require('./constants') +const Server = require('./server') +const runner = require('./runner') +const stopper = require('./stopper') +const launcher = require('./launcher') +const cfg = require('./config') // TODO: remove in 1.0 -var oldServer = { +const oldServer = { start: function (cliOptions, done) { console.error('WARN `start` method is deprecated since 0.13. It will be removed in 0.14. Please use \n' + ' server = new Server(config, [done])\n' + ' server.start()\n' + 'instead.') - var server = new Server(cliOptions, done) + const server = new Server(cliOptions, done) server.start() } } diff --git a/test/unit/index.spec.js b/test/unit/index.spec.js index ab1d979e0..8adc84f4f 100644 --- a/test/unit/index.spec.js +++ b/test/unit/index.spec.js @@ -1,7 +1,9 @@ -var cfg = require('../../lib/config') +'use strict' + +const cfg = require('../../lib/config') describe('index', () => { - var index = require('../../lib/index') + const index = require('../../lib/index') it('should expose the `config` object', () => { expect(index.config.parseConfig).to.be.eq(cfg.parseConfig) From af8c6e407fa88de1b8ee034cf41a4c83ad832877 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Sat, 19 May 2018 02:29:32 +0300 Subject: [PATCH 20/50] fix: a missed argument in a debug message (#3009) --- lib/file-list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/file-list.js b/lib/file-list.js index b3b27b866..13129cd32 100644 --- a/lib/file-list.js +++ b/lib/file-list.js @@ -176,7 +176,7 @@ class FileList { const file = new File(path, mtime, doNotCache, type) if (file.doNotCache) { - log.debug('Not preprocessing "%s" due to nocache') + log.debug('Not preprocessing "%s" due to nocache', pattern) return Promise.resolve(file) } From 6847ca04df4eecfc413bb75807b0146ba0d157a5 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Mon, 21 May 2018 23:18:45 +0900 Subject: [PATCH 21/50] fix(docs): Remove mention of pre 1.0.0 version (#3010) --- docs/about/01-versioning.md | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/docs/about/01-versioning.md b/docs/about/01-versioning.md index b5b326628..7c5ce6802 100644 --- a/docs/about/01-versioning.md +++ b/docs/about/01-versioning.md @@ -1,20 +1,12 @@ -Karma uses [Semantic Versioning]. There are some special rules at the moment, -as we have not yet released a `1.0.0`. +Karma uses [Semantic Versioning]. -* Minor versions could introduce breaking changes. -* Patch versions are expected to be compatible at all times. +It is recommended that you add Karma by running: -It is recommended that you add the following entry to your `package.json` -file, either manually -```javascript -{ - "devDependencies": { - "karma": "^0.13.0" - } -} +```bash +$ yarn add --dev karma ``` -or by running +or: ```bash $ npm --save-dev install karma From a0535709412d5fa1c630a6206148507562c4dbb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Usarz?= Date: Tue, 22 May 2018 01:35:06 +0200 Subject: [PATCH 22/50] refactor(init): refactor karma init (#2998) --- lib/init.js | 100 ++++++++++++++++---------------------- lib/init/log-queue.js | 15 ++++++ lib/init/state_machine.js | 98 +++++++++++++++++++------------------ 3 files changed, 107 insertions(+), 106 deletions(-) create mode 100644 lib/init/log-queue.js diff --git a/lib/init.js b/lib/init.js index a257e05b2..0eef4f03e 100755 --- a/lib/init.js +++ b/lib/init.js @@ -1,30 +1,26 @@ -var readline = require('readline') -var path = require('path') -var glob = require('glob') -var mm = require('minimatch') -var exec = require('child_process').exec +'use strict' -var helper = require('./helper') -var logger = require('./logger') +const readline = require('readline') +const path = require('path') +const glob = require('glob') +const mm = require('minimatch') +const exec = require('child_process').exec -var log = logger.create('init') +const helper = require('./helper') +const logger = require('./logger') -var StateMachine = require('./init/state_machine') -var COLOR_SCHEME = require('./init/color_schemes') -var formatters = require('./init/formatters') +const log = logger.create('init') +const logQueue = require('./init/log-queue') + +const StateMachine = require('./init/state_machine') +const COLOR_SCHEME = require('./init/color_schemes') +const formatters = require('./init/formatters') // TODO(vojta): coverage // TODO(vojta): html preprocessors // TODO(vojta): SauceLabs // TODO(vojta): BrowserStack -var logQueue = [] -var printLogQueue = function () { - while (logQueue.length) { - logQueue.shift()() - } -} - var NODE_MODULES_DIR = path.resolve(__dirname, '../..') // Karma is not in node_modules, probably a symlink, @@ -33,7 +29,7 @@ if (!/node_modules$/.test(NODE_MODULES_DIR)) { NODE_MODULES_DIR = path.resolve('node_modules') } -var installPackage = function (pkgName) { +function installPackage (pkgName) { // Do not install if already installed. try { require(NODE_MODULES_DIR + '/' + pkgName) @@ -42,7 +38,7 @@ var installPackage = function (pkgName) { log.debug('Missing plugin "%s". Installing...', pkgName) - var options = { + const options = { cwd: path.resolve(NODE_MODULES_DIR, '..') } @@ -65,22 +61,22 @@ var installPackage = function (pkgName) { }) } -var validatePattern = function (pattern) { +function validatePattern (pattern) { if (!glob.sync(pattern).length) { log.warn('There is no file matching this pattern.\n') } } -var validateBrowser = function (name) { +function validateBrowser (name) { // TODO(vojta): check if the path resolves to a binary installPackage('karma-' + name.toLowerCase().replace('canary', '') + '-launcher') } -var validateFramework = function (name) { +function validateFramework (name) { installPackage('karma-' + name) } -var validateRequireJs = function (useRequire) { +function validateRequireJs (useRequire) { if (useRequire) { validateFramework('requirejs') } @@ -127,9 +123,7 @@ var questions = [{ hint: 'This will generate test-main.js/coffee that configures RequireJS and starts the tests.', options: ['no', 'yes'], boolean: true, - condition: function (answers) { - return answers.requirejs - } + condition: answers => answers.requirejs }, { id: 'includedFiles', question: 'Which files do you want to include with