@@ -7,10 +7,11 @@ const eslintScope = require('eslint-scope');
7
7
const estraverse = require ( 'estraverse' ) ;
8
8
const assert = require ( 'chai' ) . assert ;
9
9
const utils = require ( '../../lib/utils' ) ;
10
+ const typescriptEslintParser = require ( '@typescript-eslint/parser' ) ;
10
11
11
12
describe ( 'utils' , ( ) => {
12
13
describe ( 'getRuleInfo' , ( ) => {
13
- describe ( 'the file does not have a valid rule' , ( ) => {
14
+ describe ( 'the file does not have a valid rule (CJS) ' , ( ) => {
14
15
[
15
16
'' ,
16
17
'module.exports;' ,
@@ -39,6 +40,19 @@ describe('utils', () => {
39
40
'export const foo = { create() {} }' ,
40
41
'export default { foo: {} }' ,
41
42
'const foo = {}; export default foo' ,
43
+
44
+ // Incorrect TypeScript helper structure:
45
+ 'export default foo()({ create() {}, meta: {} });' ,
46
+ 'export default foo().bar({ create() {}, meta: {} });' ,
47
+ 'export default foo.bar.baz({ create() {}, meta: {} });' ,
48
+ 'export default foo(123);' ,
49
+ 'export default foo.bar(123);' ,
50
+ 'export default foo.bar()(123);' ,
51
+
52
+ // Correct TypeScript helper structure but missing parameterized types:
53
+ 'export default createESLintRule({ create() {}, meta: {} })' ,
54
+ 'export default util.createRule({ create() {}, meta: {} });' ,
55
+ 'export default ESLintUtils.RuleCreator(docsUrl)({ create() {}, meta: {} });' ,
42
56
] . forEach ( noRuleCase => {
43
57
it ( `returns null for ${ noRuleCase } ` , ( ) => {
44
58
const ast = espree . parse ( noRuleCase , { ecmaVersion : 8 , range : true , sourceType : 'module' } ) ;
@@ -47,9 +61,66 @@ describe('utils', () => {
47
61
} ) ;
48
62
} ) ;
49
63
50
- describe ( 'the file has a valid rule' , ( ) => {
64
+ describe ( 'the file does not have a valid rule (TypeScript + TypeScript parser)' , ( ) => {
65
+ [
66
+ // Incorrect TypeScript helper structure:
67
+ 'export default foo()<Options, MessageIds>({ create() {}, meta: {} });' ,
68
+ 'export default foo().bar<Options, MessageIds>({ create() {}, meta: {} });' ,
69
+ 'export default foo.bar.baz<Options, MessageIds>({ create() {}, meta: {} });' ,
70
+ 'export default foo<Options, MessageIds>(123);' ,
71
+ 'export default foo.bar<Options, MessageIds>(123);' ,
72
+ 'export default foo.bar()<Options, MessageIds>(123);' ,
73
+
74
+ // Correct TypeScript helper structure but missing parameterized types:
75
+ 'export default createESLintRule({ create() {}, meta: {} })' ,
76
+ 'export default createESLintRule<>({ create() {}, meta: {} })' ,
77
+ 'export default createESLintRule<OnlyOneType>({ create() {}, meta: {} })' ,
78
+ 'export default util.createRule({ create() {}, meta: {} });' ,
79
+ 'export default ESLintUtils.RuleCreator(docsUrl)({ create() {}, meta: {} });' ,
80
+ ] . forEach ( noRuleCase => {
81
+ it ( `returns null for ${ noRuleCase } ` , ( ) => {
82
+ const ast = typescriptEslintParser . parse ( noRuleCase , { ecmaVersion : 8 , range : true , sourceType : 'module' } ) ;
83
+ assert . isNull ( utils . getRuleInfo ( { ast } ) , 'Expected no rule to be found' ) ;
84
+ } ) ;
85
+ } ) ;
86
+ } ) ;
87
+
88
+ describe ( 'the file has a valid rule (TypeScript + TypeScript parser)' , ( ) => {
89
+ const CASES = {
90
+ // Util function only
91
+ 'export default createESLintRule<Options, MessageIds>({ create() {}, meta: {} })' : {
92
+ create : { type : 'FunctionExpression' } ,
93
+ meta : { type : 'ObjectExpression' } ,
94
+ isNewStyle : true ,
95
+ } ,
96
+ // Util function from util object
97
+ 'export default util.createRule<Options, MessageIds>({ create() {}, meta: {} });' : {
98
+ create : { type : 'FunctionExpression' } ,
99
+ meta : { type : 'ObjectExpression' } ,
100
+ isNewStyle : true ,
101
+ } ,
102
+ // Util function from util object with additional doc URL argument
103
+ 'export default ESLintUtils.RuleCreator(docsUrl)<Options, MessageIds>({ create() {}, meta: {} });' : {
104
+ create : { type : 'FunctionExpression' } ,
105
+ meta : { type : 'ObjectExpression' } ,
106
+ isNewStyle : true ,
107
+ } ,
108
+ } ;
109
+
110
+ Object . keys ( CASES ) . forEach ( ruleSource => {
111
+ it ( ruleSource , ( ) => {
112
+ const ast = typescriptEslintParser . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : 'module' } ) ;
113
+ const ruleInfo = utils . getRuleInfo ( { ast } ) ;
114
+ assert (
115
+ lodash . isMatch ( ruleInfo , CASES [ ruleSource ] ) ,
116
+ `Expected \n${ inspect ( ruleInfo ) } \nto match\n${ inspect ( CASES [ ruleSource ] ) } `
117
+ ) ;
118
+ } ) ;
119
+ } ) ;
120
+ } ) ;
121
+
122
+ describe ( 'the file has a valid rule (CJS)' , ( ) => {
51
123
const CASES = {
52
- // CJS
53
124
'module.exports = { create: function foo() {} };' : {
54
125
create : { type : 'FunctionExpression' , id : { name : 'foo' } } , // (This property will actually contain the AST node.)
55
126
meta : null ,
@@ -125,7 +196,22 @@ describe('utils', () => {
125
196
meta : null ,
126
197
isNewStyle : false ,
127
198
} ,
199
+ } ;
200
+
201
+ Object . keys ( CASES ) . forEach ( ruleSource => {
202
+ it ( ruleSource , ( ) => {
203
+ const ast = espree . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : 'script' } ) ;
204
+ const ruleInfo = utils . getRuleInfo ( { ast } ) ;
205
+ assert (
206
+ lodash . isMatch ( ruleInfo , CASES [ ruleSource ] ) ,
207
+ `Expected \n${ inspect ( ruleInfo ) } \nto match\n${ inspect ( CASES [ ruleSource ] ) } `
208
+ ) ;
209
+ } ) ;
210
+ } ) ;
211
+ } ) ;
128
212
213
+ describe ( 'the file has a valid rule (ESM)' , ( ) => {
214
+ const CASES = {
129
215
// ESM (object style)
130
216
'export default { create() {} }' : {
131
217
create : { type : 'FunctionExpression' } ,
@@ -153,15 +239,17 @@ describe('utils', () => {
153
239
154
240
Object . keys ( CASES ) . forEach ( ruleSource => {
155
241
it ( ruleSource , ( ) => {
156
- const ast = espree . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : ruleSource . startsWith ( 'export default' ) ? ' module' : 'script ' } ) ;
242
+ const ast = espree . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : ' module' } ) ;
157
243
const ruleInfo = utils . getRuleInfo ( { ast } ) ;
158
244
assert (
159
245
lodash . isMatch ( ruleInfo , CASES [ ruleSource ] ) ,
160
246
`Expected \n${ inspect ( ruleInfo ) } \nto match\n${ inspect ( CASES [ ruleSource ] ) } `
161
247
) ;
162
248
} ) ;
163
249
} ) ;
250
+ } ) ;
164
251
252
+ describe ( 'the file has a valid rule (different scope options)' , ( ) => {
165
253
for ( const scopeOptions of [
166
254
{ ignoreEval : true , ecmaVersion : 6 , sourceType : 'script' , nodejsScope : true } ,
167
255
{ ignoreEval : true , ecmaVersion : 6 , sourceType : 'script' } ,
0 commit comments