Skip to content

Commit

Permalink
[New] add --no-only flag/NODE_TAPE_NO_ONLY_TEST
Browse files Browse the repository at this point in the history
  • Loading branch information
jocrah authored and ljharb committed Jan 22, 2022
1 parent 8594f3b commit 567b106
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 4 deletions.
5 changes: 3 additions & 2 deletions .eslintrc
Expand Up @@ -17,12 +17,13 @@
"no-magic-numbers": "off",
"max-lines": "warn",
"max-lines-per-function": "warn",
"max-statements": "warn",
"max-statements-per-line": [2, { "max": 2 }],
"max-statements": "warn",
"multiline-comment-style": "off",
"no-negated-condition": "off",
"no-use-before-define": "warn",
"no-underscore-dangle": "warn",
"no-use-before-define": "warn",
"object-curly-newline": "off",
"sort-keys": "warn",
},
"ignorePatterns": ["syntax-error.*"],
Expand Down
7 changes: 6 additions & 1 deletion bin/tape
Expand Up @@ -8,9 +8,14 @@ var objectKeys = require('object-keys');
var opts = parseOpts(process.argv.slice(2), {
alias: { r: 'require', i: 'ignore' },
string: ['require', 'ignore'],
default: { r: [], i: null }
boolean: ['only'],
default: { r: [], i: null, only: null }
});

if (typeof opts.only === 'boolean') {
process.env.NODE_TAPE_NO_ONLY_TEST = !opts.only;
}

var cwd = process.cwd();

if (typeof opts.require === 'string') {
Expand Down
4 changes: 3 additions & 1 deletion index.js
Expand Up @@ -66,7 +66,8 @@ module.exports = (function () {
function createExitHarness(conf, wait) {
var config = conf || {};
var harness = createHarness({
autoclose: defined(config.autoclose, false)
autoclose: defined(config.autoclose, false),
noOnly: defined(conf.noOnly, defined(process.env.NODE_TAPE_NO_ONLY_TEST, false))
});
var running = false;
var ended = false;
Expand Down Expand Up @@ -163,6 +164,7 @@ function createHarness(conf_) {
var only = false;
test.only = function () {
if (only) { throw new Error('there can only be one only test'); }
if (conf_.noOnly) { throw new Error('`only` tests are prohibited'); }
only = true;
var t = test.apply(null, arguments);
results.only(t);
Expand Down
37 changes: 37 additions & 0 deletions readme.markdown
Expand Up @@ -144,6 +144,41 @@ By default, uncaught exceptions in your tests will not be intercepted, and will
- In-process reporting with https://github.com/DavidAnson/tape-player
- Describe blocks with https://github.com/mattriley/tape-describe

# command-line flags

While running tests, top-level configurations can be passed via the command line to specify desired behavior.

Available configurations are listed below:

## --require

**Alias**: `-r`

This is used to load modules before running tests and is explained extensively in the [preloading modules](#preloading-modules) section.

## --ignore

**Alias**: `-i`

This flag is used when tests from certain folders and/or files are not intended to be run. It defaults to `.gitignore` file when passed with no argument.

```sh
tape -i .ignore **/*.js
```

An error is thrown if the specified file passed as argument does not exist.

## --no-only
This is particularly useful in a CI environment where an [only test](#testonlyname-opts-cb) is not supposed to go unnoticed.

By passing the `--no-only` flag, any existing [only test](#testonlyname-opts-cb) causes tests to fail.

```sh
tape --no-only **/*.js
```

Alternatively, the environment variable `NODE_TAPE_NO_ONLY_TEST` can be set to `true` to achieve the same behavior; the command-line flag takes precedence.

# methods

The assertion methods in `tape` are heavily influenced or copied from the methods in [node-tap](https://github.com/isaacs/node-tap).
Expand Down Expand Up @@ -362,6 +397,8 @@ By default the TAP output goes to `console.log()`. You can pipe the output to so

Like `test([name], [opts], cb)` except if you use `.only` this is the only test case that will run for the entire process, all other test cases using `tape` will be ignored.

Check out how the usage of [the --no-only flag](#--no-only) could help ensure there is no `.only` test running in a specified environment.

## var stream = test.createStream(opts)

Create a stream of output, bypassing the default output stream that writes messages to `console.log()`. By default `stream` will be a text stream of TAP output, but you can get an object stream instead by setting `opts.objectMode` to `true`.
Expand Down
123 changes: 123 additions & 0 deletions test/no_only.js
@@ -0,0 +1,123 @@
'use strict';

var tap = require('tap');
var path = require('path');
var spawn = require('child_process').spawn;
var concat = require('concat-stream');

var stripFullStack = require('./common').stripFullStack;

var tapeBin = path.join(__dirname, '../bin/tape');

var expectedFailure = (/^0\.10\.\d+$/).test(process.versions.node);

tap.test(
'Should throw error when --no-only is passed via cli and there is a .only test',
{ todo: expectedFailure ? 'Fails on these node versions' : false },
function (tt) {
tt.plan(2);

var testStderr = function (rows) {
tt.ok((/Error: `only` tests are prohibited\n/).test(stripFullStack(rows.toString('utf8')).join('\n')));
};

var ps = spawn(tapeBin, ['--no-only', '**/*.js'], { cwd: path.join(__dirname, 'no_only') });
ps.stderr.pipe(concat(testStderr));
ps.on('exit', function (code) {
tt.equal(code, 1);
});
}
);

tap.test(
'Should throw error when NODE_TAPE_NO_ONLY_TEST is passed via envs and there is an .only test',
{ todo: expectedFailure ? 'Fails on these node versions' : false },
function (tt) {
tt.plan(2);

var testStderr = function (rows) {
tt.ok((/Error: `only` tests are prohibited\n/).test(stripFullStack(rows.toString('utf8')).join('\n')));
};
var ps = spawn(tapeBin, ['**/*.js'], {
cwd: path.join(__dirname, 'no_only'),
env: { PATH: process.env.PATH, NODE_TAPE_NO_ONLY_TEST: 'true' }
});
ps.stderr.pipe(concat(testStderr));
ps.on('exit', function (code) {
tt.equal(code, 1);
});
}
);

tap.test(
'Should override NODE_TAPE_NO_ONLY_TEST env if --no-only is passed from cli',
{ todo: expectedFailure ? 'Fails on these node versions' : false },
function (tt) {
tt.plan(2);

var testStderr = function (rows) {
tt.ok((/Error: `only` tests are prohibited\n/).test(stripFullStack(rows.toString('utf8')).join('\n')));
};

var ps = spawn(tapeBin, ['--no-only', '**/*.js'], {
cwd: path.join(__dirname, 'no_only'),
env: { PATH: process.env.PATH, NODE_TAPE_NO_ONLY_TEST: 'false' }
});
ps.stderr.pipe(concat(testStderr));
ps.on('exit', function (code) {
tt.equal(code, 1);
});
}
);

tap.test('Should run successfully if there is no only test', function (tt) {
tt.plan(2);

var testStdout = function (rows) {
tt.same(stripFullStack(rows.toString('utf8')), [
'TAP version 13',
'# should pass',
'ok 1 should be truthy',
'',
'1..1',
'# tests 1',
'# pass 1',
'',
'# ok',
'',
''
]);
};

var ps = spawn(tapeBin, ['**/test-a.js', '--no-only'], { cwd: path.join(__dirname, 'no_only') });
ps.stdout.pipe(concat(testStdout));
ps.on('exit', function (code) {
tt.equal(code, 0);
});
});

tap.test('Should run successfully if there is an only test and no --no-only flag', function (tt) {
tt.plan(2);

var testStdout = function (rows) {
tt.same(stripFullStack(rows.toString('utf8')), [
'TAP version 13',
'# should pass again',
'ok 1 should be truthy',
'',
'1..1',
'# tests 1',
'# pass 1',
'',
'# ok',
'',
''
]);
};

var ps = spawn(tapeBin, ['**/test-b.js'], { cwd: path.join(__dirname, 'no_only') });
ps.stdout.pipe(concat(testStdout));
ps.on('exit', function (code) {
tt.equal(code, 0);
});
});
8 changes: 8 additions & 0 deletions test/no_only/test-a.js
@@ -0,0 +1,8 @@
'use strict';

var tape = require('../../');

tape.test('should pass', function (t) {
t.plan(1);
t.ok(1);
});
14 changes: 14 additions & 0 deletions test/no_only/test-b.js
@@ -0,0 +1,14 @@
'use strict';

var tape = require('../../');

tape.test('should pass', function (t) {
t.plan(1);
t.ok(1);
});

tape.test.only('should pass again', function (t) {
t.plan(1);
t.ok(1);
});

0 comments on commit 567b106

Please sign in to comment.