@@ -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;' ,
@@ -25,6 +26,11 @@ describe('utils', () => {
25
26
'module.exports = { create: foo }' ,
26
27
'module.exports = { create: function* foo() {} }' ,
27
28
'module.exports = { create: async function foo() {} }' ,
29
+
30
+ // Correct TypeScript helper structure but missing parameterized types (note: we don't support CJS for TypeScript rules):
31
+ 'module.exports = createESLintRule({ create() {}, meta: {} });' ,
32
+ 'module.exports = util.createRule({ create() {}, meta: {} });' ,
33
+ 'module.exports = ESLintUtils.RuleCreator(docsUrl)({ create() {}, meta: {} });' ,
28
34
] . forEach ( noRuleCase => {
29
35
it ( `returns null for ${ noRuleCase } ` , ( ) => {
30
36
const ast = espree . parse ( noRuleCase , { ecmaVersion : 8 , range : true } ) ;
@@ -39,6 +45,19 @@ describe('utils', () => {
39
45
'export const foo = { create() {} }' ,
40
46
'export default { foo: {} }' ,
41
47
'const foo = {}; export default foo' ,
48
+
49
+ // Incorrect TypeScript helper structure:
50
+ 'export default foo()({ create() {}, meta: {} });' ,
51
+ 'export default foo().bar({ create() {}, meta: {} });' ,
52
+ 'export default foo.bar.baz({ create() {}, meta: {} });' ,
53
+ 'export default foo(123);' ,
54
+ 'export default foo.bar(123);' ,
55
+ 'export default foo.bar()(123);' ,
56
+
57
+ // Correct TypeScript helper structure but missing parameterized types:
58
+ 'export default createESLintRule({ create() {}, meta: {} });' ,
59
+ 'export default util.createRule({ create() {}, meta: {} });' ,
60
+ 'export default ESLintUtils.RuleCreator(docsUrl)({ create() {}, meta: {} });' ,
42
61
] . forEach ( noRuleCase => {
43
62
it ( `returns null for ${ noRuleCase } ` , ( ) => {
44
63
const ast = espree . parse ( noRuleCase , { ecmaVersion : 8 , range : true , sourceType : 'module' } ) ;
@@ -47,9 +66,80 @@ describe('utils', () => {
47
66
} ) ;
48
67
} ) ;
49
68
50
- describe ( 'the file has a valid rule' , ( ) => {
69
+ describe ( 'the file does not have a valid rule (TypeScript + TypeScript parser + ESM)' , ( ) => {
70
+ [
71
+ // Incorrect TypeScript helper structure:
72
+ 'export default foo()<Options, MessageIds>({ create() {}, meta: {} });' ,
73
+ 'export default foo().bar<Options, MessageIds>({ create() {}, meta: {} });' ,
74
+ 'export default foo.bar.baz<Options, MessageIds>({ create() {}, meta: {} });' ,
75
+ 'export default foo<Options, MessageIds>(123);' ,
76
+ 'export default foo.bar<Options, MessageIds>(123);' ,
77
+ 'export default foo.bar()<Options, MessageIds>(123);' ,
78
+
79
+ // Correct TypeScript helper structure but missing parameterized types:
80
+ 'export default createESLintRule({ create() {}, meta: {} });' ,
81
+ 'export default createESLintRule<>({ create() {}, meta: {} });' ,
82
+ 'export default createESLintRule<OnlyOneType>({ create() {}, meta: {} });' ,
83
+ 'export default util.createRule({ create() {}, meta: {} });' ,
84
+ 'export default ESLintUtils.RuleCreator(docsUrl)({ create() {}, meta: {} });' ,
85
+ ] . forEach ( noRuleCase => {
86
+ it ( `returns null for ${ noRuleCase } ` , ( ) => {
87
+ const ast = typescriptEslintParser . parse ( noRuleCase , { ecmaVersion : 8 , range : true , sourceType : 'module' } ) ;
88
+ assert . isNull ( utils . getRuleInfo ( { ast } ) , 'Expected no rule to be found' ) ;
89
+ } ) ;
90
+ } ) ;
91
+ } ) ;
92
+
93
+ describe ( 'the file does not have a valid rule (TypeScript + TypeScript parser + CJS)' , ( ) => {
94
+ [
95
+ // Correct TypeScript helper structure but missing parameterized types (note: we don't support CJS for TypeScript rules):
96
+ 'module.exports = createESLintRule<Options, MessageIds>({ create() {}, meta: {} });' ,
97
+ 'module.exports = util.createRule<Options, MessageIds>({ create() {}, meta: {} });' ,
98
+ 'module.exports = ESLintUtils.RuleCreator(docsUrl)<Options, MessageIds>({ create() {}, meta: {} });' ,
99
+ ] . forEach ( noRuleCase => {
100
+ it ( `returns null for ${ noRuleCase } ` , ( ) => {
101
+ const ast = typescriptEslintParser . parse ( noRuleCase , { range : true , sourceType : 'script' } ) ;
102
+ assert . isNull ( utils . getRuleInfo ( { ast } ) , 'Expected no rule to be found' ) ;
103
+ } ) ;
104
+ } ) ;
105
+ } ) ;
106
+
107
+ describe ( 'the file has a valid rule (TypeScript + TypeScript parser + ESM)' , ( ) => {
108
+ const CASES = {
109
+ // Util function only
110
+ 'export default createESLintRule<Options, MessageIds>({ create() {}, meta: {} });' : {
111
+ create : { type : 'FunctionExpression' } ,
112
+ meta : { type : 'ObjectExpression' } ,
113
+ isNewStyle : true ,
114
+ } ,
115
+ // Util function from util object
116
+ 'export default util.createRule<Options, MessageIds>({ create() {}, meta: {} });' : {
117
+ create : { type : 'FunctionExpression' } ,
118
+ meta : { type : 'ObjectExpression' } ,
119
+ isNewStyle : true ,
120
+ } ,
121
+ // Util function from util object with additional doc URL argument
122
+ 'export default ESLintUtils.RuleCreator(docsUrl)<Options, MessageIds>({ create() {}, meta: {} });' : {
123
+ create : { type : 'FunctionExpression' } ,
124
+ meta : { type : 'ObjectExpression' } ,
125
+ isNewStyle : true ,
126
+ } ,
127
+ } ;
128
+
129
+ Object . keys ( CASES ) . forEach ( ruleSource => {
130
+ it ( ruleSource , ( ) => {
131
+ const ast = typescriptEslintParser . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : 'module' } ) ;
132
+ const ruleInfo = utils . getRuleInfo ( { ast } ) ;
133
+ assert (
134
+ lodash . isMatch ( ruleInfo , CASES [ ruleSource ] ) ,
135
+ `Expected \n${ inspect ( ruleInfo ) } \nto match\n${ inspect ( CASES [ ruleSource ] ) } `
136
+ ) ;
137
+ } ) ;
138
+ } ) ;
139
+ } ) ;
140
+
141
+ describe ( 'the file has a valid rule (CJS)' , ( ) => {
51
142
const CASES = {
52
- // CJS
53
143
'module.exports = { create: function foo() {} };' : {
54
144
create : { type : 'FunctionExpression' , id : { name : 'foo' } } , // (This property will actually contain the AST node.)
55
145
meta : null ,
@@ -125,7 +215,22 @@ describe('utils', () => {
125
215
meta : null ,
126
216
isNewStyle : false ,
127
217
} ,
218
+ } ;
219
+
220
+ Object . keys ( CASES ) . forEach ( ruleSource => {
221
+ it ( ruleSource , ( ) => {
222
+ const ast = espree . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : 'script' } ) ;
223
+ const ruleInfo = utils . getRuleInfo ( { ast } ) ;
224
+ assert (
225
+ lodash . isMatch ( ruleInfo , CASES [ ruleSource ] ) ,
226
+ `Expected \n${ inspect ( ruleInfo ) } \nto match\n${ inspect ( CASES [ ruleSource ] ) } `
227
+ ) ;
228
+ } ) ;
229
+ } ) ;
230
+ } ) ;
128
231
232
+ describe ( 'the file has a valid rule (ESM)' , ( ) => {
233
+ const CASES = {
129
234
// ESM (object style)
130
235
'export default { create() {} }' : {
131
236
create : { type : 'FunctionExpression' } ,
@@ -153,15 +258,17 @@ describe('utils', () => {
153
258
154
259
Object . keys ( CASES ) . forEach ( ruleSource => {
155
260
it ( ruleSource , ( ) => {
156
- const ast = espree . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : ruleSource . startsWith ( 'export default' ) ? ' module' : 'script ' } ) ;
261
+ const ast = espree . parse ( ruleSource , { ecmaVersion : 6 , range : true , sourceType : ' module' } ) ;
157
262
const ruleInfo = utils . getRuleInfo ( { ast } ) ;
158
263
assert (
159
264
lodash . isMatch ( ruleInfo , CASES [ ruleSource ] ) ,
160
265
`Expected \n${ inspect ( ruleInfo ) } \nto match\n${ inspect ( CASES [ ruleSource ] ) } `
161
266
) ;
162
267
} ) ;
163
268
} ) ;
269
+ } ) ;
164
270
271
+ describe ( 'the file has a valid rule (different scope options)' , ( ) => {
165
272
for ( const scopeOptions of [
166
273
{ ignoreEval : true , ecmaVersion : 6 , sourceType : 'script' , nodejsScope : true } ,
167
274
{ ignoreEval : true , ecmaVersion : 6 , sourceType : 'script' } ,
0 commit comments