Skip to content

Commit

Permalink
Merge pull request #12 from MailOnline/feat/highlight
Browse files Browse the repository at this point in the history
feat: highlight error code in terminal
  • Loading branch information
streamich authored Nov 14, 2017
2 parents 790ff2f + 6cbddcd commit 7684dfb
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 41 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ Available log levels are: `ERROR`, `WARN`, `INFO`.

## License

MIT, see [LICENSE.md](./LICENSE).
MIT, see [LICENSE](./LICENSE).
1 change: 1 addition & 0 deletions demo/broken.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
throw new Error('Error in test suite itself, reporter should report it properly.');
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"dependencies": {
"chalk": "^2.3.0",
"strip-ansi": "4.0.0",
"utf8-bar": "0.1.0"
"utf8-bar": "0.1.0",
"@babel/code-frame": "7.0.0-beta.32"
}
}
59 changes: 33 additions & 26 deletions src/LineWriter.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
/* eslint-disable complexity, no-use-extend-native/no-use-extend-native */
const path = require('path');
const chalk = require('chalk');
const progressBar = require('./progressBar');
const formatCodeFrame = require('./format/formatCodeFrame');
const formatStatsBar = require('./format/formatStatsBar');
const formatFailureMessageTraceLine = require('./format/formatFailureMessageTraceLine');

const REG_TRACE_LINE = /\s*(.+)\((.+):([0-9]+):([0-9]+)\)$/;
const REG_INTERNALS = /^(node_modules|internal)\//;
const REG_AT_PATH = /^\s*at (\/[^:]+):([0-9]+):([0-9]+)\s*$/;
const REG_AT = /^\s*at/;
const REG_ERROR = /^\s*Error:\s*/;
const REG_RECEIVED = /^\s*Received:/;
const REG_EXPECTED = /^\s*Expected value to equal:/;
const REG_EXPECTED = /^\s*Expected value to[^:]+:/;
const REG_DIFFERENCE = /^\s*Difference:/;

const MDASH = '\u2014';
Expand All @@ -27,28 +30,6 @@ const PASS = chalk.supportsColor ?

const formatComment = (line) => chalk`{hidden #} ${line}`;

const formatFailureMessageTraceLine = (description, relativeFilePath, row, column) =>
chalk`${description}({cyan ${relativeFilePath}}:{black.bold ${row}}:{black.bold ${column}})`;

const formatStatsBar = (percent, hasErrors) => {
let percentFormatted = Math.round(100 * percent) + '%';

percentFormatted = percentFormatted.padStart(3, ' ');
percentFormatted = percentFormatted.padEnd(4, ' ');

const bar = progressBar(percent, hasErrors ? 'red' : 'grey.dim');

let textStyles = 'green';

if (hasErrors) {
textStyles = 'red.bold';
} else if (percent < 1) {
textStyles = 'yellow';
}

return chalk`{${textStyles} ${percentFormatted}} ${bar}`;
};

class LineWriter {
constructor (logger, root) {
this.counter = 0;
Expand All @@ -71,6 +52,14 @@ class LineWriter {
this.logger.info(formatComment(line));
}

commentBlock (str) {
const lines = str.split('\n');

for (const line of lines) {
this.comment(line);
}
}

start (numSuites) {
this.blank();
this.blank();
Expand Down Expand Up @@ -192,6 +181,7 @@ class LineWriter {
};
const pushTraceLine = (line) => push(chalk` {grey ${line}}`);
const pushTraceLineDim = (line) => pushTraceLine(chalk`{dim ${line}}`);
const pushCodeFrameLine = (line) => push(' ' + line);

let firstLineFormatted = firstLine;

Expand Down Expand Up @@ -234,9 +224,26 @@ class LineWriter {
pushTraceLineDim(formatFailureMessageTraceLine(description, relativeFilePath, row, column));
} else {
pushTraceLine(formatFailureMessageTraceLine(description, relativeFilePath, row, column));

const codeFrame = formatCodeFrame(file, row, column);

if (codeFrame) {
push('');
codeFrame.split('\n').forEach((codeFrameLine) => pushCodeFrameLine(codeFrameLine));
push('');
}
}
} else {
pushTraceLine(line);
const atPathMatches = line.match(REG_AT_PATH);
const pushMethod = internalsStarted ? pushTraceLineDim : pushTraceLine;

if (atPathMatches) {
const [, atPathPath, atPathRow, atPathColumn] = atPathMatches;

pushMethod(chalk`at {cyan ${this.getPathRelativeToRoot(atPathPath)}}:{bold ${atPathRow}}:{bold ${atPathColumn}}`);
} else {
pushMethod(line);
}
}
} else {
// eslint-disable-next-line no-lonely-if
Expand All @@ -259,7 +266,7 @@ class LineWriter {
push(' ' + line);
break;
case 'difference':
push(' ' + line);
push(' ' + line.trim());
break;
default:
push(line);
Expand Down
23 changes: 13 additions & 10 deletions src/TapReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,23 @@ class TapReporter {
}
}

onTestResult (contexts, suite) {
const {testResults, testFilePath, numFailingTests} = suite;
onTestResult (test, testResult) {
const {testExecError, testResults, testFilePath, numFailingTests} = testResult;
const {dir, base} = path.parse(testFilePath);
const suiteFailed = Boolean(testExecError);

if (testFilePath) {
const {dir, base} = path.parse(testFilePath);

if (!this.globalConfig.watch) {
this.writer.blank();
}
this.writer.suite(numFailingTests > 0, dir, base);
if (!this.globalConfig.watch) {
this.writer.blank();
}
this.writer.suite(numFailingTests > 0 || suiteFailed, dir, base);
this.writer.blank();

testResults.forEach(this.onAssertionResult);
// If error in test suite itself.
if (suiteFailed) {
this.writer.errors([testExecError.stack]);
} else {
testResults.forEach(this.onAssertionResult);
}
}

onRunStart (results, options) {
Expand Down
28 changes: 28 additions & 0 deletions src/format/formatCodeFrame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const fs = require('fs');
const {codeFrameColumns} = require('@babel/code-frame');

const formatCodeFrame = (filePath, line, column, margin = 4) => {
try {
const source = fs.readFileSync(filePath, 'utf8');
const location = {
start: {
column,
line
}
};

const formatted = codeFrameColumns(source, location, {
highlightCode: true,
linesAbove: margin,
linesBelow: margin
});

// This below is because for some reason `@babel/code-frame` is not honoring
// `linesBelow` setting.
return formatted.split('\n').slice(0, 2 * margin + 1).join('\n');
} catch (error) {
return '';
}
};

module.exports = formatCodeFrame;
6 changes: 6 additions & 0 deletions src/format/formatFailureMessageTraceLine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const chalk = require('chalk');

const formatFailureMessageTraceLine = (description, relativeFilePath, row, column) =>
chalk`${description}({cyan ${relativeFilePath}}:{black.bold ${row}}:{black.bold ${column}})`;

module.exports = formatFailureMessageTraceLine;
23 changes: 23 additions & 0 deletions src/format/formatStatsBar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const chalk = require('chalk');
const progressBar = require('../progressBar');

const formatStatsBar = (percent, hasErrors) => {
let percentFormatted = Math.round(100 * percent) + '%';

percentFormatted = percentFormatted.padStart(3, ' ');
percentFormatted = percentFormatted.padEnd(4, ' ');

const bar = progressBar(percent, hasErrors ? 'red' : 'grey.dim');

let textStyles = 'green';

if (hasErrors) {
textStyles = 'red.bold';
} else if (percent < 1) {
textStyles = 'yellow';
}

return chalk`{${textStyles} ${percentFormatted}} ${bar}`;
};

module.exports = formatStatsBar;
3 changes: 2 additions & 1 deletion test/fixtures/failingTestSuite.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
"name":"/jest-tap-reporter/test/index.spec.js",
"startTime":1500478841634,
"status":"failed",
"summary":""
"summary":"",
"testFilePath": "/jest-tap-reporter/test/TapReporter.spec.js"
}
3 changes: 2 additions & 1 deletion test/fixtures/severalTestsSuite.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@
"name":"/jest-tap-reporter/test/index.spec.js",
"startTime":1500478996144,
"status":"passed",
"summary":""
"summary":"",
"testFilePath": "/jest-tap-reporter/test/TapReporter.spec.js"
}
3 changes: 2 additions & 1 deletion test/fixtures/skippedTestSuite.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
"name":"/jest-tap-reporter/test/index.spec.js",
"startTime":1500479077405,
"status":"passed",
"summary":""
"summary":"",
"testFilePath": "/jest-tap-reporter/test/TapReporter.spec.js"
}

0 comments on commit 7684dfb

Please sign in to comment.