escover 1.12.0 → 1.16.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,3 +1,30 @@
1
+ 2022.01.27, v1.16.0
2
+
3
+ feature:
4
+ - escover: add support of ternary
5
+
6
+
7
+ 2022.01.26, v1.15.0
8
+
9
+ fix:
10
+ - escover: logical: find up
11
+
12
+
13
+ 2022.01.21, v1.14.0
14
+
15
+ feature:
16
+ - escover: instrument: integrate with putout with crawling enabled
17
+ - escover: format: files: add align center
18
+
19
+
20
+ 2022.01.20, v1.13.0
21
+
22
+ feature:
23
+ - escover: add ability to read lcov
24
+ - coverage-file: add ability to parse lcov
25
+ - escover: mark: add support of break
26
+
27
+
1
28
  2022.01.19, v1.12.0
2
29
 
3
30
  feature:
package/README.md CHANGED
@@ -31,7 +31,11 @@ which are needed to load module again, and apply mocks.
31
31
 
32
32
  ### 🤷‍ How to get coverage when mocks are used?
33
33
 
34
- ☝️ Use 🎩 `ESCover`! It supports loaders, `ESM` and collects coverage as a loader!
34
+ ☝️ Use 🎩`ESCover`! It supports loaders, `ESM` and collects coverage as a loader!
35
+
36
+ ### 🤷‍ What with [`coveralls`](https://coveralls.io/)? Does [`lcov`](https://github.com/StevenLooman/mocha-lcov-reporter) supported?
37
+
38
+ ☝️ Sure! `coverage/lcov.info` is main coverage file for 🎩`ESCover`.
35
39
 
36
40
  ## Install
37
41
 
@@ -55,6 +59,15 @@ When everything is covered:
55
59
 
56
60
  ![image](https://user-images.githubusercontent.com/1573141/149822261-ff9bc3b4-6ee4-452c-9ada-3cc922b630ec.png)
57
61
 
62
+ ## What formatters exists?
63
+
64
+ There is two types of formatters:
65
+
66
+ - `lines` adds links to each line;
67
+ - `files` shows information in table;
68
+
69
+ You can choose formatter with `ESCOVER_FORMAT` env variable.
70
+
58
71
  ## What if I want to use 🎩`ESCover` with `mock-import`?
59
72
 
60
73
  Experimental `loaders` supports only one, for now. So [zenload](https://github.com/coderaiser/zenload) should be used.
@@ -8,15 +8,13 @@ import {getFileEntries} from '../c4.js';
8
8
  import {transform} from '../transform.js';
9
9
  import {merge} from '../merge.js';
10
10
  import {findCacheDir} from './find-cache-dir.js';
11
- import {createLcov} from './lcov.js';
12
-
13
- const {
14
- stringify,
15
- parse,
16
- } = JSON;
11
+ import {
12
+ generateLcov,
13
+ parseLcov,
14
+ } from './lcov.js';
17
15
 
18
16
  const NAME = 'escover';
19
- const buildName = (a) => `${a}/${NAME}.json`;
17
+ const LCOV = 'lcov.info';
20
18
 
21
19
  export const writeCoverage = () => {
22
20
  const files = getFileEntries();
@@ -26,27 +24,26 @@ export const writeCoverage = () => {
26
24
 
27
25
  const parsed = transform(files);
28
26
  const merged = merge(parsed);
29
- const lcov = createLcov(merged);
27
+ const lcov = generateLcov(merged);
30
28
 
31
29
  const dir = findCacheDir({
32
30
  name: NAME,
33
31
  create: true,
34
32
  });
35
33
 
36
- writeFileSync(join(dir, 'lcov.info'), lcov);
37
- writeFileSync(buildName(dir), stringify(merged, null, 4));
34
+ writeFileSync(join(dir, LCOV), lcov);
38
35
  };
39
36
 
40
37
  export const readCoverage = () => {
41
- const name = findCacheDir({
38
+ const dir = findCacheDir({
42
39
  name: NAME,
43
40
  });
44
41
 
45
- const [error, data] = tryCatch(readFileSync, buildName(name), 'utf8');
42
+ const [error, data] = tryCatch(readFileSync, join(dir, LCOV), 'utf8');
46
43
 
47
44
  if (error)
48
45
  return [];
49
46
 
50
- return parse(data);
47
+ return parseLcov(data);
51
48
  };
52
49
 
@@ -1,6 +1,6 @@
1
1
  const {entries} = Object;
2
2
 
3
- export const createLcov = (files) => {
3
+ export const generateLcov = (files) => {
4
4
  const result = [];
5
5
 
6
6
  for (const {name, lines} of files) {
@@ -9,9 +9,44 @@ export const createLcov = (files) => {
9
9
  const count = covered ? 1 : 0;
10
10
  result.push(`DA:${line},${count}`);
11
11
  }
12
+
13
+ result.push('end_of_record');
12
14
  }
13
15
 
14
- result.push('end_of_record');
15
-
16
16
  return result.join('\n');
17
17
  };
18
+
19
+ const isEnd = (a) => a === 'end_of_record';
20
+
21
+ export const parseLcov = (lcov) => {
22
+ const files = [];
23
+ let name = '';
24
+ let lines = {};
25
+
26
+ for (const current of lcov.split('\n')) {
27
+ const [cmd, arg] = current.split(':');
28
+
29
+ if (cmd === 'SF') {
30
+ name = arg;
31
+ lines = {};
32
+ continue;
33
+ }
34
+
35
+ if (cmd === 'DA') {
36
+ const [line, covered] = arg.split(',');
37
+ lines[line] = Boolean(Number(covered));
38
+ continue;
39
+ }
40
+
41
+ if (isEnd(cmd)) {
42
+ files.push({
43
+ name,
44
+ lines,
45
+ });
46
+ continue;
47
+ }
48
+ }
49
+
50
+ return files;
51
+ };
52
+
@@ -35,6 +35,8 @@ export default (coverageFile) => {
35
35
  },
36
36
  columns: [{
37
37
  paddingLeft: 0,
38
+ }, {
39
+ alignment: 'center',
38
40
  }],
39
41
  border: {
40
42
  ...getBorderCharacters('void'),
@@ -1,7 +1,8 @@
1
1
  import chalk from 'chalk';
2
- const {entries} = Object;
3
2
 
3
+ const {entries} = Object;
4
4
  const createOut = (output) => (a) => output.push(a);
5
+
5
6
  export default (coverageFile) => {
6
7
  const output = [];
7
8
  const out = createOut(output);
@@ -56,19 +57,15 @@ export default (coverageFile) => {
56
57
  out(`1..${files.length}`);
57
58
  out(`# files: ${files.length}`);
58
59
  out(`# covered: ${coverage.coveredCount}`);
59
-
60
60
  out('');
61
61
 
62
- if (!coverage.uncoveredCount) {
62
+ if (!coverage.uncoveredCount)
63
63
  out('#️ 🌴 ok');
64
- }
65
64
 
66
- if (coverage.uncoveredCount) {
65
+ if (coverage.uncoveredCount)
67
66
  out(`# 🧨 fail: ${coverage.uncoveredCount}`);
68
- }
69
67
 
70
68
  out('');
71
69
 
72
70
  return output.join('\n');
73
71
  };
74
-
@@ -1,5 +1,4 @@
1
1
  import putout from 'putout';
2
-
3
2
  import * as mark from './plugin-mark/index.js';
4
3
 
5
4
  export const instrument = (url, source) => {
@@ -1,7 +1,7 @@
1
1
  import {types} from 'putout';
2
2
  const {SequenceExpression} = types;
3
3
 
4
- export const addMarkToReturn = (path, lineNode) => {
4
+ export const addMarkToArgument = (path, lineNode) => {
5
5
  const {node} = path;
6
6
  const {expression} = lineNode;
7
7
 
@@ -4,10 +4,8 @@ import {
4
4
  operator,
5
5
  } from 'putout';
6
6
 
7
- import {addMarkToReturn} from './return.js';
7
+ import {addMarkToArgument} from './argument.js';
8
8
  import {addMarkToArrowFunction} from './arrow.js';
9
- import {addMarkToThrow} from './throw.js';
10
- import {addMarkToContinue} from './continue.js';
11
9
 
12
10
  const {
13
11
  NumericLiteral,
@@ -19,6 +17,7 @@ const {
19
17
  replaceWith,
20
18
  compareAny,
21
19
  compare,
20
+ replaceWithMultiple,
22
21
  } = operator;
23
22
 
24
23
  const LINE = `__c4['🧨'](__l, __c)`;
@@ -39,12 +38,10 @@ export const report = () => 'Mark line';
39
38
 
40
39
  export const fix = (path, {options}) => {
41
40
  const {node} = path;
42
-
43
41
  const {start} = path.node.loc;
44
42
 
45
43
  const {
46
44
  c4 = {
47
- mark: () => {},
48
45
  init: () => {},
49
46
  },
50
47
  } = options;
@@ -56,8 +53,9 @@ export const fix = (path, {options}) => {
56
53
  return;
57
54
  }
58
55
 
59
- if (path.isCallExpression()) {
56
+ if (path.isCallExpression() || path.isNewExpression()) {
60
57
  const {node} = path;
58
+
61
59
  replaceWith(path, SequenceExpression([
62
60
  lineNode.expression,
63
61
  node,
@@ -65,17 +63,11 @@ export const fix = (path, {options}) => {
65
63
  return;
66
64
  }
67
65
 
68
- if (path.isLogicalExpression()) {
69
- replaceWith(path.get('left'), SequenceExpression([
66
+ if (path.parentPath.isLogicalExpression())
67
+ return replaceWith(path, SequenceExpression([
70
68
  lineNode.expression,
71
- path.node.left,
69
+ path.node,
72
70
  ]));
73
- replaceWith(path.get('right'), SequenceExpression([
74
- getLineNode(c4, path.node.right.loc.start).expression,
75
- path.node.right,
76
- ]));
77
- return;
78
- }
79
71
 
80
72
  if (path.isAssignmentPattern() || path.isAssignmentExpression()) {
81
73
  replaceWith(path.get('right'), SequenceExpression([
@@ -85,25 +77,18 @@ export const fix = (path, {options}) => {
85
77
  return;
86
78
  }
87
79
 
88
- if (path.isNewExpression()) {
89
- replaceWith(path, SequenceExpression([
90
- lineNode.expression,
91
- node,
92
- ]));
93
- return;
94
- }
95
-
96
- if (path.isReturnStatement())
97
- return addMarkToReturn(path, lineNode);
98
-
99
80
  if (path.isArrowFunctionExpression())
100
81
  return addMarkToArrowFunction(path, lineNode);
101
82
 
102
- if (path.isThrowStatement())
103
- return addMarkToThrow(path, lineNode);
83
+ if (path.isReturnStatement() || path.isThrowStatement())
84
+ return addMarkToArgument(path, lineNode);
104
85
 
105
- if (path.isContinueStatement())
106
- return addMarkToContinue(path, lineNode);
86
+ if (path.isContinueStatement() || path.isBreakStatement()) {
87
+ return replaceWithMultiple(path, [
88
+ lineNode,
89
+ path.node,
90
+ ]);
91
+ }
107
92
 
108
93
  replaceWith(path, BlockStatement([
109
94
  node,
@@ -112,51 +97,68 @@ export const fix = (path, {options}) => {
112
97
 
113
98
  const EXCLUDE = [
114
99
  LINE,
115
- `(${LINE}, __z)`,
116
100
  `return (${LINE}, __z)`,
117
101
  `return ${LINE}`,
118
102
  `throw (${LINE}, __z)`,
119
103
  ];
120
104
 
121
- export const exclude = () => EXCLUDE;
105
+ const SEQUENCE = `(${LINE}, __z)`;
106
+ const isExclude = (node) => {
107
+ const templates = [
108
+ ...EXCLUDE,
109
+ SEQUENCE,
110
+ ];
111
+ return compareAny(node, templates, {
112
+ findUp: false,
113
+ });
114
+ };
122
115
 
123
- export const include = () => [
124
- 'CallExpression',
125
- 'NewExpression',
126
- 'ReturnStatement',
127
- 'ThrowStatement',
128
- ];
116
+ export const exclude = () => EXCLUDE;
129
117
 
130
118
  export const traverse = ({push}) => ({
131
- 'AssignmentPattern|AssignmentExpression'(path) {
132
- if (compareAny(path.get('right'), EXCLUDE))
119
+ 'ThrowStatement|ReturnStatement'(path) {
120
+ push(path);
121
+ },
122
+ CallExpression(path) {
123
+ if (compare(path.parentPath.node, SEQUENCE))
133
124
  return;
134
125
 
135
126
  push(path);
136
127
  },
137
- ArrowFunctionExpression(path) {
138
- if (path.get('body').isBlockStatement())
128
+ 'CallExpression|NewExpression'(path) {
129
+ if (compare(path.parentPath.node, SEQUENCE))
139
130
  return;
140
131
 
141
132
  push(path);
142
133
  },
143
- ContinueStatement(path) {
144
- if (!path.parentPath.isBlockStatement())
134
+ 'AssignmentPattern|AssignmentExpression'(path) {
135
+ if (isExclude(path.get('right')))
145
136
  return;
146
137
 
147
- const {body} = path.parentPath.node;
148
-
149
- if (compare(body[0], LINE))
138
+ push(path);
139
+ },
140
+ ArrowFunctionExpression(path) {
141
+ if (path.get('body').isBlockStatement())
150
142
  return;
151
143
 
152
144
  push(path);
153
145
  },
154
- LogicalExpression(path) {
155
- if (compareAny(path.get('left'), EXCLUDE))
146
+ 'ContinueStatement|BreakStatement'(path) {
147
+ if (compare(path.getPrevSibling(), LINE))
156
148
  return;
157
149
 
158
150
  push(path);
159
151
  },
152
+ LogicalExpression(path) {
153
+ const leftPath = path.get('left');
154
+ const rightPath = path.get('right');
155
+
156
+ if (!isExclude(leftPath))
157
+ push(leftPath);
158
+
159
+ if (!isExclude(rightPath))
160
+ push(rightPath);
161
+ },
160
162
  BlockStatement(path) {
161
163
  if (path.node.body.length)
162
164
  return;
@@ -164,6 +166,10 @@ export const traverse = ({push}) => ({
164
166
  push(path);
165
167
  },
166
168
  SequenceExpression(path) {
169
+ if (compare(path, `(${LINE}, __z)`)) {
170
+ return;
171
+ }
172
+
167
173
  const expressions = path.get('expressions');
168
174
 
169
175
  for (const expPath of expressions) {
@@ -173,17 +179,17 @@ export const traverse = ({push}) => ({
173
179
  push(expPath);
174
180
  }
175
181
  },
176
- IfStatement(path) {
182
+ 'IfStatement|ConditionalExpression'(path) {
177
183
  const consequentPath = path.get('consequent');
178
184
  const alternatePath = path.get('alternate');
179
185
 
180
- if (!consequentPath.isBlockStatement() && !compareAny(consequentPath, EXCLUDE))
186
+ if (!consequentPath.isBlockStatement() && !isExclude(consequentPath))
181
187
  push(consequentPath);
182
188
 
183
189
  if (!alternatePath.node)
184
190
  return;
185
191
 
186
- if (!alternatePath.isBlockStatement())
192
+ if (!alternatePath.isBlockStatement() && !isExclude(alternatePath))
187
193
  push(alternatePath);
188
194
  },
189
195
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escover",
3
- "version": "1.12.0",
3
+ "version": "1.16.0",
4
4
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
5
5
  "description": "Coverage for EcmaScript Modules",
6
6
  "main": "lib/escover.js",
@@ -1,10 +0,0 @@
1
- import {operator} from 'putout';
2
- const {replaceWithMultiple} = operator;
3
-
4
- export const addMarkToContinue = (path, lineNode) => {
5
- return replaceWithMultiple(path, [
6
- lineNode,
7
- path.node,
8
- ]);
9
- };
10
-
@@ -1,17 +0,0 @@
1
- import {
2
- types,
3
- operator,
4
- } from 'putout';
5
- const {SequenceExpression} = types;
6
-
7
- const {replaceWith} = operator;
8
-
9
- export const addMarkToThrow = (path, lineNode) => {
10
- const argumentPath = path.get('argument');
11
-
12
- return replaceWith(argumentPath, SequenceExpression([
13
- lineNode.expression,
14
- argumentPath.node,
15
- ]));
16
- };
17
-