Skip to content

Commit 2fb5a66

Browse files
jocrahljharb
andcommittedJan 22, 2022
[New] add --no-only flag/NODE_TAPE_NO_ONLY_TEST
Co-authored-by: Joshua Ocrah <[email protected]> Co-authored-by: Jordan Harband <[email protected]>
1 parent 8594f3b commit 2fb5a66

File tree

7 files changed

+181
-4
lines changed

7 files changed

+181
-4
lines changed
 

‎.eslintrc

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
"no-magic-numbers": "off",
1818
"max-lines": "warn",
1919
"max-lines-per-function": "warn",
20-
"max-statements": "warn",
2120
"max-statements-per-line": [2, { "max": 2 }],
21+
"max-statements": "warn",
2222
"multiline-comment-style": "off",
2323
"no-negated-condition": "off",
24-
"no-use-before-define": "warn",
2524
"no-underscore-dangle": "warn",
25+
"no-use-before-define": "warn",
26+
"object-curly-newline": "off",
2627
"sort-keys": "warn",
2728
},
2829
"ignorePatterns": ["syntax-error.*"],

‎bin/tape

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@ var objectKeys = require('object-keys');
88
var opts = parseOpts(process.argv.slice(2), {
99
alias: { r: 'require', i: 'ignore' },
1010
string: ['require', 'ignore'],
11-
default: { r: [], i: null }
11+
boolean: ['only'],
12+
default: { r: [], i: null, only: null }
1213
});
1314

15+
if (typeof opts.only === 'boolean') {
16+
process.env.NODE_TAPE_NO_ONLY_TEST = !opts.only;
17+
}
18+
1419
var cwd = process.cwd();
1520

1621
if (typeof opts.require === 'string') {

‎index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ module.exports = (function () {
6666
function createExitHarness(conf, wait) {
6767
var config = conf || {};
6868
var harness = createHarness({
69-
autoclose: defined(config.autoclose, false)
69+
autoclose: defined(config.autoclose, false),
70+
noOnly: defined(conf.noOnly, defined(process.env.NODE_TAPE_NO_ONLY_TEST, false))
7071
});
7172
var running = false;
7273
var ended = false;
@@ -163,6 +164,7 @@ function createHarness(conf_) {
163164
var only = false;
164165
test.only = function () {
165166
if (only) { throw new Error('there can only be one only test'); }
167+
if (conf_.noOnly) { throw new Error('`only` tests are prohibited'); }
166168
only = true;
167169
var t = test.apply(null, arguments);
168170
results.only(t);

‎readme.markdown

+37
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,41 @@ By default, uncaught exceptions in your tests will not be intercepted, and will
144144
- In-process reporting with https://github.com/DavidAnson/tape-player
145145
- Describe blocks with https://github.com/mattriley/tape-describe
146146

147+
# command-line flags
148+
149+
While running tests, top-level configurations can be passed via the command line to specify desired behavior.
150+
151+
Available configurations are listed below:
152+
153+
## --require
154+
155+
**Alias**: `-r`
156+
157+
This is used to load modules before running tests and is explained extensively in the [preloading modules](#preloading-modules) section.
158+
159+
## --ignore
160+
161+
**Alias**: `-i`
162+
163+
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.
164+
165+
```sh
166+
tape -i .ignore **/*.js
167+
```
168+
169+
An error is thrown if the specified file passed as argument does not exist.
170+
171+
## --no-only
172+
This is particularly useful in a CI environment where an [only test](#testonlyname-opts-cb) is not supposed to go unnoticed.
173+
174+
By passing the `--no-only` flag, any existing [only test](#testonlyname-opts-cb) causes tests to fail.
175+
176+
```sh
177+
tape --no-only **/*.js
178+
```
179+
180+
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.
181+
147182
# methods
148183

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

363398
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.
364399

400+
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.
401+
365402
## var stream = test.createStream(opts)
366403

367404
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`.

‎test/no_only.js

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
'use strict';
2+
3+
var tap = require('tap');
4+
var path = require('path');
5+
var exec = require('child_process').exec;
6+
7+
var stripFullStack = require('./common').stripFullStack;
8+
9+
var tapeBin = path.join(__dirname, '../bin/tape');
10+
11+
var expectedExitCodeFailure = (/^0\.10\.\d+$/).test(process.versions.node);
12+
var expectedStackTraceBug = (/^3\.[012]\.\d+$/).test(process.versions.node); // https://github.com/nodejs/node/issues/2581
13+
14+
tap.test(
15+
'Should throw error when --no-only is passed via cli and there is a .only test',
16+
{ todo: expectedExitCodeFailure || expectedStackTraceBug ? 'Fails on these node versions' : false },
17+
function (tt) {
18+
tt.plan(3);
19+
20+
exec(tapeBin + ' --no-only "**/*.js"', {
21+
cwd: path.join(__dirname, 'no_only')
22+
}, function (err, stdout, stderr) {
23+
tt.same(stdout.toString('utf8'), '');
24+
tt.match(stripFullStack(stderr.toString('utf8')).join('\n'), /Error: `only` tests are prohibited\n/);
25+
tt.equal(err.code, 1);
26+
});
27+
}
28+
);
29+
30+
tap.test(
31+
'Should throw error when NODE_TAPE_NO_ONLY_TEST is passed via envs and there is an .only test',
32+
{ todo: expectedExitCodeFailure || expectedStackTraceBug ? 'Fails on these node versions' : false },
33+
function (tt) {
34+
tt.plan(3);
35+
36+
exec(tapeBin + ' "**/*.js"', {
37+
cwd: path.join(__dirname, 'no_only'),
38+
env: { PATH: process.env.PATH, NODE_TAPE_NO_ONLY_TEST: 'true' }
39+
}, function (err, stdout, stderr) {
40+
tt.same(stdout.toString('utf8'), '');
41+
tt.match(stripFullStack(stderr.toString('utf8')).join('\n'), /Error: `only` tests are prohibited\n/);
42+
tt.equal(err.code, 1);
43+
});
44+
}
45+
);
46+
47+
tap.test(
48+
'Should override NODE_TAPE_NO_ONLY_TEST env if --no-only is passed from cli',
49+
{ todo: expectedExitCodeFailure || expectedStackTraceBug ? 'Fails on these node versions' : false },
50+
function (tt) {
51+
tt.plan(3);
52+
53+
exec(tapeBin + ' --no-only "**/*.js"', {
54+
cwd: path.join(__dirname, 'no_only'),
55+
env: { PATH: process.env.PATH, NODE_TAPE_NO_ONLY_TEST: 'false' }
56+
}, function (err, stdout, stderr) {
57+
tt.same(stdout.toString('utf8'), '');
58+
tt.match(stripFullStack(stderr.toString('utf8')).join('\n'), /Error: `only` tests are prohibited\n/);
59+
tt.equal(err.code, 1);
60+
});
61+
}
62+
);
63+
64+
tap.test('Should run successfully if there is no only test', function (tt) {
65+
tt.plan(3);
66+
67+
exec(tapeBin + ' --no-only "**/test-a.js"', {
68+
cwd: path.join(__dirname, 'no_only')
69+
}, function (err, stdout, stderr) {
70+
tt.match(stderr.toString('utf8'), /^\s*(\(node:\d+\) ExperimentalWarning: The ESM module loader is experimental\.)?\s*$/);
71+
tt.same(stripFullStack(stdout.toString('utf8')), [
72+
'TAP version 13',
73+
'# should pass',
74+
'ok 1 should be truthy',
75+
'',
76+
'1..1',
77+
'# tests 1',
78+
'# pass 1',
79+
'',
80+
'# ok',
81+
'',
82+
''
83+
]);
84+
tt.equal(err, null); // code 0
85+
});
86+
});
87+
88+
tap.test('Should run successfully if there is an only test and no --no-only flag', function (tt) {
89+
tt.plan(3);
90+
91+
exec(tapeBin + ' "**/test-b.js"', {
92+
cwd: path.join(__dirname, 'no_only')
93+
}, function (err, stdout, stderr) {
94+
tt.same(stripFullStack(stdout.toString('utf8')), [
95+
'TAP version 13',
96+
'# should pass again',
97+
'ok 1 should be truthy',
98+
'',
99+
'1..1',
100+
'# tests 1',
101+
'# pass 1',
102+
'',
103+
'# ok',
104+
'',
105+
''
106+
]);
107+
tt.match(stderr.toString('utf8'), /^\s*(\(node:\d+\) ExperimentalWarning: The ESM module loader is experimental\.)?\s*$/);
108+
tt.equal(err, null); // code 0
109+
});
110+
});

‎test/no_only/test-a.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
var tape = require('../../');
4+
5+
tape.test('should pass', function (t) {
6+
t.plan(1);
7+
t.ok(1);
8+
});

‎test/no_only/test-b.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
3+
var tape = require('../../');
4+
5+
tape.test('should pass', function (t) {
6+
t.plan(1);
7+
t.ok(1);
8+
});
9+
10+
tape.test.only('should pass again', function (t) {
11+
t.plan(1);
12+
t.ok(1);
13+
});
14+

0 commit comments

Comments
 (0)
Please sign in to comment.