-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9616dde
commit c9e6e6f
Showing
20 changed files
with
1,157 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
'use strict'; | ||
const fs = require('fs'); | ||
const equalLength = require('equal-length'); | ||
const codeExcerpt = require('code-excerpt'); | ||
const truncate = require('cli-truncate'); | ||
const chalk = require('chalk'); | ||
|
||
const formatLineNumber = (lineNumber, maxLineNumber) => { | ||
return ' '.repeat(String(maxLineNumber).length - String(lineNumber).length) + lineNumber; | ||
}; | ||
|
||
module.exports = (file, line, options) => { | ||
options = options || {}; | ||
|
||
const maxWidth = options.maxWidth || 80; | ||
const source = fs.readFileSync(file, 'utf8'); | ||
const excerpt = codeExcerpt(source, line, {around: 1}); | ||
if (!excerpt) { | ||
return null; | ||
} | ||
|
||
const lines = excerpt.map(item => ({ | ||
line: item.line, | ||
value: truncate(item.value, maxWidth - String(line).length - 5) | ||
})); | ||
|
||
const joinedLines = lines.map(line => line.value).join('\n'); | ||
const extendedLines = equalLength(joinedLines).split('\n'); | ||
|
||
return lines | ||
.map((item, index) => ({ | ||
line: item.line, | ||
value: extendedLines[index] | ||
})) | ||
.map(item => { | ||
const isErrorSource = item.line === line; | ||
|
||
const lineNumber = formatLineNumber(item.line, line) + ':'; | ||
const coloredLineNumber = isErrorSource ? lineNumber : chalk.grey(lineNumber); | ||
const result = ` ${coloredLineNumber} ${item.value}`; | ||
|
||
return isErrorSource ? chalk.bgRed(result) : result; | ||
}) | ||
.join('\n'); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,79 @@ | ||
'use strict'; | ||
|
||
module.exports = enhanceAssert; | ||
module.exports.formatter = formatter; | ||
const dotProp = require('dot-prop'); | ||
|
||
// When adding patterns, don't forget to add to | ||
// https://github.com/avajs/babel-preset-transform-test-files/blob/master/espower-patterns.json | ||
// Then release a new version of that preset and bump the SemVer range here. | ||
module.exports.PATTERNS = [ | ||
const PATTERNS = [ | ||
't.truthy(value, [message])', | ||
't.falsy(value, [message])', | ||
't.true(value, [message])', | ||
't.false(value, [message])', | ||
't.is(value, expected, [message])', | ||
't.not(value, expected, [message])', | ||
't.deepEqual(value, expected, [message])', | ||
't.notDeepEqual(value, expected, [message])', | ||
't.regex(contents, regex, [message])', | ||
't.notRegex(contents, regex, [message])' | ||
]; | ||
|
||
module.exports.NON_ENHANCED_PATTERNS = [ | ||
const NON_ENHANCED_PATTERNS = [ | ||
't.pass([message])', | ||
't.fail([message])', | ||
't.throws(fn, [message])', | ||
't.notThrows(fn, [message])', | ||
't.ifError(error, [message])', | ||
't.snapshot(contents, [message])' | ||
't.snapshot(contents, [message])', | ||
't.is(value, expected, [message])', | ||
't.not(value, expected, [message])', | ||
't.deepEqual(value, expected, [message])', | ||
't.notDeepEqual(value, expected, [message])' | ||
]; | ||
|
||
function enhanceAssert(opts) { | ||
const enhanceAssert = opts => { | ||
const empower = require('empower-core'); | ||
|
||
const enhanced = empower( | ||
opts.assert, | ||
{ | ||
destructive: false, | ||
onError: opts.onError, | ||
onSuccess: opts.onSuccess, | ||
patterns: module.exports.PATTERNS, | ||
wrapOnlyPatterns: module.exports.NON_ENHANCED_PATTERNS, | ||
bindReceiver: false | ||
} | ||
); | ||
const enhanced = empower(opts.assert, { | ||
destructive: false, | ||
onError: opts.onError, | ||
onSuccess: opts.onSuccess, | ||
patterns: PATTERNS, | ||
wrapOnlyPatterns: NON_ENHANCED_PATTERNS, | ||
bindReceiver: false | ||
}); | ||
|
||
return enhanced; | ||
} | ||
}; | ||
|
||
function formatter() { | ||
const createFormatter = require('power-assert-context-formatter'); | ||
const SuccinctRenderer = require('power-assert-renderer-succinct'); | ||
const AssertionRenderer = require('power-assert-renderer-assertion'); | ||
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]); | ||
}; | ||
|
||
return createFormatter({ | ||
renderers: [ | ||
{ | ||
ctor: AssertionRenderer | ||
}, | ||
{ | ||
ctor: SuccinctRenderer, | ||
options: { | ||
maxDepth: 3 | ||
} | ||
} | ||
] | ||
}); | ||
} | ||
const computeStatement = (tokens, range) => { | ||
return tokens | ||
.filter(token => isRangeMatch(token.range, range)) | ||
.map(token => token.value === undefined ? token.type.label : token.value) | ||
.join(''); | ||
}; | ||
|
||
const getNode = (ast, path) => dotProp.get(ast, path.replace(/\//g, '.')); | ||
|
||
const formatter = () => { | ||
return 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; | ||
|
||
return [computeStatement(tokens, range), arg.value]; | ||
}) | ||
.reverse(); | ||
}; | ||
}; | ||
|
||
module.exports = enhanceAssert; | ||
module.exports.PATTERNS = PATTERNS; | ||
module.exports.NON_ENHANCED_PATTERNS = NON_ENHANCED_PATTERNS; | ||
module.exports.formatter = formatter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
'use strict'; | ||
const stackLineRegex = /^.+ \(.+:[0-9]+:[0-9]+\)$/; | ||
|
||
module.exports = stack => { | ||
return stack | ||
.split('\n') | ||
.filter(line => stackLineRegex.test(line)) | ||
.map(line => line.trim()) | ||
.join('\n'); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
'use strict'; | ||
const indentString = require('indent-string'); | ||
const chalk = require('chalk'); | ||
const diff = require('diff'); | ||
|
||
const cleanUp = line => { | ||
if (line[0] === '+') { | ||
return `${chalk.green('+')} ${line.slice(1)}`; | ||
} | ||
|
||
if (line[0] === '-') { | ||
return `${chalk.red('-')} ${line.slice(1)}`; | ||
} | ||
|
||
if (line.match(/@@/)) { | ||
return null; | ||
} | ||
|
||
if (line.match(/\\ No newline/)) { | ||
return null; | ||
} | ||
|
||
return ` ${line}`; | ||
}; | ||
|
||
module.exports = err => { | ||
if (err.statements) { | ||
const statements = JSON.parse(err.statements); | ||
|
||
return statements | ||
.map(statement => `${statement[0]}\n${chalk.grey('=>')} ${statement[1]}`) | ||
.join('\n\n') + '\n'; | ||
} | ||
|
||
if ((err.actualType === 'object' || err.actualType === 'array') && err.actualType === err.expectedType) { | ||
const patch = diff.createPatch('string', err.actual, err.expected); | ||
const msg = patch | ||
.split('\n') | ||
.slice(4) | ||
.map(cleanUp) | ||
.filter(Boolean) | ||
.join('\n'); | ||
|
||
return `Difference:\n\n${msg}`; | ||
} | ||
|
||
if (err.actualType === 'string' && err.expectedType === 'string') { | ||
const patch = diff.diffChars(err.actual, err.expected); | ||
const msg = patch | ||
.map(part => { | ||
if (part.added) { | ||
return chalk.bgGreen.black(part.value); | ||
} | ||
|
||
if (part.removed) { | ||
return chalk.bgRed.black(part.value); | ||
} | ||
|
||
return part.value; | ||
}) | ||
.join(''); | ||
|
||
return `Difference:\n\n${msg}\n`; | ||
} | ||
|
||
return [ | ||
'Actual:\n', | ||
`${indentString(err.actual, 2)}\n`, | ||
'Expected:\n', | ||
`${indentString(err.expected, 2)}\n` | ||
].join('\n'); | ||
}; |
Oops, something went wrong.