supertape 6.7.4 → 6.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog +11 -0
- package/README.md +4 -1
- package/help.json +1 -0
- package/lib/cli.js +6 -0
- package/lib/operators.mjs +19 -3
- package/lib/run-tests.js +36 -25
- package/lib/supertape.js +6 -0
- package/lib/validator.js +16 -11
- package/package.json +1 -1
package/ChangeLog
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
2021.09.24, v6.8.0
|
|
2
|
+
|
|
3
|
+
fix:
|
|
4
|
+
- (supertape) check that no assertions called after t.end()
|
|
5
|
+
|
|
6
|
+
feature:
|
|
7
|
+
- (supertape) add support of check assertions count
|
|
8
|
+
- (@supertape/operator-stub) add calledBefore, calledAfter
|
|
9
|
+
- (@supertape/operator-stub) notCalled: add additional check: called with args
|
|
10
|
+
|
|
11
|
+
|
|
1
12
|
2021.09.20, v6.7.4
|
|
2
13
|
|
|
3
14
|
fix:
|
package/README.md
CHANGED
|
@@ -46,6 +46,8 @@ Options
|
|
|
46
46
|
-v, --version output version information and exit
|
|
47
47
|
-f, --format use a specific output format - default: progress-bar/tap on CI
|
|
48
48
|
-r, --require require module
|
|
49
|
+
--check-scopes check that messages contains scope: 'scope: message'
|
|
50
|
+
--check-assertions-count check that assertion count is no more then 1
|
|
49
51
|
--no-check-duplicates do not check messages for duplicates
|
|
50
52
|
```
|
|
51
53
|
|
|
@@ -53,7 +55,8 @@ Options
|
|
|
53
55
|
|
|
54
56
|
- `SUPERTAPE_TIMEOUT` - timeout for long running processes;
|
|
55
57
|
- `SUPERTAPE_CHECK_DUPLICATES` - toggle check duplicates;
|
|
56
|
-
- `SUPERTAPE_CHECK_SCOPES` - check that test message has a scope: `scope: subject
|
|
58
|
+
- `SUPERTAPE_CHECK_SCOPES` - check that test message has a scope: `scope: subject`;
|
|
59
|
+
- `SUPERTAPE_CHECK_ASSERTIONS_COUNT` - check that assertion count is no more then 1;
|
|
57
60
|
|
|
58
61
|
```js
|
|
59
62
|
test('tape: error', (t) => {
|
package/help.json
CHANGED
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
"-f, --format ": "use a specific output format - default: progress-bar/tap on CI",
|
|
5
5
|
"-r, --require ": "require module",
|
|
6
6
|
"--check-scopes ": "check that messages contains scope: 'scope: message'",
|
|
7
|
+
"--check-assertions-count ": "check that assertion count is no more then 1",
|
|
7
8
|
"--no-check-duplicates ": "do not check messages for duplicates"
|
|
8
9
|
}
|
package/lib/cli.js
CHANGED
|
@@ -33,6 +33,7 @@ const filesCount = fullstore(0);
|
|
|
33
33
|
const {
|
|
34
34
|
SUPERTAPE_CHECK_DUPLICATES = '1',
|
|
35
35
|
SUPERTAPE_CHECK_SCOPES = '0',
|
|
36
|
+
SUPERTAPE_CHECK_ASSERTIONS_COUNT = '0',
|
|
36
37
|
} = process.env;
|
|
37
38
|
|
|
38
39
|
module.exports = async ({argv, cwd, stdout, stderr, exit}) => {
|
|
@@ -89,6 +90,7 @@ const yargsOptions = {
|
|
|
89
90
|
'help',
|
|
90
91
|
'check-duplicates',
|
|
91
92
|
'check-scopes',
|
|
93
|
+
'check-assertions-count',
|
|
92
94
|
],
|
|
93
95
|
alias: {
|
|
94
96
|
version: 'v',
|
|
@@ -97,12 +99,14 @@ const yargsOptions = {
|
|
|
97
99
|
require: 'r',
|
|
98
100
|
checkDuplicates: 'd',
|
|
99
101
|
checkScopes: 's',
|
|
102
|
+
checkAssertionsCount: 'a',
|
|
100
103
|
},
|
|
101
104
|
default: {
|
|
102
105
|
format: 'progress-bar',
|
|
103
106
|
require: [],
|
|
104
107
|
checkDuplicates: SUPERTAPE_CHECK_DUPLICATES !== '0',
|
|
105
108
|
checkScopes: SUPERTAPE_CHECK_SCOPES === '1',
|
|
109
|
+
checkAssertionsCount: SUPERTAPE_CHECK_ASSERTIONS_COUNT === '1',
|
|
106
110
|
},
|
|
107
111
|
};
|
|
108
112
|
|
|
@@ -148,6 +152,7 @@ async function cli({argv, cwd, stdout, isStop}) {
|
|
|
148
152
|
format,
|
|
149
153
|
checkDuplicates,
|
|
150
154
|
checkScopes,
|
|
155
|
+
checkAssertionsCount,
|
|
151
156
|
} = args;
|
|
152
157
|
|
|
153
158
|
supertape.init({
|
|
@@ -157,6 +162,7 @@ async function cli({argv, cwd, stdout, isStop}) {
|
|
|
157
162
|
isStop,
|
|
158
163
|
checkDuplicates,
|
|
159
164
|
checkScopes,
|
|
165
|
+
checkAssertionsCount,
|
|
160
166
|
});
|
|
161
167
|
|
|
162
168
|
supertape.createStream().pipe(stdout);
|
package/lib/operators.mjs
CHANGED
|
@@ -14,7 +14,6 @@ const isFn = (a) => typeof a === 'function';
|
|
|
14
14
|
const isStr = (a) => typeof a === 'string';
|
|
15
15
|
const isObj = (a) => typeof a === 'object';
|
|
16
16
|
|
|
17
|
-
// backward compatibility or maybe formatters support
|
|
18
17
|
const end = () => {};
|
|
19
18
|
|
|
20
19
|
const ok = (actual, message = 'should be truthy') => ({
|
|
@@ -170,6 +169,21 @@ const initOperator = (runnerState) => (name) => {
|
|
|
170
169
|
};
|
|
171
170
|
|
|
172
171
|
return (...a) => {
|
|
172
|
+
if (name === 'end') {
|
|
173
|
+
runnerState.isEnded(true);
|
|
174
|
+
return end;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
runnerState.incAssertionsCount();
|
|
178
|
+
|
|
179
|
+
if (runnerState.isEnded()) {
|
|
180
|
+
return run(
|
|
181
|
+
'fail',
|
|
182
|
+
runnerState,
|
|
183
|
+
operators.fail(`Cannot run assertions after 't.end()' called`),
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
173
187
|
const testState = fn(...a);
|
|
174
188
|
return run(name, runnerState, testState);
|
|
175
189
|
};
|
|
@@ -223,13 +237,15 @@ function run(name, {formatter, count, incCount, incPassed, incFailed}, testState
|
|
|
223
237
|
});
|
|
224
238
|
}
|
|
225
239
|
|
|
226
|
-
export const initOperators = ({formatter, count, incCount, incPassed, incFailed, extensions}) => {
|
|
240
|
+
export const initOperators = ({formatter, count, incCount, incPassed, incFailed, incAssertionsCount, isEnded, extensions}) => {
|
|
227
241
|
const operator = initOperator({
|
|
228
242
|
formatter,
|
|
229
243
|
count,
|
|
230
244
|
incCount,
|
|
231
245
|
incPassed,
|
|
232
246
|
incFailed,
|
|
247
|
+
isEnded,
|
|
248
|
+
incAssertionsCount,
|
|
233
249
|
});
|
|
234
250
|
|
|
235
251
|
const extendedOperators = {};
|
|
@@ -251,7 +267,7 @@ export const initOperators = ({formatter, count, incCount, incPassed, incFailed,
|
|
|
251
267
|
comment: comment({formatter}),
|
|
252
268
|
match: operator('match'),
|
|
253
269
|
notMatch: operator('notMatch'),
|
|
254
|
-
end,
|
|
270
|
+
end: operator('end'),
|
|
255
271
|
|
|
256
272
|
...extendedOperators,
|
|
257
273
|
};
|
package/lib/run-tests.js
CHANGED
|
@@ -3,24 +3,16 @@
|
|
|
3
3
|
const fullstore = require('fullstore');
|
|
4
4
|
const wraptile = require('wraptile');
|
|
5
5
|
const tryToCatch = require('try-to-catch');
|
|
6
|
-
const once = require('once');
|
|
7
6
|
const isDebug = require('./is-debug');
|
|
8
7
|
|
|
9
8
|
const {createValidator} = require('./validator');
|
|
10
9
|
|
|
11
10
|
const inc = wraptile((store) => store(store() + 1));
|
|
12
|
-
|
|
13
11
|
const isOnly = ({only}) => only;
|
|
14
|
-
|
|
15
12
|
const isSkip = ({skip}) => skip;
|
|
16
|
-
|
|
17
13
|
const notSkip = ({skip}) => !skip;
|
|
18
14
|
|
|
19
|
-
const getInitOperators =
|
|
20
|
-
const {initOperators} = await import('./operators.mjs');
|
|
21
|
-
|
|
22
|
-
return initOperators;
|
|
23
|
-
});
|
|
15
|
+
const getInitOperators = async () => await import('./operators.mjs');
|
|
24
16
|
|
|
25
17
|
const {
|
|
26
18
|
SUPERTAPE_TIMEOUT = 3000,
|
|
@@ -83,7 +75,7 @@ async function runTests(tests, {formatter, operators, skiped, isStop}) {
|
|
|
83
75
|
tests,
|
|
84
76
|
});
|
|
85
77
|
|
|
86
|
-
for (const {fn, message, extensions, at} of tests) {
|
|
78
|
+
for (const {fn, message, extensions, at, validations} of tests) {
|
|
87
79
|
if (wasStop())
|
|
88
80
|
break;
|
|
89
81
|
|
|
@@ -104,6 +96,7 @@ async function runTests(tests, {formatter, operators, skiped, isStop}) {
|
|
|
104
96
|
incFailed,
|
|
105
97
|
incPassed,
|
|
106
98
|
getValidationMessage,
|
|
99
|
+
validations,
|
|
107
100
|
|
|
108
101
|
extensions: {
|
|
109
102
|
...operators,
|
|
@@ -127,12 +120,18 @@ async function runTests(tests, {formatter, operators, skiped, isStop}) {
|
|
|
127
120
|
};
|
|
128
121
|
}
|
|
129
122
|
|
|
130
|
-
async function runOneTest({message, at, fn, extensions, formatter, count, total, failed, incCount, incPassed, incFailed, getValidationMessage}) {
|
|
123
|
+
async function runOneTest({message, at, fn, extensions, formatter, count, total, failed, incCount, incPassed, incFailed, getValidationMessage, validations}) {
|
|
124
|
+
const isReturn = fullstore(false);
|
|
125
|
+
const assertionsCount = fullstore(0);
|
|
126
|
+
const isEnded = fullstore(false);
|
|
127
|
+
const incAssertionsCount = inc(assertionsCount);
|
|
128
|
+
|
|
131
129
|
formatter.emit('test', {
|
|
132
130
|
test: message,
|
|
133
131
|
});
|
|
134
132
|
|
|
135
|
-
const initOperators = await getInitOperators();
|
|
133
|
+
const {initOperators} = await getInitOperators();
|
|
134
|
+
const {checkIfEnded} = validations;
|
|
136
135
|
|
|
137
136
|
const t = initOperators({
|
|
138
137
|
formatter,
|
|
@@ -140,16 +139,35 @@ async function runOneTest({message, at, fn, extensions, formatter, count, total,
|
|
|
140
139
|
incCount,
|
|
141
140
|
incPassed,
|
|
142
141
|
incFailed,
|
|
142
|
+
assertionsCount,
|
|
143
|
+
incAssertionsCount,
|
|
144
|
+
isEnded,
|
|
143
145
|
extensions,
|
|
146
|
+
checkIfEnded,
|
|
144
147
|
});
|
|
145
148
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
if (!isReturn()) {
|
|
150
|
+
const [timer, stopTimer] = timeout(SUPERTAPE_TIMEOUT, ['timeout']);
|
|
151
|
+
const [error] = await Promise.race([tryToCatch(fn, t), timer]);
|
|
152
|
+
stopTimer();
|
|
153
|
+
isEnded(false);
|
|
154
|
+
|
|
155
|
+
if (error) {
|
|
156
|
+
t.fail(error, at);
|
|
157
|
+
t.end();
|
|
158
|
+
isReturn(true);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
149
161
|
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
|
|
162
|
+
if (!isReturn()) {
|
|
163
|
+
const [validationMessage, atLine] = getValidationMessage(message, {
|
|
164
|
+
assertionsCount: assertionsCount(),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
if (atLine) {
|
|
168
|
+
t.fail(validationMessage, atLine);
|
|
169
|
+
t.end();
|
|
170
|
+
}
|
|
153
171
|
}
|
|
154
172
|
|
|
155
173
|
formatter.emit('test:end', {
|
|
@@ -158,11 +176,4 @@ async function runOneTest({message, at, fn, extensions, formatter, count, total,
|
|
|
158
176
|
test: message,
|
|
159
177
|
failed: failed(),
|
|
160
178
|
});
|
|
161
|
-
|
|
162
|
-
const [validationMessage, atLine] = getValidationMessage(message);
|
|
163
|
-
|
|
164
|
-
if (atLine) {
|
|
165
|
-
t.fail(validationMessage, atLine);
|
|
166
|
-
t.end();
|
|
167
|
-
}
|
|
168
179
|
}
|
package/lib/supertape.js
CHANGED
|
@@ -35,6 +35,8 @@ const defaultOptions = {
|
|
|
35
35
|
getOperators,
|
|
36
36
|
isStop: () => false,
|
|
37
37
|
checkDuplicates: true,
|
|
38
|
+
checkIfEnded: true,
|
|
39
|
+
checkAssertionsCount: false,
|
|
38
40
|
checkScopes: false,
|
|
39
41
|
};
|
|
40
42
|
|
|
@@ -111,6 +113,8 @@ function test(message, fn, options = {}) {
|
|
|
111
113
|
isStop,
|
|
112
114
|
checkDuplicates,
|
|
113
115
|
checkScopes,
|
|
116
|
+
checkAssertionsCount,
|
|
117
|
+
checkIfEnded,
|
|
114
118
|
} = {
|
|
115
119
|
...defaultOptions,
|
|
116
120
|
...initedOptions,
|
|
@@ -120,6 +124,8 @@ function test(message, fn, options = {}) {
|
|
|
120
124
|
const validations = {
|
|
121
125
|
checkDuplicates,
|
|
122
126
|
checkScopes,
|
|
127
|
+
checkAssertionsCount,
|
|
128
|
+
checkIfEnded,
|
|
123
129
|
};
|
|
124
130
|
|
|
125
131
|
setValidations(validations);
|
package/lib/validator.js
CHANGED
|
@@ -14,11 +14,13 @@ const processedList = new Set();
|
|
|
14
14
|
const validations = {
|
|
15
15
|
checkDuplicates: true,
|
|
16
16
|
checkScopes: false,
|
|
17
|
+
checkAssertionsCount: true,
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
const validators = {
|
|
20
21
|
checkDuplicates,
|
|
21
22
|
checkScopes,
|
|
23
|
+
checkAssertionsCount,
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
const {
|
|
@@ -33,16 +35,17 @@ const findByMessage = (msg, tests) => {
|
|
|
33
35
|
return filtered;
|
|
34
36
|
};
|
|
35
37
|
|
|
36
|
-
module.exports.setValidations = ({checkDuplicates, checkScopes}) => {
|
|
38
|
+
module.exports.setValidations = ({checkDuplicates, checkScopes, checkAssertionsCount}) => {
|
|
37
39
|
assign(validations, {
|
|
38
40
|
checkDuplicates,
|
|
39
41
|
checkScopes,
|
|
42
|
+
checkAssertionsCount,
|
|
40
43
|
});
|
|
41
44
|
};
|
|
42
45
|
|
|
43
46
|
const isValidationEnabled = (a) => values(a).filter(Boolean).length;
|
|
44
47
|
|
|
45
|
-
module.exports.createValidator = ({tests}) => (msg) => {
|
|
48
|
+
module.exports.createValidator = ({tests}) => (msg, options) => {
|
|
46
49
|
if (!isValidationEnabled(validations))
|
|
47
50
|
return [];
|
|
48
51
|
|
|
@@ -55,7 +58,7 @@ module.exports.createValidator = ({tests}) => (msg) => {
|
|
|
55
58
|
if (!filtered.length)
|
|
56
59
|
throw Error('☝️Looks like message cannot be find in tests, this should never happen');
|
|
57
60
|
|
|
58
|
-
const [message, at] = validators[name](msg, filtered);
|
|
61
|
+
const [message, at] = validators[name](msg, filtered, options);
|
|
59
62
|
|
|
60
63
|
if (at)
|
|
61
64
|
return [message, at];
|
|
@@ -65,14 +68,6 @@ module.exports.createValidator = ({tests}) => (msg) => {
|
|
|
65
68
|
};
|
|
66
69
|
|
|
67
70
|
module.exports.getAt = () => {
|
|
68
|
-
const {
|
|
69
|
-
checkDuplicates,
|
|
70
|
-
checkScopes,
|
|
71
|
-
} = validations;
|
|
72
|
-
|
|
73
|
-
if (!checkDuplicates && !checkScopes)
|
|
74
|
-
return '';
|
|
75
|
-
|
|
76
71
|
return getFileName();
|
|
77
72
|
};
|
|
78
73
|
|
|
@@ -91,6 +86,16 @@ function getFileName() {
|
|
|
91
86
|
return '';
|
|
92
87
|
}
|
|
93
88
|
|
|
89
|
+
function checkAssertionsCount(msg, filtered, options) {
|
|
90
|
+
const {assertionsCount} = options;
|
|
91
|
+
const [, at] = filtered[0];
|
|
92
|
+
|
|
93
|
+
if (assertionsCount > 1)
|
|
94
|
+
return [`Only one assertion per test allowed, looks like you have more`, at];
|
|
95
|
+
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
|
|
94
99
|
function checkScopes(msg, filtered) {
|
|
95
100
|
const [message, at] = filtered[0];
|
|
96
101
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supertape",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.8.0",
|
|
4
4
|
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
5
5
|
"description": "tape compatible test runner with superpowers",
|
|
6
6
|
"homepage": "http://github.com/coderaiser/supertape",
|