diff --git a/lib/enhance-assert.js b/lib/enhance-assert.js index 6e127b3d6..6991caf40 100644 --- a/lib/enhance-assert.js +++ b/lib/enhance-assert.js @@ -1,6 +1,7 @@ 'use strict'; const concordance = require('concordance'); const dotProp = require('dot-prop'); +const generate = require('babel-generator').default; const concordanceOptions = require('./concordance-options').default; // When adding patterns, don't forget to add to @@ -15,31 +16,16 @@ const PATTERNS = [ 't.notRegex(contents, regex, [message])' ]; -const isRangeMatch = (a, b) => { - return (a[0] === b[0] && a[1] === b[1]) || - (a[0] > b[0] && a[0] < b[1]) || - (a[1] > b[0] && a[1] < b[1]); -}; - -const computeStatement = (tokens, range) => { - return tokens - .filter(token => isRangeMatch(token.range, range)) - .map(token => token.value === undefined ? token.type.label : token.value) - .join(''); -}; - +const computeStatement = node => generate(node, {quotes: 'single'}).code; const getNode = (ast, path) => dotProp.get(ast, path.replace(/\//g, '.')); const formatter = context => { const ast = JSON.parse(context.source.ast); - const tokens = JSON.parse(context.source.tokens); const args = context.args[0].events; - return args .map(arg => { - const range = getNode(ast, arg.espath).range; - const statement = computeStatement(tokens, range); - + const node = getNode(ast, arg.espath); + const statement = computeStatement(node); const formatted = concordance.format(arg.value, concordanceOptions); return [statement, formatted]; }) diff --git a/package-lock.json b/package-lock.json index 44e879ca3..f80b0bbf7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -317,7 +317,7 @@ "integrity": "sha1-jEKFZNzh4fQfszfsNPTDsCK1rYM=", "requires": { "babel-code-frame": "6.22.0", - "babel-generator": "6.24.1", + "babel-generator": "6.26.0", "babel-helpers": "6.24.1", "babel-messages": "6.23.0", "babel-register": "6.24.1", @@ -348,13 +348,13 @@ } }, "babel-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", - "integrity": "sha1-5xX0hsWN7SVknYiJRNUqoHxdlJc=", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", "requires": { "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-types": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", "detect-indent": "4.0.0", "jsesc": "1.3.0", "lodash": "4.17.4", @@ -362,10 +362,35 @@ "trim-right": "1.0.1" }, "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.4.1", + "regenerator-runtime": "0.11.0" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==" } } }, @@ -482,7 +507,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-espower/-/babel-plugin-espower-2.3.2.tgz", "integrity": "sha1-VRa4/NsmyfDh2BYHSfbkxl5xJx4=", "requires": { - "babel-generator": "6.24.1", + "babel-generator": "6.26.0", "babylon": "6.17.2", "call-matcher": "1.0.1", "core-js": "2.4.1", diff --git a/package.json b/package.json index 0aee08080..7d635e631 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "auto-bind": "^1.1.0", "ava-init": "^0.2.0", "babel-core": "^6.17.0", + "babel-generator": "^6.26.0", "bluebird": "^3.0.0", "caching-transform": "^1.0.0", "chalk": "^2.0.1", diff --git a/test/api.js b/test/api.js index e0f6c9fdc..9c2ffeb98 100644 --- a/test/api.js +++ b/test/api.js @@ -371,6 +371,43 @@ function generateTests(prefix, apiCreator) { }); }); + test(`${prefix} enhanced assertion formatting necessary whitespace and empty strings`, t => { + const expected = [ + [ + /foo === '' && '' === foo/, + /foo === ''/, + /foo/ + ], + [ + /new Object\(foo\) instanceof Object/, + /Object/, + /new Object\(foo\)/, + /foo/ + ], + [ + /\[foo].filter\(item => {\n\s+return item === 'bar';\n}\).length > 0/, + /\[foo].filter\(item => {\n\s+return item === 'bar';\n}\).length/, + /\[foo].filter\(item => {\n\s+return item === 'bar';\n}\)/, + /\[foo]/, + /foo/ + ] + ]; + + t.plan(14); + const api = apiCreator(); + return api.run([path.join(__dirname, 'fixture/enhanced-assertion-formatting.js')]) + .then(result => { + t.is(result.errors.length, 3); + t.is(result.passCount, 0); + + result.errors.forEach((error, errorIndex) => { + error.error.statements.forEach((statement, statementIndex) => { + t.match(statement[0], expected[errorIndex][statementIndex]); + }); + }); + }); + }); + test(`${prefix} stack traces for exceptions are corrected using a source map file (cache off)`, t => { t.plan(4); diff --git a/test/fixture/enhanced-assertion-formatting.js b/test/fixture/enhanced-assertion-formatting.js new file mode 100644 index 000000000..748de1d6f --- /dev/null +++ b/test/fixture/enhanced-assertion-formatting.js @@ -0,0 +1,21 @@ +import test from '../..'; + +const foo = 'foo'; + +test('fails with multiple empty string expressions and mixed quotes', t => { + // eslint-disable-next-line quotes, yoda + t.true(foo === '' && "" === foo); +}); + +test('fails with "instanceof" expression', t => { + // eslint-disable-next-line no-new-object + t.false(new Object(foo) instanceof Object); +}); + +test('fails with multiple lines', t => { + t.true( + [foo].filter(item => { + return item === 'bar'; + }).length > 0 + ); +});