]> git.proxmox.com Git - pve-eslint.git/blob - eslint/tests/lib/rules/complexity.js
import 8.3.0 source
[pve-eslint.git] / eslint / tests / lib / rules / complexity.js
1 /**
2 * @fileoverview Tests for complexity rule.
3 * @author Patrick Brosset
4 */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const rule = require("../../../lib/rules/complexity"),
13 { RuleTester } = require("../../../lib/rule-tester");
14
15 //------------------------------------------------------------------------------
16 // Helpers
17 //------------------------------------------------------------------------------
18
19 /**
20 * Generates a code string with the amount of complexity specified in the parameter
21 * @param {int} complexity The level of complexity
22 * @returns {string} Code with the amount of complexity specified in the parameter
23 * @private
24 */
25 function createComplexity(complexity) {
26 let funcString = "function test (a) { if (a === 1) {";
27
28 for (let i = 2; i < complexity; i++) {
29 funcString += `} else if (a === ${i}) {`;
30 }
31
32 funcString += "} };";
33
34 return funcString;
35 }
36
37 /**
38 * Create an expected error object
39 * @param {string} name The name of the symbol being tested
40 * @param {number} complexity The cyclomatic complexity value of the symbol
41 * @param {number} max The maximum cyclomatic complexity value of the symbol
42 * @returns {Object} The error object
43 */
44 function makeError(name, complexity, max) {
45 return {
46 messageId: "complex",
47 data: { name, complexity, max }
48 };
49 }
50
51 //------------------------------------------------------------------------------
52 // Tests
53 //------------------------------------------------------------------------------
54
55 const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2021 } });
56
57 ruleTester.run("complexity", rule, {
58 valid: [
59 "function a(x) {}",
60 { code: "function b(x) {}", options: [1] },
61 { code: "function a(x) {if (true) {return x;}}", options: [2] },
62 { code: "function a(x) {if (true) {return x;} else {return x+1;}}", options: [2] },
63 { code: "function a(x) {if (true) {return x;} else if (false) {return x+1;} else {return 4;}}", options: [3] },
64 { code: "function a(x) {for(var i = 0; i < 5; i ++) {x ++;} return x;}", options: [2] },
65 { code: "function a(obj) {for(var i in obj) {obj[i] = 3;}}", options: [2] },
66 { code: "function a(x) {for(var i = 0; i < 5; i ++) {if(i % 2 === 0) {x ++;}} return x;}", options: [3] },
67 { code: "function a(obj) {if(obj){ for(var x in obj) {try {x.getThis();} catch (e) {x.getThat();}}} else {return false;}}", options: [4] },
68 { code: "function a(x) {try {x.getThis();} catch (e) {x.getThat();}}", options: [2] },
69 { code: "function a(x) {return x === 4 ? 3 : 5;}", options: [2] },
70 { code: "function a(x) {return x === 4 ? 3 : (x === 3 ? 2 : 1);}", options: [3] },
71 { code: "function a(x) {return x || 4;}", options: [2] },
72 { code: "function a(x) {x && 4;}", options: [2] },
73 { code: "function a(x) {x ?? 4;}", options: [2] },
74 { code: "function a(x) {x ||= 4;}", options: [2] },
75 { code: "function a(x) {x &&= 4;}", options: [2] },
76 { code: "function a(x) {x ??= 4;}", options: [2] },
77 { code: "function a(x) {x = 4;}", options: [1] },
78 { code: "function a(x) {x |= 4;}", options: [1] },
79 { code: "function a(x) {x &= 4;}", options: [1] },
80 { code: "function a(x) {x += 4;}", options: [1] },
81 { code: "function a(x) {x >>= 4;}", options: [1] },
82 { code: "function a(x) {x >>>= 4;}", options: [1] },
83 { code: "function a(x) {x == 4;}", options: [1] },
84 { code: "function a(x) {x === 4;}", options: [1] },
85 { code: "function a(x) {switch(x){case 1: 1; break; case 2: 2; break; default: 3;}}", options: [3] },
86 { code: "function a(x) {switch(x){case 1: 1; break; case 2: 2; break; default: if(x == 'foo') {5;};}}", options: [4] },
87 { code: "function a(x) {while(true) {'foo';}}", options: [2] },
88 { code: "function a(x) {do {'foo';} while (true)}", options: [2] },
89 { code: "if (foo) { bar(); }", options: [3] },
90 { code: "var a = (x) => {do {'foo';} while (true)}", options: [2], parserOptions: { ecmaVersion: 6 } },
91
92 // class fields
93 { code: "function foo() { class C { x = a || b; y = c || d; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
94 { code: "function foo() { class C { static x = a || b; static y = c || d; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
95 { code: "function foo() { class C { x = a || b; y = c || d; } e || f; }", options: [2], parserOptions: { ecmaVersion: 2022 } },
96 { code: "function foo() { a || b; class C { x = c || d; y = e || f; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
97 { code: "function foo() { class C { [x || y] = a || b; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
98 { code: "class C { x = a || b; y() { c || d; } z = e || f; }", options: [2], parserOptions: { ecmaVersion: 2022 } },
99 { code: "class C { x() { a || b; } y = c || d; z() { e || f; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
100 { code: "class C { x = (() => { a || b }) || (() => { c || d }) }", options: [2], parserOptions: { ecmaVersion: 2022 } },
101 { code: "class C { x = () => { a || b }; y = () => { c || d } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
102 { code: "class C { x = a || (() => { b || c }); }", options: [2], parserOptions: { ecmaVersion: 2022 } },
103 { code: "class C { x = class { y = a || b; z = c || d; }; }", options: [2], parserOptions: { ecmaVersion: 2022 } },
104 { code: "class C { x = a || class { y = b || c; z = d || e; }; }", options: [2], parserOptions: { ecmaVersion: 2022 } },
105 { code: "class C { x; y = a; static z; static q = b; }", options: [1], parserOptions: { ecmaVersion: 2022 } },
106
107 // class static blocks
108 { code: "function foo() { class C { static { a || b; } static { c || d; } } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
109 { code: "function foo() { a || b; class C { static { c || d; } } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
110 { code: "function foo() { class C { static { a || b; } } c || d; }", options: [2], parserOptions: { ecmaVersion: 2022 } },
111 { code: "function foo() { class C { static { a || b; } } class D { static { c || d; } } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
112 { code: "class C { static { a || b; } static { c || d; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
113 { code: "class C { static { a || b; } static { c || d; } static { e || f; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
114 { code: "class C { static { () => a || b; c || d; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
115 { code: "class C { static { a || b; () => c || d; } static { c || d; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
116 { code: "class C { static { a } }", options: [1], parserOptions: { ecmaVersion: 2022 } },
117 { code: "class C { static { a } static { b } }", options: [1], parserOptions: { ecmaVersion: 2022 } },
118 { code: "class C { static { a || b; } } class D { static { c || d; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
119 { code: "class C { static { a || b; } static c = d || e; }", options: [2], parserOptions: { ecmaVersion: 2022 } },
120 { code: "class C { static a = b || c; static { c || d; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
121 { code: "class C { static { a || b; } c = d || e; }", options: [2], parserOptions: { ecmaVersion: 2022 } },
122 { code: "class C { a = b || c; static { d || e; } }", options: [2], parserOptions: { ecmaVersion: 2022 } },
123 { code: "class C { static { a || b; c || d; } }", options: [3], parserOptions: { ecmaVersion: 2022 } },
124 { code: "class C { static { if (a || b) c = d || e; } }", options: [4], parserOptions: { ecmaVersion: 2022 } },
125
126 // object property options
127 { code: "function b(x) {}", options: [{ max: 1 }] }
128 ],
129 invalid: [
130 { code: "function a(x) {}", options: [0], errors: [makeError("Function 'a'", 1, 0)] },
131 { code: "var func = function () {}", options: [0], errors: [makeError("Function", 1, 0)] },
132 { code: "var obj = { a(x) {} }", options: [0], parserOptions: { ecmaVersion: 6 }, errors: [makeError("Method 'a'", 1, 0)] },
133 { code: "class Test { a(x) {} }", options: [0], parserOptions: { ecmaVersion: 6 }, errors: [makeError("Method 'a'", 1, 0)] },
134 { code: "var a = (x) => {if (true) {return x;}}", options: [1], parserOptions: { ecmaVersion: 6 }, errors: 1 },
135 { code: "function a(x) {if (true) {return x;}}", options: [1], errors: 1 },
136 { code: "function a(x) {if (true) {return x;} else {return x+1;}}", options: [1], errors: 1 },
137 { code: "function a(x) {if (true) {return x;} else if (false) {return x+1;} else {return 4;}}", options: [2], errors: 1 },
138 { code: "function a(x) {for(var i = 0; i < 5; i ++) {x ++;} return x;}", options: [1], errors: 1 },
139 { code: "function a(obj) {for(var i in obj) {obj[i] = 3;}}", options: [1], errors: 1 },
140 { code: "function a(obj) {for(var i of obj) {obj[i] = 3;}}", options: [1], parserOptions: { ecmaVersion: 6 }, errors: 1 },
141 { code: "function a(x) {for(var i = 0; i < 5; i ++) {if(i % 2 === 0) {x ++;}} return x;}", options: [2], errors: 1 },
142 { code: "function a(obj) {if(obj){ for(var x in obj) {try {x.getThis();} catch (e) {x.getThat();}}} else {return false;}}", options: [3], errors: 1 },
143 { code: "function a(x) {try {x.getThis();} catch (e) {x.getThat();}}", options: [1], errors: 1 },
144 { code: "function a(x) {return x === 4 ? 3 : 5;}", options: [1], errors: 1 },
145 { code: "function a(x) {return x === 4 ? 3 : (x === 3 ? 2 : 1);}", options: [2], errors: 1 },
146 { code: "function a(x) {return x || 4;}", options: [1], errors: 1 },
147 { code: "function a(x) {x && 4;}", options: [1], errors: 1 },
148 { code: "function a(x) {x ?? 4;}", options: [1], errors: 1 },
149 { code: "function a(x) {x ||= 4;}", options: [1], errors: 1 },
150 { code: "function a(x) {x &&= 4;}", options: [1], errors: 1 },
151 { code: "function a(x) {x ??= 4;}", options: [1], errors: 1 },
152 { code: "function a(x) {switch(x){case 1: 1; break; case 2: 2; break; default: 3;}}", options: [2], errors: 1 },
153 { code: "function a(x) {switch(x){case 1: 1; break; case 2: 2; break; default: if(x == 'foo') {5;};}}", options: [3], errors: 1 },
154 { code: "function a(x) {while(true) {'foo';}}", options: [1], errors: 1 },
155 { code: "function a(x) {do {'foo';} while (true)}", options: [1], errors: 1 },
156 { code: "function a(x) {(function() {while(true){'foo';}})(); (function() {while(true){'bar';}})();}", options: [1], errors: 2 },
157 { code: "function a(x) {(function() {while(true){'foo';}})(); (function() {'bar';})();}", options: [1], errors: 1 },
158 { code: "var obj = { a(x) { return x ? 0 : 1; } };", options: [1], parserOptions: { ecmaVersion: 6 }, errors: [makeError("Method 'a'", 2, 1)] },
159 { code: "var obj = { a: function b(x) { return x ? 0 : 1; } };", options: [1], errors: [makeError("Method 'a'", 2, 1)] },
160 {
161 code: createComplexity(21),
162 errors: [makeError("Function 'test'", 21, 20)]
163 },
164 {
165 code: createComplexity(21),
166 options: [{}],
167 errors: [makeError("Function 'test'", 21, 20)]
168 },
169
170 // class fields
171 {
172 code: "function foo () { a || b; class C { x; } c || d; }",
173 options: [2],
174 parserOptions: { ecmaVersion: 2022 },
175 errors: [makeError("Function 'foo'", 3, 2)]
176 },
177 {
178 code: "function foo () { a || b; class C { x = c; } d || e; }",
179 options: [2],
180 parserOptions: { ecmaVersion: 2022 },
181 errors: [makeError("Function 'foo'", 3, 2)]
182 },
183 {
184 code: "function foo () { a || b; class C { [x || y]; } }",
185 options: [2],
186 parserOptions: { ecmaVersion: 2022 },
187 errors: [makeError("Function 'foo'", 3, 2)]
188 },
189 {
190 code: "function foo () { a || b; class C { [x || y] = c; } }",
191 options: [2],
192 parserOptions: { ecmaVersion: 2022 },
193 errors: [makeError("Function 'foo'", 3, 2)]
194 },
195 {
196 code: "function foo () { class C { [x || y]; } a || b; }",
197 options: [2],
198 parserOptions: { ecmaVersion: 2022 },
199 errors: [makeError("Function 'foo'", 3, 2)]
200 },
201 {
202 code: "function foo () { class C { [x || y] = a; } b || c; }",
203 options: [2],
204 parserOptions: { ecmaVersion: 2022 },
205 errors: [makeError("Function 'foo'", 3, 2)]
206 },
207 {
208 code: "function foo () { class C { [x || y]; [z || q]; } }",
209 options: [2],
210 parserOptions: { ecmaVersion: 2022 },
211 errors: [makeError("Function 'foo'", 3, 2)]
212 },
213 {
214 code: "function foo () { class C { [x || y] = a; [z || q] = b; } }",
215 options: [2],
216 parserOptions: { ecmaVersion: 2022 },
217 errors: [makeError("Function 'foo'", 3, 2)]
218 },
219 {
220 code: "function foo () { a || b; class C { x = c || d; } e || f; }",
221 options: [2],
222 parserOptions: { ecmaVersion: 2022 },
223 errors: [makeError("Function 'foo'", 3, 2)]
224 },
225 {
226 code: "class C { x(){ a || b; } y = c || d || e; z() { f || g; } }",
227 options: [2],
228 parserOptions: { ecmaVersion: 2022 },
229 errors: [makeError("Class field initializer", 3, 2)]
230 },
231 {
232 code: "class C { x = a || b; y() { c || d || e; } z = f || g; }",
233 options: [2],
234 parserOptions: { ecmaVersion: 2022 },
235 errors: [makeError("Method 'y'", 3, 2)]
236 },
237 {
238 code: "class C { x; y() { c || d || e; } z; }",
239 options: [2],
240 parserOptions: { ecmaVersion: 2022 },
241 errors: [makeError("Method 'y'", 3, 2)]
242 },
243 {
244 code: "class C { x = a || b; }",
245 options: [1],
246 parserOptions: { ecmaVersion: 2022 },
247 errors: [makeError("Class field initializer", 2, 1)]
248 },
249 {
250 code: "(class { x = a || b; })",
251 options: [1],
252 parserOptions: { ecmaVersion: 2022 },
253 errors: [makeError("Class field initializer", 2, 1)]
254 },
255 {
256 code: "class C { static x = a || b; }",
257 options: [1],
258 parserOptions: { ecmaVersion: 2022 },
259 errors: [makeError("Class field initializer", 2, 1)]
260 },
261 {
262 code: "(class { x = a ? b : c; })",
263 options: [1],
264 parserOptions: { ecmaVersion: 2022 },
265 errors: [makeError("Class field initializer", 2, 1)]
266 },
267 {
268 code: "class C { x = a || b || c; }",
269 options: [2],
270 parserOptions: { ecmaVersion: 2022 },
271 errors: [makeError("Class field initializer", 3, 2)]
272 },
273 {
274 code: "class C { x = a || b; y = b || c || d; z = e || f; }",
275 options: [2],
276 parserOptions: { ecmaVersion: 2022 },
277 errors: [{
278 ...makeError("Class field initializer", 3, 2),
279 line: 1,
280 column: 27,
281 endLine: 1,
282 endColumn: 38
283 }]
284 },
285 {
286 code: "class C { x = a || b || c; y = d || e; z = f || g || h; }",
287 options: [2],
288 parserOptions: { ecmaVersion: 2022 },
289 errors: [
290 {
291 ...makeError("Class field initializer", 3, 2),
292 line: 1,
293 column: 15,
294 endLine: 1,
295 endColumn: 26
296 },
297 {
298 ...makeError("Class field initializer", 3, 2),
299 line: 1,
300 column: 44,
301 endLine: 1,
302 endColumn: 55
303 }
304 ]
305 },
306 {
307 code: "class C { x = () => a || b || c; }",
308 options: [2],
309 parserOptions: { ecmaVersion: 2022 },
310 errors: [makeError("Method 'x'", 3, 2)]
311 },
312 {
313 code: "class C { x = (() => a || b || c) || d; }",
314 options: [2],
315 parserOptions: { ecmaVersion: 2022 },
316 errors: [makeError("Arrow function", 3, 2)]
317 },
318 {
319 code: "class C { x = () => a || b || c; y = d || e; }",
320 options: [2],
321 parserOptions: { ecmaVersion: 2022 },
322 errors: [makeError("Method 'x'", 3, 2)]
323 },
324 {
325 code: "class C { x = () => a || b || c; y = d || e || f; }",
326 options: [2],
327 parserOptions: { ecmaVersion: 2022 },
328 errors: [
329 makeError("Method 'x'", 3, 2),
330 {
331 ...makeError("Class field initializer", 3, 2),
332 line: 1,
333 column: 38,
334 endLine: 1,
335 endColumn: 49
336 }
337 ]
338 },
339 {
340 code: "class C { x = function () { a || b }; y = function () { c || d }; }",
341 options: [1],
342 parserOptions: { ecmaVersion: 2022 },
343 errors: [
344 makeError("Method 'x'", 2, 1),
345 makeError("Method 'y'", 2, 1)
346 ]
347 },
348 {
349 code: "class C { x = class { [y || z]; }; }",
350 options: [1],
351 parserOptions: { ecmaVersion: 2022 },
352 errors: [
353 {
354 ...makeError("Class field initializer", 2, 1),
355 line: 1,
356 column: 15,
357 endLine: 1,
358 endColumn: 34
359 }
360 ]
361 },
362 {
363 code: "class C { x = class { [y || z] = a; }; }",
364 options: [1],
365 parserOptions: { ecmaVersion: 2022 },
366 errors: [
367 {
368 ...makeError("Class field initializer", 2, 1),
369 line: 1,
370 column: 15,
371 endLine: 1,
372 endColumn: 38
373 }
374 ]
375 },
376 {
377 code: "class C { x = class { y = a || b; }; }",
378 options: [1],
379 parserOptions: { ecmaVersion: 2022 },
380 errors: [
381 {
382 ...makeError("Class field initializer", 2, 1),
383 line: 1,
384 column: 27,
385 endLine: 1,
386 endColumn: 33
387 }
388 ]
389 },
390
391 // class static blocks
392 {
393 code: "function foo () { a || b; class C { static {} } c || d; }",
394 options: [2],
395 parserOptions: { ecmaVersion: 2022 },
396 errors: [makeError("Function 'foo'", 3, 2)]
397 },
398 {
399 code: "function foo () { a || b; class C { static { c || d; } } e || f; }",
400 options: [2],
401 parserOptions: { ecmaVersion: 2022 },
402 errors: [makeError("Function 'foo'", 3, 2)]
403 },
404 {
405 code: "class C { static { a || b; } }",
406 options: [1],
407 parserOptions: { ecmaVersion: 2022 },
408 errors: [makeError("Class static block", 2, 1)]
409 },
410 {
411 code: "class C { static { a || b || c; } }",
412 options: [2],
413 parserOptions: { ecmaVersion: 2022 },
414 errors: [makeError("Class static block", 3, 2)]
415 },
416 {
417 code: "class C { static { a || b; c || d; } }",
418 options: [2],
419 parserOptions: { ecmaVersion: 2022 },
420 errors: [makeError("Class static block", 3, 2)]
421 },
422 {
423 code: "class C { static { a || b; c || d; e || f; } }",
424 options: [3],
425 parserOptions: { ecmaVersion: 2022 },
426 errors: [makeError("Class static block", 4, 3)]
427 },
428 {
429 code: "class C { static { a || b; c || d; { e || f; } } }",
430 options: [3],
431 parserOptions: { ecmaVersion: 2022 },
432 errors: [makeError("Class static block", 4, 3)]
433 },
434 {
435 code: "class C { static { if (a || b) c = d || e; } }",
436 options: [3],
437 parserOptions: { ecmaVersion: 2022 },
438 errors: [makeError("Class static block", 4, 3)]
439 },
440 {
441 code: "class C { static { if (a || b) c = (d => e || f)() || (g => h || i)(); } }",
442 options: [3],
443 parserOptions: { ecmaVersion: 2022 },
444 errors: [makeError("Class static block", 4, 3)]
445 },
446 {
447 code: "class C { x(){ a || b; } static { c || d || e; } z() { f || g; } }",
448 options: [2],
449 parserOptions: { ecmaVersion: 2022 },
450 errors: [makeError("Class static block", 3, 2)]
451 },
452 {
453 code: "class C { x = a || b; static { c || d || e; } y = f || g; }",
454 options: [2],
455 parserOptions: { ecmaVersion: 2022 },
456 errors: [makeError("Class static block", 3, 2)]
457 },
458 {
459 code: "class C { static x = a || b; static { c || d || e; } static y = f || g; }",
460 options: [2],
461 parserOptions: { ecmaVersion: 2022 },
462 errors: [makeError("Class static block", 3, 2)]
463 },
464 {
465 code: "class C { static { a || b; } static(){ c || d || e; } static { f || g; } }",
466 options: [2],
467 parserOptions: { ecmaVersion: 2022 },
468 errors: [makeError("Method 'static'", 3, 2)]
469 },
470 {
471 code: "class C { static { a || b; } static static(){ c || d || e; } static { f || g; } }",
472 options: [2],
473 parserOptions: { ecmaVersion: 2022 },
474 errors: [makeError("Static method 'static'", 3, 2)]
475 },
476 {
477 code: "class C { static { a || b; } static x = c || d || e; static { f || g; } }",
478 options: [2],
479 parserOptions: { ecmaVersion: 2022 },
480 errors: [{
481 ...makeError("Class field initializer", 3, 2),
482 column: 41,
483 endColumn: 52
484 }]
485 },
486 {
487 code: "class C { static { a || b || c || d; } static { e || f || g; } }",
488 options: [3],
489 parserOptions: { ecmaVersion: 2022 },
490 errors: [{
491 ...makeError("Class static block", 4, 3),
492 column: 11,
493 endColumn: 39
494 }]
495 },
496 {
497 code: "class C { static { a || b || c; } static { d || e || f || g; } }",
498 options: [3],
499 parserOptions: { ecmaVersion: 2022 },
500 errors: [{
501 ...makeError("Class static block", 4, 3),
502 column: 35,
503 endColumn: 63
504 }]
505 },
506 {
507 code: "class C { static { a || b || c || d; } static { e || f || g || h; } }",
508 options: [3],
509 parserOptions: { ecmaVersion: 2022 },
510 errors: [
511 {
512 ...makeError("Class static block", 4, 3),
513 column: 11,
514 endColumn: 39
515 },
516 {
517 ...makeError("Class static block", 4, 3),
518 column: 40,
519 endColumn: 68
520 }
521 ]
522 },
523
524 // object property options
525 { code: "function a(x) {}", options: [{ max: 0 }], errors: [makeError("Function 'a'", 1, 0)] }
526 ]
527 });