]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Tests for operator-assignment rule. | |
3 | * @author Brandon Mills | |
4 | */ | |
5 | ||
6 | "use strict"; | |
7 | ||
8 | //------------------------------------------------------------------------------ | |
9 | // Requirements | |
10 | //------------------------------------------------------------------------------ | |
11 | ||
12 | const rule = require("../../../lib/rules/operator-assignment"), | |
13 | { RuleTester } = require("../../../lib/rule-tester"); | |
14 | ||
15 | //------------------------------------------------------------------------------ | |
16 | // Tests | |
17 | //------------------------------------------------------------------------------ | |
18 | ||
6f036462 | 19 | const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2021 } }); |
eb39fafa DC |
20 | |
21 | const EXPECTED_OPERATOR_ASSIGNMENT = [{ messageId: "replaced", type: "AssignmentExpression" }]; | |
22 | const UNEXPECTED_OPERATOR_ASSIGNMENT = [{ messageId: "unexpected", type: "AssignmentExpression" }]; | |
23 | ||
24 | ruleTester.run("operator-assignment", rule, { | |
25 | ||
26 | valid: [ | |
27 | "x = y", | |
28 | "x = y + x", | |
29 | "x += x + y", | |
30 | "x = (x + y) - z", | |
31 | "x -= y", | |
32 | "x = y - x", | |
33 | "x *= x", | |
34 | "x = y * z", | |
35 | "x = (x * y) * z", | |
36 | "x = y / x", | |
37 | "x /= y", | |
38 | "x %= y", | |
39 | "x <<= y", | |
40 | "x >>= x >> y", | |
41 | "x >>>= y", | |
42 | "x &= y", | |
43 | "x **= y", | |
44 | "x ^= y ^ z", | |
45 | "x |= x | y", | |
46 | "x = x && y", | |
47 | "x = x || y", | |
48 | "x = x < y", | |
49 | "x = x > y", | |
50 | "x = x <= y", | |
51 | "x = x >= y", | |
52 | "x = x instanceof y", | |
53 | "x = x in y", | |
54 | "x = x == y", | |
55 | "x = x != y", | |
56 | "x = x === y", | |
57 | "x = x !== y", | |
58 | "x[y] = x['y'] + z", | |
59 | "x.y = x['y'] / z", | |
60 | "x.y = z + x.y", | |
61 | "x[fn()] = x[fn()] + y", | |
62 | { | |
63 | code: "x += x + y", | |
64 | options: ["always"] | |
65 | }, | |
66 | { | |
67 | code: "x = x + y", | |
68 | options: ["never"] | |
69 | }, | |
70 | { | |
71 | code: "x = x ** y", | |
72 | options: ["never"] | |
73 | }, | |
74 | "x = y ** x", | |
75 | "x = x * y + z", | |
76 | { | |
77 | code: "this.x = this.y + z", | |
78 | options: ["always"] | |
79 | }, | |
80 | { | |
81 | code: "this.x = foo.x + y", | |
82 | options: ["always"] | |
83 | }, | |
84 | { | |
85 | code: "this.x = foo.this.x + y", | |
86 | options: ["always"] | |
6f036462 TL |
87 | }, |
88 | ||
89 | // does not check logical operators | |
90 | { | |
91 | code: "x = x && y", | |
92 | options: ["always"] | |
93 | }, | |
94 | { | |
95 | code: "x = x || y", | |
96 | options: ["always"] | |
97 | }, | |
98 | { | |
99 | code: "x = x ?? y", | |
100 | options: ["always"] | |
101 | }, | |
102 | { | |
103 | code: "x &&= y", | |
104 | options: ["never"] | |
105 | }, | |
106 | { | |
107 | code: "x ||= y", | |
108 | options: ["never"] | |
109 | }, | |
110 | { | |
111 | code: "x ??= y", | |
112 | options: ["never"] | |
eb39fafa DC |
113 | } |
114 | ], | |
115 | ||
116 | invalid: [{ | |
117 | code: "x = x + y", | |
118 | output: "x += y", | |
119 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
120 | }, { | |
121 | code: "x = x - y", | |
122 | output: "x -= y", | |
123 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
124 | }, { | |
125 | code: "x = x * y", | |
126 | output: "x *= y", | |
127 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
128 | }, { | |
129 | code: "x = y * x", | |
130 | output: null, // not fixed (possible change in behavior if y and x have valueOf() functions) | |
131 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
132 | }, { | |
133 | code: "x = (y * z) * x", | |
134 | output: null, // not fixed (possible change in behavior if y/z and x have valueOf() functions) | |
135 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
136 | }, { | |
137 | code: "x = x / y", | |
138 | output: "x /= y", | |
139 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
140 | }, { | |
141 | code: "x = x % y", | |
142 | output: "x %= y", | |
143 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
144 | }, { | |
145 | code: "x = x << y", | |
146 | output: "x <<= y", | |
147 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
148 | }, { | |
149 | code: "x = x >> y", | |
150 | output: "x >>= y", | |
151 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
152 | }, { | |
153 | code: "x = x >>> y", | |
154 | output: "x >>>= y", | |
155 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
156 | }, { | |
157 | code: "x = x & y", | |
158 | output: "x &= y", | |
159 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
160 | }, { | |
161 | code: "x = x ^ y", | |
162 | output: "x ^= y", | |
163 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
164 | }, { | |
165 | code: "x = x | y", | |
166 | output: "x |= y", | |
167 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
168 | }, { | |
169 | code: "x[0] = x[0] - y", | |
170 | output: "x[0] -= y", | |
171 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
172 | }, { | |
173 | code: "x.y[z['a']][0].b = x.y[z['a']][0].b * 2", | |
174 | output: null, // not fixed; might activate getters more than before | |
175 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
176 | }, { | |
177 | code: "x = x + y", | |
178 | output: "x += y", | |
179 | options: ["always"], | |
180 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
181 | }, { | |
182 | code: "x = (x + y)", | |
183 | output: "x += y", | |
184 | options: ["always"], | |
185 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
186 | }, { | |
187 | code: "x = x + (y)", | |
188 | output: "x += (y)", | |
189 | options: ["always"], | |
190 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
191 | }, { | |
192 | code: "x += (y)", | |
193 | output: "x = x + (y)", | |
194 | options: ["never"], | |
195 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
196 | }, { | |
197 | code: "x += y", | |
198 | output: "x = x + y", | |
199 | options: ["never"], | |
200 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
201 | }, { | |
202 | code: "foo.bar = foo.bar + baz", | |
203 | output: "foo.bar += baz", | |
204 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
205 | }, { | |
206 | code: "foo.bar += baz", | |
207 | output: "foo.bar = foo.bar + baz", | |
208 | options: ["never"], | |
209 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
210 | }, { | |
211 | code: "this.foo = this.foo + bar", | |
212 | output: "this.foo += bar", | |
213 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
214 | }, { | |
215 | code: "this.foo += bar", | |
216 | output: "this.foo = this.foo + bar", | |
217 | options: ["never"], | |
218 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
219 | }, { | |
220 | code: "foo.bar.baz = foo.bar.baz + qux", | |
221 | output: null, // not fixed; fixing would cause a foo.bar getter to activate once rather than twice | |
222 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
223 | }, { | |
224 | code: "foo.bar.baz += qux", | |
225 | output: null, // not fixed; fixing would cause a foo.bar getter to activate twice rather than once | |
226 | options: ["never"], | |
227 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
228 | }, { | |
229 | code: "this.foo.bar = this.foo.bar + baz", | |
230 | output: null, // not fixed; fixing would cause a this.foo getter to activate once rather than twice | |
231 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
232 | }, { | |
233 | code: "this.foo.bar += baz", | |
234 | output: null, // not fixed; fixing would cause a this.foo getter to activate twice rather than once | |
235 | options: ["never"], | |
236 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
237 | }, { | |
238 | code: "foo[bar] = foo[bar] + baz", | |
239 | output: null, // not fixed; fixing would cause bar.toString() to get called once instead of twice | |
240 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
241 | }, { | |
242 | code: "this[foo] = this[foo] + bar", | |
243 | output: null, // not fixed; fixing would cause foo.toString() to get called once instead of twice | |
244 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
245 | }, { | |
246 | code: "foo[bar] >>>= baz", | |
247 | output: null, // not fixed; fixing would cause bar.toString() to get called twice instead of once | |
248 | options: ["never"], | |
249 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
250 | }, { | |
251 | code: "this[foo] >>>= bar", | |
252 | output: null, // not fixed; fixing would cause foo.toString() to get called twice instead of once | |
253 | options: ["never"], | |
254 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
255 | }, { | |
256 | code: "foo[5] = foo[5] / baz", | |
257 | output: "foo[5] /= baz", // this is ok because 5 is a literal, so toString won't get called | |
258 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
259 | }, { | |
260 | code: "this[5] = this[5] / foo", | |
261 | output: "this[5] /= foo", // this is ok because 5 is a literal, so toString won't get called | |
262 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
263 | }, { | |
264 | code: "/*1*/x/*2*/./*3*/y/*4*/= x.y +/*5*/z/*6*/./*7*/w/*8*/;", | |
265 | output: "/*1*/x/*2*/./*3*/y/*4*/+=/*5*/z/*6*/./*7*/w/*8*/;", // these comments are preserved | |
266 | options: ["always"], | |
267 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
268 | }, { | |
269 | code: "x // 1\n . // 2\n y // 3\n = x.y + //4\n z //5\n . //6\n w;", | |
270 | output: "x // 1\n . // 2\n y // 3\n += //4\n z //5\n . //6\n w;", // these comments are preserved | |
271 | options: ["always"], | |
272 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
273 | }, { | |
274 | code: "x = /*1*/ x + y", | |
275 | output: null, // not fixed; fixing would remove this comment | |
276 | options: ["always"], | |
277 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
278 | }, { | |
279 | code: "x = //1\n x + y", | |
280 | output: null, // not fixed; fixing would remove this comment | |
281 | options: ["always"], | |
282 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
283 | }, { | |
284 | code: "x.y = x/*1*/.y + z", | |
285 | output: null, // not fixed; fixing would remove this comment | |
286 | options: ["always"], | |
287 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
288 | }, { | |
289 | code: "x.y = x. //1\n y + z", | |
290 | output: null, // not fixed; fixing would remove this comment | |
291 | options: ["always"], | |
292 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
293 | }, { | |
294 | code: "x = x /*1*/ + y", | |
295 | output: null, // not fixed; fixing would remove this comment | |
296 | options: ["always"], | |
297 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
298 | }, { | |
299 | code: "x = x //1\n + y", | |
300 | output: null, // not fixed; fixing would remove this comment | |
301 | options: ["always"], | |
302 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
303 | }, { | |
304 | code: "/*1*/x +=/*2*/y/*3*/;", | |
305 | output: "/*1*/x = x +/*2*/y/*3*/;", // these comments are preserved and not duplicated | |
306 | options: ["never"], | |
307 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
308 | }, { | |
309 | code: "x +=//1\n y", | |
310 | output: "x = x +//1\n y", // this comment is preserved and not duplicated | |
311 | options: ["never"], | |
312 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
313 | }, { | |
314 | code: "(/*1*/x += y)", | |
315 | output: "(/*1*/x = x + y)", // this comment is preserved and not duplicated | |
316 | options: ["never"], | |
317 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
318 | }, { | |
319 | code: "x/*1*/+= y", | |
320 | output: null, // not fixed; fixing would duplicate this comment | |
321 | options: ["never"], | |
322 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
323 | }, { | |
324 | code: "x //1\n += y", | |
325 | output: null, // not fixed; fixing would duplicate this comment | |
326 | options: ["never"], | |
327 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
328 | }, { | |
329 | code: "(/*1*/x) += y", | |
330 | output: null, // not fixed; fixing would duplicate this comment | |
331 | options: ["never"], | |
332 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
333 | }, { | |
334 | code: "x/*1*/.y += z", | |
335 | output: null, // not fixed; fixing would duplicate this comment | |
336 | options: ["never"], | |
337 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
338 | }, { | |
339 | code: "x.//1\n y += z", | |
340 | output: null, // not fixed; fixing would duplicate this comment | |
341 | options: ["never"], | |
342 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
343 | }, { | |
344 | code: "(foo.bar) ^= ((((((((((((((((baz))))))))))))))))", | |
345 | output: "(foo.bar) = (foo.bar) ^ ((((((((((((((((baz))))))))))))))))", | |
346 | options: ["never"], | |
347 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
348 | }, { | |
349 | code: "foo = foo ** bar", | |
350 | output: "foo **= bar", | |
351 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
352 | }, { | |
353 | code: "foo **= bar", | |
354 | output: "foo = foo ** bar", | |
355 | options: ["never"], | |
356 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
357 | }, { | |
358 | code: "foo *= bar + 1", | |
359 | output: "foo = foo * (bar + 1)", | |
360 | options: ["never"], | |
361 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
362 | }, { | |
363 | code: "foo -= bar - baz", | |
364 | output: "foo = foo - (bar - baz)", | |
365 | options: ["never"], | |
366 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
367 | }, { | |
368 | code: "foo += bar + baz", | |
369 | output: "foo = foo + (bar + baz)", // addition is not associative in JS, e.g. (1 + 2) + '3' !== 1 + (2 + '3') | |
370 | options: ["never"], | |
371 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
372 | }, { | |
373 | code: "foo += bar = 1", | |
374 | output: "foo = foo + (bar = 1)", | |
375 | options: ["never"], | |
376 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
377 | }, { | |
378 | code: "foo *= (bar + 1)", | |
379 | output: "foo = foo * (bar + 1)", | |
380 | options: ["never"], | |
381 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
382 | }, { | |
383 | code: "foo+=-bar", | |
384 | output: "foo= foo+-bar", // tokens can be adjacent | |
385 | options: ["never"], | |
386 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
387 | }, { | |
388 | code: "foo/=bar", | |
389 | output: "foo= foo/bar", // tokens can be adjacent | |
390 | options: ["never"], | |
391 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
392 | }, { | |
393 | code: "foo/=/**/bar", | |
394 | output: "foo= foo/ /**/bar", // // tokens cannot be adjacent, insert a space between | |
395 | options: ["never"], | |
396 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
397 | }, { | |
398 | code: "foo/=//\nbar", | |
399 | output: "foo= foo/ //\nbar", // // tokens cannot be adjacent, insert a space between | |
400 | options: ["never"], | |
401 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
402 | }, { | |
403 | code: "foo/=/^bar$/", | |
404 | output: "foo= foo/ /^bar$/", // // tokens cannot be adjacent, insert a space between | |
405 | options: ["never"], | |
406 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
407 | }, { | |
408 | code: "foo+=+bar", | |
409 | output: "foo= foo+ +bar", // tokens cannot be adjacent, insert a space between | |
410 | options: ["never"], | |
411 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
412 | }, { | |
413 | code: "foo+= +bar", | |
414 | output: "foo= foo+ +bar", // tokens cannot be adjacent, but there is already a space between | |
415 | options: ["never"], | |
416 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
417 | }, { | |
418 | code: "foo+=/**/+bar", | |
419 | output: "foo= foo+/**/+bar", // tokens cannot be adjacent, but there is a comment between | |
420 | options: ["never"], | |
421 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
422 | }, { | |
423 | code: "foo+=+bar===baz", | |
424 | output: "foo= foo+(+bar===baz)", // tokens cannot be adjacent, but the right side will be parenthesised | |
425 | options: ["never"], | |
426 | errors: UNEXPECTED_OPERATOR_ASSIGNMENT | |
6f036462 TL |
427 | }, |
428 | ||
429 | // Optional chaining | |
430 | { | |
431 | code: "(obj?.a).b = (obj?.a).b + y", | |
432 | output: null, | |
433 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
434 | }, | |
435 | { | |
436 | code: "obj.a = obj?.a + b", | |
437 | output: null, | |
438 | errors: EXPECTED_OPERATOR_ASSIGNMENT | |
439 | } | |
440 | ||
441 | ] | |
eb39fafa DC |
442 | |
443 | }); |