escover 1.10.0 → 1.14.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,31 @@
1
+ 2022.01.21, v1.14.0
2
+
3
+ feature:
4
+ - escover: instrument: integrate with putout with crawling enabled
5
+ - escover: format: files: add align center
6
+
7
+
8
+ 2022.01.20, v1.13.0
9
+
10
+ feature:
11
+ - escover: add ability to read lcov
12
+ - coverage-file: add ability to parse lcov
13
+ - escover: mark: add support of break
14
+
15
+
16
+ 2022.01.19, v1.12.0
17
+
18
+ feature:
19
+ - escover: add lcov support
20
+
21
+
22
+ 2022.01.19, v1.11.0
23
+
24
+ feature:
25
+ - escover: mark: add support of continue
26
+ - escover: coverage-file: read -> readCoverage
27
+
28
+
1
29
  2022.01.19, v1.10.0
2
30
 
3
31
  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.
package/bin/escover.js CHANGED
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import {cli} from '../lib/cli/cli.js';
4
- import {read} from '../lib/coverage-file/coverage-file.js';
4
+ import {readCoverage} from '../lib/coverage-file/coverage-file.js';
5
+ import {readConfig} from '../lib/config.js';
5
6
 
6
7
  cli({
7
8
  argv: process.argv,
8
9
  exit: process.exit,
9
- read,
10
+ readCoverage,
11
+ readConfig,
10
12
  });
11
13
 
package/lib/cli/cli.js CHANGED
@@ -8,7 +8,7 @@ import reportFiles from '../formatters/files.js';
8
8
 
9
9
  const {ESCOVER_FORMAT, NODE_OPTIONS = ''} = process.env;
10
10
 
11
- export const cli = ({argv, exit, read}) => {
11
+ export const cli = ({argv, exit, readCoverage}) => {
12
12
  const args = yargsParser(argv.slice(2), {
13
13
  string: [
14
14
  'format',
@@ -36,7 +36,7 @@ export const cli = ({argv, exit, read}) => {
36
36
  execute('"' + cmd.join(`" "`) + '"', exit);
37
37
  }
38
38
 
39
- const coverage = read();
39
+ const coverage = readCoverage();
40
40
 
41
41
  let output = '';
42
42
 
@@ -3,46 +3,47 @@ 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
- export const write = () => {
19
+ export const writeCoverage = () => {
20
20
  const files = getFileEntries();
21
21
 
22
22
  if (!files.size)
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
- export const read = () => {
37
- const name = findCacheDir({
37
+ export const readCoverage = () => {
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
 
@@ -0,0 +1,52 @@
1
+ const {entries} = Object;
2
+
3
+ export const generateLcov = (files) => {
4
+ const result = [];
5
+
6
+ for (const {name, lines} of files) {
7
+ result.push(`SF:${name}`);
8
+ for (const [line, covered] of entries(lines)) {
9
+ const count = covered ? 1 : 0;
10
+ result.push(`DA:${line},${count}`);
11
+ }
12
+
13
+ result.push('end_of_record');
14
+ }
15
+
16
+ return result.join('\n');
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
+
package/lib/exit.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import once from 'once';
2
- import {write} from './coverage-file/coverage-file.js';
2
+ import {writeCoverage} from './coverage-file/coverage-file.js';
3
3
 
4
4
  export const exit = once(() => {
5
- write();
5
+ writeCoverage();
6
6
  });
@@ -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
 
@@ -3,9 +3,9 @@ import {
3
3
  types,
4
4
  operator,
5
5
  } from 'putout';
6
- import {addMarkToReturn} from './return.js';
6
+
7
+ import {addMarkToArgument} from './argument.js';
7
8
  import {addMarkToArrowFunction} from './arrow.js';
8
- import {addMarkToThrow} from './throw.js';
9
9
 
10
10
  const {
11
11
  NumericLiteral,
@@ -16,6 +16,8 @@ const {
16
16
  const {
17
17
  replaceWith,
18
18
  compareAny,
19
+ compare,
20
+ replaceWithMultiple,
19
21
  } = operator;
20
22
 
21
23
  const LINE = `__c4['🧨'](__l, __c)`;
@@ -36,12 +38,10 @@ export const report = () => 'Mark line';
36
38
 
37
39
  export const fix = (path, {options}) => {
38
40
  const {node} = path;
39
-
40
41
  const {start} = path.node.loc;
41
42
 
42
43
  const {
43
44
  c4 = {
44
- mark: () => {},
45
45
  init: () => {},
46
46
  },
47
47
  } = options;
@@ -53,8 +53,9 @@ export const fix = (path, {options}) => {
53
53
  return;
54
54
  }
55
55
 
56
- if (path.isCallExpression()) {
56
+ if (path.isCallExpression() || path.isNewExpression()) {
57
57
  const {node} = path;
58
+
58
59
  replaceWith(path, SequenceExpression([
59
60
  lineNode.expression,
60
61
  node,
@@ -82,24 +83,19 @@ export const fix = (path, {options}) => {
82
83
  return;
83
84
  }
84
85
 
85
- if (path.isNewExpression()) {
86
- replaceWith(path, SequenceExpression([
87
- lineNode.expression,
88
- node,
89
- ]));
90
- return;
91
- }
86
+ if (path.isArrowFunctionExpression())
87
+ return addMarkToArrowFunction(path, lineNode);
92
88
 
93
- if (path.isReturnStatement())
94
- return addMarkToReturn(path, lineNode);
89
+ if (path.isReturnStatement() || path.isThrowStatement())
90
+ return addMarkToArgument(path, lineNode);
95
91
 
96
- if (path.isArrowFunctionExpression()) {
97
- return addMarkToArrowFunction(path, lineNode);
92
+ if (path.isContinueStatement() || path.isBreakStatement()) {
93
+ return replaceWithMultiple(path, [
94
+ lineNode,
95
+ path.node,
96
+ ]);
98
97
  }
99
98
 
100
- if (path.isThrowStatement())
101
- return addMarkToThrow(path, lineNode);
102
-
103
99
  replaceWith(path, BlockStatement([
104
100
  node,
105
101
  ]));
@@ -107,24 +103,39 @@ export const fix = (path, {options}) => {
107
103
 
108
104
  const EXCLUDE = [
109
105
  LINE,
110
- `(${LINE}, __z)`,
111
106
  `return (${LINE}, __z)`,
112
107
  `return ${LINE}`,
113
108
  `throw (${LINE}, __z)`,
114
109
  ];
115
110
 
116
- export const exclude = () => EXCLUDE;
111
+ const SEQUENCE = `(${LINE}, __z)`;
112
+ const isExclude = (node) => {
113
+ return compareAny(node, [
114
+ ...EXCLUDE,
115
+ SEQUENCE,
116
+ ]);
117
+ };
117
118
 
118
- export const include = () => [
119
- 'CallExpression',
120
- 'NewExpression',
121
- 'ReturnStatement',
122
- 'ThrowStatement',
123
- ];
119
+ export const exclude = () => EXCLUDE;
124
120
 
125
121
  export const traverse = ({push}) => ({
122
+ 'ThrowStatement|ReturnStatement'(path) {
123
+ push(path);
124
+ },
125
+ CallExpression(path) {
126
+ if (compare(path.parentPath.node, SEQUENCE))
127
+ return;
128
+
129
+ push(path);
130
+ },
131
+ 'CallExpression|NewExpression'(path) {
132
+ if (compare(path.parentPath.node, SEQUENCE))
133
+ return;
134
+
135
+ push(path);
136
+ },
126
137
  'AssignmentPattern|AssignmentExpression'(path) {
127
- if (compareAny(path.get('right'), EXCLUDE))
138
+ if (isExclude(path.get('right')))
128
139
  return;
129
140
 
130
141
  push(path);
@@ -135,8 +146,14 @@ export const traverse = ({push}) => ({
135
146
 
136
147
  push(path);
137
148
  },
149
+ 'ContinueStatement|BreakStatement'(path) {
150
+ if (compare(path.getPrevSibling(), LINE))
151
+ return;
152
+
153
+ push(path);
154
+ },
138
155
  LogicalExpression(path) {
139
- if (compareAny(path.get('left'), EXCLUDE))
156
+ if (isExclude(path.get('left')))
140
157
  return;
141
158
 
142
159
  push(path);
@@ -148,6 +165,9 @@ export const traverse = ({push}) => ({
148
165
  push(path);
149
166
  },
150
167
  SequenceExpression(path) {
168
+ if (compare(path, `(${LINE}, __z)`))
169
+ return;
170
+
151
171
  const expressions = path.get('expressions');
152
172
 
153
173
  for (const expPath of expressions) {
@@ -161,7 +181,7 @@ export const traverse = ({push}) => ({
161
181
  const consequentPath = path.get('consequent');
162
182
  const alternatePath = path.get('alternate');
163
183
 
164
- if (!consequentPath.isBlockStatement() && !compareAny(consequentPath, EXCLUDE))
184
+ if (!consequentPath.isBlockStatement() && !isExclude(consequentPath))
165
185
  push(consequentPath);
166
186
 
167
187
  if (!alternatePath.node)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escover",
3
- "version": "1.10.0",
3
+ "version": "1.14.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",
@@ -27,6 +27,7 @@
27
27
  "fix:lint": "madrun fix:lint",
28
28
  "report": "madrun report",
29
29
  "watcher": "madrun watcher",
30
+ "watch:test": "madrun watch:test",
30
31
  "watch:lint": "madrun watch:lint",
31
32
  "watch:tape": "madrun watch:tape",
32
33
  "prewisdom": "madrun prewisdom"
@@ -40,6 +41,7 @@
40
41
  "once": "^1.4.0",
41
42
  "picomatch": "^2.3.1",
42
43
  "putout": "^24.0.2",
44
+ "strip-ansi": "^7.0.1",
43
45
  "table": "^6.8.0",
44
46
  "try-catch": "^3.0.0",
45
47
  "yargs-parser": "^21.0.0",
@@ -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
-