karma-sonarqube-execution-reporter
Advanced tools
Comparing version 0.0.2 to 0.1.0
@@ -13,1 +13,17 @@ # Changelog | ||
* Removed 27 vulnerabilities (18 low, 8 high, 1 critical) | ||
## 0.1.0 (2018-11-22) | ||
### Features | ||
* `File path` is path to spec file in default | ||
* Parsing key-words in spec files: | ||
* `describe()` | ||
* `describe ()` | ||
* `describe.only()` | ||
* `describe.only ()` | ||
### Code changes | ||
* Extracted nested functions. | ||
* Added new unit-tests for different `describe()` key-word combinantions. |
152
index.js
@@ -6,34 +6,30 @@ const path = require('path'); | ||
const SonarQubeUnitReporter = function (baseReporterDecorator, config, logger, helper, formatError) { | ||
const SonarQubeExecutionReporter = function(baseReporterDecorator, config, logger, helper, formatError) { | ||
const log = logger.create('reporter.sonarqubeUnit'); | ||
const reporterConfig = config.sonarQubeUnitReporter || {}; | ||
const sonarQubeVersion = reporterConfig.sonarQubeVersion || 'LATEST'; | ||
const pkgName = reporterConfig.suite || ''; | ||
const outputFile = reporterConfig.outputFile; | ||
let outputDir = reporterConfig.outputDir; | ||
let useBrowserName = reporterConfig.useBrowserName; | ||
// Get configuration | ||
const repConf = config.sonarQubeExecutionReporter || {}; | ||
const sonarQubeVersion = repConf.sonarQubeVersion || 'LATEST'; | ||
const pkgName = repConf.suite || ''; | ||
const outputFile = repConf.outputFile; | ||
const outputDir = helper.normalizeWinPath(path.resolve(config.basePath, repConf.outputDir || '.')) + path.sep; | ||
const useBrowserName = (!repConf.useBrowserName) ? false : true; | ||
let filenameFormatter = reporterConfig.filenameFormatter || null; | ||
const testnameFormatter = reporterConfig.testnameFormatter || null; | ||
const testPath = repConf.testPath || './'; | ||
const testPaths = repConf.testPaths || [testPath]; | ||
const testFilePattern = repConf.testFilePattern || '.spec.(ts|js)'; | ||
const filesForDescriptions = fileUtil.getFilesForDescriptions(testPaths, testFilePattern); | ||
// Init data | ||
let suites; | ||
let pendingFileWritings = 0; | ||
let fileWritingFinished = function () {}; | ||
let fileWritingFinished = () => null; | ||
const allMessages = []; | ||
if (outputDir == null) { | ||
outputDir = '.'; | ||
} | ||
outputDir = helper.normalizeWinPath(path.resolve(config.basePath, outputDir)) + path.sep; | ||
if (typeof useBrowserName === 'undefined') { | ||
useBrowserName = true; | ||
} | ||
baseReporterDecorator(this); | ||
this.adapters = [ | ||
function (msg) { | ||
function(msg) { | ||
allMessages.push(msg); | ||
@@ -43,3 +39,9 @@ } | ||
const initliazeXmlForBrowser = function (browser) { | ||
// Helpers functions | ||
const transformDescribeToPath = function(nextPath, _result) { | ||
return filesForDescriptions[nextPath]; | ||
}; | ||
const initliazeXmlForBrowser = function(browser) { | ||
let tagName; | ||
@@ -61,3 +63,3 @@ switch (sonarQubeVersion) { | ||
const writeXmlForBrowser = function (browser) { | ||
const writeXmlForBrowser = function(browser) { | ||
const safeBrowserName = browser.name.replace(/ /g, '_'); | ||
@@ -95,24 +97,30 @@ let newOutputFile; | ||
const getClassName = function (browser, result) { | ||
const getClassName = function(browser, result) { | ||
const browserName = browser.name.replace(/ /g, '_').replace(/\./g, '_') + '.'; | ||
return (useBrowserName ? browserName : '') + (pkgName ? pkgName + '/' : '') + result.suite[0]; | ||
}; | ||
this.onRunStart = function (browsers) { | ||
const getTestName = function(result) { | ||
let desc = result.description; | ||
for (let i = result.suite.length - 1; i >= 0; i--) { | ||
desc = result.suite[i] + ' ' + desc; | ||
} | ||
return desc; | ||
}; | ||
// Karma methods override | ||
const karmaOnRunStart = function() { | ||
suites = Object.create(null); | ||
// TODO(vojta): remove once we don't care about Karma 0.10 | ||
browsers.forEach(initliazeXmlForBrowser); | ||
}; | ||
this.onBrowserStart = function (browser) { | ||
const karmaOnBrowserStart = function(browser) { | ||
initliazeXmlForBrowser(browser); | ||
}; | ||
this.onBrowserComplete = function (browser) { | ||
const karmaOnBrowserComplete = function(browser) { | ||
const suite = suites[browser.id]; | ||
const result = browser.lastResult; | ||
if (!suite || !result) { | ||
return; // don't die if browser didn't start | ||
return; | ||
} | ||
@@ -123,3 +131,3 @@ | ||
this.onRunComplete = function () { | ||
const karmaOnRunComplete = function() { | ||
suites = null; | ||
@@ -129,18 +137,11 @@ allMessages.length = 0; | ||
this.specSuccess = this.specSkipped = this.specFailure = function (browser, result) { | ||
const preMapped = getClassName(browser, result).replace(/\\/g, '/'); | ||
let nextPath = preMapped; | ||
if (filenameFormatter !== null) { | ||
nextPath = filenameFormatter(nextPath, result); | ||
if (preMapped !== nextPath) { | ||
log.debug('Transformed File name "' + preMapped + '" -> "' + nextPath + '"'); | ||
} else { | ||
log.debug('Name not transformed for File "' + preMapped + '"'); | ||
} | ||
} | ||
const karmaSpecDone = function(browser, result) { | ||
const specDescribe = getClassName(browser, result).replace(/\\/g, '/'); | ||
const nextPath = transformDescribeToPath(specDescribe, result); | ||
log.debug('Transformed File name "' + specDescribe + '" -> "' + nextPath + '"'); | ||
let lastFilePath; | ||
const fileNodes = suites[browser.id]; | ||
let lastFilePath; | ||
const numberOfFileNodes = fileNodes.children.length; | ||
const numberOfFileNodes = fileNodes.children.length; | ||
if (numberOfFileNodes > 0) { | ||
@@ -158,39 +159,19 @@ lastFilePath = fileNodes.children[numberOfFileNodes - 1].attributes.path.value; | ||
} | ||
lastFilePath = nextPath; | ||
const appendToThisNode = suites[browser.id].children[suites[browser.id].children.length - 1]; | ||
const testname = getTestName(result); | ||
const testCase = appendToThisNode.ele('testCase', { name: testname, duration: (result.time || 1) }); | ||
function getDescription (result) { | ||
let desc = result.description; | ||
for (let i = result.suite.length - 1; i >= 0; i--) { | ||
desc = result.suite[i] + ' ' + desc; | ||
} | ||
return desc; | ||
} | ||
const testname = getDescription(result); | ||
let testnameFormatted = testname; | ||
if (testnameFormatter !== null) { | ||
testnameFormatted = testnameFormatter(testname, result); | ||
if (testnameFormatted && testnameFormatted !== testname) { | ||
log.debug('Transformed test name "' + testname + '" -> "' + testnameFormatted + '"'); | ||
} else { | ||
testnameFormatted = testname; | ||
log.debug('Name not transformed for test "' + testnameFormatted + '"'); | ||
} | ||
} | ||
const testCase = appendToThisNode.ele('testCase', {name: testnameFormatted, duration: (result.time || 1)}); | ||
if (result.skipped) { | ||
testCase.ele('skipped', {message: 'Skipped'}); | ||
testCase.ele('skipped', { message: 'Skipped' }); | ||
} | ||
if (!result.success) { | ||
testCase.ele('failure', {message: 'Error'}, formatError(result.log.join('\n\n'))); | ||
testCase.ele('failure', { message: 'Error' }, formatError(result.log.join('\n\n'))); | ||
} | ||
}; | ||
// wait for writing all the xml files, before exiting | ||
this.onExit = function (done) { | ||
const karmaOnExit = function(done) { | ||
if (pendingFileWritings) { | ||
@@ -203,23 +184,18 @@ fileWritingFinished = done; | ||
// look for jasmine test files in the specified path | ||
const overrideTestDescription = reporterConfig.overrideTestDescription || false; | ||
const testPath = reporterConfig.testPath || './'; | ||
const testPaths = reporterConfig.testPaths || [testPath]; | ||
const testFilePattern = reporterConfig.testFilePattern || '(.spec.ts|.spec.js)'; | ||
const filesForDescriptions = fileUtil.getFilesForDescriptions(testPaths, testFilePattern); | ||
function defaultFilenameFormatter (nextPath, _result) { | ||
return filesForDescriptions[nextPath]; | ||
} | ||
if (overrideTestDescription) { | ||
filenameFormatter = defaultFilenameFormatter; | ||
} | ||
// Bind karma functions | ||
this.onRunStart = karmaOnRunStart; | ||
this.onBrowserStart = karmaOnBrowserStart; | ||
this.onBrowserComplete = karmaOnBrowserComplete; | ||
this.onRunComplete = karmaOnRunComplete; | ||
this.specSuccess = karmaSpecDone; | ||
this.specSkipped = karmaSpecDone; | ||
this.specFailure = karmaSpecDone; | ||
this.onExit = karmaOnExit; | ||
}; | ||
SonarQubeUnitReporter.$inject = ['baseReporterDecorator', 'config', 'logger', 'helper', 'formatError']; | ||
SonarQubeExecutionReporter.$inject = ['baseReporterDecorator', 'config', 'logger', 'helper', 'formatError']; | ||
// PUBLISH DI MODULE | ||
module.exports = { | ||
'reporter:sonarqubeUnit': ['type', SonarQubeUnitReporter] | ||
'reporter:sonarqubeUnit': ['type', SonarQubeExecutionReporter] | ||
}; |
{ | ||
"name": "karma-sonarqube-execution-reporter", | ||
"version": "0.0.2", | ||
"version": "0.1.0", | ||
"description": "A Karma plugin. Report execution results in sonar-unit-tests xml format.", | ||
@@ -32,6 +32,5 @@ "license": "MIT", | ||
"peerDependencies": { | ||
"karma": ">=0.9" | ||
"karma": ">=2.0" | ||
}, | ||
"dependencies": { | ||
"karma": "^3.1.1", | ||
"xmlbuilder": "^10.1.1" | ||
@@ -38,0 +37,0 @@ }, |
148
README.md
@@ -1,2 +0,2 @@ | ||
### karma-sonarqube-execution-reporter | ||
# karma-sonarqube-execution-reporter | ||
@@ -6,3 +6,3 @@ [![NpmLicense](https://img.shields.io/npm/l/karma-sonarqube-execution-reporter.svg)](https://opensource.org/licenses/MIT) [![npm](https://img.shields.io/npm/dt/karma-sonarqube-execution-reporter.svg)](https://npmjs.com/package/karma-sonarqube-execution-reporter) [![NpmVersion](https://img.shields.io/npm/v/karma-sonarqube-execution-reporter.svg)](https://npmjs.com/package/karma-sonarqube-execution-reporter) | ||
##### Motivation | ||
## Motivation | ||
@@ -13,123 +13,47 @@ This solution is based on https://github.com/tornaia/karma-sonarqube-unit-reporter | ||
##### How to get | ||
## How to get | ||
Available on npmjs.org | ||
Just run `npm install --save-dev karma-sonarqube-unit-reporter` in your project directory. | ||
Package is also available on npmjs.org | ||
https://www.npmjs.com/package/https://github.com/lisrec/karma-sonarqube-execution-reporter | ||
##### How to use | ||
## How to use | ||
Sample karma.conf.ci.js | ||
```xml | ||
'use strict'; | ||
1. Import plugin to karma.conf.js in `plugins` section: | ||
var path = require('path'); | ||
var conf = require('./gulp/conf'); | ||
var _ = require('lodash'); | ||
var wiredep = require('wiredep'); | ||
var pathSrcHtml = [ | ||
path.join(conf.paths.src, '/**/*.html'), | ||
path.join(conf.paths.src_test, '/**/*.html') | ||
]; | ||
function listFiles() { | ||
var wiredepOptions = _.extend({}, conf.wiredep, { | ||
dependencies: true, | ||
devDependencies: true | ||
}); | ||
return wiredep(wiredepOptions).js | ||
.concat([ | ||
path.join(conf.paths.src, '/app/**/*.module.js'), | ||
path.join(conf.paths.src, '/app/**/*.js'), | ||
path.join(conf.paths.src, '/**/*.spec.js'), | ||
path.join(conf.paths.src, '/**/*.mock.js'), | ||
path.join(conf.paths.src_test, '/app/**/*.module.js'), | ||
path.join(conf.paths.src_test, '/app/**/*.js'), | ||
path.join(conf.paths.src_test, '/**/*.spec.js'), | ||
path.join(conf.paths.src_test, '/**/*.mock.js') | ||
]) | ||
.concat(pathSrcHtml); | ||
```js | ||
module.exports = function (config) { | ||
config.set({ | ||
plugins: [ | ||
require('karma-sonarqube-execution-reporter') | ||
] | ||
}) | ||
} | ||
``` | ||
module.exports = function(config) { | ||
2. Add basic configuration to karma.conf.js in `config.set` section: | ||
var configuration = { | ||
files: listFiles(), | ||
singleRun: true, | ||
colors: false, | ||
autoWatch: false, | ||
ngHtml2JsPreprocessor: { | ||
stripPrefix: conf.paths.src + '/', | ||
moduleName: 'TODO_PUT_HERE_YOUR_MODULE_NAME' | ||
}, | ||
logLevel: 'WARN', | ||
frameworks: ['jasmine', 'angular-filesort'], | ||
angularFilesort: { | ||
whitelist: [path.join(conf.paths.src, '/**/!(*.html|*.spec|*.mock).js'), path.join(conf.paths.src_test, '/**/!(*.html|*.spec|*.mock).js')] | ||
}, | ||
browsers: ['PhantomJS'], | ||
sonarQubeUnitReporter: { | ||
```js | ||
module.exports = function (config) { | ||
config.set({ | ||
sonarQubeExecutionReporter: { | ||
sonarQubeVersion: 'LATEST', | ||
outputFile: 'reports/ut_report.xml', | ||
useBrowserName: false | ||
testPaths: ['./src/app'], | ||
testFilePattern: '.spec.ts', | ||
outputDir: './coverage', | ||
outputFile: 'ut_report.xml' | ||
}, | ||
plugins: [ | ||
'karma-phantomjs-launcher', | ||
'karma-angular-filesort', | ||
'karma-coverage', | ||
'karma-jasmine', | ||
'karma-ng-html2js-preprocessor', | ||
'karma-sonarqube-unit-reporter' | ||
], | ||
coverageReporter: { | ||
type : 'lcov', | ||
dir : 'reports', | ||
subdir : 'coverage' | ||
}, | ||
reporters: ['progress', 'sonarqubeUnit', 'coverage'], | ||
preprocessors: { | ||
'src/**/*.js': ['coverage'], | ||
'test/**/*.js': ['coverage'] | ||
} | ||
}; | ||
config.set(configuration); | ||
}; | ||
}) | ||
} | ||
``` | ||
By default, the description of the jasmine tests used as the path attribute in the generated xml. If this is not the case with your tests, you can use the following options to automagically find the right path values. It is the recommended way to use this plugin but to be backward compatible it is not enabled by default. | ||
``` | ||
sonarQubeUnitReporter: { | ||
sonarQubeVersion: 'LATEST', | ||
outputFile: 'reports/ut_report.xml', | ||
overrideTestDescription: true, | ||
testPaths: ['./test', './moreTests'], | ||
testFilePattern: '.spec.js', | ||
useBrowserName: false | ||
}, | ||
``` | ||
##### Prerequisites for development | ||
* NodeJS 8.0.0 https://nodejs.org/download/release/v8.0.0/ | ||
##### Build | ||
* npm install | ||
* npm build | ||
## Avaible options - descriptions [TODO] | ||
### sonarQubeVersion | ||
### suite | ||
### outputFile | ||
### outputDir | ||
### useBrowserName | ||
### testPath | ||
### testPaths | ||
### testFilePattern |
const path = require('path'); | ||
const fs = require('fs'); | ||
module.exports = { | ||
getFilesForDescriptions: getFilesForDescriptions | ||
}; | ||
function getFilesForDescriptions (startPaths, filter) { | ||
const ret = {}; | ||
const findDescribeInText = function(textToSearch) { | ||
const keyWords = [ | ||
'describe(', | ||
'describe (', | ||
'describe.only(', | ||
'describe.only (', | ||
]; | ||
startPaths.forEach((startPathItem) => { | ||
const files = findFilesInDir(startPathItem, filter); | ||
files.forEach(findDescriptionInFile); | ||
}); | ||
for(const idx in keyWords) { | ||
function findDescriptionInFile (item, _index) { | ||
try { | ||
let fileText = fs.readFileSync(item, 'utf8'); | ||
let position = 0; | ||
while (position !== -1) { | ||
let describe; | ||
position = fileText.indexOf('describe('); | ||
if (position !== -1) { | ||
const delimeter = fileText[position + 9]; | ||
const descriptionEnd = fileText.indexOf(delimeter, position + 10) + 1; | ||
describe = fileText.substring(position + 10, descriptionEnd - 1); | ||
describe = describe.replace(/\\\\/g, '/'); | ||
item = item.replace(/\\\\/g, '/').replace(/\\/g, '/'); | ||
ret[describe] = item; | ||
position = 0; | ||
fileText = fileText.substring(descriptionEnd); | ||
} | ||
} | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.error('Error:', e.stack); | ||
const pos = textToSearch.indexOf(keyWords[idx]); | ||
if (pos !== -1) { | ||
return { | ||
position: pos, | ||
length: keyWords[idx].length | ||
}; | ||
} | ||
} | ||
return ret; | ||
} | ||
return { | ||
position: -1, | ||
length: 0 | ||
}; | ||
}; | ||
function findFilesInDir (startPath, filter) { | ||
let results = []; | ||
const findFilesInDir = function(startPath, filter) { | ||
@@ -52,15 +39,64 @@ if (!fs.existsSync(startPath)) { | ||
let results = []; | ||
const files = fs.readdirSync(startPath); | ||
const filterRegex = new RegExp(filter); | ||
for (let i = 0; i < files.length; i++) { | ||
const filename = path.join(startPath, files[i]); | ||
const stat = fs.lstatSync(filename); | ||
if (stat.isDirectory()) { | ||
if (filename !== 'node_modules') { | ||
results = results.concat(findFilesInDir(filename, filter)); | ||
} | ||
} else if (filename.endsWith(filter)) { | ||
if (stat.isDirectory() && filename !== 'node_modules') { | ||
results = results.concat(findFilesInDir(filename, filter)); | ||
} else if (filterRegex.test(filename)) { | ||
results.push(filename); | ||
} | ||
} | ||
return results; | ||
} | ||
}; | ||
const findDescriptionInFile = (respArray) => (item, _index) => { | ||
try { | ||
let fileText = fs.readFileSync(item, 'utf8'); | ||
let position = 0; | ||
while (position !== -1) { | ||
let describe; | ||
const findDescribe = findDescribeInText(fileText); | ||
position = findDescribe.position; | ||
if (position !== -1) { | ||
const startDescribePosition = position + findDescribe.length; | ||
const delimeter = fileText[startDescribePosition]; | ||
const descriptionEnd = fileText.indexOf(delimeter, startDescribePosition + 1) + 1; | ||
describe = fileText.substring(startDescribePosition + 1, descriptionEnd - 1); | ||
describe = describe.replace(/\\\\/g, '/'); | ||
item = item.replace(/\\\\/g, '/').replace(/\\/g, '/'); | ||
fileText = fileText.substring(descriptionEnd); | ||
respArray[describe] = item; | ||
position = 0; | ||
} | ||
} | ||
} catch (e) { | ||
// eslint-disable-next-line no-console | ||
console.error('Error:', e.stack); | ||
} | ||
}; | ||
const getFilesForDescriptions = function(startPaths, filter) { | ||
const ret = {}; | ||
startPaths.forEach((startPathItem) => { | ||
const files = findFilesInDir(startPathItem, filter); | ||
files.forEach(findDescriptionInFile(ret)); | ||
}); | ||
return ret; | ||
}; | ||
module.exports = { getFilesForDescriptions }; |
@@ -58,2 +58,24 @@ /* eslint-disable no-undef */ | ||
}); | ||
it('spaces in describe key-word', () => { | ||
const filesForDescriptions = fileUtil.getFilesForDescriptions(['test/resources/spaces_multiple_files_multiple_descriptions'], '.spec.js'); | ||
const expectedPath1 = 'test/resources/spaces_multiple_files_multiple_descriptions/first_test.spec.js'; | ||
const expectedPath2 = 'test/resources/spaces_multiple_files_multiple_descriptions/second_test.spec.js'; | ||
const expected = { | ||
'first test first description': expectedPath1, | ||
'first test second description': expectedPath1, | ||
'first test third description': expectedPath1, | ||
'first test fourth description': expectedPath1, | ||
'second test first description': expectedPath2, | ||
'second test second description': expectedPath2, | ||
'second test third description': expectedPath2, | ||
'second test fourth description': expectedPath2 | ||
}; | ||
expect(filesForDescriptions).toEqual(expected); | ||
}); | ||
}); | ||
/* eslint-disable no-undef */ | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2
301
16467
58
+ Added@colors/colors@1.5.0(transitive)
+ Added@socket.io/component-emitter@3.1.2(transitive)
+ Added@types/cookie@0.4.1(transitive)
+ Added@types/cors@2.8.17(transitive)
+ Added@types/node@22.9.3(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedanymatch@3.1.3(transitive)
+ Addedbase64id@2.0.0(transitive)
+ Addedbinary-extensions@2.3.0(transitive)
+ Addedbraces@3.0.3(transitive)
+ Addedchokidar@3.6.0(transitive)
+ Addedcliui@7.0.4(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedcookie@0.7.2(transitive)
+ Addedcors@2.8.5(transitive)
+ Addeddate-format@4.0.14(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedengine.io@6.6.2(transitive)
+ Addedengine.io-parser@5.2.3(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addedfill-range@7.1.1(transitive)
+ Addedflatted@3.3.2(transitive)
+ Addedfs-extra@8.1.0(transitive)
+ Addedfsevents@2.3.3(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedglob-parent@5.1.2(transitive)
+ Addedis-binary-path@2.1.0(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedis-number@7.0.0(transitive)
+ Addedisbinaryfile@4.0.10(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedkarma@6.4.4(transitive)
+ Addedlog4js@6.9.1(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedpicomatch@2.3.1(transitive)
+ Addedreaddirp@3.6.0(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedsocket.io@4.8.1(transitive)
+ Addedsocket.io-adapter@2.5.5(transitive)
+ Addedsocket.io-parser@4.2.4(transitive)
+ Addedstreamroller@3.1.5(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedtmp@0.2.3(transitive)
+ Addedto-regex-range@5.0.1(transitive)
+ Addedua-parser-js@0.7.39(transitive)
+ Addedundici-types@6.19.8(transitive)
+ Addeduniversalify@0.1.2(transitive)
+ Addedvary@1.1.2(transitive)
+ Addedwrap-ansi@7.0.0(transitive)
+ Addedws@8.17.1(transitive)
+ Addedy18n@5.0.8(transitive)
+ Addedyargs@16.2.0(transitive)
+ Addedyargs-parser@20.2.9(transitive)
- Removedkarma@^3.1.1
- Removedafter@0.8.2(transitive)
- Removedanymatch@2.0.0(transitive)
- Removedarr-diff@4.0.0(transitive)
- Removedarr-flatten@1.1.0(transitive)
- Removedarr-union@3.1.0(transitive)
- Removedarray-slice@0.2.3(transitive)
- Removedarray-unique@0.2.10.3.2(transitive)
- Removedarraybuffer.slice@0.0.7(transitive)
- Removedassign-symbols@1.0.0(transitive)
- Removedasync-each@1.0.6(transitive)
- Removedasync-limiter@1.0.1(transitive)
- Removedatob@2.1.2(transitive)
- Removedbacko2@1.0.2(transitive)
- Removedbase@0.11.2(transitive)
- Removedbase64-arraybuffer@0.1.5(transitive)
- Removedbase64id@1.0.0(transitive)
- Removedbetter-assert@1.0.2(transitive)
- Removedbinary-extensions@1.13.1(transitive)
- Removedbindings@1.5.0(transitive)
- Removedblob@0.0.5(transitive)
- Removedbluebird@3.7.2(transitive)
- Removedbraces@0.1.52.3.2(transitive)
- Removedbuffer-alloc@1.2.0(transitive)
- Removedbuffer-alloc-unsafe@1.1.0(transitive)
- Removedbuffer-fill@1.0.0(transitive)
- Removedcache-base@1.0.1(transitive)
- Removedcallsite@1.0.0(transitive)
- Removedchokidar@2.1.8(transitive)
- Removedcircular-json@0.5.9(transitive)
- Removedclass-utils@0.3.6(transitive)
- Removedcollection-visit@1.0.0(transitive)
- Removedcolors@1.4.0(transitive)
- Removedcombine-lists@1.0.1(transitive)
- Removedcomponent-bind@1.0.0(transitive)
- Removedcomponent-emitter@1.2.11.3.1(transitive)
- Removedcomponent-inherit@0.0.3(transitive)
- Removedcookie@0.3.1(transitive)
- Removedcopy-descriptor@0.1.1(transitive)
- Removedcore-js@2.6.12(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removeddate-format@1.2.0(transitive)
- Removeddebug@3.1.03.2.7(transitive)
- Removeddecode-uri-component@0.2.2(transitive)
- Removeddefine-property@0.2.51.0.02.0.2(transitive)
- Removedengine.io@3.2.1(transitive)
- Removedengine.io-client@3.2.1(transitive)
- Removedengine.io-parser@2.1.3(transitive)
- Removedexpand-braces@0.1.2(transitive)
- Removedexpand-brackets@2.1.4(transitive)
- Removedexpand-range@0.1.1(transitive)
- Removedextend-shallow@2.0.13.0.2(transitive)
- Removedextglob@2.0.4(transitive)
- Removedfile-uri-to-path@1.0.0(transitive)
- Removedfill-range@4.0.0(transitive)
- Removedflatted@2.0.2(transitive)
- Removedfor-in@1.0.2(transitive)
- Removedfragment-cache@0.2.1(transitive)
- Removedfsevents@1.2.13(transitive)
- Removedget-value@2.0.6(transitive)
- Removedglob-parent@3.1.0(transitive)
- Removedhas-binary2@1.0.3(transitive)
- Removedhas-cors@1.1.0(transitive)
- Removedhas-value@0.3.11.0.0(transitive)
- Removedhas-values@0.1.41.0.0(transitive)
- Removedindexof@0.0.1(transitive)
- Removedis-accessor-descriptor@1.0.1(transitive)
- Removedis-binary-path@1.0.1(transitive)
- Removedis-buffer@1.1.6(transitive)
- Removedis-data-descriptor@1.0.1(transitive)
- Removedis-descriptor@0.1.71.0.3(transitive)
- Removedis-extendable@0.1.11.0.1(transitive)
- Removedis-glob@3.1.0(transitive)
- Removedis-number@0.1.13.0.0(transitive)
- Removedis-plain-object@2.0.4(transitive)
- Removedis-windows@1.0.2(transitive)
- Removedisarray@1.0.02.0.1(transitive)
- Removedisbinaryfile@3.0.3(transitive)
- Removedisobject@2.1.03.0.1(transitive)
- Removedkarma@3.1.4(transitive)
- Removedkind-of@3.2.24.0.06.0.3(transitive)
- Removedlog4js@3.0.6(transitive)
- Removedlru-cache@4.1.5(transitive)
- Removedmap-cache@0.2.2(transitive)
- Removedmap-visit@1.0.0(transitive)
- Removedmicromatch@3.1.10(transitive)
- Removedminimist@0.0.10(transitive)
- Removedmixin-deep@1.3.2(transitive)
- Removednan@2.22.0(transitive)
- Removednanomatch@1.2.13(transitive)
- Removednormalize-path@2.1.1(transitive)
- Removedobject-component@0.0.3(transitive)
- Removedobject-copy@0.1.0(transitive)
- Removedobject-visit@1.0.1(transitive)
- Removedobject.pick@1.3.0(transitive)
- Removedoptimist@0.6.1(transitive)
- Removedos-tmpdir@1.0.2(transitive)
- Removedparseqs@0.0.5(transitive)
- Removedparseuri@0.0.5(transitive)
- Removedpascalcase@0.1.1(transitive)
- Removedpath-dirname@1.0.2(transitive)
- Removedposix-character-classes@0.1.1(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedpseudomap@1.0.2(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedreaddirp@2.2.1(transitive)
- Removedregex-not@1.0.2(transitive)
- Removedremove-trailing-separator@1.1.0(transitive)
- Removedrepeat-element@1.1.4(transitive)
- Removedrepeat-string@0.2.21.6.1(transitive)
- Removedresolve-url@0.2.1(transitive)
- Removedret@0.1.15(transitive)
- Removedrimraf@2.7.1(transitive)
- Removedsafe-buffer@5.1.25.2.1(transitive)
- Removedsafe-regex@1.1.0(transitive)
- Removedset-value@2.0.1(transitive)
- Removedsnapdragon@0.8.2(transitive)
- Removedsnapdragon-node@2.1.1(transitive)
- Removedsnapdragon-util@3.0.1(transitive)
- Removedsocket.io@2.1.1(transitive)
- Removedsocket.io-adapter@1.1.2(transitive)
- Removedsocket.io-client@2.1.1(transitive)
- Removedsocket.io-parser@3.2.0(transitive)
- Removedsource-map@0.5.7(transitive)
- Removedsource-map-resolve@0.5.3(transitive)
- Removedsource-map-url@0.4.1(transitive)
- Removedsplit-string@3.1.0(transitive)
- Removedstatic-extend@0.1.2(transitive)
- Removedstreamroller@0.7.0(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedtmp@0.0.33(transitive)
- Removedto-array@0.1.4(transitive)
- Removedto-object-path@0.3.0(transitive)
- Removedto-regex@3.0.2(transitive)
- Removedto-regex-range@2.1.1(transitive)
- Removedultron@1.1.1(transitive)
- Removedunion-value@1.0.1(transitive)
- Removedunset-value@1.0.0(transitive)
- Removedupath@1.2.0(transitive)
- Removedurix@0.1.0(transitive)
- Removeduse@3.1.1(transitive)
- Removeduseragent@2.3.0(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedwordwrap@0.0.3(transitive)
- Removedws@3.3.3(transitive)
- Removedxmlhttprequest-ssl@1.5.5(transitive)
- Removedyallist@2.1.2(transitive)
- Removedyeast@0.1.2(transitive)