escover 1.0.3 โ†’ 1.1.1

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,27 @@
1
+ 2022.01.11, v1.1.1
2
+
3
+ feature:
4
+ - escover: bin only shows report
5
+
6
+
7
+ 2022.01.11, v1.1.0
8
+
9
+ feature:
10
+ - (escover) add bin
11
+
12
+
13
+ 2022.01.08, v1.0.5
14
+
15
+ feature:
16
+ - escover: report
17
+
18
+
19
+ 2022.01.08, v1.0.4
20
+
21
+ feature:
22
+ - escover: add support of AssignmentExpression
23
+
24
+
1
25
  2022.01.08, v1.0.3
2
26
 
3
27
  feature:
package/README.md CHANGED
@@ -9,20 +9,44 @@
9
9
  [CoverageURL]: https://coveralls.io/github/coderaiser/escover?branch=master
10
10
  [CoverageIMGURL]: https://coveralls.io/repos/coderaiser/escover/badge.svg?branch=master&service=github
11
11
 
12
- Explosive coverage tool
12
+ Coverage for EcmaScript Modules based on ๐ŸŠ[`Putout`](https://github.com/coderaiser/putout) and [loaders](https://nodejs.org/dist/latest-v16.x/docs/api/esm.html#loaders).
13
+
14
+ # Why another coverage tool?
15
+
16
+ When you want to use `ESM` in `Node.js` without transpiling to `CommonJS` (that's what `jest`, `ava`, `tap` does),
17
+ you have a couple problems to solve.
18
+
19
+ ๐Ÿคทโ€ What test runner does no transpiling to `CommonJS`?
20
+ โ˜๏ธ that's easy! ๐Ÿ“ผ [`Supertape`](https://github.com/coderaiser/supertape) supports `ESM` from the box;
21
+
22
+ ๐Ÿคทโ€ How to mock modules without [mock-require](https://github.com/boblauer/mock-require) (we in `ESM`!);
23
+ โ˜๏ธ that's solved! [`mock-import`](https://github.com/coderaiser/mock-import) does the thing using `loaders`;
24
+
25
+ ๐Ÿคทโ€ How to get coverage when `nyc` doesn't supported?
26
+ โ˜๏ธ `c8` could help, but [no](https://github.com/coderaiser/c8-reproduce) it supports no `query paramters`
27
+ which are needed to load module again, and apply mocks.
28
+
29
+ ๐Ÿคทโ€ How to get coverage when mocks are used?
30
+ โ˜๏ธ Use ๐ŸŽฉ `ESCover`! It supports loaders, `ESM` and collects coverage as a loader!
13
31
 
14
32
  ## Install
15
33
 
16
34
  ```
17
- npm i escover -g
35
+ npm i escover -D
18
36
  ```
19
37
 
20
- Then run using:
38
+ Run to collect coverage:
21
39
 
22
40
  ```sh
23
41
  NODE_OPTIONS="'--loader escover'" escover npm test
24
42
  ```
25
43
 
44
+ Run to show coverage report:
45
+
46
+ ```sh
47
+ escover
48
+ ```
49
+
26
50
  ## How it looks like?
27
51
 
28
52
  When everything is covered:
@@ -33,6 +57,26 @@ When some lines missing coverage:
33
57
 
34
58
  ![image](https://user-images.githubusercontent.com/1573141/147944130-9b901646-05ff-4a76-86c9-30631b0a0dd4.png)
35
59
 
60
+ ## What if I want to use with `mock-import`?
61
+
62
+ Experimental `loaders` supports only one, for now. So [zenload](https://github.com/coderaiser/zenload) should be used.
63
+
64
+ Install it with:
65
+
66
+ ```sh
67
+ npm i escover mock-import zenload
68
+ ```
69
+
70
+ Then run:
71
+
72
+ ```sh
73
+ NODE_OPTIONS="'--loader zenlend'" ZENLOAD='escover,mock-import' escover npm test
74
+ ```
75
+
76
+ This configuration will add coverage collectors and then apply mocks with help of `mock-import`.
77
+ Of course the most comfortable way of doing this things will be [madrun](https://github.com/coderaiser/madrun).
78
+ Run you `package-scripts` in `JavaScript` :)!
79
+
36
80
  ## License
37
81
 
38
82
  MIT
package/bin/escover.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {cli} from '../lib/cli/cli.js';
4
+ import {read} from '../lib/config.js';
5
+
6
+ cli({
7
+ argv: process.argv,
8
+ exit: process.exit,
9
+ read,
10
+ });
11
+
package/lib/c4.js CHANGED
@@ -5,10 +5,10 @@ export const createFileEntry = (url) => {
5
5
  files.set(url, lines);
6
6
 
7
7
  return {
8
- mark: (line, column) => {
8
+ '๐Ÿงจ': (line, column) => {
9
9
  lines.set(`${line}:${column}`, true);
10
10
  },
11
- init: (line, column) => {
11
+ 'init': (line, column) => {
12
12
  lines.set(`${line}:${column}`, false);
13
13
  },
14
14
  };
package/lib/cli/cli.js ADDED
@@ -0,0 +1,24 @@
1
+ import yargsParser from 'yargs-parser';
2
+
3
+ import {version} from './version.js';
4
+ import {report} from '../report.js';
5
+
6
+ export const cli = ({argv, exit, read}) => {
7
+ const args = yargsParser(argv.slice(2), {
8
+ boolean: [
9
+ 'version',
10
+ ],
11
+ alias: {
12
+ v: 'version',
13
+ },
14
+ configuration: {},
15
+ });
16
+
17
+ if (args.version) {
18
+ console.log(`v${version()}`);
19
+ return exit();
20
+ }
21
+
22
+ const coverage = read();
23
+ report(coverage);
24
+ };
@@ -0,0 +1,12 @@
1
+ import {readFileSync} from 'fs';
2
+ const {parse} = JSON;
3
+
4
+ const packageJson = new URL('../../package.json', import.meta.url);
5
+
6
+ export const version = () => {
7
+ const data = readFileSync(packageJson, 'utf8');
8
+ const {version} = parse(data);
9
+
10
+ return version;
11
+ };
12
+
package/lib/config.js ADDED
@@ -0,0 +1,43 @@
1
+ import tryCatch from 'try-catch';
2
+ import {
3
+ writeFileSync,
4
+ readFileSync,
5
+ } from 'fs';
6
+ import {getFiles} from './c4.js';
7
+ import {transform} from './transform.js';
8
+ import {merge} from './merge.js';
9
+ import findCacheDir from 'find-cache-dir';
10
+
11
+ const {
12
+ stringify,
13
+ parse,
14
+ } = JSON;
15
+
16
+ const NAME = 'escover';
17
+ const buildName = (a) => `${a}/${NAME}.json`;
18
+
19
+ export const write = () => {
20
+ const files = getFiles();
21
+ const parsed = transform(files);
22
+ const merged = merge(parsed);
23
+ const name = findCacheDir({
24
+ name: NAME,
25
+ create: true,
26
+ });
27
+
28
+ writeFileSync(buildName(name), stringify(merged, null, 4));
29
+ };
30
+
31
+ export const read = () => {
32
+ const name = findCacheDir({
33
+ name: NAME,
34
+ });
35
+
36
+ const [error, data] = tryCatch(readFileSync, buildName(name), 'utf8');
37
+
38
+ if (error)
39
+ return [];
40
+
41
+ return parse(data);
42
+ };
43
+
package/lib/escover.js CHANGED
@@ -8,6 +8,8 @@ import {createFileEntry} from './c4.js';
8
8
 
9
9
  global.__createC4 = createFileEntry;
10
10
 
11
+ process.once('exit', exit);
12
+
11
13
  export async function load(url, context, defaultLoad) {
12
14
  const {format, source: rawSource} = await defaultLoad(url, context, defaultLoad);
13
15
 
@@ -27,13 +29,9 @@ export async function load(url, context, defaultLoad) {
27
29
  ${instrument(url, rawSource)}
28
30
  `;
29
31
 
30
- console.log(source);
31
-
32
32
  return {
33
33
  format,
34
34
  source,
35
35
  };
36
36
  }
37
37
 
38
- process.once('exit', exit);
39
-
package/lib/exit.js CHANGED
@@ -1,9 +1,6 @@
1
1
  import once from 'once';
2
-
3
- import {save} from './save.js';
4
- import {report} from './report.js';
2
+ import {write} from './config.js';
5
3
 
6
4
  export const exit = once(() => {
7
- save();
8
- report();
5
+ write();
9
6
  });
@@ -1,6 +1,6 @@
1
1
  export const nothing = (a, b) => {
2
- return __c4.mark(2, 4);
2
+ return __c4['๐Ÿงจ'](2, 4);
3
3
  };
4
4
  export const sum = (a, b) => {
5
- return __c4.mark(5, 4), a + b;
5
+ return __c4['๐Ÿงจ'](5, 4), a + b;
6
6
  };
@@ -1 +1,2 @@
1
- const [error, {packageJson} = (__c4.mark(1, 14), {})] = (__c4.mark(1, 36), tryCatch(readPackageUpSync));
1
+ const [error, {packageJson} = (__c4['๐Ÿงจ'](1, 14), {})] = (__c4['๐Ÿงจ'](1, 36), tryCatch(readPackageUpSync));
2
+ data += (__c4['๐Ÿงจ'](2, 0), 'fix:' + '\n');
@@ -1 +1,2 @@
1
1
  const [error, {packageJson} = {}] = tryCatch(readPackageUpSync);
2
+ data += 'fix:' + '\n';
@@ -1,3 +1,6 @@
1
1
  if (error) {
2
- throw (__c4.mark(2, 4), `error reading package.json: ${error.message}`);
2
+ throw (__c4['๐Ÿงจ'](2, 4), `error reading package.json: ${error.message}`);
3
3
  }
4
+
5
+ if (error)
6
+ throw (__c4['๐Ÿงจ'](6, 4), (__c4.mark(11, 8), `error reading package.json: ${error.message}`));
@@ -1,3 +1,6 @@
1
1
  if (error) {
2
2
  throw `error reading package.json: ${error.message}`;
3
3
  }
4
+
5
+ if (error)
6
+ throw (__c4.mark(11, 8), `error reading package.json: ${error.message}`);
@@ -1,3 +1,3 @@
1
- if ((__c4.mark(1, 4), a) || (__c4.mark(1, 9), b)) {
2
- __c4.mark(1, 12);
1
+ if ((__c4['๐Ÿงจ'](1, 4), a) || (__c4['๐Ÿงจ'](1, 9), b)) {
2
+ __c4['๐Ÿงจ'](1, 12);
3
3
  }
@@ -1,30 +1,30 @@
1
1
  const a = () => {
2
- a = 5;
3
- __c4.mark(3, 4), console.log(5);
2
+ a = (__c4['๐Ÿงจ'](2, 4), 5);
3
+ __c4['๐Ÿงจ'](3, 4), console.log(5);
4
4
  };
5
5
 
6
6
 
7
7
  function x() {
8
8
 
9
9
  if (a > 2) {
10
- __c4.mark(9, 14), a();
10
+ __c4['๐Ÿงจ'](9, 14), a();
11
11
  } else {
12
- __c4.mark(10, 9), b();
12
+ __c4['๐Ÿงจ'](10, 9), b();
13
13
  }
14
14
  }
15
15
 
16
16
  for (const x of y) {
17
- __c4.mark(13, 19);
17
+ __c4['๐Ÿงจ'](13, 19);
18
18
  }
19
19
 
20
- const ax = ((__c4.mark(16, 12), a()), (__c4.mark(16, 17), b()));
21
- const bx = (c, (__c4.mark(17, 15), d()));
20
+ const ax = ((__c4['๐Ÿงจ'](16, 12), a()), (__c4['๐Ÿงจ'](16, 17), b()));
21
+ const bx = (c, (__c4['๐Ÿงจ'](17, 15), d()));
22
22
 
23
- if ((__c4.mark(19, 4), a) || (__c4.mark(19, 9), b)) {
24
- __c4.mark(19, 12);
23
+ if ((__c4['๐Ÿงจ'](19, 4), a) || (__c4['๐Ÿงจ'](19, 9), b)) {
24
+ __c4['๐Ÿงจ'](19, 12);
25
25
  }
26
26
 
27
27
 
28
- function x1(a, b = (__c4.mark(23, 15), 5)) {
29
- __c4.mark(23, 22);
28
+ function x1(a, b = (__c4['๐Ÿงจ'](23, 15), 5)) {
29
+ __c4['๐Ÿงจ'](23, 22);
30
30
  }
@@ -1 +1 @@
1
- const files = (__c4.mark(1, 14), new Map());
1
+ const files = (__c4['๐Ÿงจ'](1, 14), new Map());
@@ -1,8 +1,8 @@
1
- __c4.mark(1, 0), cli({
1
+ __c4['๐Ÿงจ'](1, 0), cli({
2
2
  stdout,
3
3
  stderr,
4
4
  exit,
5
- cwd: (__c4.mark(5, 9), process.cwd()),
6
- argv: (__c4.mark(6, 10), process.argv.slice(2))
5
+ cwd: (__c4['๐Ÿงจ'](5, 9), process.cwd()),
6
+ argv: (__c4['๐Ÿงจ'](6, 10), process.argv.slice(2))
7
7
  });
8
8
 
@@ -5,6 +5,7 @@ import {
5
5
  } from 'putout';
6
6
  import {addMarkToReturn} from './return.js';
7
7
  import {addMarkToArrowFunction} from './arrow.js';
8
+ import {addMarkToThrow} from './throw.js';
8
9
 
9
10
  const {
10
11
  NumericLiteral,
@@ -13,12 +14,11 @@ const {
13
14
  } = types;
14
15
 
15
16
  const {
16
- replaceWithMultiple,
17
17
  replaceWith,
18
18
  compareAny,
19
19
  } = operator;
20
20
 
21
- const LINE = '__c4.mark(__l, __c)';
21
+ const LINE = `__c4['๐Ÿงจ'](__l, __c)`;
22
22
  const buildLineNode = template(LINE, {
23
23
  placeholderPattern: /^__[a-z]$/,
24
24
  });
@@ -80,11 +80,11 @@ export const fix = (path, {options}) => {
80
80
  return;
81
81
  }
82
82
 
83
- if (path.isAssignmentPattern()) {
84
- replaceWithMultiple(path.get('right'), [
85
- lineNode,
83
+ if (path.isAssignmentPattern() || path.isAssignmentExpression()) {
84
+ replaceWith(path.get('right'), SequenceExpression([
85
+ lineNode.expression,
86
86
  node.right,
87
- ]);
87
+ ]));
88
88
  return;
89
89
  }
90
90
 
@@ -99,16 +99,13 @@ export const fix = (path, {options}) => {
99
99
  if (path.isReturnStatement())
100
100
  return addMarkToReturn(path, lineNode);
101
101
 
102
- if (path.isArrowFunctionExpression())
102
+ if (path.isArrowFunctionExpression()) {
103
103
  return addMarkToArrowFunction(path, lineNode);
104
-
105
- if (path.isThrowStatement()) {
106
- return replaceWith(path.get('argument'), SequenceExpression([
107
- lineNode.expression,
108
- node.argument,
109
- ]));
110
104
  }
111
105
 
106
+ if (path.isThrowStatement())
107
+ return addMarkToThrow(path, lineNode);
108
+
112
109
  replaceWith(path, BlockStatement([
113
110
  node,
114
111
  ]));
@@ -132,7 +129,7 @@ export const include = () => [
132
129
  ];
133
130
 
134
131
  export const traverse = ({push}) => ({
135
- AssignmentPattern(path) {
132
+ 'AssignmentPattern|AssignmentExpression'(path) {
136
133
  if (compareAny(path.get('right'), EXCLUDE))
137
134
  return;
138
135
 
@@ -170,7 +167,7 @@ export const traverse = ({push}) => ({
170
167
  const consequentPath = path.get('consequent');
171
168
  const alternatePath = path.get('alternate');
172
169
 
173
- if (!consequentPath.isBlockStatement())
170
+ if (!consequentPath.isBlockStatement() && !compareAny(consequentPath, EXCLUDE))
174
171
  push(consequentPath);
175
172
 
176
173
  if (!alternatePath.node)
package/lib/report.js CHANGED
@@ -1,12 +1,7 @@
1
1
  import chalk from 'chalk';
2
- import {readFileSync} from 'fs';
3
-
4
- const {parse} = JSON;
5
2
  const {entries} = Object;
6
3
 
7
- export const report = () => {
8
- const coverageFile = parse(readFileSync('./coverage.json', 'utf8'));
9
-
4
+ export const report = (coverageFile) => {
10
5
  const files = [];
11
6
  const coverage = {
12
7
  files,
@@ -14,7 +9,7 @@ export const report = () => {
14
9
  uncoveredCount: 0,
15
10
  };
16
11
 
17
- console.log('# TAP version 13');
12
+ console.log('# CAP version 13');
18
13
  console.log('');
19
14
 
20
15
  for (const {name, lines} of coverageFile) {
@@ -45,26 +40,30 @@ export const report = () => {
45
40
  for (const {name, covered, uncoveredLines} of files) {
46
41
  if (!covered) {
47
42
  console.log(`# ${name}`);
48
- console.log('โŒ should be covered');
43
+ console.log('๐Ÿงจ should be covered');
49
44
  console.log('---');
50
- console.log(`lines: ${chalk.red(uncoveredLines.join(','))}`);
45
+ console.log(`lines:`);
46
+ for (const line of uncoveredLines) {
47
+ console.log(`๏ธ- ${chalk.red(line)} at file://${name}:${line}`);
48
+ }
49
+ console.log('');
51
50
  }
52
51
  }
53
52
 
54
- if (coverage.uncoveredCount)
55
- console.log('');
56
-
57
53
  console.log(`1..${files.length}`);
58
54
  console.log(`# files: ${files.length}`);
59
55
  console.log(`# covered: ${coverage.coveredCount}`);
60
56
 
57
+ console.log('');
58
+
61
59
  if (!coverage.uncoveredCount) {
62
- console.log('');
63
- console.log('# โ˜˜๏ธ ok');
60
+ console.log('#๏ธ ๐ŸŒด ok');
64
61
  }
65
62
 
66
63
  if (coverage.uncoveredCount) {
67
64
  console.log(`# ๐Ÿงจ fail: ${coverage.uncoveredCount}`);
68
65
  }
66
+
67
+ console.log('');
69
68
  };
70
69
 
@@ -1,4 +1,4 @@
1
- export const parse = (files) => {
1
+ export const transform = (files) => {
2
2
  const result = [];
3
3
 
4
4
  for (const [rawName, places] of files.entries()) {
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "escover",
3
- "version": "1.0.3",
3
+ "version": "1.1.1",
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",
7
7
  "type": "module",
8
+ "bin": {
9
+ "escover": "bin/escover.js"
10
+ },
8
11
  "repository": {
9
12
  "type": "git",
10
13
  "url": "git://github.com/coderaiser/escover.git"
@@ -15,8 +18,11 @@
15
18
  "loader"
16
19
  ],
17
20
  "scripts": {
21
+ "loader": "madrun loader",
18
22
  "test": "madrun test",
23
+ "test:only": "madrun test:only",
19
24
  "coverage": "madrun coverage",
25
+ "c4": "madrun c4",
20
26
  "lint": "madrun lint",
21
27
  "fresh:lint": "madrun fresh:lint",
22
28
  "lint:fresh": "madrun lint:fresh",
@@ -30,9 +36,13 @@
30
36
  },
31
37
  "dependencies": {
32
38
  "chalk": "^5.0.0",
39
+ "find-cache-dir": "^3.3.2",
40
+ "find-up": "^6.2.0",
33
41
  "montag": "^1.2.1",
34
42
  "once": "^1.4.0",
35
- "putout": "^23.5.0"
43
+ "putout": "^23.5.0",
44
+ "try-catch": "^3.0.0",
45
+ "yargs-parser": "^21.0.0"
36
46
  },
37
47
  "engines": {
38
48
  "node": ">=14"
@@ -41,6 +51,7 @@
41
51
  "devDependencies": {
42
52
  "@putout/test": "^4.1.0",
43
53
  "c8": "^7.8.0",
54
+ "escover": ".",
44
55
  "eslint": "^8.3.0",
45
56
  "eslint-plugin-node": "^11.1.0",
46
57
  "eslint-plugin-putout": "^12.2.0",
package/c4.json DELETED
@@ -1,15 +0,0 @@
1
- [{
2
- "name": "changelog.js",
3
- "lines": {
4
- "1": false,
5
- "7": false,
6
- "9": false
7
- }
8
- }, {
9
- "name": "simple.js",
10
- "lines": {
11
- "1": true,
12
- "7": true,
13
- "9": true
14
- }
15
- }]
package/coverage.json DELETED
@@ -1,8 +0,0 @@
1
- [
2
- {
3
- "name": "/Users/coderaiser/escover/example/example.js",
4
- "lines": {
5
- "1": true
6
- }
7
- }
8
- ]
package/lib/save.js DELETED
@@ -1,14 +0,0 @@
1
- import {writeFileSync} from 'fs';
2
- import {getFiles} from './c4.js';
3
- import {parse} from './parse.js';
4
- import {merge} from './merge.js';
5
-
6
- const {stringify} = JSON;
7
-
8
- export const save = () => {
9
- const files = getFiles();
10
- const parsed = parse(files);
11
- const merged = merge(parsed);
12
-
13
- writeFileSync('./coverage.json', stringify(merged, null, 4));
14
- };