diff --git a/.eslintrc.js b/.eslintrc.js index 0999a0af..84b5bf14 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,6 +10,7 @@ module.exports = { 'consistent-return': 'off', 'class-methods-use-this': 'off', 'no-plusplus': 'off', + 'func-names': 'off', // Temporary overrides. Logic to be rewritten. // TODO https://github.com/apiaryio/gavel.js/issues/150 diff --git a/bin/gavel b/bin/gavel index b419d5d7..d7f8e779 100755 --- a/bin/gavel +++ b/bin/gavel @@ -1,9 +1,10 @@ #!/usr/bin/env node +/* eslint-disable */ var cmd = require('commander'); var httpParser = require('http-string-parser'); var curlParser = require('curl-trace-parser'); -var gavel = require('../lib/gavel'); +var gavel = require('../lib'); var fs = require('fs'); cmd.version('0.0.1'); @@ -23,29 +24,16 @@ process.stdin.on('end', function() { var realHttp = curlParser.parseBack(stdin); - var realRequest = httpParser.parseRequest(realHttp['request']); - var realResponse = httpParser.parseResponse(realHttp['response']); + var realRequest = httpParser.parseRequest(realHttp.request); + var realResponse = httpParser.parseResponse(realHttp.response); - var expectedRequest = httpParser.parseRequest(expectedHttp['request']); - var expectedResponse = httpParser.parseResponse(expectedHttp['response']); + var expectedRequest = httpParser.parseRequest(expectedHttp.request); + var expectedResponse = httpParser.parseResponse(expectedHttp.response); - var requestResult = false; - var responseResult = false; + const requestResult = gavel.validate(expectedRequest, realRequest); + const responseResult = gavel.validate(expectedResponse, realResponse); - gavel.isValid(realRequest, expectedRequest, 'request', function( - err, - result - ) { - requestResult = result; - gavel.isValid(realResponse, expectedResponse, 'response', function( - err, - result - ) { - responseResult = result; - }); - }); - - if (requestResult && responseResult) { + if (requestResult.isValid && responseResult.isValid) { process.exit(0); } else { process.exit(1); diff --git a/lib/gavel.js b/lib/gavel.js deleted file mode 100644 index 353cc79b..00000000 --- a/lib/gavel.js +++ /dev/null @@ -1,17 +0,0 @@ -const { HttpRequest, ExpectedHttpRequest } = require('./model/http-request'); -const { HttpResponse, ExpectedHttpResponse } = require('./model/http-response'); -const { isValid, isValidatable } = require('./validate'); -const validate = require('./next/validate'); - -module.exports = { - // next - validate, - - // legacy - HttpRequest, - HttpResponse, - ExpectedHttpRequest, - ExpectedHttpResponse, - isValid, - isValidatable -}; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 00000000..1f9421a4 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,5 @@ +const { validate } = require('./validate'); + +module.exports = { + validate +}; diff --git a/lib/mixins/validatable-http-message.js b/lib/mixins/validatable-http-message.js deleted file mode 100644 index 90c14984..00000000 --- a/lib/mixins/validatable-http-message.js +++ /dev/null @@ -1,449 +0,0 @@ -const jph = require('json-parse-helpfulerror'); -const mediaTyper = require('media-typer'); -const contentType = require('content-type'); -const isset = require('../utils/isset'); -const validators = require('../validators'); -const { isValid } = require('../next/units/isValid'); - -const APIARY_VENDOR_HEADER = 'application/vnd.apiary.http-headers+json'; - -class Validatable { - validate() { - this.validation = {}; - this.lowercaseHeaders(); - - if (this.headers && this.expected && this.expected.headers) { - this.validateHeaders(); - } - - if ( - isset(this.body) && - (isset(this.expected.body) || isset(this.expected.bodySchema)) - ) { - this.validateBody(); - } - - if (this.statusCode) { - this.validateStatusCode(); - } - - return Object.assign({}, this.validation, { - version: '2', - isValid: isValid(this.validation) - }); - } - - isValidatable() { - return this.constructor.validatableComponents.some((component) => { - return typeof this[component] !== 'undefined'; - }); - } - - isValid() { - if (!this.validation) { - this.validate(); - } - - const hasInvalidComponent = this.constructor.validatableComponents.some( - (component) => { - const validationCounterpart = this.validation[component]; - const componentResults = - validationCounterpart && validationCounterpart.results; - - return ( - componentResults && - componentResults.some((result) => { - return result.severity === 'error'; - }) - ); - } - ); - - return !hasInvalidComponent; - } - - validationResults() { - if (!this.validation) { - this.validate(); - } - - return this.validation; - } - - lowercaseHeaders() { - if (this.headers) { - this.headers = Object.keys(this.headers).reduce( - (acc, headerName) => - Object.assign({}, acc, { - [headerName.toLowerCase()]: this.headers[headerName] - }), - {} - ); - } - - const { headers: expectedHeaders } = this.expected || {}; - if (expectedHeaders) { - this.expected.headers = Object.keys(expectedHeaders).reduce( - (acc, headerName) => - Object.assign({}, acc, { - [headerName.toLowerCase()]: expectedHeaders[headerName] - }), - {} - ); - } - } - - ensureValidationHeaders() { - const existingValidation = this.validation; - if (!existingValidation || !existingValidation.headers) { - this.validation = Object.assign({}, existingValidation, { - headers: { - results: [] - } - }); - } - } - - validateHeaders() { - this.ensureValidationHeaders(); - this.setHeadersRealType(); - this.setHeadersExpectedType(); - this.setHeadersValidator(); - this.runHeadersValidator(); - } - - setHeadersRealType() { - this.ensureValidationHeaders(); - const { headers } = this; - this.validation.headers.realType = - headers instanceof Object && !Array.isArray(headers) - ? APIARY_VENDOR_HEADER - : null; - } - - setHeadersExpectedType() { - this.ensureValidationHeaders(); - const expectedHeaders = this.expected.headers; - this.validation.headers.expectedType = - expectedHeaders instanceof Object && !Array.isArray(expectedHeaders) - ? APIARY_VENDOR_HEADER - : null; - } - - setHeadersValidator() { - const expectsJson = APIARY_VENDOR_HEADER; - - if ( - this.validation.headers.realType === expectsJson && - this.validation.headers.expectedType === expectsJson - ) { - this.validation.headers.validator = 'HeadersJsonExample'; - } else { - this.validation.headers.validator = null; - - if (!this.validation.headers.results) { - this.validation.headers.results = []; - } - - const entry = { - message: `\ -No validator found for real data media type \ -"${JSON.stringify(this.validation.headers.realType)}" \ -and expected data media type \ -"${JSON.stringify(this.validation.headers.expectedType)}".\ - `, - severity: 'error' - }; - - this.validation.headers.results.push(entry); - } - } - - runHeadersValidator() { - // throw new Error JSON.stringify @validation.headers.validator, null, 2 - let validator; - - if (this.validation.headers.validator == null) { - this.validation.headers.rawData = null; - } else { - const ValidatorClass = validators[this.validation.headers.validator]; - validator = new ValidatorClass(this.headers, this.expected.headers); - this.validation.headers.rawData = validator.validate(); - } - - if (!Array.isArray(this.validation.headers.results)) { - this.validation.headers.results = []; - } - - if (this.validation.headers.rawData !== null) { - const results = validator.evaluateOutputToResults(); - this.validation.headers.results = results.concat( - this.validation.headers.results - ); - } - } - - validateBody() { - this.validation.body = {}; - this.validation.body.results = []; - - this.setBodyRealType(); - this.setBodyExpectedType(); - this.setBodyValidator(); - this.runBodyValidator(); - } - - setBodyRealType() { - this.validation.body.realType = null; - const bodyType = typeof this.body; - - if (bodyType !== 'string') { - throw new Error( - `Expected HTTP body to be a String, but got: ${bodyType}` - ); - } - - const headersContentType = this.headers && this.headers['content-type']; - - if (this.isJsonContentType(headersContentType)) { - try { - jph.parse(this.body); - this.validation.body.realType = headersContentType; - } catch (error) { - const message = { - message: `\ -Real body 'Content-Type' header is '${headersContentType}' \ -but body is not a parseable JSON:\n${error.message}\ -`, - severity: 'error' - }; - - this.validation.body.results.push(message); - } - } else { - try { - jph.parse(this.body); - this.validation.body.realType = 'application/json'; - } catch (error) { - this.validation.body.realType = 'text/plain'; - } - } - } - - setBodyExpectedType() { - this.validation.body.expectedType = null; - - if (this.validation.body.results == null) { - this.validation.body.results = []; - } - - if (this.expected.bodySchema != null) { - if (typeof this.expected.bodySchema === 'string') { - try { - const parsed = jph.parse(this.expected.bodySchema); - - if (typeof parsed === 'object') { - this.validation.body.expectedType = 'application/schema+json'; - } else { - // Explicit empty error to be caught by the underlying "catch" block. - // Introduced to remove nasty shadowing and local variables mutations. - // TODO https://github.com/apiaryio/gavel.js/issues/150 - throw new Error(''); - } - } catch (error) { - this.validation.body.results.push({ - message: `Can't validate. Expected body JSON Schema is not a parseable JSON:\n${ - error.message - }`, - severity: 'error' - }); - } - } else { - this.validation.body.expectedType = 'application/schema+json'; - } - } else { - const expectedContentType = - this.expected.headers != null - ? this.expected.headers['content-type'] - : undefined; - - if (this.isJsonContentType(expectedContentType)) { - try { - jph.parse(this.expected.body); - this.validation.body.expectedType = expectedContentType; - } catch (error) { - this.validation.body.results.push({ - message: `\ -Can't validate. Expected body 'Content-Type' is '${expectedContentType}' \ -but body is not a parseable JSON:\n${error.message}\ -`, - severity: 'error' - }); - } - } else { - try { - jph.parse(this.expected.body); - this.validation.body.expectedType = 'application/json'; - } catch (error) { - this.validation.body.expectedType = 'text/plain'; - } - } - } - } - - setBodyValidator() { - this.validation.body.validator = null; - - if (this.validation.body.results == null) { - this.validation.body.results = []; - } - - const validationErrors = this.validation.body.results.filter((result) => - ['error'].includes(result.severity) - ); - const errorsLength = validationErrors.length; - - if (errorsLength === 0) { - if (this.isJsonContentType(this.validation.body.realType)) { - if (this.validation.body.expectedType === 'application/schema+json') { - this.validation.body.validator = 'JsonSchema'; - } else if (this.isJsonContentType(this.validation.body.expectedType)) { - this.validation.body.validator = 'JsonExample'; - } else { - this.validation.body.results.push({ - message: `Can't validate real media type '${ - this.validation.body.realType - }' against expected media type '${ - this.validation.body.expectedType - }'.`, - severity: 'error' - }); - } - } else if (this.validation.body.realType === 'text/plain') { - if (this.validation.body.expectedType === 'text/plain') { - this.validation.body.validator = 'TextDiff'; - } else { - this.validation.body.results.push({ - message: `Can't validate real media type '${ - this.validation.body.realType - }' against expected media type '${ - this.validation.body.expectedType - }'.`, - severity: 'error' - }); - } - } else { - this.validation.body.results.push({ - message: `Can't validate real media type '${ - this.validation.body.realType - }' against expected media type '${ - this.validation.body.expectedType - }'.`, - severity: 'error' - }); - } - } - } - - /* - * decaffeinate suggestions: - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ - runBodyValidator() { - if (this.validation.body.validator === null) { - this.validation.body.rawData = null; - } else { - let expected; - let real; - let results; - - const ValidatorClass = validators[this.validation.body.validator]; - - if (this.validation.body.validator === 'JsonSchema') { - real = this.body; - expected = this.expected.bodySchema; - } else { - real = this.body; - expected = this.expected.body; - } - - if (this.validation.body.validator !== null) { - if (!Array.isArray(this.validation.body.results)) { - this.validation.body.results = []; - } - } - - try { - const validator = new ValidatorClass(real, expected); - this.validation.body.rawData = validator.validate(); - - results = validator.evaluateOutputToResults(); - this.validation.body.results = results.concat( - this.validation.body.results - ); - } catch (error) { - const message = { - message: error.message, - severity: 'error' - }; - - this.validation.body.results.push(message); - } - } - } - - validateStatusCode() { - this.validation.statusCode = {}; - this.validation.statusCode.realType = 'text/vnd.apiary.status-code'; - this.validation.statusCode.expectedType = 'text/vnd.apiary.status-code'; - this.validation.statusCode.validator = 'TextDiff'; - - const real = String(this.statusCode).trim(); - const expected = String(this.expected.statusCode).trim(); - - const validator = new validators.TextDiff(real, expected); - this.validation.statusCode.rawData = validator.validate(); - - this.validation.statusCode.results = []; - const results = validator.evaluateOutputToResults(); - this.validation.statusCode.results = results.concat( - this.validation.statusCode.results - ); - - this.validation.statusCode.results = this.validation.statusCode.results.map( - (current) => - Object.assign({}, current, { - message: - current.message === 'Real and expected data does not match.' - ? `Status code is '${real}' instead of '${expected}'` - : current.message - }) - ); - } - - isJsonContentType(contentTypeValue) { - if (!contentTypeValue) { - return false; - } - try { - const { type } = contentType.parse(`${contentTypeValue}`); - const parsed = mediaTyper.parse(type); - return ( - (parsed.type === 'application' && parsed.subtype === 'json') || - parsed.suffix === 'json' - ); - } catch (e) { - // The Content-Type value is basically a user input, it can be any - // kind of rubbish, and it is neither this function's nor Gavel's problem - // if it's invalid - return false; - } - } -} - -Validatable.validatableComponents = ['headers', 'body', 'statusCode']; - -module.exports = { - Validatable -}; diff --git a/lib/model/http-request.js b/lib/model/http-request.js deleted file mode 100644 index fedf26b7..00000000 --- a/lib/model/http-request.js +++ /dev/null @@ -1,51 +0,0 @@ -const clone = require('clone'); -const { Validatable } = require('../mixins/validatable-http-message'); - -class HttpRequest extends Validatable { - /** - * @option {string} method - * @option {string} uri - * @option {Object} headers - * @option {string} body - * @option {ExpectedHttpResponse} expected - */ - constructor(resources = {}) { - super(); - - this.constructor.resourceKeys.forEach((resourceKey) => { - this[resourceKey] = clone(resources[resourceKey], false); - }); - } -} - -HttpRequest.resourceKeys = ['method', 'uri', 'headers', 'body', 'expected']; - -class ExpectedHttpRequest { - /** - * @option {string} method - * @option {string} uri - * @option {Object} headers - * @option {string} body - * @option {Object} headersSchema If not defined, generated from headers ({SchemaGenerator}) - * @option {Object} bodySchema If not defined, generated from body ({SchemaGenerator}) - */ - constructor(resources = {}) { - this.constructor.resourceKeys.forEach((resourceKey) => { - this[resourceKey] = clone(resources[resourceKey], false); - }); - } -} - -ExpectedHttpRequest.resourceKeys = [ - 'method', - 'uri', - 'headers', - 'body', - 'headersSchema', - 'bodySchema' -]; - -module.exports = { - HttpRequest, - ExpectedHttpRequest -}; diff --git a/lib/model/http-response.js b/lib/model/http-response.js deleted file mode 100644 index c6663f4b..00000000 --- a/lib/model/http-response.js +++ /dev/null @@ -1,58 +0,0 @@ -const clone = require('clone'); -const { Validatable } = require('../mixins/validatable-http-message'); - -class HttpResponse extends Validatable { - /** - * - * @option {number} statusCode - * @option {string} statusMessage - * @option {Object} headers - * @option {string} body - * @option {ExpectedHttpResponse} expected - */ - constructor(resources = {}) { - super(); - this.constructor.resourceKeys.forEach((resourceKey) => { - this[resourceKey] = clone(resources[resourceKey], false); - }); - } -} - -HttpResponse.resourceKeys = [ - 'statusCode', - 'statusMessage', - 'headers', - 'body', - 'expected' -]; - -class ExpectedHttpResponse { - /** - * - * @option {number} statusCode - * @option {string} statusMessage - * @option {Object} headers - * @option {string} body - * @option {Object} headersSchema If not defined, generated from headers ({SchemaGenerator}) - * @option {Object} bodySchema If not defined, generated from body ({SchemaGenerator}) - */ - constructor(resources = {}) { - this.constructor.resourceKeys.forEach((resourceKey) => { - this[resourceKey] = clone(resources[resourceKey], false); - }); - } -} - -ExpectedHttpResponse.resourceKeys = [ - 'statusCode', - 'statusMessage', - 'headers', - 'body', - 'headersSchema', - 'bodySchema' -]; - -module.exports = { - HttpResponse, - ExpectedHttpResponse -}; diff --git a/lib/next/units/coerce/coerceHeaders.js b/lib/next/units/coerce/coerceHeaders.js deleted file mode 100644 index 885fb86e..00000000 --- a/lib/next/units/coerce/coerceHeaders.js +++ /dev/null @@ -1,8 +0,0 @@ -// Coerces given headers to an empty Object in case not present. -// Conceptually, diff between missing headers and empty headers -// should be treated the same. -const coerceHeaders = (headers) => { - return headers || {}; -}; - -module.exports = { coerceHeaders }; diff --git a/lib/next/units/coerce/index.js b/lib/next/units/coerce/index.js deleted file mode 100644 index 8458089b..00000000 --- a/lib/next/units/coerce/index.js +++ /dev/null @@ -1,15 +0,0 @@ -const evolve = require('../../utils/evolve'); -const { coerceHeaders } = require('./coerceHeaders'); - -const coercionMap = { - headers: coerceHeaders -}; - -// Coercion uses strict evolve to ensure the properties -// set in expected schema are set on the result object, -// even if not present in data object. This is what -// coercion is about, in the end. -const coerce = evolve(coercionMap, { strict: true }); -const coerceWeak = evolve(coercionMap); - -module.exports = { coerce, coerceWeak }; diff --git a/lib/next/units/isValid.js b/lib/next/units/isValid.js deleted file mode 100644 index a616ef2b..00000000 --- a/lib/next/units/isValid.js +++ /dev/null @@ -1,11 +0,0 @@ -// Returns a boolean indicating whether a given validation result -// concludes two HTTP messages as valid (matching). -// Separated into its own util only to be used in both next and legacy API. -// TODO Move to "validateMessage" after legacy "gavel.validate()" removal. -function isValid(validationResult) { - return Object.values(validationResult).every((resultGroup) => { - return resultGroup.results.every((result) => result.severity !== 'error'); - }); -} - -module.exports = { isValid }; diff --git a/lib/next/validate.js b/lib/next/validate.js deleted file mode 100644 index 14a6859a..00000000 --- a/lib/next/validate.js +++ /dev/null @@ -1,33 +0,0 @@ -const { validateMessage } = require('./validateMessage'); - -/** - * Validates the given HTTP messages pair and returns - * a legacy-compliant validation results. - * @param {Object} real - * @param {Object} expected - * @param {'request'|'response'} type - * @param {(error: Error, result: Object) => void} callback - */ -function validate(real, expected, type, callback) { - if (type !== 'request' && type !== 'response') { - throw new Error( - `Can't validate: expected transaction "type" to be "request" or "response", but got: ${type}.` - ); - } - - let results; - - try { - results = validateMessage(real, expected); - } catch (error) { - callback(error, null); - return; - } - - callback(null, { - version: '2', - ...results - }); -} - -module.exports = validate; diff --git a/lib/next/validateMessage.js b/lib/next/validateMessage.js deleted file mode 100644 index 7b55bd40..00000000 --- a/lib/next/validateMessage.js +++ /dev/null @@ -1,41 +0,0 @@ -const isset = require('../utils/isset'); -const { coerce, coerceWeak } = require('./units/coerce'); -const { normalize } = require('./units/normalize'); -const { isValid } = require('./units/isValid'); -const { validateStatusCode } = require('./units/validateStatusCode'); -const { validateHeaders } = require('./units/validateHeaders'); -const { validateBody } = require('./units/validateBody'); - -function validateMessage(realMessage, expectedMessage) { - const results = {}; - - // Uses strict coercion on real message. - // Strict coercion ensures real message has properties illegible - // for validation with the expected message. - const real = normalize(coerce(realMessage)); - - // Use weak coercion on expected message. - // This means that only the properties present in expected message - // will be coerced. We don't want to mutate user's assertion. - // However, we want to use the same coercion logic for any coercion type. - const expected = normalize(coerceWeak(expectedMessage)); - - if (expected.statusCode) { - results.statusCode = validateStatusCode(real, expected); - } - - if (expected.headers) { - results.headers = validateHeaders(real, expected); - } - - if (isset(expected.body) || isset(expected.bodySchema)) { - results.body = validateBody(real, expected); - } - - // Indicates the validity of the real message - results.isValid = isValid(results); - - return results; -} - -module.exports = { validateMessage }; diff --git a/lib/units/coerce/index.js b/lib/units/coerce/index.js new file mode 100644 index 00000000..f2229fd9 --- /dev/null +++ b/lib/units/coerce/index.js @@ -0,0 +1,23 @@ +const evolve = require('../../utils/evolve'); +const otherwise = require('../../utils/otherwise'); + +const coercionMap = { + method: otherwise(''), + uri: otherwise(''), + headers: otherwise({}) +}; + +// Coercion is strict by default, meaning it would populate +// all the keys illegible for coercion on the given object, +// even if those keys are missing. +const coerce = evolve(coercionMap, { strict: true }); + +// There is also a weak variant of coercion that operates +// only on the present keys in the given object. +// This is used for coercing expected HTTP message, for example. +const coerceWeak = evolve(coercionMap); + +module.exports = { + coerce, + coerceWeak +}; diff --git a/lib/units/isValid.js b/lib/units/isValid.js new file mode 100644 index 00000000..6e427cd1 --- /dev/null +++ b/lib/units/isValid.js @@ -0,0 +1,23 @@ +/** + * Concludes HTTP message's component validity based on the given + * list of validation errors. + * @param {Object} errors + * @returns {boolean} + */ +function isValidField({ errors }) { + return errors.length === 0; +} + +/** + * Returns a boolean indicating the given validation result as valid. + * @param {Object} validationResult + * @returns {boolean} + */ +function isValidResult(validationResult) { + return Object.values(validationResult.fields).every(isValidField); +} + +module.exports = { + isValidResult, + isValidField +}; diff --git a/lib/next/units/normalize/index.js b/lib/units/normalize/index.js similarity index 77% rename from lib/next/units/normalize/index.js rename to lib/units/normalize/index.js index b5c0a9d9..7d12c4a3 100644 --- a/lib/next/units/normalize/index.js +++ b/lib/units/normalize/index.js @@ -1,8 +1,10 @@ const evolve = require('../../utils/evolve'); +const { normalizeMethod } = require('./normalizeMethod'); const { normalizeStatusCode } = require('./normalizeStatusCode'); const { normalizeHeaders } = require('./normalizeHeaders'); const normalize = evolve({ + method: normalizeMethod, statusCode: normalizeStatusCode, headers: normalizeHeaders }); diff --git a/lib/next/units/normalize/normalizeHeaders.js b/lib/units/normalize/normalizeHeaders.js similarity index 86% rename from lib/next/units/normalize/normalizeHeaders.js rename to lib/units/normalize/normalizeHeaders.js index 9e11397f..ef96c46a 100644 --- a/lib/next/units/normalize/normalizeHeaders.js +++ b/lib/units/normalize/normalizeHeaders.js @@ -3,9 +3,9 @@ const normalizeStringValue = (value) => { }; /** - * Normalizes the given headers. - * @param {Object} headers - * @returns {Object} + * Normalizes given headers. + * @param {Object} headers + * @returns {Object} */ const normalizeHeaders = (headers) => { const headersType = typeof headers; diff --git a/lib/units/normalize/normalizeMethod.js b/lib/units/normalize/normalizeMethod.js new file mode 100644 index 00000000..1eac5127 --- /dev/null +++ b/lib/units/normalize/normalizeMethod.js @@ -0,0 +1,10 @@ +/** + * Normalizes given method. + * @param {string} method + * @returns {string} + */ +const normalizeMethod = (method) => { + return method.trim().toUpperCase(); +}; + +module.exports = { normalizeMethod }; diff --git a/lib/next/units/normalize/normalizeStatusCode.js b/lib/units/normalize/normalizeStatusCode.js similarity index 60% rename from lib/next/units/normalize/normalizeStatusCode.js rename to lib/units/normalize/normalizeStatusCode.js index 4673856c..0b3e2955 100644 --- a/lib/next/units/normalize/normalizeStatusCode.js +++ b/lib/units/normalize/normalizeStatusCode.js @@ -1,3 +1,8 @@ +/** + * Normalizes given status code. + * @param {string} value + * @returns {string} + */ function normalizeStatusCode(value) { return value == null ? '' : String(value).trim(); } diff --git a/lib/next/units/validateBody.js b/lib/units/validateBody.js similarity index 85% rename from lib/next/units/validateBody.js rename to lib/units/validateBody.js index 54e0fd17..60d6d060 100644 --- a/lib/next/units/validateBody.js +++ b/lib/units/validateBody.js @@ -2,9 +2,8 @@ const jph = require('json-parse-helpfulerror'); const mediaTyper = require('media-typer'); const contentTypeUtils = require('content-type'); -const { TextDiff } = require('../../../lib/validators/text-diff'); -const { JsonExample } = require('../../../lib/validators/json-example'); -const { JsonSchema } = require('../../../lib/validators/json-schema'); +const { TextDiff, JsonExample, JsonSchema } = require('../validators'); +const { isValidField } = require('./isValid'); function isPlainText(mediaType) { return mediaType.type === 'text' && mediaType.subtype === 'plain'; @@ -61,9 +60,9 @@ function isJsonContentType(contentType) { * Returns a tuple of error and body media type based * on the given body and normalized headers. * @param {string} body - * @param {Object} headers - * @param {'real'|'expected'} bodyType - * @returns {[error, bodyType]} + * @param {string} contentType + * @param {'real'|'expected'} httpMessageOrigin + * @returns {[string, MediaType]} */ function getBodyType(body, contentType, httpMessageOrigin) { const hasJsonContentType = isJsonContentType(contentType); @@ -91,7 +90,7 @@ ${parsingError.message}` * Returns a tuple of error and schema media type * based on given body schema. * @param {string} bodySchema - * @returns {[error, schemaType]} + * @returns {[string, string]} */ function getBodySchemaType(bodySchema) { const jsonSchemaType = mediaTyper.parse('application/schema+json'); @@ -153,11 +152,11 @@ function getBodyValidator(realType, expectedType) { /** * Validates given bodies of transaction elements. - * @param {Object} real - * @param {Object} expected + * @param {Object} expected + * @param {Object} real */ -function validateBody(real, expected) { - const results = []; +function validateBody(expected, real) { + const errors = []; const bodyType = typeof real.body; if (bodyType !== 'string') { @@ -178,22 +177,18 @@ function validateBody(real, expected) { ); if (realTypeError) { - results.push({ - message: realTypeError, - severity: 'error' + errors.push({ + message: realTypeError }); } if (expectedTypeError) { - results.push({ - message: expectedTypeError, - severity: 'error' + errors.push({ + message: expectedTypeError }); } - const hasErrors = results.some((result) => - ['error'].includes(result.severity) - ); + const hasErrors = errors.length > 0; // Skipping body validation in case errors during // real/expected body type definition. @@ -202,9 +197,8 @@ function validateBody(real, expected) { : getBodyValidator(realType, expectedType); if (validatorError) { - results.push({ - message: validatorError, - severity: 'error' + errors.push({ + message: validatorError }); } @@ -216,15 +210,16 @@ function validateBody(real, expected) { usesJsonSchema ? expected.bodySchema : expected.body ); const rawData = validator && validator.validate(); - const validatorResults = validator ? validator.evaluateOutputToResults() : []; - results.push(...validatorResults); + const validationErrors = validator ? validator.evaluateOutputToResults() : []; + errors.push(...validationErrors); return { + isValid: isValidField({ errors }), validator: ValidatorClass && ValidatorClass.name, realType: mediaTyper.format(realType), expectedType: mediaTyper.format(expectedType), rawData, - results + errors }; } diff --git a/lib/next/units/validateHeaders.js b/lib/units/validateHeaders.js similarity index 72% rename from lib/next/units/validateHeaders.js rename to lib/units/validateHeaders.js index 27f530cb..bcfed620 100644 --- a/lib/next/units/validateHeaders.js +++ b/lib/units/validateHeaders.js @@ -1,4 +1,5 @@ -const { HeadersJsonExample } = require('../../validators/headers-json-example'); +const { HeadersJsonExample } = require('../validators'); +const { isValidField } = require('./isValid'); const APIARY_JSON_HEADER_TYPE = 'application/vnd.apiary.http-headers+json'; @@ -10,13 +11,13 @@ function getHeadersType(headers) { /** * Validates given real and expected transaction elements. - * @param {Object} real - * @param {Object} expected + * @param {Object} expected + * @param {Object} real */ -function validateHeaders(real, expected) { - const realType = getHeadersType(real.headers); +function validateHeaders(expected, real) { const expectedType = getHeadersType(expected.headers); - const results = []; + const realType = getHeadersType(real.headers); + const errors = []; const hasJsonHeaders = realType === APIARY_JSON_HEADER_TYPE && @@ -28,25 +29,25 @@ function validateHeaders(real, expected) { const rawData = validator && validator.validate(); if (validator) { - results.push(...validator.evaluateOutputToResults()); + errors.push(...validator.evaluateOutputToResults()); } else { - results.push({ + errors.push({ message: `\ No validator found for real data media type "${realType}" and expected data media type "${expectedType}".\ -`, - severity: 'error' +` }); } return { + isValid: isValidField({ errors }), validator: validator && 'HeadersJsonExample', realType, expectedType, rawData, - results + errors }; } diff --git a/lib/units/validateMethod.js b/lib/units/validateMethod.js new file mode 100644 index 00000000..ef14f144 --- /dev/null +++ b/lib/units/validateMethod.js @@ -0,0 +1,24 @@ +const APIARY_METHOD_TYPE = 'text/vnd.apiary.method'; + +function validateMethod(expected, real) { + const { method: expectedMethod } = expected; + const { method: realMethod } = real; + const isValid = realMethod === expectedMethod; + const errors = []; + + if (!isValid) { + errors.push({ + message: `Expected "method" field to equal "${expectedMethod}", but got "${realMethod}".` + }); + } + + return { + isValid, + validator: null, + realType: APIARY_METHOD_TYPE, + expectedType: APIARY_METHOD_TYPE, + errors + }; +} + +module.exports = { validateMethod }; diff --git a/lib/next/units/validateStatusCode.js b/lib/units/validateStatusCode.js similarity index 80% rename from lib/next/units/validateStatusCode.js rename to lib/units/validateStatusCode.js index 2824118d..5c757514 100644 --- a/lib/next/units/validateStatusCode.js +++ b/lib/units/validateStatusCode.js @@ -5,25 +5,25 @@ const APIARY_STATUS_CODE_TYPE = 'text/vnd.apiary.status-code'; * @param {Object} real * @param {number} expected */ -function validateStatusCode(real, expected) { - const results = []; +function validateStatusCode(expected, real) { const isValid = real.statusCode === expected.statusCode; + const errors = []; if (!isValid) { - results.push({ + errors.push({ message: `Status code is '${real.statusCode}' instead of '${ expected.statusCode - }'`, - severity: 'error' + }'` }); } return { + isValid, validator: 'TextDiff', realType: APIARY_STATUS_CODE_TYPE, expectedType: APIARY_STATUS_CODE_TYPE, rawData: '', - results + errors }; } diff --git a/lib/units/validateURI.js b/lib/units/validateURI.js new file mode 100644 index 00000000..7f769c11 --- /dev/null +++ b/lib/units/validateURI.js @@ -0,0 +1,53 @@ +const url = require('url'); +const deepEqual = require('deep-equal'); + +const APIARY_URI_TYPE = 'text/vnd.apiary.uri'; + +/** + * Parses the given URI and returns the properties + * elligible for comparison. Leaves out raw properties like "path" + * that cannot be compared due to struct query parameters order. + * @param {string} uri + * @returns {Object} + */ +const parseURI = (uri) => { + const { pathname, port, hash, query } = url.parse(uri, true); + return { + pathname, + port, + hash, + query + }; +}; + +const validateURI = (expected, real) => { + const { uri: expectedURI } = expected; + const { uri: realURI } = real; + + // Parses URI to perform a correct comparison: + // - literal comparison of pathname + // - order-insensitive comparison of query parameters + const parsedExpected = parseURI(expectedURI, true); + const parsedReal = parseURI(realURI, true); + + // Note the different order of arguments between + // "validateURI" and "deepEqual". + const isValid = deepEqual(parsedReal, parsedExpected); + const errors = []; + + if (!isValid) { + errors.push({ + message: `Expected "uri" field to equal "${expectedURI}", but got: "${realURI}".` + }); + } + + return { + isValid, + validator: null, + expectedType: APIARY_URI_TYPE, + realType: APIARY_URI_TYPE, + errors + }; +}; + +module.exports = { validateURI }; diff --git a/lib/next/utils/evolve.js b/lib/utils/evolve.js similarity index 100% rename from lib/next/utils/evolve.js rename to lib/utils/evolve.js diff --git a/lib/utils/otherwise.js b/lib/utils/otherwise.js new file mode 100644 index 00000000..e4fb6d9a --- /dev/null +++ b/lib/utils/otherwise.js @@ -0,0 +1,9 @@ +/** + * Accepts a fallback value and returns an ensuring function + * that uses the fallback value in case real one is not provided. + */ +const otherwise = (fallbackValue) => (realValue) => { + return realValue || fallbackValue; +}; + +module.exports = otherwise; diff --git a/lib/validate.js b/lib/validate.js index ea7f489c..ba456b72 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -1,62 +1,55 @@ -const { HttpRequest, ExpectedHttpRequest } = require('./model/http-request'); -const { HttpResponse, ExpectedHttpResponse } = require('./model/http-response'); - -function proxy(validatableObject, method, cb) { - let result; - - try { - result = validatableObject[method](); - } catch (error) { - return cb(error, null); +const isset = require('./utils/isset'); +const { coerce, coerceWeak } = require('./units/coerce'); +const { normalize } = require('./units/normalize'); +const { isValidResult } = require('./units/isValid'); +const { validateMethod } = require('./units/validateMethod'); +const { validateURI } = require('./units/validateURI'); +const { validateStatusCode } = require('./units/validateStatusCode'); +const { validateHeaders } = require('./units/validateHeaders'); +const { validateBody } = require('./units/validateBody'); + +function validate(expectedMessage, realMessage) { + const result = { + fields: {} + }; + + // Uses strict coercion on real message. + // Strict coercion ensures that real message always has properties + // illegible for validation with the expected message, even if they + // are not present in the real message. + const real = normalize(coerce(realMessage)); + + // Use weak coercion on expected message. + // Weak coercion will transform only the properties present in the + // expected message. Properties meant for coercion, but not provided + // in the expected message are left out, as we don't want to mutate + // user's assertion. + const expected = normalize(coerceWeak(expectedMessage)); + + if (expected.method) { + result.fields.method = validateMethod(expected, real); } - return cb(null, result); -} - -/** - * @param {string} real - * @param {string} expected - * @param {'request'|'response'} type - */ -function getValidatableObject(real, expected, type) { - let request; - let response; - - switch (type) { - case 'request': - request = new HttpRequest(real); - request.expected = new ExpectedHttpRequest(expected); - return request; - case 'response': - response = new HttpResponse(real); - response.expected = new ExpectedHttpResponse(expected); - return response; - default: - throw new Error( - `Can't validate: expected HTTP message type to be "request" or "response", but got: ${type}.` - ); + if (expected.uri) { + result.fields.uri = validateURI(expected, real); } -} -function isValid(real, expected, type, cb) { - console.warn(`\ -Usage of "isValid" is deprecated and will be removed in the future releases of Gavel. -Use "isValid" property of the validation result instead: + if (expected.statusCode) { + result.fields.statusCode = validateStatusCode(expected, real); + } -const { validate } = require('gavel'); + if (expected.headers) { + result.fields.headers = validateHeaders(expected, real); + } -const result = validate(real, expected, 'request'); -const { isValid } = result;\ -`); + if (isset(expected.body) || isset(expected.bodySchema)) { + result.fields.body = validateBody(expected, real); + } - return proxy(getValidatableObject(real, expected, type), 'isValid', cb); -} + // Indicates the validity of the real message + result.isValid = isValidResult(result); -function isValidatable(real, expected, type, cb) { - return proxy(getValidatableObject(real, expected, type), 'isValidatable', cb); + return result; } -module.exports = { - isValid, - isValidatable -}; +module.exports = { validate }; diff --git a/lib/validators.js b/lib/validators.js deleted file mode 100644 index 0d81976b..00000000 --- a/lib/validators.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - HeadersJsonExample: require('./validators/headers-json-example') - .HeadersJsonExample, - TextDiff: require('./validators/text-diff').TextDiff, - JsonExample: require('./validators/json-example').JsonExample, - JsonSchema: require('./validators/json-schema').JsonSchema, -} diff --git a/lib/validators/index.js b/lib/validators/index.js new file mode 100644 index 00000000..caee105f --- /dev/null +++ b/lib/validators/index.js @@ -0,0 +1,11 @@ +const { HeadersJsonExample } = require('./headers-json-example'); +const { TextDiff } = require('./text-diff'); +const { JsonExample } = require('./json-example'); +const { JsonSchema } = require('./json-schema'); + +module.exports = { + HeadersJsonExample, + TextDiff, + JsonExample, + JsonSchema +}; diff --git a/lib/validators/json-schema.js b/lib/validators/json-schema.js index af35f885..c43d716e 100644 --- a/lib/validators/json-schema.js +++ b/lib/validators/json-schema.js @@ -246,8 +246,7 @@ class JsonSchema { return { pointer: jsonPointer.compile(pathArray), - message: item.message, - severity: 'error' + message: item.message }; }); diff --git a/lib/validators/text-diff.js b/lib/validators/text-diff.js index 8fa2ffe6..0fc73f92 100644 --- a/lib/validators/text-diff.js +++ b/lib/validators/text-diff.js @@ -62,8 +62,8 @@ class TextDiff { return [ { - message: 'Real and expected data does not match.', - severity: 'error' + // TODO Improve the message to contain real and expected data + message: 'Real and expected data does not match.' } ]; } diff --git a/package-lock.json b/package-lock.json index 7188257e..39c9ec9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,9 +67,9 @@ } }, "@babel/parser": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.4.tgz", - "integrity": "sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", "dev": true }, "@babel/runtime": { @@ -93,37 +93,20 @@ } }, "@babel/traverse": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.4.tgz", - "integrity": "sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "@babel/generator": "^7.4.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.4", + "@babel/parser": "^7.4.5", "@babel/types": "^7.4.4", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.11" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } } }, "@babel/types": { @@ -154,12 +137,12 @@ "dev": true }, "@octokit/endpoint": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.1.5.tgz", - "integrity": "sha512-Es0Qj6ynp0mznTnayCX8veXev43/fGjwVvctynwgzcnW+KIK6nrHdqQXUnAA1Az0DsRgbGsh9fDHjP/3Ybfyyw==", + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.1.7.tgz", + "integrity": "sha512-MfsXHx9z9EPxLYSf7PYuzWvVZTotx+/QTFk7UMp4Fv83k3QrvmovEjP0pl141g+Uq/w9CcDuuXhsiq4X3oxVsA==", "dev": true, "requires": { - "deepmerge": "3.2.0", + "deepmerge": "3.2.1", "is-plain-object": "^3.0.0", "universal-user-agent": "^2.1.0", "url-template": "^2.0.8" @@ -183,9 +166,9 @@ } }, "@octokit/request": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-4.1.0.tgz", - "integrity": "sha512-RvpQAba4i+BNH0z8i0gPRc1ShlHidj4puQjI/Tno6s+Q3/Mzb0XRSHJiOhpeFrZ22V7Mwjq1E7QS27P5CgpWYA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-4.1.1.tgz", + "integrity": "sha512-LOyL0i3oxRo418EXRSJNk/3Q4I0/NKawTn6H/CQp+wnrG1UFLGu080gSsgnWobhPo5BpUNgSQ5BRk5FOOJhD1Q==", "dev": true, "requires": { "@octokit/endpoint": "^5.1.0", @@ -215,9 +198,9 @@ } }, "@octokit/request-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.0.2.tgz", - "integrity": "sha512-T9swMS/Vc4QlfWrvyeSyp/GjhXtYaBzCcibjGywV4k4D2qVrQKfEMPy8OxMDEj7zkIIdpHwqdpVbKCvnUPqkXw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.0.4.tgz", + "integrity": "sha512-L4JaJDXn8SGT+5G0uX79rZLv0MNJmfGa4vb4vy1NnpjSnWDLJRy6m90udGwvMmavwsStgbv2QNkPzzTCMmL+ig==", "dev": true, "requires": { "deprecation": "^2.0.0", @@ -225,9 +208,9 @@ } }, "@octokit/rest": { - "version": "16.28.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.28.1.tgz", - "integrity": "sha512-9H/5F0f2bSVhk78ypu/A9dkK5GCH/aI8CxRJ0L8JU/XEYNIYozxqD6HVC7shsofrCfR61YORfjTE+GxfZ/wasQ==", + "version": "16.28.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.28.2.tgz", + "integrity": "sha512-csuYiHvJ1P/GFDadVn0QhwO83R1+YREjcwCY7ZIezB6aJTRIEidJZj+R7gAkUhT687cqYb4cXTZsDVu9F+Fmug==", "dev": true, "requires": { "@octokit/request": "^4.0.1", @@ -266,23 +249,6 @@ "debug": "^4.0.0", "import-from": "^3.0.0", "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "@semantic-release/error": { @@ -316,15 +282,6 @@ "url-join": "^4.0.0" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "globby": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", @@ -341,18 +298,6 @@ "slash": "^2.0.0" } }, - "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -427,15 +372,6 @@ "lodash": "^4.17.4" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "get-stream": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", @@ -444,19 +380,13 @@ "requires": { "pump": "^3.0.0" } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true } } }, "@sinonjs/commons": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", - "integrity": "sha1-ez7C2Wr0gdegMhJS57HJRyTsWng=", + "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -465,7 +395,7 @@ "@sinonjs/formatio": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", - "integrity": "sha1-UjEPL5vLxnvawYyUrUkBuV/eJn4=", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", "dev": true, "requires": { "@sinonjs/commons": "^1", @@ -475,7 +405,7 @@ "@sinonjs/samsam": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", - "integrity": "sha1-6IxT+9nZGtnw8rAUDBbHwQf+DQc=", + "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", "dev": true, "requires": { "@sinonjs/commons": "^1.0.2", @@ -486,7 +416,7 @@ "@sinonjs/text-encoding": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha1-jaXGUwkVZT86Hzj9XxAdjD+AecU=", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, "@types/events": { @@ -533,7 +463,7 @@ "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha1-MgjB8I06TZkmGrZPkjArwV4RHKA=", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "requires": { "jsonparse": "^1.2.0", @@ -543,7 +473,7 @@ "acorn": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha1-fSWuBbuK0fm2mRCOEJTs14hK3B8=", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, "acorn-dynamic-import": { @@ -577,9 +507,9 @@ "dev": true }, "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha1-2J5ZmfeXh1Z0wH2H8mD8Qeg+jKk=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" @@ -610,7 +540,7 @@ "amanda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amanda/-/amanda-1.0.1.tgz", - "integrity": "sha1-CSnzzg3NSnTSjQVOKy5xLLyM5YI=" + "integrity": "sha512-DJZMA1t7skqQgH5yq4NxBfqun+jDQUSYJRYGg+AqnKc3I0/hs8eX3PDdlfgiADkHgo4HlesD5QuoqFcCYA280Q==" }, "amdefine": { "version": "1.0.1", @@ -631,9 +561,9 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { @@ -696,7 +626,7 @@ "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "~1.0.2" @@ -717,7 +647,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "arr-union": { @@ -855,7 +785,7 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, "assign-symbols": { @@ -896,7 +826,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, "atob-lite": { @@ -926,7 +856,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -950,7 +880,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -959,7 +889,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -968,25 +898,13 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -1032,7 +950,7 @@ "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -1042,7 +960,7 @@ "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { "arr-flatten": "^1.1.0", @@ -1123,7 +1041,7 @@ "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "browserify": { @@ -1298,7 +1216,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -1310,14 +1228,6 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "cached-path-relative": { @@ -1387,9 +1297,9 @@ } }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "camelcase-keys": { @@ -1401,6 +1311,14 @@ "camelcase": "^4.1.0", "map-obj": "^2.0.0", "quick-lru": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } } }, "cardinal": { @@ -1421,7 +1339,7 @@ "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha1-dgqnLPION5XoSxKHfODoNzeqKeU=", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", "dev": true, "requires": { "assertion-error": "^1.1.0", @@ -1502,7 +1420,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -1519,12 +1437,6 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true } } }, @@ -1554,7 +1466,7 @@ "dependencies": { "colors": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", "dev": true } @@ -1570,6 +1482,12 @@ "string-width": "^1.0.1" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -1595,6 +1513,15 @@ "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } } } }, @@ -1607,7 +1534,7 @@ "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { "string-width": "^2.1.1", @@ -1616,18 +1543,50 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } } } @@ -1662,7 +1621,7 @@ "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -1677,7 +1636,7 @@ "colors": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha1-OeAF1Uav4B4B+cTKj6UPaGoBIF0=", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, "combine-source-map": { @@ -1704,7 +1663,7 @@ "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha1-1YuytcHuj4ew00ACfp6U4iLFpCI=" + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" }, "commondir": { "version": "1.0.1", @@ -1723,9 +1682,9 @@ } }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, "concat-map": { @@ -1868,14 +1827,14 @@ "dev": true }, "cosmiconfig": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz", - "integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, "requires": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", - "js-yaml": "^3.13.0", + "js-yaml": "^3.13.1", "parse-json": "^4.0.0" }, "dependencies": { @@ -1919,14 +1878,6 @@ "log-driver": "^1.2.7", "minimist": "^1.2.0", "request": "^2.86.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "coverify": { @@ -1960,12 +1911,6 @@ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", @@ -1978,6 +1923,12 @@ "string_decoder": "~0.10.x" } }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", @@ -2066,7 +2017,7 @@ "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { "nice-try": "^1.0.4", @@ -2128,13 +2079,8 @@ "dependencies": { "commander": { "version": "2.14.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==" - }, - "http-string-parser": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/http-string-parser/-/http-string-parser-0.0.6.tgz", - "integrity": "sha1-QIihq6K4kVXOE5GLz7XLvqbE5+k=" } } }, @@ -2148,12 +2094,13 @@ } }, "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { - "es5-ext": "^0.10.9" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, "dash-ast": { @@ -2190,12 +2137,12 @@ "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "decamelize": { @@ -2237,7 +2184,7 @@ "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -2261,9 +2208,9 @@ "dev": true }, "deepmerge": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.2.0.tgz", - "integrity": "sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.2.1.tgz", + "integrity": "sha512-+hbDSzTqEW0fWgnlKksg7XAOtT+ddZS5lHZJ6f6MdixRs9wQy+50fm1uUCVb1IkvjLUYX/SfFO021ZNwriURTw==", "dev": true }, "default-require-extensions": { @@ -2287,7 +2234,7 @@ "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { "is-descriptor": "^1.0.2", @@ -2297,7 +2244,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -2306,7 +2253,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -2315,25 +2262,13 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -2372,9 +2307,9 @@ "dev": true }, "deprecation": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.0.0.tgz", - "integrity": "sha512-lbQN037mB3VfA2JFuguM5GCJ+zPinMeCrFe+AfSZ6eqrnJA/Fs+EYMnd6Nb2mn9lf2jO9xwEd9o9lic+D4vkcw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, "deps-sort": { @@ -2408,20 +2343,12 @@ "acorn-node": "^1.6.1", "defined": "^1.0.0", "minimist": "^1.1.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "diffie-hellman": { @@ -2497,7 +2424,7 @@ "duration": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", - "integrity": "sha1-3fFJvDvGkBFQ/pAXER0BazNX9Sk=", + "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", "dev": true, "requires": { "d": "1", @@ -2544,7 +2471,7 @@ "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -2563,7 +2490,7 @@ "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" @@ -2632,14 +2559,14 @@ } }, "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true }, "es6-promisify": { "version": "5.0.0", - "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { @@ -2704,38 +2631,6 @@ "strip-json-comments": "^2.0.1", "table": "^5.2.3", "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "eslint-config-airbnb": { @@ -2777,6 +2672,23 @@ "requires": { "debug": "^2.6.9", "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "eslint-module-utils": { @@ -2787,6 +2699,23 @@ "requires": { "debug": "^2.6.8", "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "eslint-plugin-import": { @@ -2808,6 +2737,15 @@ "resolve": "^1.11.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "doctrine": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", @@ -2818,14 +2756,11 @@ "isarray": "^1.0.0" } }, - "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -2871,7 +2806,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "esquery": { @@ -2923,7 +2858,7 @@ "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", @@ -2950,6 +2885,15 @@ "to-regex": "^3.0.1" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -2967,6 +2911,12 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -2989,7 +2939,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -3011,7 +2961,7 @@ "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { "array-unique": "^0.3.2", @@ -3045,7 +2995,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3054,7 +3004,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3063,19 +3013,13 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -3089,13 +3033,30 @@ "debug": "2.6.9", "mkdirp": "0.5.1", "yauzl": "2.4.1" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true }, "falafel": { "version": "2.1.0", @@ -3236,6 +3197,30 @@ "path-exists": "^3.0.0" } }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -3420,8 +3405,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -3442,14 +3426,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3464,20 +3446,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -3594,8 +3573,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -3607,7 +3585,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3622,7 +3599,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3630,14 +3606,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3656,7 +3630,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3737,8 +3710,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3750,7 +3722,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3836,8 +3807,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -3873,7 +3843,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3893,7 +3862,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3937,21 +3905,19 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "functional-red-black-tree": { @@ -3972,9 +3938,9 @@ } }, "gavel-spec": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gavel-spec/-/gavel-spec-2.0.0.tgz", - "integrity": "sha512-f3IT+WwGvn8m1q9zY3Lxc9PXMJ4bu/kwBzJu2TbJ2hY2D6wdc0U2wInr8iPTHrCSGlqJSZGLXODX++Ism/MU/w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gavel-spec/-/gavel-spec-3.0.0.tgz", + "integrity": "sha512-mhckU6tKeynG+URVRV7GPlW4gnYtRwgIWv74dEFpLerWK5Xraq9qZKutUEAfbvE4NpnuScXJUEwuZmd8zHK9UA==", "dev": true }, "get-assigned-identifiers": { @@ -3984,9 +3950,9 @@ "dev": true }, "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-func-name": { @@ -4010,7 +3976,7 @@ "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { "pump": "^3.0.0" @@ -4063,9 +4029,9 @@ } }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -4130,13 +4096,13 @@ "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha1-/7cD4QZuig7qpMi4C6klPu77+wA=", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4=", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, "handlebars": { @@ -4154,19 +4120,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "uglify-js": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.12.tgz", - "integrity": "sha512-KeQesOpPiZNgVwJj8Ge3P4JYbQHUdZzpx6Fahy6eKAYRSV4zhVmLXoC+JtOeYxcHCHTve8RG1ZGdTvpeOUM26Q==", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" - } } } }, @@ -4189,7 +4144,7 @@ "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -4202,6 +4157,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-flag": { @@ -4225,14 +4188,6 @@ "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "has-values": { @@ -4245,26 +4200,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -4331,7 +4266,7 @@ "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "htmlescape": { @@ -4358,6 +4293,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -4386,7 +4327,7 @@ "https-proxy-agent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha1-UVUpcPoE1yPgTFbQQXjD+SWSu8A=", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { "agent-base": "^4.1.0", @@ -4396,17 +4337,11 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", - "dev": true } } }, @@ -4462,6 +4397,15 @@ "p-try": "^2.0.0" } }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -4488,12 +4432,13 @@ }, "dependencies": { "find-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.0.0.tgz", - "integrity": "sha512-zoH7ZWPkRdgwYCDVoQTzqjG8JSPANhtvLhh4KVUHyKnaUJJrNeFmWIkTcNuJmR3GLMEmGYEf2S2bjgx26JTF+Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^5.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "locate-path": { @@ -4513,6 +4458,12 @@ "requires": { "p-limit": "^2.2.0" } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true } } }, @@ -4527,12 +4478,6 @@ "parse-json": "^4.0.0", "type-fest": "^0.4.1" } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true } } }, @@ -4705,7 +4650,7 @@ "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha1-c5P1r6Weyf9fZ6J2INEcIm4+7AI=", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "is-accessor-descriptor": { @@ -4715,6 +4660,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-arrayish": { @@ -4735,7 +4691,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-callable": { @@ -4760,6 +4716,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-date-object": { @@ -4771,7 +4738,7 @@ "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -4782,7 +4749,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } @@ -4833,6 +4800,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-obj": { @@ -4883,18 +4861,10 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "is-promise": { @@ -4957,7 +4927,7 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "isarray": { @@ -5028,9 +4998,9 @@ }, "dependencies": { "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", "dev": true } } @@ -5070,21 +5040,6 @@ "source-map": "^0.6.1" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5094,9 +5049,9 @@ } }, "istanbul-reports": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.4.tgz", - "integrity": "sha512-QCHGyZEK0bfi9GR215QSm+NJwFKEShbtc7tfbUdLAEzn3kKhLDDZqvljn8rPZM9v8CEOhzL1nlYoO4r1ryl67w==", + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", "dev": true, "requires": { "handlebars": "^4.1.2" @@ -5144,7 +5099,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-parse-helpfulerror": { @@ -5172,7 +5127,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify": { @@ -5232,17 +5187,14 @@ "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", - "integrity": "sha1-8/R/ffyg+YnFVBCn68iFSwcQivw=", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true }, "labeled-stream-splicer": { "version": "2.0.2", @@ -5257,7 +5209,7 @@ "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha1-bvXS32DlL4LrIopMNz6NHzlyU88=", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { "invert-kv": "^2.0.0" @@ -5320,12 +5272,6 @@ "ms": "^2.1.1" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -5387,6 +5333,12 @@ "strip-ansi": "^3.0.1" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -5415,6 +5367,15 @@ "chalk": "^1.0.0" } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -5466,23 +5427,12 @@ "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" - }, - "dependencies": { - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - } } }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash.capitalize": { @@ -5575,39 +5525,12 @@ "ansi-escapes": "^3.0.0", "cli-cursor": "^2.0.0", "wrap-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } } }, "lolex": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.0.1.tgz", - "integrity": "sha512-UHuOBZ5jjsKuzbB/gRNNW8Vg8f00Emgskdq2kvZxgBJCS0aqquAuXai/SkWORlKeZEiNQWZjFZOqIUcH9LqKCw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", + "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==", "dev": true }, "loud-rejection": { @@ -5663,7 +5586,7 @@ "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo=", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { "p-defer": "^1.0.0" @@ -5736,20 +5659,20 @@ "integrity": "sha512-/ky7iFD18Y2mN5BdOS4zotSSgu11BsIR2l3L7eK2bTaRWQidoSBmSxGgMFd/XOSGyivlhtQUdDLoUzlr1PWb1g==" }, "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" }, "dependencies": { - "p-is-promise": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true } } @@ -5783,12 +5706,6 @@ "strip-bom": "^3.0.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -5863,7 +5780,7 @@ "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -5879,14 +5796,6 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } } }, "miller-rabin": { @@ -5900,9 +5809,9 @@ } }, "mime": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, "mime-db": { @@ -5955,16 +5864,16 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "minimist-options": { @@ -5980,7 +5889,7 @@ "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -5990,7 +5899,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -6005,8 +5914,16 @@ "dev": true, "requires": { "minimist": "0.0.8" - } - }, + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, "mocaccino": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/mocaccino/-/mocaccino-4.1.1.tgz", @@ -6085,6 +6002,12 @@ } } } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -6119,18 +6042,6 @@ "yargs-unparser": "1.5.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -6149,11 +6060,19 @@ "locate-path": "^3.0.0" } }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "locate-path": { "version": "3.0.0", @@ -6171,42 +6090,29 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "p-try": "^2.0.0" } }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "p-limit": "^2.0.0" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true }, "supports-color": { "version": "6.0.0", @@ -6216,35 +6122,6 @@ "requires": { "has-flag": "^3.0.0" } - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } - }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, @@ -6327,6 +6204,12 @@ } } }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", @@ -6368,9 +6251,9 @@ } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "mute-stream": { @@ -6389,7 +6272,7 @@ "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -6403,26 +6286,6 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } } }, "natural-compare": { @@ -6458,34 +6321,26 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "nise": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", - "integrity": "sha1-rkagmiZDb66Ro4pgkZNWrm2xQ7Y=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", + "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", "dev": true, "requires": { "@sinonjs/formatio": "^3.1.0", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", - "lolex": "^2.3.2", + "lolex": "^4.1.0", "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha1-ETAB1Wv8fgLVbjYpHMXEE9GqBzM=", - "dev": true - } } }, "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw=", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "requires": { "lower-case": "^1.1.1" @@ -6508,14 +6363,6 @@ "requires": { "object.getownpropertydescriptors": "^2.0.3", "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true - } } }, "node-fetch": { @@ -10076,32 +9923,9 @@ "yargs-parser": "^13.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, "convert-source-map": { "version": "1.6.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { @@ -10110,22 +9934,16 @@ }, "find-up": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" } }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, "locate-path": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { @@ -10133,82 +9951,29 @@ "path-exists": "^3.0.0" } }, - "os-locale": { - "version": "3.1.0", - "resolved": false, - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "p-try": "^2.0.0" } }, - "yargs": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.0" + "p-limit": "^2.0.0" } }, - "yargs-parser": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.0.tgz", - "integrity": "sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true } } }, @@ -10243,6 +10008,15 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -10259,14 +10033,6 @@ "dev": true, "requires": { "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "object.assign": { @@ -10310,14 +10076,6 @@ "dev": true, "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "octokit-pagination-methods": { @@ -10354,6 +10112,12 @@ "wordwrap": "~0.0.2" }, "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -10389,37 +10153,14 @@ "dev": true }, "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" - }, - "dependencies": { - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } } }, "os-name": { @@ -10485,42 +10226,25 @@ "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { "p-try": "^1.0.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "^2.0.0" - }, - "dependencies": { - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", - "dev": true - } + "p-limit": "^1.1.0" } }, "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha1-5OlPMR6rvIYzoeeZCBZfyiYkG2s=", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, "p-reduce": { @@ -10655,7 +10379,7 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-platform": { @@ -10826,14 +10550,6 @@ "requires": { "colors": "^1.1.2", "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "process": { @@ -10845,13 +10561,13 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, "property-expr": { @@ -10895,7 +10611,7 @@ "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -10922,23 +10638,6 @@ "proxy-from-env": "^1.0.0", "rimraf": "^2.6.1", "ws": "^6.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "q": { @@ -11000,14 +10699,6 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "read-only-stream": { @@ -11043,7 +10734,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -11094,7 +10785,7 @@ "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { "extend-shallow": "^3.0.2", @@ -11135,7 +10826,7 @@ "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true }, "repeat-string": { @@ -11179,15 +10870,15 @@ "dev": true }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "resolve": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", - "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -11196,7 +10887,7 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-url": { @@ -11218,7 +10909,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, "retry": { @@ -11230,7 +10921,7 @@ "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { "glob": "^7.1.3" @@ -11273,12 +10964,12 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -11288,7 +10979,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "saucelabs": { @@ -11334,15 +11025,6 @@ "yargs": "^13.1.0" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "figures": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz", @@ -11353,12 +11035,13 @@ } }, "find-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.0.0.tgz", - "integrity": "sha512-zoH7ZWPkRdgwYCDVoQTzqjG8JSPANhtvLhh4KVUHyKnaUJJrNeFmWIkTcNuJmR3GLMEmGYEf2S2bjgx26JTF+Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^5.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "get-stream": { @@ -11379,12 +11062,6 @@ "p-locate": "^4.1.0" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "p-limit": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", @@ -11419,6 +11096,12 @@ "json-parse-better-errors": "^1.0.1" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "read-pkg": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.1.1.tgz", @@ -11471,9 +11154,9 @@ } }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "semver-compare": { @@ -11497,7 +11180,7 @@ "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -11599,29 +11282,12 @@ "dev": true }, "simple-git": { - "version": "1.113.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.113.0.tgz", - "integrity": "sha512-i9WVsrK2u0G/cASI9nh7voxOk9mhanWY9eGtWBDSYql6m49Yk5/Fan6uZsDr/xmzv8n+eQ8ahKCoEr8cvU3h+g==", + "version": "1.115.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.115.0.tgz", + "integrity": "sha512-PXcDVDgXifUE7/M2xUfQQ8uG3r73+kYRyPmsbc/iWwUrPbOASHt8p+HEbu85k546qmXixbcSPDg83kegw1vqcA==", "dev": true, "requires": { "debug": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "sinon": { @@ -11640,9 +11306,9 @@ } }, "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "slice-ansi": { @@ -11659,7 +11325,7 @@ "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { "base": "^0.11.1", @@ -11672,6 +11338,15 @@ "use": "^3.1.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -11689,13 +11364,19 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { "define-property": "^1.0.0", @@ -11715,7 +11396,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -11724,7 +11405,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -11733,47 +11414,46 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", "dev": true }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { "atob": "^2.1.1", @@ -11823,7 +11503,7 @@ "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha1-+4PlBERSaPFUsHTiGMh8ADzTHfQ=", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -11833,13 +11513,13 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -11864,7 +11544,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -11917,7 +11597,7 @@ }, "sprintf-js": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, @@ -11956,7 +11636,7 @@ "stackframe": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", - "integrity": "sha1-NXskqZL5Qny6a1RdlqFO0svKGHs=", + "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==", "dev": true } } @@ -11975,14 +11655,6 @@ "requires": { "source-map": "0.5.6", "stackframe": "~0.3" - }, - "dependencies": { - "source-map": { - "version": "0.5.6", - "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - } } }, "stacktrace-js": { @@ -12075,34 +11747,17 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -12120,12 +11775,12 @@ } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^3.0.0" } }, "strip-bom": { @@ -12136,7 +11791,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -12159,14 +11814,6 @@ "dev": true, "requires": { "minimist": "^1.1.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "supports-color": { @@ -12218,9 +11865,9 @@ } }, "table": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/table/-/table-5.3.3.tgz", - "integrity": "sha512-3wUNCgdWX6PNpOe3amTTPWPuF6VGvgzjKCaO1snFj0z7Y3mUPWf5+zDtxUVGispJkDECPmR29wbzh6bVMOHbcw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.1.tgz", + "integrity": "sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w==", "dev": true, "requires": { "ajv": "^6.9.1", @@ -12300,6 +11947,30 @@ "path-exists": "^3.0.0" } }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -12345,12 +12016,6 @@ "find-up": "^3.0.0", "read-pkg": "^3.0.0" } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true } } }, @@ -12368,14 +12033,14 @@ }, "through": { "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { "readable-stream": "~2.3.6", @@ -12419,12 +12084,23 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { "define-property": "^2.0.2", @@ -12441,17 +12117,6 @@ "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - } } }, "toposort": { @@ -12503,9 +12168,9 @@ "dev": true }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, "tty-browserify": { @@ -12534,6 +12199,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz", + "integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -12546,7 +12217,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "type-fest": { @@ -12561,6 +12232,26 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "uglify-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, "umd": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", @@ -12667,12 +12358,6 @@ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true } } }, @@ -12691,7 +12376,7 @@ "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -12736,7 +12421,7 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, "util": { @@ -12757,13 +12442,13 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE=", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "dev": true }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -12805,7 +12490,7 @@ "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -12842,35 +12527,13 @@ "dev": true }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" } }, "wrappy": { @@ -12889,9 +12552,9 @@ } }, "write-file-atomic": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", - "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -12917,7 +12580,7 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { @@ -12927,12 +12590,12 @@ "dev": true }, "yargs": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", "dev": true, "requires": { - "cliui": "^5.0.0", + "cliui": "^4.0.0", "find-up": "^3.0.0", "get-caller-file": "^2.0.1", "os-locale": "^3.1.0", @@ -12942,7 +12605,7 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.0" + "yargs-parser": "^13.0.0" }, "dependencies": { "ansi-regex": { @@ -12951,23 +12614,6 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -12977,12 +12623,6 @@ "locate-path": "^3.0.0" } }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -12993,21 +12633,28 @@ "path-exists": "^3.0.0" } }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "p-try": "^2.0.0" } }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "string-width": { @@ -13029,46 +12676,17 @@ "requires": { "ansi-regex": "^4.1.0" } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha1-h5oIZZc7yp9rq1y987HGfsfTvPQ=", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true - } } }, "yargs-unparser": { @@ -13091,6 +12709,12 @@ "locate-path": "^3.0.0" } }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -13101,6 +12725,36 @@ "path-exists": "^3.0.0" } }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "yargs": { "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", @@ -13120,6 +12774,16 @@ "y18n": "^3.2.1 || ^4.0.0", "yargs-parser": "^11.1.1" } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, diff --git a/package.json b/package.json index 7dd2af0c..960e352c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "gavel", "version": "0.0.0-semantically-released", "description": "Validator of HTTP transactions (JavaScript implementation)", - "main": "lib/gavel.js", + "main": "lib/index.js", "engines": { "node": ">= 8" }, @@ -11,15 +11,14 @@ }, "scripts": { "lint": "eslint lib/**/*.js test/**/*.js", - "test": "npm run test:next && npm run test:server && npm run test:browser && npm run test:features", - "test:next": "mocha \"lib/next/test/**/*.test.js\"", - "test:server": "mocha \"test/unit/**/*-test.js\"", + "test": "npm run test:server && npm run test:browser && npm run test:features", + "test:server": "mocha \"test/**/*.test.js\"", "test:server:coverage": "nyc npm run test:server", - "test:browser": "mochify \"test/unit/**/*.js\"", + "test:browser": "mochify \"test/**/*.js\"", "test:features": "node scripts/cucumber.js", "coveralls": "nyc --reporter=text-lcov npm run test:server | coveralls", "ci:lint": "npm run lint", - "ci:test": "npm run coveralls && npm run test:next && npm run test:browser && npm run test:features", + "ci:test": "npm run coveralls && npm run test:browser && npm run test:features", "ci:release": "semantic-release", "precommit": "lint-staged" }, @@ -56,7 +55,7 @@ "eslint-config-airbnb-base": "13.1.0", "eslint-config-prettier": "5.0.0", "eslint-plugin-import": "2.17.3", - "gavel-spec": "2.0.0", + "gavel-spec": "3.0.0", "husky": "2.4.1", "lint-staged": "8.2.1", "mocha": "6.1.4", diff --git a/test/cucumber/step_definitions/javascript_steps.js b/test/cucumber/step_definitions/javascript_steps.js index d32501fb..7fb8314f 100644 --- a/test/cucumber/step_definitions/javascript_steps.js +++ b/test/cucumber/step_definitions/javascript_steps.js @@ -1,4 +1,14 @@ +/* eslint-disable */ module.exports = function() { + this.Given( + /^you define following( expected)? HTTP (request|response) object:/, + function(isExpected, messageType, string, callback) { + this.codeBuffer += `${string}\n`; + return callback(); + } + ); + + // this.Given(/^you define the following "([^"]*)" variable:$/, function( arg1, string, @@ -8,15 +18,6 @@ module.exports = function() { return callback(); }); - this.Given(/^you define following "([^"]*)" object:$/, function( - objectName, - string, - callback - ) { - this.codeBuffer += string + '\n'; - return callback(); - }); - this.Given(/^you add expected "([^"]*)" to real "([^"]*)":$/, function( arg1, arg2, diff --git a/test/cucumber/step_definitions/method_steps.js b/test/cucumber/step_definitions/method_steps.js new file mode 100644 index 00000000..53801647 --- /dev/null +++ b/test/cucumber/step_definitions/method_steps.js @@ -0,0 +1,17 @@ +module.exports = function() { + this.Given( + /^you expect HTTP message method "([^"]*)"$/, + (method, callback) => { + this.expected.method = method; + return callback(); + } + ); + + return this.When( + /^real HTTP message method is "([^"]*)"$/, + (method, callback) => { + this.real.message = method; + return callback(); + } + ); +}; diff --git a/test/cucumber/step_definitions/model_steps.js b/test/cucumber/step_definitions/model_steps.js index 7253f5ff..e21f6dac 100644 --- a/test/cucumber/step_definitions/model_steps.js +++ b/test/cucumber/step_definitions/model_steps.js @@ -1,5 +1,6 @@ -const gavel = require('../../../lib/gavel'); +/* eslint-disable */ const deepEqual = require('deep-equal'); +const gavel = require('../../../lib'); module.exports = function() { // TODO consider refactoring for for better acceptace testing to separated steps @@ -23,26 +24,20 @@ module.exports = function() { return this.Then( /^"([^"]*)" JSON representation will look like this:$/, function(objectTypeString, string, callback) { - let data, klass; + let data; const expectedObject = JSON.parse(string); if (objectTypeString === 'HTTP Request') { - klass = 'HttpRequest'; data = this.model.request; } else if (objectTypeString === 'HTTP Response') { - klass = 'HttpResponse'; data = this.model.response; } else if (objectTypeString === 'Expected HTTP Request') { - klass = 'ExpectedHttpRequest'; data = this.expected; } else if (objectTypeString === 'Expected HTTP Response') { - klass = 'ExpectedHttpResponse'; data = this.expected; } - const instance = new gavel[klass](data); - - const jsonizedInstance = JSON.parse(JSON.stringify(instance)); + const jsonizedInstance = JSON.parse(JSON.stringify(data)); if (!deepEqual(expectedObject, jsonizedInstance, { strict: true })) { callback( diff --git a/test/cucumber/step_definitions/uri_steps.js b/test/cucumber/step_definitions/uri_steps.js new file mode 100644 index 00000000..120827dc --- /dev/null +++ b/test/cucumber/step_definitions/uri_steps.js @@ -0,0 +1,11 @@ +module.exports = function() { + this.Given(/^you expect HTTP message URI "([^"]*)"$/, (uri, callback) => { + this.expected.uri = uri; + return callback(); + }); + + return this.When(/^real HTTP message URI is "([^"]*)"$/, (uri, callback) => { + this.real.uri = uri; + return callback(); + }); +}; diff --git a/test/cucumber/step_definitions/validation_errors_thens.js b/test/cucumber/step_definitions/validation_errors_thens.js index cbfe3950..4758af25 100644 --- a/test/cucumber/step_definitions/validation_errors_thens.js +++ b/test/cucumber/step_definitions/validation_errors_thens.js @@ -1,79 +1,46 @@ -module.exports = function() { - this.Then(/^Gavel will set some error for "([^"]*)"$/, function( - component, - callback - ) { - return this.validate((error, result) => { - if (error) { - callback(new Error(`Error during validation: ${error}`)); - } - - component = this.toCamelCase(component); - const componentValidation = result[component]; - const results = componentValidation['results']; - const errorsCount = results.length; - - if (!errorsCount > 0) { - callback( - new Error( - `Expected validation errors on '${component}', but there are no validation errors.` - ) - ); - } +const { assert } = require('chai'); - return callback(); - }); - }); - - this.Then(/^Gavel will NOT set any errors for "([^"]*)"$/, function( - component, +module.exports = function() { + this.Then(/^field "([^"]*)" is( NOT)? valid$/, function( + fieldName, + isNotValid, callback ) { - return this.validate((error, result) => { - if (error) { - callback(new Error(`Error during validation: ${error}`)); - } - component = this.toCamelCase(component); - const componentValidation = result[component]; - const results = componentValidation['results']; - const errorsCount = results.length; - - if (errorsCount > 0) { - callback( - new Error( - "No errors on '" + - component + - "' expected, but there are " + - errorsCount + - ' validation errors:' + - JSON.stringify(results, null, 2) - ) - ); - } - - return callback(); - }); + const result = this.validate(); + + assert.property( + result.fields, + fieldName, + `Expected to have "${fieldName}" field in the validation result, but got none.` + ); + + assert.propertyVal( + result.fields[fieldName], + 'isValid', + !isNotValid, + `Expected "result.fields.${fieldName}" to be valid, but it's not.` + ); + + return callback(); }); this.Then(/^Request or Response is NOT valid$/, function(callback) { - return this.isValid((error, result) => { - if (result) { - callback( - new Error('Request or Response is valid and should NOT be valid.') - ); - } - return callback(); - }); + const result = this.validate(); + if (result.isValid) { + callback( + new Error('Request or Response is valid and should NOT be valid.') + ); + } + return callback(); }); return this.Then(/^Request or Response is valid$/, function(callback) { - return this.isValid((error, result) => { - if (!result) { - callback( - new Error('Request or Response is NOT valid and should be valid.') - ); - } - return callback(); - }); + const result = this.validate(); + if (!result.isValid) { + callback( + new Error('Request or Response is NOT valid and should be valid.') + ); + } + return callback(); }); }; diff --git a/test/cucumber/step_definitions/validators_steps.js b/test/cucumber/step_definitions/validators_steps.js index 4cc5f1ff..7eb10a60 100644 --- a/test/cucumber/step_definitions/validators_steps.js +++ b/test/cucumber/step_definitions/validators_steps.js @@ -1,3 +1,4 @@ +/* eslint-disable */ const tv4 = require('tv4'); const { assert } = require('chai'); const deepEqual = require('deep-equal'); @@ -25,20 +26,14 @@ module.exports = function() { body: json2 }; - return this.validate((error, result) => { - if (error) { - callback(new Error(`Got error during validation:\n${error}`)); - } + try { + const result = this.validate(); this.results = JSON.parse(JSON.stringify(result)); - - return this.isValid((error, result) => { - if (error) { - callback(new Error(error)); - } - this.booleanResult = result; - return callback(); - }); - }); + this.booleanResult = result.isValid; + return callback(); + } catch (error) { + callback(new Error(`Got error during validation:\n${error}`)); + } } ); @@ -46,7 +41,7 @@ module.exports = function() { /^the validator output for the HTTP component looks like the following JSON:$/, function(expectedJson, callback) { const expected = JSON.parse(expectedJson); - const real = this.results[this.component]; + const real = this.results.fields[this.component]; if (!deepEqual(real, expected, { strict: true })) { return callback( new Error( @@ -75,7 +70,7 @@ module.exports = function() { /^the validator output for the HTTP component is valid against "([^"]*)" model JSON schema:$/, function(model, schema, callback) { const valid = tv4.validate( - this.results[this.component], + this.results.fields[this.component], JSON.parse(schema) ); if (!valid) { @@ -94,7 +89,7 @@ module.exports = function() { this.Then( /^each result entry under "([^"]*)" key must contain "([^"]*)" key$/, function(key1, key2, callback) { - const error = this.results[this.component]; + const error = this.results.fields[this.component]; if (error === undefined) { callback( new Error( @@ -114,7 +109,7 @@ module.exports = function() { this.Then( /^the output JSON contains key "([^"]*)" with one of the following values:$/, function(key, table, callback) { - const error = this.results[this.component]; + const error = this.results.fields[this.component]; const validators = [].concat.apply([], table.raw()); @@ -165,22 +160,21 @@ module.exports = function() { this.When(/^you perform validation on the HTTP component$/, function( callback ) { - return this.validate((error, result) => { - if (error) { - callback(new Error(`Error during validation: ${error}`)); - } - + try { + const result = this.validate(); this.results = result; - this.componentResults = this.results[this.component]; + this.componentResults = this.results.fields[this.component]; return callback(); - }); + } catch (error) { + callback(new Error(`Error during validation: ${error}`)); + } }); this.Then(/^validator "([^"]*)" is used for validation$/, function( validator, callback ) { - const usedValidator = this.componentResults['validator']; + const usedValidator = this.componentResults.validator; if (validator !== usedValidator) { callback( new Error( @@ -233,7 +227,7 @@ module.exports = function() { key, callback ) { - this.componentResults['results'].forEach((error) => + this.componentResults.errors.forEach((error) => assert.include(Object.keys(error), key) ); return callback(); diff --git a/test/cucumber/support/world.js b/test/cucumber/support/world.js index e3742c85..9e70eb4e 100644 --- a/test/cucumber/support/world.js +++ b/test/cucumber/support/world.js @@ -4,7 +4,8 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const gavel = require('../../../lib/gavel'); +/* eslint-disable */ +const gavel = require('../../../lib'); const vm = require('vm'); const util = require('util'); const { assert } = require('chai'); @@ -91,7 +92,10 @@ class World { // further reading on node.js load paths: // http://nodejs.org/docs/v0.8.23/api/all.html#all_all_together - const formattedCode = code.replace("require('", "require('../../../lib/"); + const formattedCode = code.replace( + "require('gavel", + "require('../../../lib" + ); try { return eval(formattedCode); @@ -107,12 +111,8 @@ class World { } } - isValid(callback) { - return gavel.isValid(this.real, this.expected, 'response', callback); - } - - validate(callback) { - return gavel.validate(this.real, this.expected, 'response', callback); + validate() { + return gavel.validate(this.expected, this.real); } parseHeaders(headersString) { @@ -175,6 +175,14 @@ class World { return parsed; } + // Hacky coercion function to parse expcected Boolean values + // from Gherkin feature suites. + toBoolean(string) { + if (string === 'true') return true; + if (string === 'false') return false; + return !!string; + } + toCamelCase(input) { const result = input.replace(/\s([a-z])/g, (strings) => strings[1].toUpperCase() diff --git a/lib/next/test/integration/validateMessage.test.js b/test/integration/validate.test.js similarity index 53% rename from lib/next/test/integration/validateMessage.test.js rename to test/integration/validate.test.js index 7e0b3477..26c504ee 100644 --- a/lib/next/test/integration/validateMessage.test.js +++ b/test/integration/validate.test.js @@ -1,5 +1,5 @@ const { assert } = require('chai'); -const { validateMessage } = require('../../validateMessage'); +const { validate } = require('../../lib/validate'); const validator = (obj, expected) => { it(`has "${expected}" validator`, () => { @@ -17,11 +17,11 @@ const realType = createTypeAssertion('real', 'realType'); const expectedType = createTypeAssertion('expected', 'expectedType'); const noErrors = (obj) => { it('has no errors', () => { - assert.lengthOf(obj.results, 0); + assert.lengthOf(obj.errors, 0); }); }; -describe('validateMessage', () => { +describe('validate', () => { describe('with matching requests', () => { const request = { method: 'POST', @@ -30,48 +30,61 @@ describe('validateMessage', () => { }, body: '{ "foo": "bar" }' }; - const result = validateMessage(request, request); + const result = validate(request, request); it('returns validation result object', () => { assert.isObject(result); }); + it('has "isValid" set to true', () => { + assert.propertyVal(result, 'isValid', true); + }); + it('contains all validatable keys', () => { - assert.hasAllKeys(result, ['isValid', 'headers', 'body']); + assert.hasAllKeys(result.fields, ['method', 'headers', 'body']); }); - it('has "isValid" set to true', () => { - assert.propertyVal(result, 'isValid', true); + describe('method', () => { + validator(result.fields.method, null); + expectedType(result.fields.method, 'text/vnd.apiary.method'); + realType(result.fields.method, 'text/vnd.apiary.method'); + noErrors(result.fields.method); }); describe('headers', () => { - validator(result.headers, 'HeadersJsonExample'); - expectedType(result.headers, 'application/vnd.apiary.http-headers+json'); - realType(result.headers, 'application/vnd.apiary.http-headers+json'); - noErrors(result.headers); + validator(result.fields.headers, 'HeadersJsonExample'); + expectedType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + realType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + noErrors(result.fields.headers); }); describe('body', () => { - validator(result.body, 'JsonExample'); - expectedType(result.body, 'application/json'); - realType(result.body, 'application/json'); - noErrors(result.body); + validator(result.fields.body, 'JsonExample'); + expectedType(result.fields.body, 'application/json'); + realType(result.fields.body, 'application/json'); + noErrors(result.fields.body); }); }); describe('with non-matching requests', () => { - const result = validateMessage( + const result = validate( + { + method: 'PUT', + headers: '', + body: '2' + }, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{ "foo": "bar" }' - }, - { - method: 'PUT', - headers: '', - body: '2' } ); @@ -79,43 +92,60 @@ describe('validateMessage', () => { assert.isObject(result); }); - it('contains all validatable keys', () => { - assert.hasAllKeys(result, ['isValid', 'headers', 'body']); - }); - it('has "isValid" set to false', () => { assert.propertyVal(result, 'isValid', false); }); + it('contains all validatable keys', () => { + assert.hasAllKeys(result.fields, ['method', 'headers', 'body']); + }); + describe('method', () => { - // See https://github.com/apiaryio/gavel.js/issues/158 - it.skip('compares methods'); + validator(result.fields.method, null); + expectedType(result.fields.method, 'text/vnd.apiary.method'); + realType(result.fields.method, 'text/vnd.apiary.method'); + + describe('produces one error', () => { + it('exactly one error', () => { + assert.lengthOf(result.fields.method.errors, 1); + }); + + it('has explanatory message', () => { + assert.propertyVal( + result.fields.method.errors[0], + 'message', + 'Expected "method" field to equal "PUT", but got "POST".' + ); + }); + }); }); describe('headers', () => { - validator(result.headers, 'HeadersJsonExample'); - expectedType(result.headers, 'application/vnd.apiary.http-headers+json'); - realType(result.headers, 'application/vnd.apiary.http-headers+json'); - noErrors(result.headers); + validator(result.fields.headers, 'HeadersJsonExample'); + expectedType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + realType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + noErrors(result.fields.headers); }); describe('body', () => { - validator(result.body, 'JsonExample'); - expectedType(result.body, 'application/json'); - realType(result.body, 'application/json'); + validator(result.fields.body, 'JsonExample'); + expectedType(result.fields.body, 'application/json'); + realType(result.fields.body, 'application/json'); describe('produces an error', () => { it('exactly one error', () => { - assert.lengthOf(result.body.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.body.results[0], 'severity', 'error'); + assert.lengthOf(result.fields.body.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - result.body.results[0], + result.fields.body.errors[0], 'message', `At '' Invalid type: object (expected integer)` ); @@ -132,39 +162,45 @@ describe('validateMessage', () => { }, body: '{ "foo": "bar" }' }; - const result = validateMessage(response, response); + const result = validate(response, response); it('returns validation result object', () => { assert.isObject(result); }); - it('contains all validatable keys', () => { - assert.hasAllKeys(result, ['isValid', 'statusCode', 'headers', 'body']); - }); - it('sets "isValid" to true', () => { assert.propertyVal(result, 'isValid', true); }); + it('contains all validatable keys', () => { + assert.hasAllKeys(result.fields, ['statusCode', 'headers', 'body']); + }); + describe('statusCode', () => { - validator(result.statusCode, 'TextDiff'); - expectedType(result.statusCode, 'text/vnd.apiary.status-code'); - realType(result.statusCode, 'text/vnd.apiary.status-code'); - noErrors(result.statusCode); + validator(result.fields.statusCode, 'TextDiff'); + expectedType(result.fields.statusCode, 'text/vnd.apiary.status-code'); + realType(result.fields.statusCode, 'text/vnd.apiary.status-code'); + noErrors(result.fields.statusCode); }); describe('headers', () => { - validator(result.headers, 'HeadersJsonExample'); - expectedType(result.headers, 'application/vnd.apiary.http-headers+json'); - realType(result.headers, 'application/vnd.apiary.http-headers+json'); - noErrors(result.headers); + validator(result.fields.headers, 'HeadersJsonExample'); + expectedType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + realType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + noErrors(result.fields.headers); }); describe('body', () => { - validator(result.body, 'JsonExample'); - expectedType(result.body, 'application/json'); - realType(result.body, 'application/json'); - noErrors(result.body); + validator(result.fields.body, 'JsonExample'); + expectedType(result.fields.body, 'application/json'); + realType(result.fields.body, 'application/json'); + noErrors(result.fields.body); }); }); @@ -181,37 +217,33 @@ describe('validateMessage', () => { 'Accept-Language': 'en-US' } }; - const result = validateMessage(realResponse, expectedResponse); + const result = validate(expectedResponse, realResponse); it('returns validation result object', () => { assert.isObject(result); }); - it('contains all validatable keys', () => { - assert.hasAllKeys(result, ['isValid', 'statusCode', 'headers']); - }); - it('has "isValid" as false', () => { assert.propertyVal(result, 'isValid', false); }); + it('contains all validatable keys', () => { + assert.hasAllKeys(result.fields, ['statusCode', 'headers']); + }); + describe('statusCode', () => { - validator(result.statusCode, 'TextDiff'); - expectedType(result.statusCode, 'text/vnd.apiary.status-code'); - realType(result.statusCode, 'text/vnd.apiary.status-code'); + validator(result.fields.statusCode, 'TextDiff'); + expectedType(result.fields.statusCode, 'text/vnd.apiary.status-code'); + realType(result.fields.statusCode, 'text/vnd.apiary.status-code'); describe('produces an error', () => { it('exactly one error', () => { - assert.lengthOf(result.statusCode.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.statusCode.results[0], 'severity', 'error'); + assert.lengthOf(result.fields.statusCode.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - result.statusCode.results[0], + result.fields.statusCode.errors[0], 'message', `Status code is '400' instead of '200'` ); @@ -220,22 +252,24 @@ describe('validateMessage', () => { }); describe('headers', () => { - validator(result.headers, 'HeadersJsonExample'); - expectedType(result.headers, 'application/vnd.apiary.http-headers+json'); - realType(result.headers, 'application/vnd.apiary.http-headers+json'); + validator(result.fields.headers, 'HeadersJsonExample'); + expectedType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + realType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); describe('produces an error', () => { it('exactly one error', () => { - assert.lengthOf(result.headers.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.headers.results[0], 'severity', 'error'); + assert.lengthOf(result.fields.headers.errors, 1); }); it('includes missing header in the message', () => { assert.propertyVal( - result.headers.results[0], + result.fields.headers.errors[0], 'message', `At '/accept-language' Missing required property: accept-language` ); @@ -245,15 +279,15 @@ describe('validateMessage', () => { }); describe('with non-matching headers', () => { - const result = validateMessage( - { - statusCode: 404 - }, + const result = validate( { statusCode: 404, headers: { 'Content-Type': 'text/plain' } + }, + { + statusCode: 404 } ); @@ -261,38 +295,40 @@ describe('validateMessage', () => { assert.isObject(result); }); - it('contains all validatable keys', () => { - assert.hasAllDeepKeys(result, ['isValid', 'statusCode', 'headers']); - }); - it('has "isValid" as false', () => { assert.propertyVal(result, 'isValid', false); }); + it('contains all validatable keys', () => { + assert.hasAllKeys(result.fields, ['statusCode', 'headers']); + }); + describe('statusCode', () => { - validator(result.statusCode, 'TextDiff'); - expectedType(result.statusCode, 'text/vnd.apiary.status-code'); - realType(result.statusCode, 'text/vnd.apiary.status-code'); - noErrors(result.statusCode); + validator(result.fields.statusCode, 'TextDiff'); + expectedType(result.fields.statusCode, 'text/vnd.apiary.status-code'); + realType(result.fields.statusCode, 'text/vnd.apiary.status-code'); + noErrors(result.fields.statusCode); }); describe('headers', () => { - validator(result.headers, 'HeadersJsonExample'); - expectedType(result.headers, 'application/vnd.apiary.http-headers+json'); - realType(result.headers, 'application/vnd.apiary.http-headers+json'); + validator(result.fields.headers, 'HeadersJsonExample'); + expectedType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + realType( + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); describe('produces an error', () => { it('exactly one error', () => { - assert.lengthOf(result.headers.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.headers.results[0], 'severity', 'error'); + assert.lengthOf(result.fields.headers.errors, 1); }); it('has pointer to missing "Content-Type"', () => { assert.propertyVal( - result.headers.results[0], + result.fields.headers.errors[0], 'pointer', '/content-type' ); @@ -300,7 +336,7 @@ describe('validateMessage', () => { it('has explanatory message', () => { assert.propertyVal( - result.headers.results[0], + result.fields.headers.errors[0], 'message', `At '/content-type' Missing required property: content-type` ); @@ -310,41 +346,41 @@ describe('validateMessage', () => { }); describe('always validates expected properties', () => { - const result = validateMessage( - { - body: 'doe' - }, + const result = validate( { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: '{ "foo": "bar" }' + }, + { + body: 'doe' } ); + it('has "isValid" as false', () => { + assert.propertyVal(result, 'isValid', false); + }); + it('contains all validatable keys', () => { - assert.hasAllKeys(result, ['isValid', 'statusCode', 'headers', 'body']); + assert.hasAllKeys(result.fields, ['statusCode', 'headers', 'body']); }); describe('for properties present in both expected and real', () => { describe('body', () => { - validator(result.body, null); - expectedType(result.body, 'application/json'); - realType(result.body, 'text/plain'); + validator(result.fields.body, null); + expectedType(result.fields.body, 'application/json'); + realType(result.fields.body, 'text/plain'); describe('produces an error', () => { it('exactly one error', () => { - assert.lengthOf(result.body.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.body.results[0], 'severity', 'error'); + assert.lengthOf(result.fields.body.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - result.body.results[0], + result.fields.body.errors[0], 'message', `Can't validate real media type 'text/plain' against expected media type 'application/json'.` ); @@ -355,26 +391,18 @@ describe('validateMessage', () => { describe('for properties present in expected, but not in real', () => { describe('statusCode', () => { - validator(result.statusCode, 'TextDiff'); - expectedType(result.statusCode, 'text/vnd.apiary.status-code'); - realType(result.statusCode, 'text/vnd.apiary.status-code'); + validator(result.fields.statusCode, 'TextDiff'); + expectedType(result.fields.statusCode, 'text/vnd.apiary.status-code'); + realType(result.fields.statusCode, 'text/vnd.apiary.status-code'); describe('produces an error', () => { it('exactly one error', () => { - assert.lengthOf(result.statusCode.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal( - result.statusCode.results[0], - 'severity', - 'error' - ); + assert.lengthOf(result.fields.statusCode.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - result.statusCode.results[0], + result.fields.statusCode.errors[0], 'message', `Status code is 'undefined' instead of '200'` ); @@ -383,25 +411,24 @@ describe('validateMessage', () => { }); describe('headers', () => { - validator(result.headers, 'HeadersJsonExample'); + validator(result.fields.headers, 'HeadersJsonExample'); expectedType( - result.headers, + result.fields.headers, + 'application/vnd.apiary.http-headers+json' + ); + realType( + result.fields.headers, 'application/vnd.apiary.http-headers+json' ); - realType(result.headers, 'application/vnd.apiary.http-headers+json'); describe('produces one error', () => { it('exactly one error', () => { - assert.lengthOf(result.headers.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.headers.results[0], 'severity', 'error'); + assert.lengthOf(result.fields.headers.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - result.headers.results[0], + result.fields.headers.errors[0], 'message', `At '/content-type' Missing required property: content-type` ); diff --git a/test/unit/.DS_Store b/test/unit/.DS_Store new file mode 100644 index 00000000..5008ddfc Binary files /dev/null and b/test/unit/.DS_Store differ diff --git a/test/unit/mixins/validatable-http-message-test.js b/test/unit/mixins/validatable-http-message-test.js deleted file mode 100644 index b083b60a..00000000 --- a/test/unit/mixins/validatable-http-message-test.js +++ /dev/null @@ -1,1501 +0,0 @@ -/* eslint-disable no-shadow */ -const { assert } = require('chai'); -const sinon = require('sinon'); - -const { HttpResponse } = require('../../../lib/model/http-response'); -const { HttpRequest } = require('../../../lib/model/http-request'); -const fixtures = require('../../fixtures'); -const INVALID_SCHEMA = require('../../fixtures/invalid-schema-v4'); - -describe('Http validatable mixin', () => { - describe('when mixed in any HTTP Message class', () => { - const methods = [ - 'isValidatable', - 'validate', - 'isValid', - 'validationResults', - - 'lowercaseHeaders', - - 'validateHeaders', - 'setHeadersRealType', - 'setHeadersExpectedType', - 'setHeadersValidator', - 'runHeadersValidator', - - 'validateBody', - 'setBodyRealType', - 'setBodyExpectedType', - 'setBodyValidator', - 'runBodyValidator', - - 'validateStatusCode' - ]; - - methods.forEach((method) => { - it(`should have '${method}' method defined`, () => { - assert.isFunction(HttpResponse.prototype[method]); - }); - }); - - describe('validatableComponents', () => { - const items = ['headers', 'body', 'statusCode']; - items.forEach((item) => { - it(`should contain '${item}'`, () => { - assert.include(HttpResponse.validatableComponents, item); - }); - }); - - describe('#isValidatable()', () => { - describe('when no validatable HTTP component in the object', () => { - it('should return false', () => { - const instance = new HttpResponse({ foo: 'bar' }); - assert.isFalse(instance.isValidatable()); - }); - }); - - describe('when any validatable HTTP component is present in the object', () => { - it('should return true for some headers', () => { - const instance = new HttpResponse({ - headers: { 'content-type:': 'application/json' } - }); - assert.isTrue(instance.isValidatable()); - }); - - it('should return true for some body', () => { - const instance = new HttpResponse({ body: '' }); - assert.isTrue(instance.isValidatable()); - }); - - it('should return true for some statusCode', () => { - const instance = new HttpResponse({ statusCode: 200 }); - assert.isTrue(instance.isValidatable()); - }); - }); - }); - - describe('any HTTP Message instance', () => { - let instance = {}; - let response = { - body: '{"a": "b"}', - headers: fixtures.sampleHeadersMissing, - statusCode: 200, - expected: { - headers: fixtures.sampleHeaders, - body: '{"b": "c"}' - } - }; - - before(() => { - instance = new HttpResponse(response); - }); - - describe('#validate()', () => { - let result = null; - before(() => { - result = instance.validate(); - }); - - it('should return an object', () => { - assert.isObject(result); - }); - - const keys = ['headers', 'body', 'statusCode', 'version']; - keys.forEach((key) => { - it(`should contain validatable Component key '${key}'`, () => { - assert.include(Object.keys(result), key); - }); - }); - - it('should create validation property', () => { - assert.isDefined(instance.validation); - }); - - // Headers - it('should call lowercaseHeaders', () => { - instance = new HttpResponse(response); - sinon.spy(instance, 'lowercaseHeaders'); - instance.validate(); - assert.isTrue(instance.lowercaseHeaders.called); - }); - - describe('real headers are present', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validateHeaders'); - instance.validate(); - }); - - it('should call validateHeaders', () => { - assert.isTrue(instance.validateHeaders.called); - }); - }); - - describe('when expected headers not present', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validateHeaders'); - instance.expected.headers = undefined; - instance.validate(); - }); - - it('should not run headers validation', () => { - assert.isFalse(instance.validateHeaders.called); - }); - }); - - describe('when expected headers are present', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validateHeaders'); - instance.validate(); - }); - - it('should call validateHeaders', () => { - assert.isTrue(instance.validateHeaders.called); - }); - }); - - describe('when real headers not present', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validateHeaders'); - instance.headers = undefined; - instance.validate(); - }); - - it('should not run headers validation', () => { - assert.isFalse(instance.validateHeaders.called); - }); - }); - - // Body - describe('when real body is present', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validateBody'); - instance.validate(); - }); - - it('should call validateBody', () => { - assert.isTrue(instance.validateBody.called); - }); - }); - - describe('when real is not present', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validateBody'); - instance.body = undefined; - // instance.validate(); - }); - - // it('should not run body validation', () => { - // assert.isFalse(instance.validateBody.called); - // }); - it('should throw upon invalid body type', () => { - assert.throws(instance.validate); - }); - }); - - describe('when expected body is present', () => { - before(() => { - instance = new HttpResponse(response); - instance.expected.body = '{"b": "c"}'; - sinon.spy(instance, 'validateBody'); - instance.validate(); - }); - - it('should call validateBody', () => { - assert.isTrue(instance.validateBody.called); - }); - }); - - describe('when expected body is not present', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validateBody'); - instance.expected.body = undefined; - // instance.validate(); - }); - - // it('should not run body validation', () => { - // assert.isFalse(instance.validateBody.called); - // }); - it('should throw upon invalid body type', () => { - assert.throws(instance.validate); - }); - }); - - describe('#isValid()', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validate'); - }); - describe('validation property is empty', () => { - it('should perform validation', () => { - instance.isValid(); - assert.isTrue(instance.validate.called); - }); - }); - - it('should return boolean', () => { - assert.isBoolean(instance.isValid()); - }); - - describe('when any HTTP component contains error message', () => { - let instance = null; - before(() => { - instance = new HttpResponse({}); - instance.validation = { - headers: { - results: [{ severity: 'error' }] - } - }; - }); - - it('should return false', () => { - assert.isFalse(instance.isValid()); - }); - }); - }); - - describe('#validationResults()', () => { - describe('when HTTP message validation property is empty', () => { - before(() => { - instance = new HttpResponse(response); - sinon.spy(instance, 'validate'); - }); - - it('should perform validation', () => { - instance.validationResults(); - assert.isTrue(instance.validate.called); - }); - - it('should return content of validation property', () => { - const validation = { booboo: 'foobar' }; - instance.validation = validation; - assert.equal(instance.validationResults(), validation); - }); - }); - }); - - describe('#lowercaseHeaders()', () => { - let inst = null; - before(() => { - inst = new HttpRequest({ - headers: { - 'Content-Type': 'application/json; charset=utf-8', - 'User-Agent': 'Dredd/0.3.5 (Darwin 13.2.0; x64)' - }, - expected: { - headers: { - 'CONTENT-TYPE': 'application/json; charset=utf-8', - 'USER-AGENT': 'Dredd/0.3.5 (Darwin 13.2.0; x64)' - } - } - }); - inst.lowercaseHeaders(); - }); - - it('should convert all keys in real headers object to lowercase', () => { - const keys = Object.keys(inst.headers); - assert.include(keys, 'content-type'); - assert.include(keys, 'user-agent'); - assert.notInclude(keys, 'Content-Type'); - assert.notInclude(keys, 'User-Agebt'); - }); - - it('should convert all keys in expected headers object to lowercase', () => { - const keys = Object.keys(inst.expected.headers); - assert.include(keys, 'content-type'); - assert.include(keys, 'user-agent'); - assert.notInclude(keys, 'Content-Type'); - assert.notInclude(keys, 'User-Agent'); - }); - }); - - // Headers validation tests - describe('#validateHeaders()', () => { - before(() => { - sinon.spy(instance, 'setHeadersRealType'); - sinon.spy(instance, 'setHeadersExpectedType'); - sinon.spy(instance, 'setHeadersValidator'); - sinon.spy(instance, 'runHeadersValidator'); - - instance.validateHeaders(); - }); - - const fields = [ - 'realType', - 'expectedType', - 'validator', - 'rawData', - 'results' - ]; - - fields.forEach((field) => { - it(`should set '${field}' property for the component`, () => { - assert.isDefined(instance.validation.headers[field]); - }); - }); - - it('should call setHeadersRealType', () => { - assert.isTrue(instance.setHeadersRealType.called); - }); - - it('should call setHeadersExpectedType', () => { - assert.isTrue(instance.setHeadersExpectedType.called); - }); - - it('should call setHeadersValidator', () => { - assert.isTrue(instance.setHeadersValidator.called); - }); - - it('should call runHeadersValidator', () => { - assert.isTrue(instance.runHeadersValidator.called); - }); - }); - - describe('#setHeadersRealType()', () => { - describe('real is an Object', () => { - before(() => { - instance.validation.headers = {}; - instance.setHeadersRealType(); - }); - - it('should set realType', () => { - assert.equal( - instance.validation.headers.realType, - 'application/vnd.apiary.http-headers+json' - ); - }); - }); - - describe('real is not an Object', () => { - before(() => { - instance.headers = 'string'; - instance.setHeadersRealType(); - }); - - it('should set real type to null', () => { - assert.equal(instance.validation.headers.realType, null); - }); - }); - }); - - describe('#setHeadersExpectedType()', () => { - describe('expected headers property is an Object', () => { - before(() => { - instance.validation.headers = {}; - instance.setHeadersExpectedType(); - }); - - it('should set expectedType', () => { - assert.equal( - instance.validation.headers.expectedType, - 'application/vnd.apiary.http-headers+json' - ); - }); - }); - - describe('expectedheaders property is not an Object', () => { - before(() => { - instance.expected.headers = 'string'; - instance.setHeadersExpectedType(); - }); - - it('should let expected type empty', () => { - assert.equal(instance.validation.headers.expectedType, null); - }); - }); - }); - - describe('#setHeadersValidator()', () => { - before(() => { - instance.validation = {}; - instance.validation.headers = {}; - instance.setHeadersValidator(); - }); - - it('should set validator property', () => { - assert.isDefined(instance.validation.headers.validator); - }); - - describe('real and expected type is application/vnd.apiary.http-headers+json', () => { - before(() => { - instance.validation.headers = { - realType: 'application/vnd.apiary.http-headers+json', - expectedType: 'application/vnd.apiary.http-headers+json' - }; - - instance.setHeadersValidator(); - }); - - it('should set HeadersJsonExample validator', () => { - assert.equal( - instance.validation.headers.validator, - 'HeadersJsonExample' - ); - }); - }); - - describe('unknown media type combination', () => { - before(() => { - instance.validation.headers = { - realType: '', - expectedType: '' - }; - - instance.setHeadersValidator(); - }); - - it('should set results to array', () => { - assert.isArray(instance.validation.headers.results); - }); - - it('should set validator to null', () => { - assert.equal(instance.validation.headers.validator, null); - }); - - it('should add some message to results', () => { - assert.isTrue(instance.validation.headers.results.length > 0); - }); - - describe('added message', () => { - let message = null; - - before(() => { - const index = instance.validation.headers.results.length - 1; - message = instance.validation.headers.results[index]; - }); - - it('should have error severity', () => { - assert.equal(message.severity, 'error'); - }); - }); - }); - }); - - describe('#runHeadersValidator', () => { - describe('if available validator', () => { - before(() => { - instance = new HttpResponse(response); - instance.validation = {}; - instance.validation.headers = {}; - - instance.expected.headers = fixtures.sampleHeaders; - instance.validation.headers.validator = 'HeadersJsonExample'; - instance.runHeadersValidator(); - }); - - it('should set rawData property', () => { - assert.isDefined(instance.validation.headers.rawData); - }); - - it('rawData should not be null', () => { - assert.isNotNull(instance.validation.headers.rawData); - }); - }); - - describe('if no validator available', () => { - before(() => { - instance = new HttpResponse(response); - instance.validation = {}; - instance.validation.headers = {}; - - instance.expected.headers = fixtures.sampleHeaders; - instance.validation.headers.validator = null; - instance.runHeadersValidator(); - }); - - it('should let rawData null', () => { - assert.isNull(instance.validation.headers.rawData); - }); - }); - }); - - describe('runHeadersValidator()', () => { - let instance; - before(() => { - instance = new HttpResponse(response); - instance.validation = {}; - instance.validation.headers = {}; - - instance.validation.headers.rawData = JSON.parse( - fixtures.sampleAmandaError - ); - instance.validation.headers.validator = 'HeadersJsonExample'; - }); - - describe('any previously set results', () => { - before(() => { - instance.validation.results = ['booboo']; - instance.runHeadersValidator(); - }); - - it('should not overwrite existing results', () => { - assert.include(instance.validation.results, 'booboo'); - }); - - it('should set results to an array', () => { - assert.isArray(instance.validation.headers.results); - }); - }); - - describe('no previous results', () => { - before(() => { - instance.validation.headers.results = []; - instance.runHeadersValidator(); - }); - - it('should set results to an array', () => { - assert.isArray(instance.validation.headers.results); - }); - - it('should have 1 result', () => { - assert.equal(instance.validation.headers.results.length, 1); - }); - }); - - describe('no rawData and validator available', () => { - before(() => { - instance.validation.headers.rawData = null; - instance.validation.headers.validator = null; - }); - - it('should not throw an error', () => { - const fn = () => { - instance.runHeadersValidator(); - }; - - assert.doesNotThrow(fn); - }); - }); - }); - - // Body validation tests - describe('#validateBody()', () => { - before(() => { - sinon.spy(instance, 'setBodyRealType'); - sinon.spy(instance, 'setBodyExpectedType'); - sinon.spy(instance, 'setBodyValidator'); - sinon.spy(instance, 'runBodyValidator'); - - instance.validateBody(); - }); - - const fields = [ - 'realType', - 'expectedType', - 'validator', - 'rawData', - 'results' - ]; - - fields.forEach((field) => { - it(`should set '${field}' property for the component`, () => - assert.isDefined(instance.validation.body[field])); - }); - - it('should call setBodyRealType', () => - assert.isTrue(instance.setBodyRealType.called)); - - it('should call setBodyExpectedType', () => - assert.isTrue(instance.setBodyExpectedType.called)); - - it('should call setBodyValidator', () => - assert.isTrue(instance.setBodyValidator.called)); - - return it('should call runBodyValidator', () => - assert.isTrue(instance.runBodyValidator.called)); - }); - - describe('#setBodyRealType()', () => { - describe('body is not a string', () => { - let instance; - before(() => { - instance = new HttpResponse({ - body: {} - }); - instance.validation = {}; - instance.validation.body = {}; - instance.validation.body.results = []; - }); - - it('should throw an error', () => { - let message = ''; - try { - instance.setBodyRealType(); - } catch (error) { - // eslint-disable-next-line - message = error.message; - } - - assert.include(message, 'String'); - }); - }); - - const jsonContentTypes = [ - 'application/json', - 'application/json; charset=utf-8', - 'application/hal+json' - ]; - - jsonContentTypes.forEach((contentType) => { - describe(`header content-type is '${contentType}'`, () => { - let instance = null; - - before(() => { - instance = new HttpResponse({ - headers: { 'content-type': contentType } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.validation.body.results = []; - }); - - describe('body is a parseable JSON', () => { - before(() => { - instance.body = '{"foo": "bar"}'; - instance.setBodyRealType(); - }); - - it(`should set real type to '${contentType}'`, () => { - assert.equal( - instance.validation.body.realType, - contentType - ); - }); - }); - - describe('body is not a parseable JSON', () => { - before(() => { - instance.body = '{"creative?": false, \'creativ\': true }'; - instance.setBodyRealType(); - }); - - it('should set realType to null', () => { - assert.equal(instance.validation.body.realType, null); - }); - - it('should add error message to results with error severity', () => { - const severities = instance.validation.body.results.map( - (result) => result.severity - ); - assert.include(severities, 'error'); - }); - - it('should add error message with lint result', () => { - const expected = `Real body 'Content-Type' header is '${contentType}' but body is not a parseable JSON: -Unexpected token '\\'' at 1:22 -{"creative?": false, 'creativ': true } - ^`; - - const messages = instance.validation.body.results.map( - (result) => result.message - ); - assert.equal(messages[0], expected); - }); - - it('should not overwrite existing errors', () => { - instance.validation.body.results = [ - { message: 'Shit happen.', severity: 'error' } - ]; - const prevResultsLength = - instance.validation.body.results.length; - instance.setBodyRealType(); - const nextResultsLength = - instance.validation.body.results.length; - assert.equal(prevResultsLength + 1, nextResultsLength); - }); - }); - }); - }); - - describe('any or no content-type header', () => { - before(() => { - instance = new HttpResponse({}); - instance.headers = undefined; - instance.validation = {}; - instance.validation.body = {}; - instance.validation.body.results = []; - }); - - describe('body is a parseable json', () => { - before(() => { - instance.body = '{"foo": "bar"}'; - instance.setBodyRealType(); - }); - it('should set real type to application/json', () => { - assert.equal( - instance.validation.body.realType, - 'application/json' - ); - }); - }); - - describe('body is not a parseable json', () => { - before(() => { - instance.body = 'Booboo foo bar john doe'; - instance.setBodyRealType(); - }); - - it('should set real type to text/plain', () => { - assert.equal(instance.validation.body.realType, 'text/plain'); - }); - }); - }); - }); - }); - - describe('#setBodyExpectedType()', () => { - // describe('expected headers property is an Object', () => { - // before(() => { - // instance.validation.headers = {} - // instance.setHeadersExpectedType() - // }) - // }) - - describe('JSON Schema for expected body is provided', () => { - let instance = {}; - - describe('schema is an object', () => { - describe('it is not a valid JSON schema', () => { - it('should set warrning'); - }); - describe('it is a valid JSON schema', () => { - before(() => { - instance = new HttpResponse({ - expected: { - bodySchema: JSON.parse(fixtures.sampleJsonSchema) - } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it('should set expected type to application/schema+json', () => { - assert.equal( - instance.validation.body.expectedType, - 'application/schema+json' - ); - }); - - it('should set not error message to result', () => { - assert.equal(instance.validation.body.results.length, 0); - }); - }); - }); - - describe('schema is a parseable JSON', () => { - describe('parsed JSON is a valid JSON Schema', () => { - before(() => { - instance = new HttpResponse({ - expected: { - bodySchema: fixtures.sampleJsonSchema - } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it('should set expected type to application/schema+json', () => { - assert.equal( - instance.validation.body.expectedType, - 'application/schema+json' - ); - }); - - it('should set not error message to result', () => { - assert.equal(instance.validation.body.results.length, 0); - }); - }); - - describe('parsed JSON is not an object', () => { - before(() => { - instance = new HttpResponse({ - expected: { - bodySchema: '0' - } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it('should set an error message to result', () => { - const severities = instance.validation.body.results.map( - (result) => result.severity - ); - assert.include(severities, 'error'); - }); - - it('should set expected type to null', () => { - assert.equal(instance.validation.body.expectedType, null); - }); - }); - - describe('parsed JSON is not a valid JSON Schema', () => { - it('should set an error message to results'); - it('should set expected type to null'); - }); - }); - - describe('schema is not a parseable JSON', () => { - before(() => { - instance = new HttpResponse({ - expected: { - bodySchema: '{()}}' - } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it('should set error messages to results', () => { - const severities = instance.validation.body.results.map( - (result) => result.severity - ); - assert.include(severities, 'error'); - }); - - it('should set expceted type to null', () => { - assert.equal(instance.validation.body.expectedType, null); - }); - }); - }); - - describe('JSON Schema for expected body is not provided', () => { - const jsonContentTypes = [ - 'application/json', - 'application/json; charset=utf-8', - 'application/hal+json' - ]; - - jsonContentTypes.forEach((contentType) => { - describe(`expected headers have content-type '${contentType}'`, () => { - describe('expected body is a parseable JSON', () => { - before(() => { - instance = new HttpResponse({ - expected: { - headers: { - 'content-type': contentType - }, - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it(`should set expected type to ${contentType}`, () => { - assert.equal( - instance.validation.body.expectedType, - contentType - ); - }); - - it('should set no error message to result', () => { - assert.equal(instance.validation.body.results.length, 0); - }); - }); - - describe('expected body is not a parseable JSON', () => { - before(() => { - instance = new HttpResponse({ - expected: { - headers: { - 'content-type': contentType - }, - body: '{"creative?": false, \'creativ\': true }' - } - }); - - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it('should set an severity "error" item to results', () => { - const severities = instance.validation.body.results.map( - (result) => result.severity - ); - assert.include(severities, 'error'); - }); - - it('should set expected type to null', () => { - assert.equal(instance.validation.body.expectedType, null); - }); - - it('should set a descriptive message to results', () => { - const messages = instance.validation.body.results.map( - (result) => result.message - ); - assert.include(messages[0], 'is not a parseable JSON'); - }); - - it('should add error message with lint result', () => { - const expected = `Can't validate. Expected body 'Content-Type' is '${contentType}' but body is not a parseable JSON: -Unexpected token '\\'' at 1:22 -{"creative?": false, 'creativ': true } - ^`; - - const messages = instance.validation.body.results.map( - (result) => result.message - ); - assert.equal(messages[0], expected); - }); - }); - }); - }); - - describe('expected headers have not content-type application/json', () => { - describe('expected body is a parseable JSON', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it('should set expected type to application/json', () => { - assert.equal( - instance.validation.body.expectedType, - 'application/json' - ); - }); - }); - - describe('expected body is not a parseable JSON', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{Boo{Boo' - } - }); - instance.validation = {}; - instance.validation.body = {}; - instance.setBodyExpectedType(); - }); - - it('should set expected body to text/plain', () => { - assert.equal( - instance.validation.body.expectedType, - 'text/plain' - ); - }); - }); - }); - }); - }); - - describe('#setBodyValidator()', () => { - describe('when there is an error prior its execution', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = { - realType: null, - expectedType: null - }; - instance.validation.body.results = [ - { - message: "I can't even", - severity: 'error' - } - ]; - instance.setBodyValidator(); - }); - - it('should not set any validator', () => { - assert.equal(instance.validation.body.validator, null); - }); - - it('it should not add any error to results', () => { - const { results } = instance.validation.body; - assert.equal(results.length, 1); - }); - }); - - describe('real or expected type is null', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = { - realType: null, - expectedType: null - }; - instance.setBodyValidator(); - }); - - it('should not set any validator', () => { - assert.equal(instance.validation.body.validator, null); - }); - - it('should set unknown validator error message to results', () => { - const severities = instance.validation.body.results.map( - (result) => result.severity - ); - assert.include(severities, 'error'); - }); - }); - - const jsonContentTypes = [ - 'application/json', - 'application/json; charset=utf-8', - 'application/hal+json' - ]; - - jsonContentTypes.forEach((realType) => { - describe(`real is ${realType}`, () => { - jsonContentTypes.forEach((expectedType) => { - describe(`expected is ${expectedType}`, () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = { - realType, - expectedType - }; - instance.setBodyValidator(); - }); - - it('should set JsonExample validator', () => { - assert.equal( - instance.validation.body.validator, - 'JsonExample' - ); - - it('should set no error message', () => { - assert.equal(instance.validation.body.results.length, 0); - }); - }); - }); - - describe('expected is application/schema+json', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = { - realType, - expectedType: 'application/schema+json' - }; - instance.setBodyValidator(); - }); - - it('should set JsonSchema', () => { - assert.equal( - instance.validation.body.validator, - 'JsonSchema' - ); - }); - - it('should set no error message', () => { - assert.equal(instance.validation.body.results.length, 0); - }); - }); - }); - - describe('expected is text/plain', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = { - expectedType: 'text/plain' - }; - instance.setBodyValidator(); - }); - - it('should set no validator for combination error message', () => { - const severities = instance.validation.body.results.map( - (result) => result.severity - ); - assert.include(severities, 'error'); - }); - - it('should not set any validator', () => { - assert.equal(instance.validation.body.validator, null); - }); - }); - }); - - describe('real is text/plain', () => { - describe('expected is text/plain', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = { - realType: 'text/plain', - expectedType: 'text/plain' - }; - instance.setBodyValidator(); - }); - - it('should set TextDiff validator', () => { - assert.equal(instance.validation.body.validator, 'TextDiff'); - }); - - it('should set no error message', () => { - assert.equal(instance.validation.body.results.length, 0); - }); - }); - - describe('expected is not text/plain', () => { - before(() => { - instance = new HttpResponse({ - expected: { - body: '{}' - } - }); - instance.validation = {}; - instance.validation.body = { - realType: 'text/plain', - expectedType: 'application/json' - }; - instance.setBodyValidator(); - }); - - it('should not set any validator', () => { - assert.equal(instance.validation.body.validator, null); - }); - - it('should set no validator for combination errror message', () => { - const severities = instance.validation.body.results.map( - (result) => result.severity - ); - assert.include(severities, 'error'); - }); - }); - }); - }); - - describe('#runBodyValidator', () => { - describe('if JsonExample validator', () => { - before(() => { - instance = new HttpResponse(response); - instance.body = fixtures.sampleJsonSimpleKeyMissing; - instance.expected = { - body: fixtures.sampleJson - }; - - instance.validation = {}; - instance.validation.body = { - validator: 'JsonExample' - }; - instance.runBodyValidator(); - }); - - it('should set rawData property', () => { - assert.isDefined(instance.validation.body.rawData); - }); - - it('rawData should not be null', () => { - assert.isNotNull(instance.validation.body.rawData); - }); - }); - - describe('when JsonSchema validator', () => { - before(() => { - instance = new HttpResponse(response); - instance.body = fixtures.sampleJsonSimpleKeyMissing; - instance.expected = { - bodySchema: fixtures.sampleJsonSchema - }; - - instance.validation = {}; - instance.validation.body = { - validator: 'JsonSchema' - }; - instance.runBodyValidator(); - }); - - it('should set rawData property', () => { - assert.isDefined(instance.validation.body.rawData); - }); - - it('rawData should not be null', () => { - assert.isNotNull(instance.validation.body.rawData); - }); - }); - - describe('when TextDiff validator', () => { - before(() => { - instance = new HttpResponse(response); - instance.body = fixtures.sampleTextLineDiffers; - instance.expected = { - body: fixtures.sampleText - }; - - instance.validation = {}; - instance.validation.body = { - validator: 'TextDiff' - }; - instance.runBodyValidator(); - }); - - it('should set rawData property', () => { - assert.isDefined(instance.validation.body.rawData); - }); - - it('rawData should not be null', () => { - assert.isNotNull(instance.validation.body.rawData); - }); - }); - - describe('when no validator available', () => { - before(() => { - instance = new HttpResponse(response); - instance.body = fixtures.sampleJsonSimpleKeyMissing; - instance.expected = { - body: fixtures.sampleJson - }; - - instance.validation = {}; - instance.validation.body = { - validator: null - }; - instance.runBodyValidator(); - }); - - it('should let rawData null', () => { - assert.isNull(instance.validation.body.rawData); - }); - }); - - describe('when a validator throws an error', () => { - before(() => { - instance = new HttpResponse(response); - instance.body = '{}'; - instance.expected = { - bodySchema: INVALID_SCHEMA - }; - instance.validation = {}; - instance.validation.body = { - validator: 'JsonSchema' - }; - }); - - it('should not throw an error', () => { - const fn = () => instance.runBodyValidator(); - assert.doesNotThrow(fn); - }); - - it('should add thrown error to results as error', () => { - instance.runBodyValidator(); - const messages = instance.validation.body.results.map( - (result) => result.message - ); - assert.include( - messages, - 'JSON schema is not valid draft v4! Data does not match any schemas from "anyOf" at path "/properties/foo/type"' - ); - }); - }); - }); - - describe('#runBodyValidator()', () => { - before(() => { - instance = new HttpResponse(response); - instance.body = fixtures.sampleTextLineDiffers; - instance.expected = { - body: fixtures.sampleText - }; - - instance.validation = {}; - instance.validation.body = {}; - - instance.validation.body.rawData = - '@@ -1,5 +1,5 @@\n text\n-1\n+2\n'; - instance.validation.body.validator = 'TextDiff'; - }); - - describe('any previously set results', () => { - before(() => { - instance.validation.body.results = ['booboo']; - instance.runBodyValidator(); - }); - - it('should not overwrite existing results', () => { - assert.include(instance.validation.body.results, 'booboo'); - }); - - it('should set results to an array', () => { - assert.isArray(instance.validation.body.results); - }); - }); - - describe('no previous results', () => { - before(() => { - instance.validation.body.results = []; - instance.runBodyValidator(); - }); - - it('should set results to an array', () => { - assert.isArray(instance.validation.body.results); - }); - - it('should have 1 result', () => { - assert.equal(instance.validation.body.results.length, 1); - }); - }); - - describe('no validator given', () => { - before(() => { - instance.validation.body.validator = null; - }); - - it('should not throw', () => { - const fn = () => { - instance.runBodyValidator(); - }; - assert.doesNotThrow(fn); - }); - }); - }); - - // Status code validation - describe('#validateStatusCode', () => { - // instance = {} - - before(() => { - response = { - statusCode: 200, - expected: { - statusCode: 200 - } - }; - - instance = new HttpResponse(response); - instance.validation = {}; - - instance.validateStatusCode(); - }); - - const fields = [ - 'realType', - 'expectedType', - 'validator', - 'rawData', - 'results' - ]; - - fields.forEach((field) => { - it(`should set '${field}' property for the component`, () => { - assert.isDefined(instance.validation.statusCode[field]); - }); - }); - - describe('expceted matches real', () => { - it('should set no errors to results', () => { - assert.equal(instance.validation.statusCode.results.length, 0); - }); - }); - - describe('expected does not match real', () => { - before(() => { - response = { - statusCode: 200, - expected: { - statusCode: 201 - } - }; - - instance = new HttpResponse(response); - instance.validation = {}; - - instance.validate(); - }); - - it('should set error message to results', () => { - assert.equal(instance.validation.statusCode.results.length, 1); - }); - - it('should return false boolean result', () => { - assert.isFalse(instance.isValid()); - }); - - it('should set beutiful error message', () => { - assert.equal( - instance.validation.statusCode.results[0].message, - "Status code is '200' instead of '201'" - ); - }); - }); - }); - - describe('#isJsonContentType', () => { - const jsonContentTypes = [ - 'application/json', - 'application/json; charset=utf-8', - 'application/hal+json', - 'application/vnd.something.internal.v1+json; charset=utf-8' - ]; - - const nonJsonContentTypes = [ - 'application/xml', - 'text/plain', - 'text/html', - 'application/xhtml+xml', - 'application/xml;q=0.9', - null, - undefined - ]; - - before(() => { - instance = new HttpResponse(response); - }); - - jsonContentTypes.forEach((contentType) => { - describe(`when content type is '${contentType}'`, () => { - it('should return true', () => { - assert.isTrue(instance.isJsonContentType(contentType)); - }); - }); - }); - - nonJsonContentTypes.forEach((contentType) => { - describe(`when content type is '${contentType}'`, () => { - it('should return false', () => { - assert.isFalse(instance.isJsonContentType(contentType)); - }); - }); - }); - }); - }); - }); - }); - }); -}); diff --git a/test/unit/model/http-request-test.js b/test/unit/model/http-request-test.js deleted file mode 100644 index d6768a07..00000000 --- a/test/unit/model/http-request-test.js +++ /dev/null @@ -1,52 +0,0 @@ -const { assert } = require('chai'); -const amanda = require('amanda'); - -const { - HttpRequest, - ExpectedHttpRequest -} = require('../../../lib/model/http-request'); -const { sampleHttpRequestSchema } = require('../../fixtures'); - -const validate = (data, schema) => { - return amanda.validate(data, schema, (error) => error); -}; - -describe('HttpRequest', () => { - httpRequest = {}; - describe('when I create new instance', () => { - before(() => { - expectedHttpRequest = new ExpectedHttpRequest({ - method: '1', - uri: '2', - headers: '3', - body: '4', - headersSchema: { type: 'object' }, - bodySchema: { type: 'object' } - }); - httpRequest = new HttpRequest({ - method: '1', - uri: '2', - headers: '3', - body: '4', - expected: expectedHttpRequest - }); - }); - - it('should have correct structure', () => { - assert.isUndefined( - validate( - JSON.parse(JSON.stringify(httpRequest)), - sampleHttpRequestSchema - ) - ); - }); - - it('should have validate method', () => { - assert.isDefined(httpRequest.validate); - }); - - it('should have isValid method', () => { - assert.isDefined(httpRequest.isValid); - }); - }); -}); diff --git a/test/unit/model/http-response-test.js b/test/unit/model/http-response-test.js deleted file mode 100644 index a63bbac2..00000000 --- a/test/unit/model/http-response-test.js +++ /dev/null @@ -1,50 +0,0 @@ -const { assert } = require('chai'); -const amanda = require('amanda'); - -const { - HttpResponse, - ExpectedHttpResponse -} = require('../../../lib/model/http-response'); -const { sampleHttpResponseSchema } = require('../../fixtures'); - -const validate = (data, schema) => { - return amanda.validate(data, schema, (error) => error); -}; - -describe('HttpResponse', () => { - httpResponse = {}; - describe('when I create new instance', () => { - before(() => { - expectedHttpResponse = new ExpectedHttpResponse({ - statusCode: '1', - statusMessage: '2', - headers: '3', - body: '4', - headersSchema: { type: 'object' }, - bodySchema: { type: 'object' } - }); - httpResponse = new HttpResponse({ - statusCode: '1', - statusMessage: '2', - headers: '3', - body: '4', - expected: expectedHttpResponse - }); - }); - - it('should has correct structure', () => { - assert.isUndefined( - validate( - JSON.parse(JSON.stringify(httpResponse)), - sampleHttpResponseSchema - ) - ); - }); - it('should has validate method', () => { - assert.isDefined(httpResponse.validate); - }); - it('should has isValid method', () => { - assert.isDefined(httpResponse.isValid); - }); - }); -}); diff --git a/test/unit/support/amanda-to-gavel-shared.js b/test/unit/support/amanda-to-gavel-shared.js index 71fd3d25..1a233c18 100644 --- a/test/unit/support/amanda-to-gavel-shared.js +++ b/test/unit/support/amanda-to-gavel-shared.js @@ -1,3 +1,4 @@ +/* eslint-disable */ const validators = require('../../../lib/validators'); const fixtures = require('../../fixtures'); const jsonPointer = require('json-pointer'); @@ -44,7 +45,7 @@ exports.shouldBehaveLikeAmandaToGavel = (instance) => { assert.isObject(item); }); - const props = ['message', 'severity', 'pointer']; + const props = ['message', 'pointer']; props.forEach((key) => { it('should have "' + key + '"', () => { assert.include(Object.keys(item), key); diff --git a/lib/next/test/unit/units/normalize/normalizeHeaders.test.js b/test/unit/units/normalize/normalizeHeaders.test.js similarity index 95% rename from lib/next/test/unit/units/normalize/normalizeHeaders.test.js rename to test/unit/units/normalize/normalizeHeaders.test.js index eb4d9aea..0c90827a 100644 --- a/lib/next/test/unit/units/normalize/normalizeHeaders.test.js +++ b/test/unit/units/normalize/normalizeHeaders.test.js @@ -1,7 +1,7 @@ const { assert } = require('chai'); const { normalizeHeaders -} = require('../../../../units/normalize/normalizeHeaders'); +} = require('../../../../lib/units/normalize/normalizeHeaders'); describe('normalizeHeaders', () => { describe('when given nothing', () => { diff --git a/test/unit/units/normalize/normalizeMethod.test.js b/test/unit/units/normalize/normalizeMethod.test.js new file mode 100644 index 00000000..ea593fa2 --- /dev/null +++ b/test/unit/units/normalize/normalizeMethod.test.js @@ -0,0 +1,14 @@ +const { assert } = require('chai'); +const { + normalizeMethod +} = require('../../../../lib/units/normalize/normalizeMethod'); + +describe('normalizeMethod', () => { + it('removes trailing spaces', () => { + assert.equal(normalizeMethod(' POST '), 'POST'); + }); + + it('converts to uppercase', () => { + assert.equal(normalizeMethod('pUt'), 'PUT'); + }); +}); diff --git a/lib/next/test/unit/units/normalize/normalizeStatusCode.test.js b/test/unit/units/normalize/normalizeStatusCode.test.js similarity index 90% rename from lib/next/test/unit/units/normalize/normalizeStatusCode.test.js rename to test/unit/units/normalize/normalizeStatusCode.test.js index 6cac3908..b30edeb4 100644 --- a/lib/next/test/unit/units/normalize/normalizeStatusCode.test.js +++ b/test/unit/units/normalize/normalizeStatusCode.test.js @@ -1,7 +1,7 @@ const { assert } = require('chai'); const { normalizeStatusCode -} = require('../../../../units/normalize/normalizeStatusCode'); +} = require('../../../../lib/units/normalize/normalizeStatusCode'); describe('normalizeStatusCode', () => { describe('when given a string', () => { diff --git a/lib/next/test/unit/units/validateBody.test.js b/test/unit/units/validateBody.test.js similarity index 83% rename from lib/next/test/unit/units/validateBody.test.js rename to test/unit/units/validateBody.test.js index db466786..8ffc892c 100644 --- a/lib/next/test/unit/units/validateBody.test.js +++ b/test/unit/units/validateBody.test.js @@ -1,5 +1,5 @@ const { assert } = require('chai'); -const { validateBody } = require('../../../units/validateBody'); +const { validateBody } = require('../../../lib/units/validateBody'); describe('validateBody', () => { describe('when given unsupported body type', () => { @@ -21,13 +21,13 @@ describe('validateBody', () => { describe('when given supported body type', () => { describe('in a combination without related validator', () => { const result = validateBody( - { - headers: { 'content-type': 'application/json' }, - body: '{ "foo": "bar" }' - }, { headers: { 'content-type': 'text/plain' }, body: '' + }, + { + headers: { 'content-type': 'application/json' }, + body: '{ "foo": "bar" }' } ); @@ -45,16 +45,12 @@ describe('validateBody', () => { describe('produces validation error', () => { it('exactly one error', () => { - assert.lengthOf(result.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.results[0], 'severity', 'error'); + assert.lengthOf(result.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - result.results[0], + result.errors[0], 'message', `Can't validate real media type 'application/json' against expected media type 'text/plain'.` ); @@ -67,11 +63,11 @@ describe('validateBody', () => { describe('with matching body type', () => { const res = validateBody( { - body: '{ "foo": "bar" }', - headers: { 'content-type': 'application/json' } + body: '{ "foo": "bar" }' }, { - body: '{ "foo": "bar" }' + body: '{ "foo": "bar" }', + headers: { 'content-type': 'application/json' } } ); @@ -88,17 +84,19 @@ describe('validateBody', () => { }); it('has no errors', () => { - assert.lengthOf(res.results, 0); + assert.lengthOf(res.errors, 0); }); }); describe('with non-matching body type', () => { const res = validateBody( + { + body: '{ "foo": "bar" }' + }, { body: 'foo', headers: { 'content-type': 'application/json' } - }, - { body: '{ "foo": "bar" }' } + } ); it('has no validator', () => { @@ -114,13 +112,9 @@ describe('validateBody', () => { }); describe('produces content-type error', () => { - it('has "error" severity', () => { - assert.propertyVal(res.results[0], 'severity', 'error'); - }); - it('has explanatory message', () => { assert.match( - res.results[0].message, + res.errors[0].message, /^Can't validate: real body 'Content-Type' header is 'application\/json' but body is not a parseable JSON:/ ); }); @@ -131,14 +125,14 @@ describe('validateBody', () => { describe('application/hal+json', () => { describe('with matching body type', () => { const res = validateBody( + { + body: '{ "foo": "bar" }' + }, { body: '{ "foo": "bar" }', headers: { 'content-type': 'application/hal+json' } - }, - { - body: '{ "foo": "bar" }' } ); @@ -155,20 +149,20 @@ describe('validateBody', () => { }); it('has no errors', () => { - assert.lengthOf(res.results, 0); + assert.lengthOf(res.errors, 0); }); }); describe('with non-matching body type', () => { const res = validateBody( + { + body: 'text' + }, { body: 'text', headers: { 'content-type': 'application/hal+json' } - }, - { - body: 'text' } ); @@ -185,13 +179,9 @@ describe('validateBody', () => { }); describe('produces error', () => { - it('has "error" severity', () => { - assert.propertyVal(res.results[0], 'severity', 'error'); - }); - it('has explanatory message', () => { assert.match( - res.results[0].message, + res.errors[0].message, /^Can't validate: real body 'Content-Type' header is 'application\/hal\+json' but body is not a parseable JSON:/ ); }); @@ -203,7 +193,14 @@ describe('validateBody', () => { describe('without explicit "Content-Type" header', () => { describe('text/plain', () => { describe('with matching bodies', () => { - const res = validateBody({ body: 'foo' }, { body: 'foo' }); + const res = validateBody( + { + body: 'foo' + }, + { + body: 'foo' + } + ); it('has "TextDiff" validator', () => { assert.propertyVal(res, 'validator', 'TextDiff'); @@ -218,12 +215,19 @@ describe('validateBody', () => { }); it('has no errors', () => { - assert.lengthOf(res.results, 0); + assert.lengthOf(res.errors, 0); }); }); describe('with non-matching bodies', () => { - const res = validateBody({ body: 'foo ' }, { body: 'bar' }); + const res = validateBody( + { + body: 'bar' + }, + { + body: 'foo ' + } + ); it('has "TextDiff" validator', () => { assert.propertyVal(res, 'validator', 'TextDiff'); @@ -239,17 +243,13 @@ describe('validateBody', () => { describe('produces validation error', () => { it('exactly one error', () => { - assert.lengthOf(res.results, 1); - }); - - it('with "error" severity', () => { - assert.propertyVal(res.results[0], 'severity', 'error'); + assert.lengthOf(res.errors, 1); }); it('with explanatory message', () => { - assert.hasAnyKeys(res.results[0], 'message'); + assert.hasAnyKeys(res.errors[0], 'message'); assert.propertyVal( - res.results[0], + res.errors[0], 'message', 'Real and expected data does not match.' ); @@ -261,8 +261,12 @@ describe('validateBody', () => { describe('application/json', () => { describe('with matching bodies', () => { const res = validateBody( - { body: '{ "foo": "bar" }' }, - { body: '{ "foo": "bar" }' } + { + body: '{ "foo": "bar" }' + }, + { + body: '{ "foo": "bar" }' + } ); it('has "JsonExample" validator', () => { @@ -278,14 +282,18 @@ describe('validateBody', () => { }); it('has no errors', () => { - assert.lengthOf(res.results, 0); + assert.lengthOf(res.errors, 0); }); }); describe('with non-matching bodies', () => { const res = validateBody( - { body: '{ "foo": "bar" }' }, - { body: '{ "bar": null }' } + { + body: '{ "bar": null }' + }, + { + body: '{ "foo": "bar" }' + } ); it('has "JsonExample" validator', () => { @@ -302,16 +310,12 @@ describe('validateBody', () => { describe('produces validation errors', () => { it('exactly one error', () => { - assert.lengthOf(res.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(res.results[0], 'severity', 'error'); + assert.lengthOf(res.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - res.results[0], + res.errors[0], 'message', `At '/bar' Missing required property: bar` ); @@ -323,11 +327,13 @@ describe('validateBody', () => { describe('application/schema+json', () => { describe('with matching bodies', () => { const res = validateBody( - { body: '{ "foo": "bar" }' }, { bodySchema: { required: ['foo'] } + }, + { + body: '{ "foo": "bar" }' } ); @@ -344,17 +350,19 @@ describe('validateBody', () => { }); it('has no errors', () => { - assert.lengthOf(res.results, 0); + assert.lengthOf(res.errors, 0); }); }); describe('with non-matching bodies', () => { const res = validateBody( - { body: '{ "oneTwoThree": "bar" }' }, { bodySchema: { required: ['doe'] } + }, + { + body: '{ "oneTwoThree": "bar" }' } ); @@ -372,16 +380,12 @@ describe('validateBody', () => { describe('produces an error', () => { it('exactly one error', () => { - assert.lengthOf(res.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(res.results[0], 'severity', 'error'); + assert.lengthOf(res.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - res.results[0], + res.errors[0], 'message', `At '/doe' Missing required property: doe` ); diff --git a/lib/next/test/unit/units/validateBody/getBodySchemaType.test.js b/test/unit/units/validateBody/getBodySchemaType.test.js similarity index 95% rename from lib/next/test/unit/units/validateBody/getBodySchemaType.test.js rename to test/unit/units/validateBody/getBodySchemaType.test.js index adc102e2..0c20f862 100644 --- a/lib/next/test/unit/units/validateBody/getBodySchemaType.test.js +++ b/test/unit/units/validateBody/getBodySchemaType.test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); const mediaTyper = require('media-typer'); -const { getBodySchemaType } = require('../../../../units/validateBody'); +const { getBodySchemaType } = require('../../../../lib/units/validateBody'); describe('getBodySchemaType', () => { describe('when given non-string schema', () => { diff --git a/lib/next/test/unit/units/validateBody/getBodyType.test.js b/test/unit/units/validateBody/getBodyType.test.js similarity index 97% rename from lib/next/test/unit/units/validateBody/getBodyType.test.js rename to test/unit/units/validateBody/getBodyType.test.js index d9ba8dd3..d6f065a8 100644 --- a/lib/next/test/unit/units/validateBody/getBodyType.test.js +++ b/test/unit/units/validateBody/getBodyType.test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); const mediaTyper = require('media-typer'); -const { getBodyType } = require('../../../../units/validateBody'); +const { getBodyType } = require('../../../../lib/units/validateBody'); const jsonTypes = ['application/json', 'application/schema+json']; const nonJsonTypes = ['text/plain']; diff --git a/lib/next/test/unit/units/validateBody/getBodyValidator.test.js b/test/unit/units/validateBody/getBodyValidator.test.js similarity index 96% rename from lib/next/test/unit/units/validateBody/getBodyValidator.test.js rename to test/unit/units/validateBody/getBodyValidator.test.js index 16bf3d2e..8406eb90 100644 --- a/lib/next/test/unit/units/validateBody/getBodyValidator.test.js +++ b/test/unit/units/validateBody/getBodyValidator.test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); const mediaTyper = require('media-typer'); -const { getBodyValidator } = require('../../../../units/validateBody'); +const { getBodyValidator } = require('../../../../lib/units/validateBody'); const getMediaTypes = (real, expected) => { return [real, expected].map(mediaTyper.parse); diff --git a/lib/next/test/unit/units/validateBody/isJson.test.js b/test/unit/units/validateBody/isJson.test.js similarity index 91% rename from lib/next/test/unit/units/validateBody/isJson.test.js rename to test/unit/units/validateBody/isJson.test.js index 54ec2008..5c01f7e5 100644 --- a/lib/next/test/unit/units/validateBody/isJson.test.js +++ b/test/unit/units/validateBody/isJson.test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); const mediaTyper = require('media-typer'); -const { isJson } = require('../../../../units/validateBody'); +const { isJson } = require('../../../../lib/units/validateBody'); describe('isJson', () => { describe('returns true', () => { diff --git a/lib/next/test/unit/units/validateBody/isJsonContentType.test.js b/test/unit/units/validateBody/isJsonContentType.test.js similarity index 90% rename from lib/next/test/unit/units/validateBody/isJsonContentType.test.js rename to test/unit/units/validateBody/isJsonContentType.test.js index 10d7f0f5..f06e4129 100644 --- a/lib/next/test/unit/units/validateBody/isJsonContentType.test.js +++ b/test/unit/units/validateBody/isJsonContentType.test.js @@ -1,5 +1,5 @@ const { assert } = require('chai'); -const { isJsonContentType } = require('../../../../units/validateBody'); +const { isJsonContentType } = require('../../../../lib/units/validateBody'); describe('isJsonContentType', () => { describe('returns true', () => { diff --git a/lib/next/test/unit/units/validateBody/isJsonSchema.test.js b/test/unit/units/validateBody/isJsonSchema.test.js similarity index 89% rename from lib/next/test/unit/units/validateBody/isJsonSchema.test.js rename to test/unit/units/validateBody/isJsonSchema.test.js index 09f8ff86..bfccac8c 100644 --- a/lib/next/test/unit/units/validateBody/isJsonSchema.test.js +++ b/test/unit/units/validateBody/isJsonSchema.test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); const mediaTyper = require('media-typer'); -const { isJsonSchema } = require('../../../../units/validateBody'); +const { isJsonSchema } = require('../../../../lib/units/validateBody'); describe('isJsonSchema', () => { describe('returns true', () => { diff --git a/lib/next/test/unit/units/validateHeaders.test.js b/test/unit/units/validateHeaders.test.js similarity index 85% rename from lib/next/test/unit/units/validateHeaders.test.js rename to test/unit/units/validateHeaders.test.js index 530a6884..3477feff 100644 --- a/lib/next/test/unit/units/validateHeaders.test.js +++ b/test/unit/units/validateHeaders.test.js @@ -1,5 +1,5 @@ const { assert } = require('chai'); -const { validateHeaders } = require('../../../units/validateHeaders'); +const { validateHeaders } = require('../../../lib/units/validateHeaders'); describe('validateHeaders', () => { describe('given matching headers', () => { @@ -39,7 +39,7 @@ describe('validateHeaders', () => { }); it('has no errors', () => { - assert.deepPropertyVal(res, 'results', []); + assert.deepPropertyVal(res, 'errors', []); }); }); @@ -47,13 +47,13 @@ describe('validateHeaders', () => { const res = validateHeaders( { headers: { + 'accept-language': 'en-US,us', + 'content-type': 'application/json', connection: 'keep-alive' } }, { headers: { - 'accept-language': 'en-US,us', - 'content-type': 'application/json', connection: 'keep-alive' } } @@ -83,19 +83,15 @@ describe('validateHeaders', () => { const missingHeaders = ['accept-language', 'content-type']; it('for two missing headers', () => { - assert.lengthOf(res.results, missingHeaders.length); + assert.lengthOf(res.errors, missingHeaders.length); }); describe('for each missing header', () => { missingHeaders.forEach((headerName, index) => { describe(headerName, () => { - it('has "error" severity', () => { - assert.propertyVal(res.results[index], 'severity', 'error'); - }); - it('has pointer to header name', () => { assert.propertyVal( - res.results[index], + res.errors[index], 'pointer', `/${headerName}` ); @@ -103,7 +99,7 @@ describe('validateHeaders', () => { it('has explanatory message', () => { assert.propertyVal( - res.results[index], + res.errors[index], 'message', `At '/${headerName}' Missing required property: ${headerName}` ); @@ -117,10 +113,10 @@ describe('validateHeaders', () => { describe('given non-json headers', () => { const res = validateHeaders( { - headers: 'foo' + headers: 'bar' }, { - headers: 'bar' + headers: 'foo' } ); @@ -138,16 +134,12 @@ describe('validateHeaders', () => { describe('produces an error', () => { it('has one error', () => { - assert.lengthOf(res.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(res.results[0], 'severity', 'error'); + assert.lengthOf(res.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - res.results[0], + res.errors[0], 'message', `No validator found for real data media type "null" diff --git a/test/unit/units/validateMethod.test.js b/test/unit/units/validateMethod.test.js new file mode 100644 index 00000000..3afef845 --- /dev/null +++ b/test/unit/units/validateMethod.test.js @@ -0,0 +1,117 @@ +const { assert } = require('chai'); +const { validateMethod } = require('../../../lib/units/validateMethod'); + +describe('validateMethod', () => { + describe('given matching methods', () => { + const result = validateMethod( + { + method: 'GET' + }, + { + method: 'GET' + } + ); + + it('has "isValid" as "true"', () => { + assert.propertyVal(result, 'isValid', true); + }); + + it('has "null" validator', () => { + assert.isNull(result.validator); + }); + + it('has "text/vnd.apiary.method" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.method'); + }); + + it('has "text/vnd.apiary.method" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.method'); + }); + + it('has no errors', () => { + assert.lengthOf(result.errors, 0); + }); + }); + + describe('given non-matching methods', () => { + const result = validateMethod( + { + method: 'POST' + }, + { + method: 'GET' + } + ); + + it('returns "isValid" as "false"', () => { + assert.propertyVal(result, 'isValid', false); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.method" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.method'); + }); + + it('has "text/vnd.apiary.method" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.method'); + }); + + describe('produces an error', () => { + it('exactly one error', () => { + assert.lengthOf(result.errors, 1); + }); + + it('has explanatory message', () => { + assert.propertyVal( + result.errors[0], + 'message', + 'Expected "method" field to equal "POST", but got "GET".' + ); + }); + }); + }); + + describe('given expected, but no real method', () => { + const result = validateMethod( + { + method: 'PATCH' + }, + { + method: '' + } + ); + + it('returns "isValid" as "false"', () => { + assert.propertyVal(result, 'isValid', false); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.method" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.method'); + }); + + it('has "text/vnd.apiary.method" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.method'); + }); + + describe('produces an error', () => { + it('exactly one error', () => { + assert.lengthOf(result.errors, 1); + }); + + it('has explanatory message', () => { + assert.propertyVal( + result.errors[0], + 'message', + 'Expected "method" field to equal "PATCH", but got "".' + ); + }); + }); + }); +}); diff --git a/lib/next/test/unit/units/validateStatusCode.test.js b/test/unit/units/validateStatusCode.test.js similarity index 83% rename from lib/next/test/unit/units/validateStatusCode.test.js rename to test/unit/units/validateStatusCode.test.js index d44dfe08..2060e958 100644 --- a/lib/next/test/unit/units/validateStatusCode.test.js +++ b/test/unit/units/validateStatusCode.test.js @@ -1,5 +1,5 @@ const { assert } = require('chai'); -const { validateStatusCode } = require('../../../units/validateStatusCode'); +const { validateStatusCode } = require('../../../lib/units/validateStatusCode'); describe('validateStatusCode', () => { describe('given matching status codes', () => { @@ -25,17 +25,17 @@ describe('validateStatusCode', () => { }); it('has no errors', () => { - assert.deepPropertyVal(result, 'results', []); + assert.deepPropertyVal(result, 'errors', []); }); }); describe('given non-matching status codes', () => { const result = validateStatusCode( { - statusCode: '200' + statusCode: '400' }, { - statusCode: '400' + statusCode: '200' } ); @@ -53,16 +53,12 @@ describe('validateStatusCode', () => { describe('produces error', () => { it('exactly one error', () => { - assert.lengthOf(result.results, 1); - }); - - it('has "error" severity', () => { - assert.propertyVal(result.results[0], 'severity', 'error'); + assert.lengthOf(result.errors, 1); }); it('has explanatory message', () => { assert.propertyVal( - result.results[0], + result.errors[0], 'message', `Status code is '200' instead of '400'` ); diff --git a/test/unit/units/validateURI.test.js b/test/unit/units/validateURI.test.js new file mode 100644 index 00000000..aaeb880b --- /dev/null +++ b/test/unit/units/validateURI.test.js @@ -0,0 +1,302 @@ +const { assert } = require('chai'); +const { validateURI } = require('../../../lib/units/validateURI'); + +describe('validateURI', () => { + describe('given matching URI', () => { + describe('without parameters', () => { + const result = validateURI( + { + uri: '/dashboard' + }, + { + uri: '/dashboard' + } + ); + + it('marks field as valid', () => { + assert.propertyVal(result, 'isValid', true); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + it('has no errors', () => { + assert.lengthOf(result.errors, 0); + }); + }); + + describe('with parameters', () => { + describe('with exact parameters', () => { + const result = validateURI( + { + uri: '/animals?type=cats' + }, + { + uri: '/animals?type=cats' + } + ); + + it('marks field as valid', () => { + assert.propertyVal(result, 'isValid', true); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + it('has no errors', () => { + assert.lengthOf(result.errors, 0); + }); + }); + + describe('with exact parameters in different order', () => { + // Order of different query params must not matter + const result = validateURI( + { + uri: '/animals?type=cats&size=10' + }, + { + uri: '/animals?size=10&type=cats' + } + ); + + it('mark field as valid', () => { + assert.propertyVal(result, 'isValid', true); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + it('has no errors', () => { + assert.lengthOf(result.errors, 0); + }); + }); + + describe('with multiple parameters in exact order', () => { + // Order of the multiple same query params matters + const result = validateURI( + { + uri: '/animals?type=cats&type=dogs' + }, + { + uri: '/animals?type=cats&type=dogs' + } + ); + + it('marks field as valid', () => { + assert.propertyVal(result, 'isValid', true); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + it('has no errors', () => { + assert.lengthOf(result.errors, 0); + }); + }); + }); + }); + + describe('given non-matching URI', () => { + describe('without parameters', () => { + const result = validateURI( + { + uri: '/dashboard' + }, + { + uri: '/profile' + } + ); + + it('marks field as invalid', () => { + assert.propertyVal(result, 'isValid', false); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + describe('produces an error', () => { + it('exactly one error', () => { + assert.lengthOf(result.errors, 1); + }); + + it('has explanatory message', () => { + assert.propertyVal( + result.errors[0], + 'message', + 'Expected "uri" field to equal "/dashboard", but got: "/profile".' + ); + }); + }); + }); + + describe('with parameters', () => { + describe('with missing parameter', () => { + const result = validateURI( + { + uri: '/account?id=123' + }, + { + uri: '/account' + } + ); + + it('marks field is invalid', () => { + assert.propertyVal(result, 'isValid', false); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + describe('produces an error', () => { + it('exactly one error', () => { + assert.lengthOf(result.errors, 1); + }); + + it('has explanatory message', () => { + assert.propertyVal( + result.errors[0], + 'message', + 'Expected "uri" field to equal "/account?id=123", but got: "/account".' + ); + }); + }); + }); + + describe('with the same parameter in different case', () => { + const result = validateURI( + { + uri: '/account?name=user' + }, + { + uri: '/account?nAmE=usEr' + } + ); + + it('marks field is invalid', () => { + assert.propertyVal(result, 'isValid', false); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + describe('produces an error', () => { + it('exactly one error', () => { + assert.lengthOf(result.errors, 1); + }); + + it('has explanatory message', () => { + assert.propertyVal( + result.errors[0], + 'message', + 'Expected "uri" field to equal "/account?name=user", but got: "/account?nAmE=usEr".' + ); + }); + }); + }); + + describe('with multiple parameters in wrong order', () => { + const result = validateURI( + { + uri: '/zoo?type=cats&type=dogs' + }, + { + uri: '/zoo?type=dogs&type=cats' + } + ); + + it('marks field is invalid', () => { + assert.propertyVal(result, 'isValid', false); + }); + + it('has "null" validator', () => { + assert.propertyVal(result, 'validator', null); + }); + + it('has "text/vnd.apiary.uri" real type', () => { + assert.propertyVal(result, 'realType', 'text/vnd.apiary.uri'); + }); + + it('has "text/vnd.apiary.uri" expected type', () => { + assert.propertyVal(result, 'expectedType', 'text/vnd.apiary.uri'); + }); + + describe('produces an error', () => { + it('exactly one error', () => { + assert.lengthOf(result.errors, 1); + }); + + it('has explanatory message', () => { + assert.propertyVal( + result.errors[0], + 'message', + 'Expected "uri" field to equal "/zoo?type=cats&type=dogs", but got: "/zoo?type=dogs&type=cats".' + ); + }); + }); + }); + }); + }); +}); diff --git a/lib/next/test/unit/utils/evolve.test.js b/test/unit/utils/evolve.test.js similarity index 98% rename from lib/next/test/unit/utils/evolve.test.js rename to test/unit/utils/evolve.test.js index 9711be3a..3cc68b01 100644 --- a/lib/next/test/unit/utils/evolve.test.js +++ b/test/unit/utils/evolve.test.js @@ -1,5 +1,5 @@ const { assert } = require('chai'); -const evolve = require('../../../utils/evolve'); +const evolve = require('../../../lib/utils/evolve'); const multiply = (a) => (n) => n * a; const unexpectedTypes = [ diff --git a/test/unit/utils/get-type-test.js b/test/unit/utils/get-type.test.js similarity index 94% rename from test/unit/utils/get-type-test.js rename to test/unit/utils/get-type.test.js index 5acbf3ed..47351ab0 100644 --- a/test/unit/utils/get-type-test.js +++ b/test/unit/utils/get-type.test.js @@ -12,7 +12,7 @@ describe('getType', () => { }); it('when given Function', () => { - func = () => 'foo'; + const func = () => 'foo'; assert.equal(getType(func), 'function'); }); @@ -43,7 +43,7 @@ describe('getType', () => { }); it('returns type as-is for unknown types', () => { - customInstance = Buffer.alloc(1); + const customInstance = Buffer.alloc(1); assert.equal(getType(customInstance), 'object'); }); }); diff --git a/test/unit/utils/otherwise.test.js b/test/unit/utils/otherwise.test.js new file mode 100644 index 00000000..6a40265b --- /dev/null +++ b/test/unit/utils/otherwise.test.js @@ -0,0 +1,18 @@ +const { assert } = require('chai'); +const otherwise = require('../../../lib/utils/otherwise'); + +describe('otherwise', () => { + describe('given existing value', () => { + it('returns the given value', () => { + const value = otherwise('')('foo'); + assert.equal(value, 'foo'); + }); + }); + + describe('given non-exiting value', () => { + it('returns fallback instead', () => { + const value = otherwise('')(null); + assert.equal(value, ''); + }); + }); +}); diff --git a/test/unit/utils/schema-v4-generator-test.js b/test/unit/utils/schema-v4-generator.test.js similarity index 96% rename from test/unit/utils/schema-v4-generator-test.js rename to test/unit/utils/schema-v4-generator.test.js index 3b253350..ef36e892 100644 --- a/test/unit/utils/schema-v4-generator-test.js +++ b/test/unit/utils/schema-v4-generator.test.js @@ -13,7 +13,7 @@ const { } = require('../../../lib/utils/schema-v4-generator'); describe('SchemaV4Generator', () => { - sg = {}; + let sg = {}; before(() => { sg = new SchemaV4Generator({ json: sampleJson }); }); @@ -44,7 +44,7 @@ describe('SchemaV4Generator', () => { }); describe('generate', () => { - schema = undefined; + let schema; before(() => { sg.properties.keysStrict = true; sg.properties.valuesStrict = true; @@ -66,7 +66,7 @@ describe('SchemaV4Generator', () => { it('which is valid json schema for amanda (doesNotThrow)', () => { assert.doesNotThrow(() => - amanda.validate(JSON.parse(sampleJson), sg.schema, (error) => {}) + amanda.validate(JSON.parse(sampleJson), sg.schema, () => {}) ); }); @@ -191,7 +191,7 @@ describe('SchemaV4Generator', () => { describe('generate strict schema only for some caseless keys', () => { before(() => { - expected = { + const expected = { 'content-type': 'application/json', location: '/here' }; @@ -206,7 +206,7 @@ describe('SchemaV4Generator', () => { describe('when missing key and its value completely', () => { it('should fail the validation against generated schema', () => { - realMissingKey = { + const realMissingKey = { 'content-type': 'application/json' }; assert.notOk(tv4.validateResult(realMissingKey, sg.schema).valid); @@ -216,7 +216,7 @@ describe('SchemaV4Generator', () => { describe('when different value of strict', () => { it('should fail the validation against generated schema', () => { - realDifferentValueOfStrict = { + const realDifferentValueOfStrict = { 'content-type': 'application/hal+json', location: '/here' }; @@ -228,7 +228,7 @@ describe('SchemaV4Generator', () => { describe('when different value of non strict', () => { it('should pass the validation against generated schema', () => { - realDifferentValueOfNonStrict = { + const realDifferentValueOfNonStrict = { 'content-type': 'application/json', location: '/there' }; diff --git a/test/unit/utils/tv4-to-headers-message-test.js b/test/unit/utils/tv4-to-headers-message.test.js similarity index 76% rename from test/unit/utils/tv4-to-headers-message-test.js rename to test/unit/utils/tv4-to-headers-message.test.js index 60e1ee55..4b49307b 100644 --- a/test/unit/utils/tv4-to-headers-message-test.js +++ b/test/unit/utils/tv4-to-headers-message.test.js @@ -4,20 +4,20 @@ const tv4ToHeadersMessage = require('../../../lib/utils/tv4-to-headers-message') const fixtures = require('../../fixtures'); describe('tv4ToHeadersMessages()', () => { - expectedHeaders = fixtures.sampleHeaders; + const expectedHeaders = fixtures.sampleHeaders; describe('when message for missing header', () => { it('should return message with right text', () => { - tv4Message = "At '/header2' Missing required property: header2"; - message = tv4ToHeadersMessage(tv4Message, expectedHeaders); + const tv4Message = "At '/header2' Missing required property: header2"; + const message = tv4ToHeadersMessage(tv4Message, expectedHeaders); assert.equal(message, "Header 'header2' is missing"); }); }); describe('when message for different value', () => { it('should return message with right text', () => { - tv4Message = + const tv4Message = 'At \'/content-type\' No enum match for: "application/fancy-madiatype"'; - message = tv4ToHeadersMessage(tv4Message, expectedHeaders); + const message = tv4ToHeadersMessage(tv4Message, expectedHeaders); assert.equal( message, "Header 'content-type' has value 'application/fancy-madiatype' instead of 'application/json'" diff --git a/test/unit/validate-test.js b/test/unit/validate-test.js deleted file mode 100644 index ae819537..00000000 --- a/test/unit/validate-test.js +++ /dev/null @@ -1,273 +0,0 @@ -const { assert } = require('chai'); -const clone = require('clone'); -const { validate, isValid, isValidatable } = require('../../lib/gavel'); - -describe('Gavel proxies to functions with callbacks', () => { - // Examples from README.md - const baseHttpMessage = { - statusCode: '200', - headers: { - 'content-type': 'application/json', - date: 'Wed, 03 Jul 2013 13:30:53 GMT', - server: 'gunicorn/0.17.4', - 'content-length': '30', - connection: 'keep-alive' - }, - body: '{\n "origin": "94.113.241.2"\n}' - }; - - const cloneHttpMessage = clone(baseHttpMessage, false); - - const differentHttpMessage = { - statusCode: '404', - headers: { - 'content-type': 'application/vnd.gavel.vX+json', // different from baseHttpMessage - date: 'Wed, 03 Jul 2014 13:30:53 GMT', - server: 'Apache/2.42', // different from baseHttpMessage - connection: 'close' // different from baseHttpMessage - // missing key "content-length" - }, - body: '{"r2":"d2"}' - }; - - const similarHttpMessage = { - statusCode: '200', - headers: { - 'CONTENT-TYPE': 'application/json', - DATE: 'Mon, 01 Jan 2011 01:01:01 GMT', // shall ignore DATE header differences - SERVER: 'gunicorn/0.17.4', - 'CONTENT-LENGTH': '30', - CONNECTION: 'keep-alive' - }, - body: '{"origin":"1.2.3.4"}' - }; - - describe('isValidatable', () => { - describe('when I provide data from README (good objects)', () => { - ['response', 'request'].forEach((variant) => { - describe(`for two cloned ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - isValidatable( - cloneHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should be ok as a result of isValidatable', () => - assert.isTrue(results)); - }); - - describe(`for similar ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - isValidatable( - similarHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should be ok as a result of isValidatable', () => - assert.isTrue(results)); - }); - - describe(`for different ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - isValidatable( - differentHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should be ok as a result of isValidatable', () => - assert.isTrue(results)); - }); - }); - }); - }); - - describe('isValid', () => { - describe('when I provide data', () => { - ['response', 'request'].forEach((variant) => { - describe(`for two cloned ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - isValid( - cloneHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should be true as a result of isValid', () => - assert.isTrue(results)); - }); - - describe(`for similar ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - isValid( - similarHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should be ok as a result of isValid', () => - assert.isTrue(results)); - }); - - describe(`for different ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - isValid( - differentHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should be false as a result of isValid', () => - assert.isFalse(results)); - }); - }); - }); - }); - - describe('validate', () => { - describe('when I provide data', () => { - ['response', 'request'].forEach((variant) => { - describe(`for two cloned ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - validate( - cloneHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should results be an object', () => assert.isObject(results)); - }); - - describe(`for similar ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - validate( - similarHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should results be an object', () => assert.isObject(results)); - }); - - describe(`for different ${variant}s`, () => { - let results = null; - let error = null; - - before((done) => { - validate( - differentHttpMessage, - baseHttpMessage, - variant, - (err, result) => { - error = err; - results = result; - done(); - } - ); - }); - - it('should call the callback without any errors', () => - assert.isNull(error)); - it('should results be an object', () => assert.isObject(results)); - it('should results contain 2 different headers messages (missing content-length, different content-type)', () => { - assert.isObject(results); - assert.property(results, 'headers'); - assert.isObject(results.headers); - assert.isArray(results.headers.results); - assert.lengthOf(results.headers.results, 2); - }); - }); - }); - }); - }); -}); diff --git a/test/unit/validate.test.js b/test/unit/validate.test.js new file mode 100644 index 00000000..5c1a00d1 --- /dev/null +++ b/test/unit/validate.test.js @@ -0,0 +1,75 @@ +const { assert } = require('chai'); +const clone = require('clone'); +const { validate } = require('../../lib'); + +describe('Gavel proxies to functions with callbacks', () => { + // Examples from README.md + const baseHttpMessage = { + statusCode: '200', + headers: { + 'content-type': 'application/json', + date: 'Wed, 03 Jul 2013 13:30:53 GMT', + server: 'gunicorn/0.17.4', + 'content-length': '30', + connection: 'keep-alive' + }, + body: '{\n "origin": "94.113.241.2"\n}' + }; + + const cloneHttpMessage = clone(baseHttpMessage, false); + + const differentHttpMessage = { + statusCode: '404', + headers: { + 'content-type': 'application/vnd.gavel.vX+json', // different from baseHttpMessage + date: 'Wed, 03 Jul 2014 13:30:53 GMT', + server: 'Apache/2.42', // different from baseHttpMessage + connection: 'close' // different from baseHttpMessage + // missing key "content-length" + }, + body: '{"r2":"d2"}' + }; + + const similarHttpMessage = { + statusCode: '200', + headers: { + 'CONTENT-TYPE': 'application/json', + DATE: 'Mon, 01 Jan 2011 01:01:01 GMT', // shall ignore DATE header differences + SERVER: 'gunicorn/0.17.4', + 'CONTENT-LENGTH': '30', + CONNECTION: 'keep-alive' + }, + body: '{"origin":"1.2.3.4"}' + }; + + describe('validate', () => { + describe('when I provide data', () => { + ['response', 'request'].forEach((variant) => { + describe(`for two cloned ${variant}s`, () => { + const results = validate(baseHttpMessage, cloneHttpMessage); + + it('should results be an object', () => assert.isObject(results)); + }); + + describe(`for similar ${variant}s`, () => { + const results = validate(baseHttpMessage, similarHttpMessage); + + it('should results be an object', () => assert.isObject(results)); + }); + + describe(`for different ${variant}s`, () => { + const results = validate(baseHttpMessage, differentHttpMessage); + + it('should results be an object', () => assert.isObject(results)); + it('should results contain 2 different headers messages (missing content-length, different content-type)', () => { + assert.isObject(results); + assert.property(results.fields, 'headers'); + assert.isObject(results.fields.headers); + assert.isArray(results.fields.headers.errors); + assert.lengthOf(results.fields.headers.errors, 2); + }); + }); + }); + }); + }); +}); diff --git a/test/unit/validators/headers-json-example-validator-test.js b/test/unit/validators/headers-json-example-validator-test.js index a2d58524..1319c8a7 100644 --- a/test/unit/validators/headers-json-example-validator-test.js +++ b/test/unit/validators/headers-json-example-validator-test.js @@ -1,3 +1,4 @@ +/* eslint-disable */ const { assert } = require('chai'); const { HeadersJsonExample diff --git a/test/unit/validators/json-example-test.js b/test/unit/validators/json-example-test.js index 4a7b934e..748ae47f 100644 --- a/test/unit/validators/json-example-test.js +++ b/test/unit/validators/json-example-test.js @@ -1,3 +1,4 @@ +/* eslint-disable */ const { assert } = require('chai'); const { JsonExample } = require('../../../lib/validators/json-example'); const { JsonSchema } = require('../../../lib/validators/json-schema'); diff --git a/test/unit/validators/json-schema-test.js b/test/unit/validators/json-schema-test.js index 71533d9e..0a130a8e 100644 --- a/test/unit/validators/json-schema-test.js +++ b/test/unit/validators/json-schema-test.js @@ -1,3 +1,4 @@ +/* eslint-disable */ const { assert } = require('chai'); const fixtures = require('../../fixtures'); const { JsonSchema } = require('../../../lib/validators/json-schema'); diff --git a/test/unit/validators/text-diff-test.js b/test/unit/validators/text-diff-test.js index 9bd70211..b9947726 100644 --- a/test/unit/validators/text-diff-test.js +++ b/test/unit/validators/text-diff-test.js @@ -1,3 +1,4 @@ +/* eslint-disable */ const { assert } = require('chai'); const DiffMatchPatch = require('googlediff'); @@ -158,13 +159,8 @@ describe('TextDiff', () => { assert.isArray(results); }); - it('should contain message with error severity', () => { - haystack = []; - results.forEach((result) => { - haystack.push(result.severity); - }); - - assert.include(haystack, 'error'); + it('should contain one error', () => { + assert.lengthOf(results, 1); }); }); }); diff --git a/test/unit/validators/validation-errors-test.js b/test/unit/validators/validation-errors-test.js index 1045c8b6..482221d5 100644 --- a/test/unit/validators/validation-errors-test.js +++ b/test/unit/validators/validation-errors-test.js @@ -1,3 +1,4 @@ +/* eslint-disable */ const fixtures = require('../../fixtures'); const { ValidationErrors