Skip to content

Commit 6c02ce4

Browse files
authored
Add visualize tester (#788)
1 parent 9989d2d commit 6c02ce4

8 files changed

+278
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
},
5050
"devDependencies": {
5151
"@ava/babel": "^1.0.1",
52+
"@babel/code-frame": "7.10.3",
5253
"@lubien/fixture-beta-package": "^1.0.0-beta.1",
5354
"@typescript-eslint/parser": "^3.4.0",
5455
"ava": "^3.9.0",

test/consistent-function-scoping.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import test from 'ava';
22
import avaRuleTester from 'eslint-ava-rule-tester';
33
import {outdent} from 'outdent';
44
import rule from '../rules/consistent-function-scoping';
5+
import visualizeRuleTester from './utils/visualize-rule-tester';
56

67
const ruleTester = avaRuleTester(test, {
78
parserOptions: {
@@ -647,3 +648,47 @@ typescriptRuleTester.run('consistent-function-scoping', rule, {
647648
],
648649
invalid: []
649650
});
651+
652+
const visualizeTester = visualizeRuleTester(test, {
653+
parserOptions: {
654+
sourceType: 'module',
655+
ecmaVersion: 2020,
656+
ecmaFeatures: {
657+
jsx: true
658+
}
659+
}
660+
});
661+
662+
visualizeTester.run('consistent-function-scoping', rule, [
663+
outdent`
664+
function foo() {
665+
function bar() {}
666+
}
667+
`,
668+
outdent`
669+
function foo() {
670+
async function bar() {}
671+
}
672+
`,
673+
outdent`
674+
function foo() {
675+
function * bar() {}
676+
}
677+
`,
678+
outdent`
679+
function foo() {
680+
async function * bar() {}
681+
}
682+
`,
683+
outdent`
684+
function foo() {
685+
const bar = () => {}
686+
}
687+
`,
688+
'const doFoo = () => bar => bar;',
689+
outdent`
690+
function foo() {
691+
const bar = async () => {}
692+
}
693+
`
694+
]);

test/no-useless-undefined.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import test from 'ava';
22
import {outdent} from 'outdent';
33
import avaRuleTester from 'eslint-ava-rule-tester';
44
import rule from '../rules/no-useless-undefined';
5+
import visualizeRuleTester from './utils/visualize-rule-tester';
56

67
const messageId = 'no-useless-undefined';
78

@@ -238,3 +239,25 @@ typescriptRuleTester.run('no-useless-undefined', rule, {
238239
],
239240
invalid: []
240241
});
242+
243+
const visualizeTester = visualizeRuleTester(test, {
244+
parserOptions: {
245+
ecmaVersion: 2020
246+
}
247+
});
248+
249+
visualizeTester.run('no-useless-undefined', rule, [
250+
outdent`
251+
foo(
252+
undefined,
253+
bar,
254+
undefined,
255+
undefined,
256+
undefined,
257+
undefined,
258+
)
259+
`,
260+
'function foo([bar = undefined] = []) {}',
261+
'foo(bar, undefined, undefined);',
262+
'let a = undefined, b = 2;'
263+
]);
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Snapshot report for `test/consistent-function-scoping.js`
2+
3+
The actual snapshot is saved in `consistent-function-scoping.js.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## consistent-function-scoping - #1
8+
9+
> Snapshot 1
10+
11+
`␊
12+
1 | function foo() {␊
13+
> 2 | function bar() {}␊
14+
| ^^^^^^^^^^^^ Move function 'bar' to the outer scope.␊
15+
3 | }␊
16+
`
17+
18+
## consistent-function-scoping - #2
19+
20+
> Snapshot 1
21+
22+
`␊
23+
1 | function foo() {␊
24+
> 2 | async function bar() {}␊
25+
| ^^^^^^^^^^^^^^^^^^ Move async function 'bar' to the outer scope.␊
26+
3 | }␊
27+
`
28+
29+
## consistent-function-scoping - #3
30+
31+
> Snapshot 1
32+
33+
`␊
34+
1 | function foo() {␊
35+
> 2 | function * bar() {}␊
36+
| ^^^^^^^^^^^^^^ Move generator function 'bar' to the outer scope.␊
37+
3 | }␊
38+
`
39+
40+
## consistent-function-scoping - #4
41+
42+
> Snapshot 1
43+
44+
`␊
45+
1 | function foo() {␊
46+
> 2 | async function * bar() {}␊
47+
| ^^^^^^^^^^^^^^^^^^^^ Move async generator function 'bar' to the outer scope.␊
48+
3 | }␊
49+
`
50+
51+
## consistent-function-scoping - #5
52+
53+
> Snapshot 1
54+
55+
`␊
56+
1 | function foo() {␊
57+
> 2 | const bar = () => {}␊
58+
| ^^ Move arrow function 'bar' to the outer scope.␊
59+
3 | }␊
60+
`
61+
62+
## consistent-function-scoping - #6
63+
64+
> Snapshot 1
65+
66+
`␊
67+
> 1 | const doFoo = () => bar => bar;␊
68+
| ^^ Move arrow function to the outer scope.␊
69+
`
70+
71+
## consistent-function-scoping - #7
72+
73+
> Snapshot 1
74+
75+
`␊
76+
1 | function foo() {␊
77+
> 2 | const bar = async () => {}␊
78+
| ^^ Move async arrow function 'bar' to the outer scope.␊
79+
3 | }␊
80+
`
449 Bytes
Binary file not shown.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Snapshot report for `test/no-useless-undefined.js`
2+
3+
The actual snapshot is saved in `no-useless-undefined.js.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## no-useless-undefined - #1
8+
9+
> Snapshot 1
10+
11+
`␊
12+
1 | foo(␊
13+
2 | undefined,␊
14+
3 | bar,␊
15+
> 4 | undefined,␊
16+
| ^^^^^^^^^^␊
17+
> 5 | undefined,␊
18+
| ^^^^^^^^^^^␊
19+
> 6 | undefined,␊
20+
| ^^^^^^^^^^^␊
21+
> 7 | undefined,␊
22+
| ^^^^^^^^^^^ Do not use useless `undefined`.␊
23+
8 | )␊
24+
`
25+
26+
## no-useless-undefined - #2
27+
28+
> Snapshot 1
29+
30+
`␊
31+
> 1 | function foo([bar = undefined] = []) {}␊
32+
| ^^^^^^^^^ Do not use useless `undefined`.␊
33+
`
34+
35+
## no-useless-undefined - #3
36+
37+
> Snapshot 1
38+
39+
`␊
40+
> 1 | foo(bar, undefined, undefined);␊
41+
| ^^^^^^^^^^^^^^^^^^^^ Do not use useless `undefined`.␊
42+
`
43+
44+
## no-useless-undefined - #4
45+
46+
> Snapshot 1
47+
48+
`␊
49+
> 1 | let a = undefined, b = 2;␊
50+
| ^^^^^^^^^ Do not use useless `undefined`.␊
51+
`
341 Bytes
Binary file not shown.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict';
2+
const {Linter} = require('eslint');
3+
const {codeFrameColumns} = require('@babel/code-frame');
4+
const codeFrameColumnsOptions = {linesAbove: Infinity, linesBelow: Infinity};
5+
6+
function visualizeRange(text, location, message) {
7+
return codeFrameColumns(
8+
text,
9+
location,
10+
{
11+
...codeFrameColumnsOptions,
12+
message
13+
}
14+
);
15+
}
16+
17+
function visualizeEslintResult(text, result) {
18+
const {line, column, endLine, endColumn, message} = result;
19+
const location = {
20+
start: {
21+
line,
22+
column
23+
}
24+
};
25+
26+
if (typeof endLine === 'number' && typeof endColumn === 'number') {
27+
location.end = {
28+
line: endLine,
29+
column: endColumn
30+
};
31+
}
32+
33+
return `\n${visualizeRange(text, location, message)}\n`;
34+
}
35+
36+
class VisualizeRuleTester {
37+
constructor(test, config) {
38+
this.test = test;
39+
this.config = config;
40+
}
41+
42+
run(ruleId, rule, tests) {
43+
const {test, config} = this;
44+
const linter = new Linter();
45+
const verifyConfig = {
46+
...config,
47+
rules: {
48+
[ruleId]: 'error'
49+
}
50+
};
51+
52+
linter.defineRule(ruleId, rule);
53+
54+
for (const [index, code] of tests.entries()) {
55+
test(`${ruleId} - #${index + 1}`, t => {
56+
const results = linter.verify(code, verifyConfig);
57+
58+
if (results.length !== 1) {
59+
throw new Error('Visualize test should has exactly one error.');
60+
}
61+
62+
const [error] = results;
63+
64+
if (error.fatal) {
65+
throw new Error(error.message);
66+
}
67+
68+
t.snapshot(visualizeEslintResult(code, error));
69+
});
70+
}
71+
}
72+
}
73+
74+
function visualizeRuleTester(test, config) {
75+
return new VisualizeRuleTester(test, config);
76+
}
77+
78+
module.exports = visualizeRuleTester;

0 commit comments

Comments
 (0)