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 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 SUPERTAPE_PROGRESS_BAR_SHORT'
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/putout/actions?query=workflow%3A%22Node+CI%22 "Build Status"
6
- [BuildStatusIMGURL]: https://github.com/coderaiser/putout/workflows/Node%20CI/badge.svg
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: true,
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
@@ -13,7 +13,7 @@ module.exports.parseAt = (stack, {reason}) => {
13
13
 
14
14
  const line = lines[reason === 'user' ? REASON_USER : REASON_EXCEPTION];
15
15
 
16
- return line.trim().replace('at', 'at:');
16
+ return line.trim();
17
17
  };
18
18
 
19
19
  module.exports.addSpaces = addSpaces;
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 duplicator = require('./duplicator');
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 getDuplicatesMessage = duplicator({
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
- getDuplicatesMessage,
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, getDuplicatesMessage}) {
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 duplicateAt = getDuplicatesMessage(message);
162
+ const [validationMessage, at] = getValidationMessage(message);
163
163
 
164
- if (duplicateAt) {
165
- t.fail('Duplicate message', duplicateAt);
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 {getDuplicatesMessage} = require('./duplicator');
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, duplicatesMessage}) => {
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
- duplicatesMessage,
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
- const duplicatesMessage = getDuplicatesMessage({
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
- duplicatesMessage,
139
+ at,
136
140
  });
137
141
 
138
142
  if (run)
@@ -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.1",
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
-