supertape 6.3.1 → 6.7.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 +29 -1
- package/README.md +15 -2
- package/help.json +1 -0
- package/lib/cli.js +11 -1
- package/lib/format.js +1 -1
- package/lib/run-tests.js +7 -7
- package/lib/supertape.js +10 -6
- package/lib/validator.js +117 -0
- package/package.json +3 -2
- package/lib/duplicator.js +0 -50
package/ChangeLog
CHANGED
|
@@ -1,10 +1,38 @@
|
|
|
1
|
+
2021.09.18, v6.7.0
|
|
2
|
+
|
|
3
|
+
feature:
|
|
4
|
+
- (supertape) add --check-scopes flag that checks that test message contains scope
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
2021.09.16, v6.6.0
|
|
8
|
+
|
|
9
|
+
feature:
|
|
10
|
+
- (supertape) add ability to show path of a duplicate
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
2021.09.15, v6.5.0
|
|
14
|
+
|
|
15
|
+
feature:
|
|
16
|
+
- (supertape) add support of file links to WebStorm: at: -> at
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
2021.09.15, v6.4.0
|
|
20
|
+
|
|
21
|
+
fix:
|
|
22
|
+
- (supertape) improve at when found duplicates
|
|
23
|
+
|
|
24
|
+
feature:
|
|
25
|
+
- (supertape) add ability to toggle check duplicates with env variables SUPERTAPE_CHECK_DUPLICATES
|
|
26
|
+
- (@supertape/formatter-progress-bar) add support of SUPERTAPE_PROGRESS_BAR_STACK'
|
|
27
|
+
|
|
28
|
+
|
|
1
29
|
2021.09.15, v6.3.1
|
|
2
30
|
|
|
3
31
|
fix:
|
|
4
32
|
- (supertape) improve at when found duplicates
|
|
5
33
|
|
|
6
34
|
feature:
|
|
7
|
-
- (@supertape/formatter-progress-bar) add support of
|
|
35
|
+
- (@supertape/formatter-progress-bar) add support of SUPERTAPE_PROGRESS_BAR_STACK'
|
|
8
36
|
|
|
9
37
|
|
|
10
38
|
2021.09.14, v6.3.0
|
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[NPMURL]: https://npmjs.org/package/supertape "npm"
|
|
4
4
|
[NPMIMGURL]: https://img.shields.io/npm/v/supertape.svg?style=flat&longCache=true
|
|
5
|
-
[BuildStatusURL]: https://github.com/coderaiser/
|
|
6
|
-
[BuildStatusIMGURL]: https://github.com/coderaiser/
|
|
5
|
+
[BuildStatusURL]: https://github.com/coderaiser/supertape/actions?query=workflow%3A%22Node+CI%22 "Build Status"
|
|
6
|
+
[BuildStatusIMGURL]: https://github.com/coderaiser/supertape/workflows/Node%20CI/badge.svg
|
|
7
7
|
[DependencyStatusURL]: https://david-dm.org/coderaiser/supertape?path=packages/supertape "Dependency Status"
|
|
8
8
|
[DependencyStatusIMGURL]: https://img.shields.io/david/coderaiser/supertape.svg?path=packages/supertape&style=flat&longCache=true
|
|
9
9
|
[CoverageURL]: https://coveralls.io/github/coderaiser/supertape?branch=master
|
|
@@ -49,6 +49,19 @@ Options
|
|
|
49
49
|
--no-check-duplicates do not check messages for duplicates
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
## Environment variables
|
|
53
|
+
|
|
54
|
+
- `SUPERTAPE_TIMEOUT` - timeout for long running processes;
|
|
55
|
+
- `SUPERTAPE_CHECK_DUPLICATES` - toggle check duplicates;
|
|
56
|
+
- `SUPERTAPE_CHECK_SCOPES` - check that test message has a scope: `scope: subject`
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
test('tape: error', (t) => {
|
|
60
|
+
t.equal(error.code, 'ENOENT');
|
|
61
|
+
t.end();
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
52
65
|
## Codemod
|
|
53
66
|
|
|
54
67
|
You can convert your codebase from `tape` to `supertape` with help of a [putout](https://github.com/coderaiser/putout) and built-in [@putout/plugin-tape](https://github.com/coderaiser/putout/tree/master/packages/plugin-tape).
|
package/help.json
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
"-v, --version ": "output version information and exit",
|
|
4
4
|
"-f, --format ": "use a specific output format - default: progress-bar/tap on CI",
|
|
5
5
|
"-r, --require ": "require module",
|
|
6
|
+
"--check-scopes ": "check that messages contains scope: 'scope: message'",
|
|
6
7
|
"--no-check-duplicates ": "do not check messages for duplicates"
|
|
7
8
|
}
|
package/lib/cli.js
CHANGED
|
@@ -30,6 +30,11 @@ const maybeArray = (a) => isArray(a) ? a : [a];
|
|
|
30
30
|
const removeDuplicates = (a) => Array.from(new Set(a));
|
|
31
31
|
const filesCount = fullstore(0);
|
|
32
32
|
|
|
33
|
+
const {
|
|
34
|
+
SUPERTAPE_CHECK_DUPLICATES = '1',
|
|
35
|
+
SUPERTAPE_CHECK_SCOPES = '0',
|
|
36
|
+
} = process.env;
|
|
37
|
+
|
|
33
38
|
module.exports = async ({argv, cwd, stdout, stderr, exit}) => {
|
|
34
39
|
const {isStop} = keypress();
|
|
35
40
|
const [error, result] = await tryToCatch(cli, {
|
|
@@ -83,6 +88,7 @@ const yargsOptions = {
|
|
|
83
88
|
'version',
|
|
84
89
|
'help',
|
|
85
90
|
'check-duplicates',
|
|
91
|
+
'check-scopes',
|
|
86
92
|
],
|
|
87
93
|
alias: {
|
|
88
94
|
version: 'v',
|
|
@@ -90,11 +96,13 @@ const yargsOptions = {
|
|
|
90
96
|
help: 'h',
|
|
91
97
|
require: 'r',
|
|
92
98
|
checkDuplicates: 'd',
|
|
99
|
+
checkScopes: 's',
|
|
93
100
|
},
|
|
94
101
|
default: {
|
|
95
102
|
format: 'progress-bar',
|
|
96
103
|
require: [],
|
|
97
|
-
checkDuplicates:
|
|
104
|
+
checkDuplicates: SUPERTAPE_CHECK_DUPLICATES !== '0',
|
|
105
|
+
checkScopes: SUPERTAPE_CHECK_SCOPES === '1',
|
|
98
106
|
},
|
|
99
107
|
};
|
|
100
108
|
|
|
@@ -139,6 +147,7 @@ async function cli({argv, cwd, stdout, isStop}) {
|
|
|
139
147
|
const {
|
|
140
148
|
format,
|
|
141
149
|
checkDuplicates,
|
|
150
|
+
checkScopes,
|
|
142
151
|
} = args;
|
|
143
152
|
|
|
144
153
|
supertape.init({
|
|
@@ -147,6 +156,7 @@ async function cli({argv, cwd, stdout, isStop}) {
|
|
|
147
156
|
format,
|
|
148
157
|
isStop,
|
|
149
158
|
checkDuplicates,
|
|
159
|
+
checkScopes,
|
|
150
160
|
});
|
|
151
161
|
|
|
152
162
|
supertape.createStream().pipe(stdout);
|
package/lib/format.js
CHANGED
package/lib/run-tests.js
CHANGED
|
@@ -6,7 +6,7 @@ const tryToCatch = require('try-to-catch');
|
|
|
6
6
|
const once = require('once');
|
|
7
7
|
|
|
8
8
|
const isDebug = require('./is-debug');
|
|
9
|
-
const
|
|
9
|
+
const {createValidator} = require('./validator');
|
|
10
10
|
|
|
11
11
|
const inc = wraptile((store) => store(store() + 1));
|
|
12
12
|
const isOnly = ({only}) => only;
|
|
@@ -76,7 +76,7 @@ async function runTests(tests, {formatter, operators, skiped, isStop}) {
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
const wasStop = fullstore();
|
|
79
|
-
const
|
|
79
|
+
const getValidationMessage = createValidator({
|
|
80
80
|
tests,
|
|
81
81
|
});
|
|
82
82
|
|
|
@@ -99,7 +99,7 @@ async function runTests(tests, {formatter, operators, skiped, isStop}) {
|
|
|
99
99
|
incCount,
|
|
100
100
|
incFailed,
|
|
101
101
|
incPassed,
|
|
102
|
-
|
|
102
|
+
getValidationMessage,
|
|
103
103
|
|
|
104
104
|
extensions: {
|
|
105
105
|
...operators,
|
|
@@ -123,7 +123,7 @@ async function runTests(tests, {formatter, operators, skiped, isStop}) {
|
|
|
123
123
|
};
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
async function runOneTest({message, fn, extensions, formatter, count, total, failed, incCount, incPassed, incFailed,
|
|
126
|
+
async function runOneTest({message, fn, extensions, formatter, count, total, failed, incCount, incPassed, incFailed, getValidationMessage}) {
|
|
127
127
|
formatter.emit('test', {
|
|
128
128
|
test: message,
|
|
129
129
|
});
|
|
@@ -159,10 +159,10 @@ async function runOneTest({message, fn, extensions, formatter, count, total, fai
|
|
|
159
159
|
failed: failed(),
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
-
const
|
|
162
|
+
const [validationMessage, at] = getValidationMessage(message);
|
|
163
163
|
|
|
164
|
-
if (
|
|
165
|
-
t.fail(
|
|
164
|
+
if (at) {
|
|
165
|
+
t.fail(validationMessage, at);
|
|
166
166
|
t.end();
|
|
167
167
|
}
|
|
168
168
|
}
|
package/lib/supertape.js
CHANGED
|
@@ -6,7 +6,7 @@ const {createSimport} = require('simport');
|
|
|
6
6
|
|
|
7
7
|
const options = require('../supertape.json');
|
|
8
8
|
|
|
9
|
-
const {
|
|
9
|
+
const {getAt, setValidations} = require('./validator');
|
|
10
10
|
const runTests = require('./run-tests');
|
|
11
11
|
const createFormatter = once(require('./formatter').createFormatter);
|
|
12
12
|
|
|
@@ -35,20 +35,21 @@ const defaultOptions = {
|
|
|
35
35
|
getOperators,
|
|
36
36
|
isStop: () => false,
|
|
37
37
|
checkDuplicates: true,
|
|
38
|
+
checkScopes: false,
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
function _createEmitter({quiet, format, getOperators, isStop}) {
|
|
41
42
|
const tests = [];
|
|
42
43
|
const emitter = new EventEmitter();
|
|
43
44
|
|
|
44
|
-
emitter.on('test', (message, fn, {skip, only, extensions,
|
|
45
|
+
emitter.on('test', (message, fn, {skip, only, extensions, at}) => {
|
|
45
46
|
tests.push({
|
|
46
47
|
message,
|
|
47
48
|
fn,
|
|
48
49
|
skip,
|
|
49
50
|
only,
|
|
50
51
|
extensions,
|
|
51
|
-
|
|
52
|
+
at,
|
|
52
53
|
});
|
|
53
54
|
});
|
|
54
55
|
|
|
@@ -108,17 +109,20 @@ function test(message, fn, options = {}) {
|
|
|
108
109
|
getOperators,
|
|
109
110
|
isStop,
|
|
110
111
|
checkDuplicates,
|
|
112
|
+
checkScopes,
|
|
111
113
|
} = {
|
|
112
114
|
...defaultOptions,
|
|
113
115
|
...initedOptions,
|
|
114
116
|
...options,
|
|
115
117
|
};
|
|
116
118
|
|
|
117
|
-
|
|
118
|
-
message,
|
|
119
|
+
setValidations({
|
|
119
120
|
checkDuplicates,
|
|
121
|
+
checkScopes,
|
|
120
122
|
});
|
|
121
123
|
|
|
124
|
+
const at = getAt();
|
|
125
|
+
|
|
122
126
|
const emitter = createEmitter({
|
|
123
127
|
format,
|
|
124
128
|
quiet,
|
|
@@ -132,7 +136,7 @@ function test(message, fn, options = {}) {
|
|
|
132
136
|
skip,
|
|
133
137
|
only,
|
|
134
138
|
extensions,
|
|
135
|
-
|
|
139
|
+
at,
|
|
136
140
|
});
|
|
137
141
|
|
|
138
142
|
if (run)
|
package/lib/validator.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const once = require('once');
|
|
4
|
+
const StackTracey = require('stacktracey');
|
|
5
|
+
|
|
6
|
+
const getDuplicatesMessage = ([, a]) => a;
|
|
7
|
+
const getMessage = ({message, at}) => [message, at];
|
|
8
|
+
const getMessagesList = (tests) => tests.map(getMessage);
|
|
9
|
+
const compareMessage = (a) => ([b]) => a === b;
|
|
10
|
+
|
|
11
|
+
const SCOPE_DEFINED = /^\w+:/;
|
|
12
|
+
const processedList = new Set();
|
|
13
|
+
|
|
14
|
+
const validations = {
|
|
15
|
+
checkDuplicates: true,
|
|
16
|
+
checkScopes: false,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const validators = {
|
|
20
|
+
checkDuplicates,
|
|
21
|
+
checkScopes,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
assign,
|
|
26
|
+
values,
|
|
27
|
+
entries,
|
|
28
|
+
} = Object;
|
|
29
|
+
|
|
30
|
+
const findByMessage = (msg, tests) => {
|
|
31
|
+
const getMessages = once(getMessagesList);
|
|
32
|
+
const filtered = getMessages(tests).filter(compareMessage(msg));
|
|
33
|
+
|
|
34
|
+
return filtered;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports.setValidations = ({checkDuplicates, checkScopes}) => {
|
|
38
|
+
assign(validations, {
|
|
39
|
+
checkDuplicates,
|
|
40
|
+
checkScopes,
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const isValidationEnabled = (a) => values(a).filter(Boolean).length;
|
|
45
|
+
|
|
46
|
+
module.exports.createValidator = ({tests}) => (msg) => {
|
|
47
|
+
if (!isValidationEnabled(validations))
|
|
48
|
+
return [];
|
|
49
|
+
|
|
50
|
+
for (const [name, enabled] of entries(validations)) {
|
|
51
|
+
if (!enabled)
|
|
52
|
+
continue;
|
|
53
|
+
|
|
54
|
+
const filtered = findByMessage(msg, tests);
|
|
55
|
+
|
|
56
|
+
if (!filtered.length)
|
|
57
|
+
throw Error('☝️Looks like message cannot be fined in tests, this should never happen');
|
|
58
|
+
|
|
59
|
+
const [message, at] = validators[name](msg, filtered);
|
|
60
|
+
|
|
61
|
+
if (at)
|
|
62
|
+
return [message, at];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return [];
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
module.exports.getAt = () => {
|
|
69
|
+
const {
|
|
70
|
+
checkDuplicates,
|
|
71
|
+
checkScopes,
|
|
72
|
+
} = validations;
|
|
73
|
+
|
|
74
|
+
if (!checkDuplicates && !checkScopes)
|
|
75
|
+
return '';
|
|
76
|
+
|
|
77
|
+
return getFileName();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const CALLS_FROM_TEST = 3;
|
|
81
|
+
|
|
82
|
+
function getFileName() {
|
|
83
|
+
const {items} = new StackTracey(Error());
|
|
84
|
+
|
|
85
|
+
for (const {beforeParse, file} of items.slice(CALLS_FROM_TEST)) {
|
|
86
|
+
if (file.includes('node_modules'))
|
|
87
|
+
continue;
|
|
88
|
+
|
|
89
|
+
return beforeParse;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return '';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function checkScopes(msg, filtered) {
|
|
96
|
+
const [message, at] = filtered[0];
|
|
97
|
+
|
|
98
|
+
if (!SCOPE_DEFINED.test(message))
|
|
99
|
+
return [`Scope should be defined before first colon: 'scope: subject', example: 'supertape: validator: enabled'`, at];
|
|
100
|
+
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function checkDuplicates(msg, filtered) {
|
|
105
|
+
if (filtered.length < 2)
|
|
106
|
+
return [];
|
|
107
|
+
|
|
108
|
+
const [first, second] = filtered.map(getDuplicatesMessage);
|
|
109
|
+
|
|
110
|
+
if (processedList.has(first))
|
|
111
|
+
return [];
|
|
112
|
+
|
|
113
|
+
processedList.add(first);
|
|
114
|
+
|
|
115
|
+
return [`Duplicate ${first}`, second];
|
|
116
|
+
}
|
|
117
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supertape",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.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",
|
|
@@ -87,7 +87,8 @@
|
|
|
87
87
|
"nodemon": "^2.0.2",
|
|
88
88
|
"pullout": "^4.0.0",
|
|
89
89
|
"putout": "^20.0.1",
|
|
90
|
-
"runsome": "^1.0.0"
|
|
90
|
+
"runsome": "^1.0.0",
|
|
91
|
+
"try-catch": "^3.0.0"
|
|
91
92
|
},
|
|
92
93
|
"license": "MIT",
|
|
93
94
|
"engines": {
|
package/lib/duplicator.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const once = require('once');
|
|
4
|
-
const StackTracey = require('stacktracey');
|
|
5
|
-
|
|
6
|
-
const getMessage = ({message, duplicatesMessage}) => [message, duplicatesMessage];
|
|
7
|
-
const getMessagesList = (tests) => tests.map(getMessage);
|
|
8
|
-
const compareMessage = (a) => ([b]) => a === b;
|
|
9
|
-
const processedList = new Set();
|
|
10
|
-
|
|
11
|
-
module.exports = ({tests}) => (msg) => {
|
|
12
|
-
const getMessages = once(getMessagesList);
|
|
13
|
-
const duplicates = getMessages(tests).filter(compareMessage(msg));
|
|
14
|
-
|
|
15
|
-
if (duplicates.length < 2)
|
|
16
|
-
return '';
|
|
17
|
-
|
|
18
|
-
const [, duplicatesMessage] = duplicates.pop();
|
|
19
|
-
|
|
20
|
-
if (processedList.has(duplicatesMessage))
|
|
21
|
-
return '';
|
|
22
|
-
|
|
23
|
-
processedList.add(duplicatesMessage);
|
|
24
|
-
return duplicatesMessage;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const messages = new Set();
|
|
28
|
-
const CALLS_FROM_TEST = 2;
|
|
29
|
-
|
|
30
|
-
module.exports.getDuplicatesMessage = ({message, checkDuplicates}) => {
|
|
31
|
-
if (!checkDuplicates)
|
|
32
|
-
return '';
|
|
33
|
-
|
|
34
|
-
if (!messages.has(message)) {
|
|
35
|
-
messages.add(message);
|
|
36
|
-
return '';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const {items} = new StackTracey(Error());
|
|
40
|
-
|
|
41
|
-
for (const {beforeParse, file} of items.slice(CALLS_FROM_TEST)) {
|
|
42
|
-
if (file.includes('node_modules'))
|
|
43
|
-
continue;
|
|
44
|
-
|
|
45
|
-
return beforeParse.replace('at', 'at: ');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return '';
|
|
49
|
-
};
|
|
50
|
-
|