Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/inline diff #167

Merged
merged 2 commits into from
Jun 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const boolOpts = [
'enableCode',
'overwrite',
'quiet',
'useInlineDiffs',
'dev'
];

Expand All @@ -37,11 +38,12 @@ function _getOption(optToGet, options, isBool) {

module.exports = function (opts) {
const options = {};
const reporterOpts = (opts && opts.reporterOptions) || {};

// Added for compatibility. enableTestCode option is deprecated as of 2.0.3
if (Object.hasOwnProperty.call(opts, 'enableTestCode')) {
opts.enableCode = opts.enableTestCode;
delete opts.enableTestCode;
if (Object.hasOwnProperty.call(reporterOpts, 'enableTestCode')) {
reporterOpts.enableCode = reporterOpts.enableTestCode;
delete reporterOpts.enableTestCode;
}

[
Expand All @@ -56,7 +58,15 @@ module.exports = function (opts) {
'timestamp',
'overwrite',
'quiet',
'inlineDiffs',
'dev'
].forEach(optName => {
options[optName] = _getOption(optName, reporterOpts, boolOpts.indexOf(optName) >= 0);
});

// Transfer options from mocha
[
'useInlineDiffs'
].forEach(optName => {
options[optName] = _getOption(optName, opts, boolOpts.indexOf(optName) >= 0);
});
Expand Down
15 changes: 7 additions & 8 deletions src/mochawesome.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const mocha = require('mocha');
const Base = require('mocha/lib/reporters/base');
const Spec = require('mocha/lib/reporters/spec');
const uuid = require('uuid');
const stringify = require('json-stringify-safe');
const conf = require('./config');
Expand Down Expand Up @@ -48,7 +49,6 @@ function done(output, config, failures, exit) {
* @param {Runner} runner
* @api public
*/

function Mochawesome(runner, options) {
// Done function will be called before mocha exits
// This is where we will save JSON and generate the HTML report
Expand All @@ -57,15 +57,14 @@ function Mochawesome(runner, options) {
// Reset total tests counter
totalTestsRegistered.total = 0;

// Create/Save necessary report dirs/files
const reporterOpts = (options && options.reporterOptions) || {};
this.config = conf(reporterOpts);
// Set the config options
this.config = conf(options);

// Call the Base mocha reporter
mocha.reporters.Base.call(this, runner);
Base.call(this, runner);

// Show the Spec Reporter in the console
new mocha.reporters.Spec(runner); // eslint-disable-line
new Spec(runner); // eslint-disable-line

const allTests = [];
const allPending = [];
Expand Down Expand Up @@ -102,7 +101,7 @@ function Mochawesome(runner, options) {

const allSuites = this.runner.suite;

traverseSuites(allSuites, totalTestsRegistered);
traverseSuites(allSuites, totalTestsRegistered, this.config);

const obj = {
stats: this.stats,
Expand Down
35 changes: 24 additions & 11 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,27 @@ function createUnifiedDiff({ actual, expected }) {
.join('\n');
}

/**
* Create an inline diff between two strings
*
* @param {Error} err Error object
* @param {string} err.actual Actual result returned
* @param {string} err.expected Result expected
*
* @return {array} diff string objects
*/
function createInlineDiff({ actual, expected }) {
return diff.diffWordsWithSpace(actual, expected);
}

/**
* Return a normalized error object
*
* @param {Error} err Error object
*
* @return {Object} normalized error
*/
function normalizeErr(err) {
function normalizeErr(err, config) {
const { name, message, actual, expected, stack, showDiff } = err;
let errMessage;
let errDiff;
Expand All @@ -133,7 +146,7 @@ function normalizeErr(err) {
err.actual = mochaUtils.stringify(actual);
err.expected = mochaUtils.stringify(expected);
}
errDiff = createUnifiedDiff(err);
errDiff = config.useInlineDiffs ? createInlineDiff(err) : createUnifiedDiff(err);
}

// Assertion libraries do not output consitent error objects so in order to
Expand All @@ -159,7 +172,7 @@ function normalizeErr(err) {
*
* @return {Object} cleaned test
*/
function cleanTest(test) {
function cleanTest(test, config) {
/* istanbul ignore next: test.fn exists prior to mocha 2.4.0 */
const code = test.fn ? test.fn.toString() : test.body;

Expand All @@ -175,7 +188,7 @@ function cleanTest(test) {
pending: test.pending,
context: stringify(test.context, null, 2),
code: code && cleanCode(code),
err: (test.err && normalizeErr(test.err)) || {},
err: (test.err && normalizeErr(test.err, config)) || {},
isRoot: test.parent && test.parent.root,
uuid: test.uuid || /* istanbul ignore next: default */uuid.v4(),
parentUUID: test.parent && test.parent.uuid,
Expand All @@ -195,11 +208,11 @@ function cleanTest(test) {
* @param {Object} totalTestsRegistered
* @param {Integer} totalTestsRegistered.total
*/
function cleanSuite(suite, totalTestsRegistered) {
function cleanSuite(suite, totalTestsRegistered, config) {
suite.uuid = uuid.v4();
const beforeHooks = _.map([].concat(suite._beforeAll, suite._beforeEach), cleanTest);
const afterHooks = _.map([].concat(suite._afterAll, suite._afterEach), cleanTest);
const cleanTests = _.map(suite.tests, cleanTest);
const beforeHooks = _.map([].concat(suite._beforeAll, suite._beforeEach), test => cleanTest(test, config));
const afterHooks = _.map([].concat(suite._afterAll, suite._afterEach), test => cleanTest(test, config));
const cleanTests = _.map(suite.tests, test => cleanTest(test, config));
const passingTests = _.filter(cleanTests, { state: 'passed' });
const failingTests = _.filter(cleanTests, { state: 'failed' });
const pendingTests = _.filter(cleanTests, { pending: true });
Expand Down Expand Up @@ -278,16 +291,16 @@ function cleanSuite(suite, totalTestsRegistered) {
* @param {Object} totalTestsRegistered
* @param {Integer} totalTestsRegistered.total
*/
function traverseSuites(suite, totalTestsRegistered) {
function traverseSuites(suite, totalTestsRegistered, config) {
const queue = [];
let next = suite;
while (next) {
if (next.root) {
cleanSuite(next, totalTestsRegistered);
cleanSuite(next, totalTestsRegistered, config);
}
if (next.suites.length) {
_.each(next.suites, (nextSuite, i) => {
cleanSuite(nextSuite, totalTestsRegistered);
cleanSuite(nextSuite, totalTestsRegistered, config);
queue.push(nextSuite);
});
}
Expand Down
12 changes: 12 additions & 0 deletions test/reporter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,18 @@ describe('Mochawesome Reporter', () => {
done();
});
});

it('should transfer mocha options', done => {
mochaReporter = new mocha._reporter(runner, { useInlineDiffs: true });

const test = makeTest('test', () => {});
subSuite.addTest(test);

runner.run(failureCount => {
mochaReporter.config.useInlineDiffs.should.equal(true);
done();
});
});
});

describe('Reporter Done Function', () => {
Expand Down
28 changes: 28 additions & 0 deletions test/sample-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,34 @@ module.exports = {
parentUUID: '56508f44-b4e6-40f0-bae8-b15e0720f120',
skipped: false,
isHook: false
},
cleanedWithInlineDiff: {
title: 'failing test',
fullTitle: 'failing test',
timedOut: false,
duration: 2,
state: 'failed',
speed: undefined,
pass: false,
fail: true,
pending: false,
context: undefined,
code: 'return tDone(new Assert(error));',
err: {
message: 'AssertionError: { a: 2 } undefined { a: 1 }',
estack: 'AssertionError: { a: 2 } undefined { a: 1 }',
diff: [
{ count: 6, value: '{\n "a": ' },
{ count: 1, added: undefined, removed: true, value: '2' },
{ count: 1, added: true, removed: undefined, value: '1' },
{ count: 2, value: '\n}' }
]
},
isRoot: false,
uuid: '2bcbe88c-acd6-4a53-ba3a-61a59188d5b0',
parentUUID: '56508f44-b4e6-40f0-bae8-b15e0720f120',
skipped: false,
isHook: false
}
},
pending: {
Expand Down
20 changes: 14 additions & 6 deletions test/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ describe('Mochawesome Utils', () => {
});

describe('cleanTest', () => {
const config = {};
const expectedProps = [
'title',
'fullTitle',
Expand All @@ -150,31 +151,38 @@ describe('Mochawesome Utils', () => {
];

it('returns cleaned passing test', () => {
const cleaned = cleanTest(sampleTests.passing.raw);
const cleaned = cleanTest(sampleTests.passing.raw, config);
cleaned.should.have.properties(expectedProps);
cleaned.should.deepEqual(sampleTests.passing.cleaned);
});

it('returns cleaned failing test', () => {
const cleaned = cleanTest(sampleTests.failing.raw);
const cleaned = cleanTest(sampleTests.failing.raw, config);
cleaned.should.have.properties(expectedProps);
cleaned.should.deepEqual(sampleTests.failing.cleaned);
});

it('returns cleaned failing test with inline diff', () => {
const cleaned = cleanTest(sampleTests.failing.raw, { useInlineDiffs: true });
cleaned.should.have.properties(expectedProps);
cleaned.should.deepEqual(sampleTests.failing.cleanedWithInlineDiff);
});

it('returns cleaned pending test', () => {
const cleaned = cleanTest(sampleTests.pending.raw);
const cleaned = cleanTest(sampleTests.pending.raw, config);
cleaned.should.have.properties(expectedProps);
cleaned.should.deepEqual(sampleTests.pending.cleaned);
});

it('returns cleaned hook', () => {
const cleaned = cleanTest(sampleTests.hook.raw);
const cleaned = cleanTest(sampleTests.hook.raw, config);
cleaned.should.have.properties(expectedProps);
cleaned.should.deepEqual(sampleTests.hook.cleaned);
});
});

describe('cleanSuite', () => {
const config = {};
const totalTestsRegistered = { total: 0 };
const expectedProps = [
'title',
Expand Down Expand Up @@ -210,14 +218,14 @@ describe('Mochawesome Utils', () => {

it('cleans a root suite', () => {
const s = cloneDeep(sampleSuite.one.raw);
cleanSuite(s, totalTestsRegistered);
cleanSuite(s, totalTestsRegistered, config);
s.should.have.properties(expectedProps);
s.should.deepEqual(sampleSuite.one.cleaned);
});

it('cleans a non-root suite', () => {
const s = cloneDeep(sampleSuite.two.raw);
cleanSuite(s, totalTestsRegistered);
cleanSuite(s, totalTestsRegistered, config);
s.should.have.properties(expectedProps);
s.should.deepEqual(sampleSuite.two.cleaned);
});
Expand Down