escover 1.11.0 → 1.15.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.26, v1.15.0
2
+
3
+ fix:
4
+ - escover: logical: find up
5
+
6
+
7
+ 2022.01.21, v1.14.0
8
+
9
+ feature:
10
+ - escover: instrument: integrate with putout with crawling enabled
11
+ - escover: format: files: add align center
12
+
13
+
14
+ 2022.01.20, v1.13.0
15
+
16
+ feature:
17
+ - escover: add ability to read lcov
18
+ - coverage-file: add ability to parse lcov
19
+ - escover: mark: add support of break
20
+
21
+
22
+ 2022.01.19, v1.12.0
23
+
24
+ feature:
25
+ - escover: add lcov support
26
+
27
+
1
28
  2022.01.19, v1.11.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.
@@ -3,18 +3,18 @@ import {
3
3
  readFileSync,
4
4
  } from 'fs';
5
5
  import tryCatch from 'try-catch';
6
+ import {join} from 'path';
6
7
  import {getFileEntries} from '../c4.js';
7
8
  import {transform} from '../transform.js';
8
9
  import {merge} from '../merge.js';
9
10
  import {findCacheDir} from './find-cache-dir.js';
10
-
11
- const {
12
- stringify,
13
- parse,
14
- } = JSON;
11
+ import {
12
+ generateLcov,
13
+ parseLcov,
14
+ } from './lcov.js';
15
15
 
16
16
  const NAME = 'escover';
17
- const buildName = (a) => `${a}/${NAME}.json`;
17
+ const LCOV = 'lcov.info';
18
18
 
19
19
  export const writeCoverage = () => {
20
20
  const files = getFileEntries();
@@ -23,26 +23,27 @@ export const writeCoverage = () => {
23
23
  return;
24
24
 
25
25
  const parsed = transform(files);
26
-
27
26
  const merged = merge(parsed);
28
- const name = findCacheDir({
27
+ const lcov = generateLcov(merged);
28
+
29
+ const dir = findCacheDir({
29
30
  name: NAME,
30
31
  create: true,
31
32
  });
32
33
 
33
- writeFileSync(buildName(name), stringify(merged, null, 4));
34
+ writeFileSync(join(dir, LCOV), lcov);
34
35
  };
35
36
 
36
37
  export const readCoverage = () => {
37
- const name = findCacheDir({
38
+ const dir = findCacheDir({
38
39
  name: NAME,
39
40
  });
40
41
 
41
- const [error, data] = tryCatch(readFileSync, buildName(name), 'utf8');
42
+ const [error, data] = tryCatch(readFileSync, join(dir, LCOV), 'utf8');
42
43
 
43
44
  if (error)
44
45
  return [];
45
46
 
46
- return parse(data);
47
+ return parseLcov(data);
47
48
  };
48
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) {
@@ -15,3 +15,38 @@ export const createLcov = (files) => {
15
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'),
@@ -56,19 +56,15 @@ export default (coverageFile) => {
56
56
  out(`1..${files.length}`);
57
57
  out(`# files: ${files.length}`);
58
58
  out(`# covered: ${coverage.coveredCount}`);
59
-
60
59
  out('');
61
60
 
62
- if (!coverage.uncoveredCount) {
61
+ if (!coverage.uncoveredCount)
63
62
  out('#️ 🌴 ok');
64
- }
65
63
 
66
- if (coverage.uncoveredCount) {
64
+ if (coverage.uncoveredCount)
67
65
  out(`# 🧨 fail: ${coverage.uncoveredCount}`);
68
- }
69
66
 
70
67
  out('');
71
68
 
72
69
  return output.join('\n');
73
70
  };
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,6 +63,12 @@ export const fix = (path, {options}) => {
65
63
  return;
66
64
  }
67
65
 
66
+ if (path.parentPath.isLogicalExpression())
67
+ return replaceWith(path, SequenceExpression([
68
+ lineNode.expression,
69
+ path.node,
70
+ ]));
71
+ /*
68
72
  if (path.isLogicalExpression()) {
69
73
  replaceWith(path.get('left'), SequenceExpression([
70
74
  lineNode.expression,
@@ -76,6 +80,7 @@ export const fix = (path, {options}) => {
76
80
  ]));
77
81
  return;
78
82
  }
83
+ */
79
84
 
80
85
  if (path.isAssignmentPattern() || path.isAssignmentExpression()) {
81
86
  replaceWith(path.get('right'), SequenceExpression([
@@ -85,25 +90,18 @@ export const fix = (path, {options}) => {
85
90
  return;
86
91
  }
87
92
 
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
93
  if (path.isArrowFunctionExpression())
100
94
  return addMarkToArrowFunction(path, lineNode);
101
95
 
102
- if (path.isThrowStatement())
103
- return addMarkToThrow(path, lineNode);
96
+ if (path.isReturnStatement() || path.isThrowStatement())
97
+ return addMarkToArgument(path, lineNode);
104
98
 
105
- if (path.isContinueStatement())
106
- return addMarkToContinue(path, lineNode);
99
+ if (path.isContinueStatement() || path.isBreakStatement()) {
100
+ return replaceWithMultiple(path, [
101
+ lineNode,
102
+ path.node,
103
+ ]);
104
+ }
107
105
 
108
106
  replaceWith(path, BlockStatement([
109
107
  node,
@@ -112,51 +110,68 @@ export const fix = (path, {options}) => {
112
110
 
113
111
  const EXCLUDE = [
114
112
  LINE,
115
- `(${LINE}, __z)`,
116
113
  `return (${LINE}, __z)`,
117
114
  `return ${LINE}`,
118
115
  `throw (${LINE}, __z)`,
119
116
  ];
120
117
 
121
- export const exclude = () => EXCLUDE;
118
+ const SEQUENCE = `(${LINE}, __z)`;
119
+ const isExclude = (node) => {
120
+ const templates = [
121
+ ...EXCLUDE,
122
+ SEQUENCE,
123
+ ];
124
+ return compareAny(node, templates, {
125
+ findUp: false,
126
+ });
127
+ };
122
128
 
123
- export const include = () => [
124
- 'CallExpression',
125
- 'NewExpression',
126
- 'ReturnStatement',
127
- 'ThrowStatement',
128
- ];
129
+ export const exclude = () => EXCLUDE;
129
130
 
130
131
  export const traverse = ({push}) => ({
131
- 'AssignmentPattern|AssignmentExpression'(path) {
132
- if (compareAny(path.get('right'), EXCLUDE))
132
+ 'ThrowStatement|ReturnStatement'(path) {
133
+ push(path);
134
+ },
135
+ CallExpression(path) {
136
+ if (compare(path.parentPath.node, SEQUENCE))
133
137
  return;
134
138
 
135
139
  push(path);
136
140
  },
137
- ArrowFunctionExpression(path) {
138
- if (path.get('body').isBlockStatement())
141
+ 'CallExpression|NewExpression'(path) {
142
+ if (compare(path.parentPath.node, SEQUENCE))
139
143
  return;
140
144
 
141
145
  push(path);
142
146
  },
143
- ContinueStatement(path) {
144
- if (!path.parentPath.isBlockStatement())
147
+ 'AssignmentPattern|AssignmentExpression'(path) {
148
+ if (isExclude(path.get('right')))
145
149
  return;
146
150
 
147
- const {body} = path.parentPath.node;
148
-
149
- if (compare(body[0], LINE))
151
+ push(path);
152
+ },
153
+ ArrowFunctionExpression(path) {
154
+ if (path.get('body').isBlockStatement())
150
155
  return;
151
156
 
152
157
  push(path);
153
158
  },
154
- LogicalExpression(path) {
155
- if (compareAny(path.get('left'), EXCLUDE))
159
+ 'ContinueStatement|BreakStatement'(path) {
160
+ if (compare(path.getPrevSibling(), LINE))
156
161
  return;
157
162
 
158
163
  push(path);
159
164
  },
165
+ LogicalExpression(path) {
166
+ const leftPath = path.get('left');
167
+ const rightPath = path.get('right');
168
+
169
+ if (!isExclude(leftPath))
170
+ push(leftPath);
171
+
172
+ if (!isExclude(rightPath))
173
+ push(rightPath);
174
+ },
160
175
  BlockStatement(path) {
161
176
  if (path.node.body.length)
162
177
  return;
@@ -164,6 +179,9 @@ export const traverse = ({push}) => ({
164
179
  push(path);
165
180
  },
166
181
  SequenceExpression(path) {
182
+ if (compare(path, `(${LINE}, __z)`))
183
+ return;
184
+
167
185
  const expressions = path.get('expressions');
168
186
 
169
187
  for (const expPath of expressions) {
@@ -177,7 +195,7 @@ export const traverse = ({push}) => ({
177
195
  const consequentPath = path.get('consequent');
178
196
  const alternatePath = path.get('alternate');
179
197
 
180
- if (!consequentPath.isBlockStatement() && !compareAny(consequentPath, EXCLUDE))
198
+ if (!consequentPath.isBlockStatement() && !isExclude(consequentPath))
181
199
  push(consequentPath);
182
200
 
183
201
  if (!alternatePath.node)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escover",
3
- "version": "1.11.0",
3
+ "version": "1.15.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
-