Browse Source

improve test coverage by adding more tests (#967)

hoisting-throws-helper
Dmitry Ananichev 8 years ago
committed by Sindre Sorhus
parent
commit
ea25b20a6d
  1. 11
      lib/reporters/mini.js
  2. 49
      test/babel-config.js
  3. 44
      test/beautify-stack.js
  4. 42
      test/cli.js
  5. 22
      test/concurrent.js
  6. 7
      test/fixture/es2015-source-maps.js
  7. 9
      test/profile.js
  8. 90
      test/reporters/mini.js
  9. 24
      test/reporters/tap.js
  10. 20
      test/reporters/verbose.js
  11. 6
      test/run-status.js

11
lib/reporters/mini.js

@ -181,16 +181,9 @@ MiniReporter.prototype.finish = function (runStatus) {
i++;
var title = test.error ? test.title : 'Unhandled Error';
var description;
var description = ' ' + test.error.message + '\n ' + stripFirstLine(test.error.stack).trimRight();
if (test.error) {
description = ' ' + test.error.message + '\n ' + stripFirstLine(test.error.stack).trimRight();
} else {
description = JSON.stringify(test);
}
status += '\n\n\n ' + colors.error(i + '.', title) + '\n';
status += '\n\n\n ' + colors.error(i + '.', test.title) + '\n';
status += colors.stack(description);
});
}

49
test/babel-config.js

@ -11,7 +11,7 @@ function fixture(name) {
return path.join(__dirname, 'fixture', name);
}
test('uses babelConfig for babel options when babelConfig is an object', function (t) {
function setUp() {
var customPlugin = sinon.stub().returns({visitor: {}});
var powerAssert = sinon.stub().returns({visitor: {}});
var rewrite = sinon.stub().returns({visitor: {}});
@ -24,9 +24,22 @@ test('uses babelConfig for babel options when babelConfig is an object', functio
return rewrite;
}
return {
customPlugin: customPlugin,
powerAssert: powerAssert,
rewrite: rewrite,
createEspowerPlugin: createEspowerPlugin,
babelDetectiveWrap: babelDetectiveWrap
};
}
test('uses babelConfig for babel options when babelConfig is an object', function (t) {
var setup = setUp();
var customPlugin = setup.customPlugin;
var babelConfigHelper = proxyquire('../lib/babel-config', {
'babel-plugin-espower/create': createEspowerPlugin,
'babel-plugin-detective/wrap-listener': babelDetectiveWrap
'babel-plugin-espower/create': setup.createEspowerPlugin,
'babel-plugin-detective/wrap-listener': setup.babelDetectiveWrap
});
var babelConfig = {
@ -45,6 +58,34 @@ test('uses babelConfig for babel options when babelConfig is an object', functio
t.true('inputSourceMap' in options);
t.false(options.babelrc);
t.strictDeepEqual(options.presets, ['stage-2', 'es2015']);
t.strictDeepEqual(options.plugins, [customPlugin, powerAssert, throwsHelper, rewrite, transformRuntime]);
t.strictDeepEqual(options.plugins, [customPlugin, setup.powerAssert, throwsHelper, setup.rewrite, transformRuntime]);
t.end();
});
test('should reuse existing source maps', function (t) {
var setup = setUp();
var customPlugin = setup.customPlugin;
var babelConfigHelper = proxyquire('../lib/babel-config', {
'babel-plugin-espower/create': setup.createEspowerPlugin,
'babel-plugin-detective/wrap-listener': setup.babelDetectiveWrap
});
var babelConfig = {
presets: ['stage-2', 'es2015'],
plugins: [customPlugin]
};
var fixturePath = fixture('es2015-source-maps.js');
var fixtureSource = fs.readFileSync(fixturePath, 'utf8');
var options = babelConfigHelper.build(babelConfig, fixturePath, fixtureSource);
t.true('filename' in options);
t.true(options.sourceMaps);
t.false(options.ast);
t.true('inputSourceMap' in options);
t.strictDeepEqual(options.presets, ['stage-2', 'es2015']);
t.strictDeepEqual(options.plugins, [customPlugin, setup.powerAssert, throwsHelper, setup.rewrite, transformRuntime]);
t.end();
});

44
test/beautify-stack.js

@ -0,0 +1,44 @@
var proxyquire = require('proxyquire').noPreserveCache();
var test = require('tap').test;
var beautifyStack = proxyquire('../lib/beautify-stack', {
debug: function () {
return {
enabled: false
};
}
});
test('does not strip ava internals and dependencies from stack trace with debug enabled', function (t) {
var beautify = proxyquire('../lib/beautify-stack', {
debug: function () {
return {
enabled: true
};
}
});
var result = beautify(
'Error: TypeError\n' +
'at null._onTimeout (node_modules/ava/cli.js:27:11)\n' +
'at Stub.listOnTimeout (timers.js:119:15)\n'
);
t.true(result.indexOf('ava/cli.js') !== -1);
t.end();
});
test('strips ava internals and dependencies from stack trace with debug disabled', function (t) {
var result = beautifyStack(
'Error: TypeError\n' +
'at null._onTimeout (node_modules/ava/cli.js:27:11)\n' +
'at Stub.listOnTimeout (timers.js:119:15)\n'
);
t.true(result.indexOf('ava/cli.js') === -1);
t.end();
});
test('returns empty string without any arguments', function (t) {
t.is(beautifyStack(), '');
t.end();
});

42
test/cli.js

@ -8,6 +8,8 @@ var figures = require('figures');
var arrify = require('arrify');
var chalk = require('chalk');
var touch = require('touch');
var proxyquire = require('proxyquire');
var sinon = require('sinon');
var cliPath = path.join(__dirname, '../cli.js');
@ -302,6 +304,15 @@ test('--match works', function (t) {
});
});
['--tap', '-t'].forEach(function (tapFlag) {
test(tapFlag + ' should produce TAP output', function (t) {
execCli([tapFlag, 'test.js'], {dirname: 'fixture/watcher'}, function (err) {
t.ok(!err);
t.end();
});
});
});
test('handles NODE_PATH', function (t) {
var nodePaths = 'fixture/node-paths/modules' + path.delimiter + 'fixture/node-paths/deep/nested';
@ -326,3 +337,34 @@ test('should warn ava is required without the cli', function (t) {
t.end();
});
});
test('prefers local version of ava', function (t) {
t.plan(1);
var stubModulePath = path.join(__dirname, '/fixture/empty');
var debugSpy = sinon.spy();
function resolveCwdStub() {
return stubModulePath;
}
function debugStub() {
return function (message) {
var result = {
enabled: false
};
if (message) {
result = debugSpy(message);
}
return result;
};
}
proxyquire('../cli', {
'debug': debugStub,
'resolve-cwd': resolveCwdStub
});
t.ok(debugSpy.calledWith('Using local install of AVA'));
t.end();
});

22
test/concurrent.js

@ -25,6 +25,14 @@ function fail(val) {
};
}
function failWithTypeError() {
return {
run: function () {
throw new TypeError('Unexpected Error');
}
};
}
function passAsync(val) {
return {
run: function () {
@ -850,3 +858,17 @@ test('sequences of sequences', function (t) {
t.end();
});
test('must be called with array of tests', function (t) {
t.throws(function () {
new Concurrent(pass('a')).run();
}, {message: 'Expected an array of tests'});
t.end();
});
test('should throw an error then test.run() fails with not AvaError', function (t) {
t.throws(function () {
new Concurrent([failWithTypeError()]).run();
}, {message: 'Unexpected Error'});
t.end();
});

7
test/fixture/es2015-source-maps.js

@ -0,0 +1,7 @@
import test from '../../';
test(t => {
t.pass();
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImVzMjAxNS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxRQUFRLENBQUM7O0FBRTFCLElBQUksQ0FBQyxDQUFDLElBQUk7QUFDVCxFQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7Q0FDVCxDQUFDLENBQUMiLCJmaWxlIjoiZXMyMDE1LXNvdXJjZS1tYXBzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QgZnJvbSAnLi4vLi4vJztcblxudGVzdCh0ID0+IHtcblx0dC5wYXNzKCk7XG59KTtcbiJdfQ==

9
test/profile.js

@ -19,6 +19,15 @@ function run(files) {
return execa(process.execPath, [profileScript].concat(arrify(files).map(fixture)), {cwd: cwd});
}
test('runs the profiler and throws an error when invoked without files to run', function (t) {
t.plan(1);
run()
.catch(function (err) {
t.ok(/Specify a test file/.test(err.stderr));
t.end();
});
});
test('exits normally when tests pass', function (t) {
t.plan(1);
run('es2015')

90
test/reporters/mini.js

@ -1,5 +1,6 @@
'use strict';
var chalk = require('chalk');
var sinon = require('sinon');
var test = require('tap').test;
var cross = require('figures').cross;
var lolex = require('lolex');
@ -455,3 +456,92 @@ test('results with watching enabled', function (t) {
t.is(actualOutput, expectedOutput);
t.end();
});
test('increases number of rejections', function (t) {
var reporter = miniReporter();
reporter.passCount = 0;
reporter.rejectionCount = 0;
var err = new Error('failure one');
err.type = 'rejection';
reporter.unhandledError(err);
t.is(reporter.rejectionCount, 1);
t.end();
});
test('increases number of exceptions', function (t) {
var reporter = miniReporter();
reporter.passCount = 0;
reporter.exceptionCount = 0;
var err = new Error('failure one');
err.type = 'exception';
reporter.unhandledError(err);
t.is(reporter.exceptionCount, 1);
t.end();
});
test('silently handles errors without body', function (t) {
var reporter = miniReporter();
reporter.failCount = 1;
var runStatus = {
errors: [{}, {}]
};
var actualOutput = reporter.finish(runStatus);
var expectedOutput = [
'\n ' + colors.error('1 failed'),
''
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
});
test('does not handle errors with body in rejections', function (t) {
var reporter = miniReporter();
reporter.rejectionCount = 1;
var runStatus = {
errors: [{
title: 'failed test'
}]
};
var actualOutput = reporter.finish(runStatus);
var expectedOutput = [
'\n ' + colors.error('1 rejection'),
''
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
});
test('returns description based on error itself if no stack available', function (t) {
var reporter = miniReporter();
reporter.exceptionCount = 1;
var err1 = new Error('failure one');
var runStatus = {
errors: [{
error: err1
}]
};
var actualOutput = reporter.finish(runStatus);
var expectedOutput = [
'\n ' + colors.error('1 exception'),
'\n\n ' + colors.error('1. Uncaught Exception'),
' ' + colors.stack(JSON.stringify({error: err1})) + '\n'
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
});
test('returns empty string (used in watcher in order to separate different test runs)', function (t) {
var reporter = miniReporter();
t.is(reporter.clear(), '');
t.end();
});
test('stderr and stdout should call _update', function (t) {
var reporter = miniReporter();
var spy = sinon.spy(reporter, '_update');
reporter.stdout();
reporter.stderr();
t.is(spy.callCount, 2);
reporter._update.restore();
t.end();
});

24
test/reporters/tap.js

@ -1,4 +1,5 @@
'use strict';
var sinon = require('sinon');
var test = require('tap').test;
var hasAnsi = require('has-ansi');
var chalk = require('chalk');
@ -194,3 +195,26 @@ test('reporter strips ANSI characters', function (t) {
t.notOk(hasAnsi(output.title));
t.end();
});
test('write should call console.log', function (t) {
var reporter = tapReporter();
var stub = sinon.stub(console, 'log');
reporter.write('result');
t.true(stub.called);
console.log.restore();
t.end();
});
test('stdout and stderr should call process.stderr.write', function (t) {
var reporter = tapReporter();
var spy = sinon.spy(process.stderr, 'write');
reporter.stdout('result');
reporter.stderr('result');
t.is(spy.callCount, 2);
process.stderr.write.restore();
t.end();
});

20
test/reporters/verbose.js

@ -1,6 +1,7 @@
'use strict';
var figures = require('figures');
var chalk = require('chalk');
var sinon = require('sinon');
var test = require('tap').test;
var lolex = require('lolex');
var repeating = require('repeating');
@ -424,6 +425,25 @@ test('full-width line when sectioning', function (t) {
t.end();
});
test('write calls console.error', function (t) {
var stub = sinon.stub(console, 'error');
var reporter = verboseReporter();
reporter.write('result');
t.true(stub.called);
console.error.restore();
t.end();
});
test('reporter.stdout and reporter.stderr both use process.stderr.write', function (t) {
var reporter = verboseReporter();
var stub = sinon.stub(process.stderr, 'write');
reporter.stdout('result');
reporter.stderr('result');
t.is(stub.callCount, 2);
process.stderr.write.restore();
t.end();
});
function fooFunc() {
barFunc();
}

6
test/run-status.js

@ -68,3 +68,9 @@ test('prefixTitle removes test- from path', function (t) {
t.is(runStatus.prefixTitle(path.normalize('backend/test-run-status.js')), 'backend' + sep + 'run-status' + sep);
t.end();
});
test('successfully initializes without any options provided', function (t) {
var runStatus = new RunStatus();
t.is(runStatus.base, '');
t.end();
});

Loading…
Cancel
Save