]> git.proxmox.com Git - pve-eslint.git/blame - eslint/tests/lib/rules/prefer-exponentiation-operator.js
import eslint 7.18.0
[pve-eslint.git] / eslint / tests / lib / rules / prefer-exponentiation-operator.js
CommitLineData
eb39fafa
DC
1/**
2 * @fileoverview Tests for the prefer-exponentiation-operator rule
3 * @author Milos Djermanovic
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Requirements
10//------------------------------------------------------------------------------
11
12const rule = require("../../../lib/rules/prefer-exponentiation-operator");
13const { RuleTester } = require("../../../lib/rule-tester");
14
15//------------------------------------------------------------------------------
16// Helpers
17//------------------------------------------------------------------------------
18
19/**
20 * Create an object for the invalid array
21 * @param {string} code source code
22 * @param {string} output fixed source code
23 * @returns {Object} result object
24 * @private
25 */
26function invalid(code, output) {
27 return {
28 code,
29 output,
30 errors: [
31 {
32 messageId: "useExponentiation",
33 type: "CallExpression"
34 }
35 ]
36 };
37}
38
39//------------------------------------------------------------------------------
40// Tests
41//------------------------------------------------------------------------------
42
6f036462 43const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2020 } });
eb39fafa
DC
44
45ruleTester.run("prefer-exponentiation-operator", rule, {
46 valid: [
47
48 // not Math.pow()
49 "Object.pow(a, b)",
50 "Math.max(a, b)",
51 "Math",
52 "Math(a, b)",
53 "pow",
54 "pow(a, b)",
55 "Math.pow",
56 "Math.Pow(a, b)",
57 "math.pow(a, b)",
58 "foo.Math.pow(a, b)",
59 "new Math.pow(a, b)",
60 "Math[pow](a, b)",
61 { code: "globalThis.Object.pow(a, b)", env: { es2020: true } },
62 { code: "globalThis.Math.max(a, b)", env: { es2020: true } },
63
64 // not the global Math
65 "/* globals Math:off*/ Math.pow(a, b)",
66 "let Math; Math.pow(a, b);",
67 "if (foo) { const Math = 1; Math.pow(a, b); }",
68 "var x = function Math() { Math.pow(a, b); }",
69 "function foo(Math) { Math.pow(a, b); }",
70 "function foo() { Math.pow(a, b); var Math; }",
71
72 "globalThis.Math.pow(a, b)",
73 { code: "globalThis.Math.pow(a, b)", env: { es6: true } },
74 { code: "globalThis.Math.pow(a, b)", env: { es2017: true } },
75 {
76 code: `
77 var globalThis = bar;
78 globalThis.Math.pow(a, b)
79 `,
80 env: { es2020: true }
81 }
82 ],
83
84 invalid: [
85
86 invalid("Math.pow(a, b)", "a**b"),
87 invalid("(Math).pow(a, b)", "a**b"),
88 invalid("Math['pow'](a, b)", "a**b"),
89 invalid("(Math)['pow'](a, b)", "a**b"),
90 invalid("var x=Math\n. pow( a, \n b )", "var x=a**b"),
91 {
92 code: "globalThis.Math.pow(a, b)",
93 output: "a**b",
94 env: { es2020: true },
95 errors: [
96 {
97 messageId: "useExponentiation",
98 type: "CallExpression",
99 line: 1,
100 column: 1,
101 endLine: 1,
102 endColumn: 26
103 }
104 ]
105 },
106 {
107 code: "globalThis.Math['pow'](a, b)",
108 output: "a**b",
109 env: { es2020: true },
110 errors: [
111 {
112 messageId: "useExponentiation",
113 type: "CallExpression",
114 line: 1,
115 column: 1,
116 endLine: 1,
117 endColumn: 29
118 }
119 ]
120 },
121
122 // able to catch some workarounds
123 invalid("Math[`pow`](a, b)", "a**b"),
124 invalid("Math[`${'pow'}`](a, b)", "a**b"),
125 invalid("Math['p' + 'o' + 'w'](a, b)", "a**b"),
126
127 // non-expression parents that don't require parens
128 invalid("var x = Math.pow(a, b);", "var x = a**b;"),
129 invalid("if(Math.pow(a, b)){}", "if(a**b){}"),
130 invalid("for(;Math.pow(a, b);){}", "for(;a**b;){}"),
131 invalid("switch(foo){ case Math.pow(a, b): break; }", "switch(foo){ case a**b: break; }"),
132 invalid("{ foo: Math.pow(a, b) }", "{ foo: a**b }"),
133 invalid("function foo(bar, baz = Math.pow(a, b), quux){}", "function foo(bar, baz = a**b, quux){}"),
134 invalid("`${Math.pow(a, b)}`", "`${a**b}`"),
135
136 // non-expression parents that do require parens
137 invalid("class C extends Math.pow(a, b) {}", "class C extends (a**b) {}"),
138
139 // parents with a higher precedence
140 invalid("+ Math.pow(a, b)", "+ (a**b)"),
141 invalid("- Math.pow(a, b)", "- (a**b)"),
142 invalid("! Math.pow(a, b)", "! (a**b)"),
143 invalid("typeof Math.pow(a, b)", "typeof (a**b)"),
144 invalid("void Math.pow(a, b)", "void (a**b)"),
145 invalid("Math.pow(a, b) .toString()", "(a**b) .toString()"),
146 invalid("Math.pow(a, b) ()", "(a**b) ()"),
147 invalid("Math.pow(a, b) ``", "(a**b) ``"),
148 invalid("(class extends Math.pow(a, b) {})", "(class extends (a**b) {})"),
149
150 // already parenthesised, shouldn't insert extra parens
151 invalid("+(Math.pow(a, b))", "+(a**b)"),
152 invalid("(Math.pow(a, b)).toString()", "(a**b).toString()"),
153 invalid("(class extends (Math.pow(a, b)) {})", "(class extends (a**b) {})"),
154 invalid("class C extends (Math.pow(a, b)) {}", "class C extends (a**b) {}"),
155
156 // parents with a higher precedence, but the expression's role doesn't require parens
157 invalid("f(Math.pow(a, b))", "f(a**b)"),
158 invalid("f(foo, Math.pow(a, b))", "f(foo, a**b)"),
159 invalid("f(Math.pow(a, b), foo)", "f(a**b, foo)"),
160 invalid("f(foo, Math.pow(a, b), bar)", "f(foo, a**b, bar)"),
161 invalid("new F(Math.pow(a, b))", "new F(a**b)"),
162 invalid("new F(foo, Math.pow(a, b))", "new F(foo, a**b)"),
163 invalid("new F(Math.pow(a, b), foo)", "new F(a**b, foo)"),
164 invalid("new F(foo, Math.pow(a, b), bar)", "new F(foo, a**b, bar)"),
165 invalid("obj[Math.pow(a, b)]", "obj[a**b]"),
166 invalid("[foo, Math.pow(a, b), bar]", "[foo, a**b, bar]"),
167
168 // parents with a lower precedence
169 invalid("a * Math.pow(b, c)", "a * b**c"),
170 invalid("Math.pow(a, b) * c", "a**b * c"),
171 invalid("a + Math.pow(b, c)", "a + b**c"),
172 invalid("Math.pow(a, b)/c", "a**b/c"),
173 invalid("a < Math.pow(b, c)", "a < b**c"),
174 invalid("Math.pow(a, b) > c", "a**b > c"),
175 invalid("a === Math.pow(b, c)", "a === b**c"),
176 invalid("a ? Math.pow(b, c) : d", "a ? b**c : d"),
177 invalid("a = Math.pow(b, c)", "a = b**c"),
178 invalid("a += Math.pow(b, c)", "a += b**c"),
179 invalid("function *f() { yield Math.pow(a, b) }", "function *f() { yield a**b }"),
180 invalid("a, Math.pow(b, c), d", "a, b**c, d"),
181
182 // '**' is right-associative, that applies to both parent and child nodes
183 invalid("a ** Math.pow(b, c)", "a ** b**c"),
184 invalid("Math.pow(a, b) ** c", "(a**b) ** c"),
185 invalid("Math.pow(a, b ** c)", "a**b ** c"),
186 invalid("Math.pow(a ** b, c)", "(a ** b)**c"),
187 invalid("a ** Math.pow(b ** c, d ** e) ** f", "a ** ((b ** c)**d ** e) ** f"),
188
189 // doesn't remove already existing unnecessary parens around the whole expression
190 invalid("(Math.pow(a, b))", "(a**b)"),
191 invalid("foo + (Math.pow(a, b))", "foo + (a**b)"),
192 invalid("(Math.pow(a, b)) + foo", "(a**b) + foo"),
193 invalid("`${(Math.pow(a, b))}`", "`${(a**b)}`"),
194
195 // base and exponent with a higher precedence
196 invalid("Math.pow(2, 3)", "2**3"),
197 invalid("Math.pow(a.foo, b)", "a.foo**b"),
198 invalid("Math.pow(a, b.foo)", "a**b.foo"),
199 invalid("Math.pow(a(), b)", "a()**b"),
200 invalid("Math.pow(a, b())", "a**b()"),
201 invalid("Math.pow(++a, ++b)", "++a**++b"),
202 invalid("Math.pow(a++, ++b)", "a++**++b"),
203 invalid("Math.pow(a--, b--)", "a--**b--"),
204 invalid("Math.pow(--a, b--)", "--a**b--"),
205
206 // doesn't preserve unnecessary parens around base and exponent
207 invalid("Math.pow((a), (b))", "a**b"),
208 invalid("Math.pow(((a)), ((b)))", "a**b"),
209 invalid("Math.pow((a.foo), b)", "a.foo**b"),
210 invalid("Math.pow(a, (b.foo))", "a**b.foo"),
211 invalid("Math.pow((a()), b)", "a()**b"),
212 invalid("Math.pow(a, (b()))", "a**b()"),
213
214 // unary expressions are exception by the language - parens are required for the base to disambiguate operator precedence
215 invalid("Math.pow(+a, b)", "(+a)**b"),
216 invalid("Math.pow(a, +b)", "a**+b"),
217 invalid("Math.pow(-a, b)", "(-a)**b"),
218 invalid("Math.pow(a, -b)", "a**-b"),
219 invalid("Math.pow(-2, 3)", "(-2)**3"),
220 invalid("Math.pow(2, -3)", "2**-3"),
456be15e
TL
221 invalid("async () => Math.pow(await a, b)", "async () => (await a)**b"),
222 invalid("async () => Math.pow(a, await b)", "async () => a**await b"),
eb39fafa
DC
223
224 // base and exponent with a lower precedence
225 invalid("Math.pow(a * b, c)", "(a * b)**c"),
226 invalid("Math.pow(a, b * c)", "a**(b * c)"),
227 invalid("Math.pow(a / b, c)", "(a / b)**c"),
228 invalid("Math.pow(a, b / c)", "a**(b / c)"),
229 invalid("Math.pow(a + b, 3)", "(a + b)**3"),
230 invalid("Math.pow(2, a - b)", "2**(a - b)"),
231 invalid("Math.pow(a + b, c + d)", "(a + b)**(c + d)"),
232 invalid("Math.pow(a = b, c = d)", "(a = b)**(c = d)"),
233 invalid("Math.pow(a += b, c -= d)", "(a += b)**(c -= d)"),
234 invalid("Math.pow((a, b), (c, d))", "(a, b)**(c, d)"),
235 invalid("function *f() { Math.pow(yield, yield) }", "function *f() { (yield)**(yield) }"),
236
237 // doesn't put extra parens
238 invalid("Math.pow((a + b), (c + d))", "(a + b)**(c + d)"),
239
240 // tokens that can be adjacent
241 invalid("a+Math.pow(b, c)+d", "a+b**c+d"),
242
243 // tokens that cannot be adjacent
244 invalid("a+Math.pow(++b, c)", "a+ ++b**c"),
245 invalid("(a)+(Math).pow((++b), c)", "(a)+ ++b**c"),
246 invalid("Math.pow(a, b)in c", "a**b in c"),
247 invalid("Math.pow(a, (b))in (c)", "a**b in (c)"),
248 invalid("a+Math.pow(++b, c)in d", "a+ ++b**c in d"),
249 invalid("a+Math.pow( ++b, c )in d", "a+ ++b**c in d"),
250
251 // tokens that cannot be adjacent, but there is already space or something else between
252 invalid("a+ Math.pow(++b, c) in d", "a+ ++b**c in d"),
253 invalid("a+/**/Math.pow(++b, c)/**/in d", "a+/**/++b**c/**/in d"),
254 invalid("a+(Math.pow(++b, c))in d", "a+(++b**c)in d"),
255
256 // tokens that cannot be adjacent, but the autofix inserts parens required for precedence, so there is no need for an extra space
257 invalid("+Math.pow(++a, b)", "+(++a**b)"),
258 invalid("Math.pow(a, b + c)in d", "a**(b + c)in d"),
259
260 {
261 code: "Math.pow(a, b) + Math.pow(c,\n d)",
262 output: "a**b + c**d",
263 errors: [
264 {
265 messageId: "useExponentiation",
266 type: "CallExpression",
267 line: 1,
268 column: 1,
269 endLine: 1,
270 endColumn: 15
271 },
272 {
273 messageId: "useExponentiation",
274 type: "CallExpression",
275 line: 1,
276 column: 18,
277 endLine: 2,
278 endColumn: 4
279 }
280 ]
281 },
282 {
283 code: "Math.pow(Math.pow(a, b), Math.pow(c, d))",
284 output: "Math.pow(a, b)**Math.pow(c, d)", // tests perform only one autofix iteration, below is the following one
285 errors: [
286 {
287 messageId: "useExponentiation",
288 type: "CallExpression",
289 column: 1,
290 endColumn: 41
291 },
292 {
293 messageId: "useExponentiation",
294 type: "CallExpression",
295 column: 10,
296 endColumn: 24
297 },
298 {
299 messageId: "useExponentiation",
300 type: "CallExpression",
301 column: 26,
302 endColumn: 40
303 }
304 ]
305 },
306 {
307 code: "Math.pow(a, b)**Math.pow(c, d)",
308 output: "(a**b)**c**d",
309 errors: [
310 {
311 messageId: "useExponentiation",
312 type: "CallExpression",
313 column: 1,
314 endColumn: 15
315 },
316 {
317 messageId: "useExponentiation",
318 type: "CallExpression",
319 column: 17,
320 endColumn: 31
321 }
322 ]
323 },
324
325 // shouldn't autofix if the call doesn't have exactly two arguments
326 invalid("Math.pow()", null),
327 invalid("Math.pow(a)", null),
328 invalid("Math.pow(a, b, c)", null),
329 invalid("Math.pow(a, b, c, d)", null),
330
331 // shouldn't autofix if any of the arguments is spread
332 invalid("Math.pow(...a)", null),
333 invalid("Math.pow(...a, b)", null),
334 invalid("Math.pow(a, ...b)", null),
335 invalid("Math.pow(a, b, ...c)", null),
336
337 // shouldn't autofix if that would remove comments
338 invalid("/* comment */Math.pow(a, b)", "/* comment */a**b"),
339 invalid("Math/**/.pow(a, b)", null),
340 invalid("Math//\n.pow(a, b)", null),
341 invalid("Math[//\n'pow'](a, b)", null),
342 invalid("Math['pow'/**/](a, b)", null),
343 invalid("Math./**/pow(a, b)", null),
344 invalid("Math.pow/**/(a, b)", null),
345 invalid("Math.pow//\n(a, b)", null),
346 invalid("Math.pow(/**/a, b)", null),
347 invalid("Math.pow(a,//\n b)", null),
348 invalid("Math.pow(a, b/**/)", null),
349 invalid("Math.pow(a, b//\n)", null),
350 invalid("Math.pow(a, b)/* comment */;", "a**b/* comment */;"),
6f036462
TL
351 invalid("Math.pow(a, b)// comment\n;", "a**b// comment\n;"),
352
353 // Optional chaining
354 invalid("Math.pow?.(a, b)", "a**b"),
355 invalid("Math?.pow(a, b)", "a**b"),
356 invalid("Math?.pow?.(a, b)", "a**b"),
357 invalid("(Math?.pow)(a, b)", "a**b"),
358 invalid("(Math?.pow)?.(a, b)", "a**b")
eb39fafa
DC
359 ]
360});