]> git.proxmox.com Git - pve-eslint.git/blame - eslint/tests/lib/rules/prefer-object-spread.js
import 8.41.0 source
[pve-eslint.git] / eslint / tests / lib / rules / prefer-object-spread.js
CommitLineData
eb39fafa
DC
1/**
2 * @fileoverview Prefers object spread property over Object.assign
3 * @author Sharmila Jesupaul
eb39fafa
DC
4 */
5
6"use strict";
7
609c276f
TL
8//------------------------------------------------------------------------------
9// Requirements
10//------------------------------------------------------------------------------
eb39fafa 11
609c276f 12const rule = require("../../../lib/rules/prefer-object-spread");
eb39fafa
DC
13const { RuleTester } = require("../../../lib/rule-tester");
14
609c276f
TL
15//------------------------------------------------------------------------------
16// Tests
17//------------------------------------------------------------------------------
18
eb39fafa
DC
19const parserOptions = {
20 ecmaVersion: 2018,
21 sourceType: "module"
22};
23
24const ruleTester = new RuleTester({ parserOptions });
25
26ruleTester.run("prefer-object-spread", rule, {
27 valid: [
28 "Object.assign()",
29 "let a = Object.assign(a, b)",
30 "Object.assign(a, b)",
31 "let a = Object.assign(b, { c: 1 })",
32 "const bar = { ...foo }",
33 "Object.assign(...foo)",
34 "Object.assign(foo, { bar: baz })",
35 "Object.assign({}, ...objects)",
36 "foo({ foo: 'bar' })",
37 `
38 const Object = {};
39 Object.assign({}, foo);
40 `,
41 `
42 Object = {};
43 Object.assign({}, foo);
44 `,
45 `
46 const Object = {};
47 Object.assign({ foo: 'bar' });
48 `,
49 `
50 Object = {};
51 Object.assign({ foo: 'bar' });
52 `,
53 `
54 const Object = require('foo');
55 Object.assign({ foo: 'bar' });
56 `,
57 `
58 import Object from 'foo';
59 Object.assign({ foo: 'bar' });
60 `,
61 `
62 import { Something as Object } from 'foo';
63 Object.assign({ foo: 'bar' });
64 `,
65 `
66 import { Object, Array } from 'globals';
67 Object.assign({ foo: 'bar' });
68 `,
69 "globalThis.Object.assign({}, foo)",
70 {
71 code: "globalThis.Object.assign({}, { foo: 'bar' })",
72 env: { es6: true }
73 },
74 {
75 code: "globalThis.Object.assign({}, baz, { foo: 'bar' })",
76 env: { es2017: true }
77 },
78 {
79 code: `
80 var globalThis = foo;
81 globalThis.Object.assign({}, foo)
82 `,
83 env: { es2020: true }
84 },
609c276f
TL
85 {
86 code: "class C { #assign; foo() { Object.#assign({}, foo); } }",
87 parserOptions: { ecmaVersion: 2022 }
88 },
eb39fafa
DC
89
90 // ignore Object.assign() with > 1 arguments if any of the arguments is an object expression with a getter/setter
91 "Object.assign({ get a() {} }, {})",
92 "Object.assign({ set a(val) {} }, {})",
93 "Object.assign({ get a() {} }, foo)",
94 "Object.assign({ set a(val) {} }, foo)",
95 "Object.assign({ foo: 'bar', get a() {}, baz: 'quux' }, quuux)",
96 "Object.assign({ foo: 'bar', set a(val) {} }, { baz: 'quux' })",
97 "Object.assign({}, { get a() {} })",
98 "Object.assign({}, { set a(val) {} })",
99 "Object.assign({}, { foo: 'bar', get a() {} }, {})",
100 "Object.assign({ foo }, bar, {}, { baz: 'quux', set a(val) {}, quuux }, {})"
101 ],
102
103 invalid: [
104 {
105 code: "Object.assign({}, foo)",
106 output: "({ ...foo})",
107 errors: [
108 {
109 messageId: "useSpreadMessage",
110 type: "CallExpression",
111 line: 1,
112 column: 1
113 }
114 ]
115 },
116 {
117 code: "Object.assign ({}, foo)",
118 output: "({ ...foo})",
119 errors: [
120 {
121 messageId: "useSpreadMessage",
122 type: "CallExpression",
123 line: 1,
124 column: 1
125 }
126 ]
127 },
128 {
129 code: "Object.assign({}, { foo: 'bar' })",
130 output: "({ foo: 'bar'})",
131 errors: [
132 {
133 messageId: "useSpreadMessage",
134 type: "CallExpression",
135 line: 1,
136 column: 1
137 }
138 ]
139 },
140 {
141 code: "Object.assign({}, baz, { foo: 'bar' })",
142 output: "({ ...baz, foo: 'bar'})",
143 errors: [
144 {
145 messageId: "useSpreadMessage",
146 type: "CallExpression",
147 line: 1,
148 column: 1
149 }
150 ]
151 },
152 {
153 code: "Object.assign({}, { foo: 'bar', baz: 'foo' })",
154 output: "({ foo: 'bar', baz: 'foo'})",
155 errors: [
156 {
157 messageId: "useSpreadMessage",
158 type: "CallExpression",
159 line: 1,
160 column: 1
161 }
162 ]
163 },
164 {
165 code: "Object.assign({ foo: 'bar' }, baz)",
166 output: "({foo: 'bar', ...baz})",
167 errors: [
168 {
169 messageId: "useSpreadMessage",
170 type: "CallExpression",
171 line: 1,
172 column: 1
173 }
174 ]
175 },
176
177 // Many args
178 {
179 code: "Object.assign({ foo: 'bar' }, cats, dogs, trees, birds)",
180 output: "({foo: 'bar', ...cats, ...dogs, ...trees, ...birds})",
181 errors: [
182 {
183 messageId: "useSpreadMessage",
184 type: "CallExpression",
185 line: 1,
186 column: 1
187 }
188 ]
189 },
190
191 {
192 code:
193 "Object.assign({ foo: 'bar' }, Object.assign({ bar: 'foo' }, baz))",
194 output: "({foo: 'bar', ...Object.assign({ bar: 'foo' }, baz)})",
195 errors: [
196 {
197 messageId: "useSpreadMessage",
198 type: "CallExpression",
199 line: 1,
200 column: 1
201 },
202 {
203 messageId: "useSpreadMessage",
204 type: "CallExpression",
205 line: 1,
206 column: 31
207 }
208 ]
209 },
210 {
211 code:
212 "Object.assign({ foo: 'bar' }, Object.assign({ bar: 'foo' }, Object.assign({}, { superNested: 'butwhy' })))",
213 output: "({foo: 'bar', ...Object.assign({ bar: 'foo' }, Object.assign({}, { superNested: 'butwhy' }))})",
214 errors: [
215 {
216 messageId: "useSpreadMessage",
217 type: "CallExpression",
218 line: 1,
219 column: 1
220 },
221 {
222 messageId: "useSpreadMessage",
223 type: "CallExpression",
224 line: 1,
225 column: 31
226 },
227 {
228 messageId: "useSpreadMessage",
229 type: "CallExpression",
230 line: 1,
231 column: 61
232 }
233 ]
234 },
235
236 // Mix spread in argument
237 {
238 code: "Object.assign({foo: 'bar', ...bar}, baz)",
239 output: "({foo: 'bar', ...bar, ...baz})",
240 errors: [
241 {
242 messageId: "useSpreadMessage",
243 type: "CallExpression",
244 line: 1,
245 column: 1
246 }
247 ]
248 },
249
250 // Object shorthand
251 {
252 code: "Object.assign({}, { foo, bar, baz })",
253 output: "({ foo, bar, baz})",
254 errors: [
255 {
256 messageId: "useSpreadMessage",
257 type: "CallExpression",
258 line: 1,
259 column: 1
260 }
261 ]
262 },
263
264 // Objects with computed properties
265 {
266 code: "Object.assign({}, { [bar]: 'foo' })",
267 output: "({ [bar]: 'foo'})",
268 errors: [
269 {
270 messageId: "useSpreadMessage",
271 type: "CallExpression",
272 line: 1,
273 column: 1
274 }
275 ]
276 },
277
278 // Objects with spread properties
279 {
280 code: "Object.assign({ ...bar }, { ...baz })",
281 output: "({...bar, ...baz})",
282 errors: [
283 {
284 messageId: "useSpreadMessage",
285 type: "CallExpression",
286 line: 1,
287 column: 1
288 }
289 ]
290 },
291
292 // Multiline objects
293 {
294 code: `Object.assign({ ...bar }, {
295 // this is a bar
296 foo: 'bar',
297 baz: "cats"
298 })`,
299 output: `({...bar, // this is a bar
300 foo: 'bar',
301 baz: "cats"})`,
302 errors: [
303 {
304 messageId: "useSpreadMessage",
305 type: "CallExpression",
306 line: 1,
307 column: 1
308 }
309 ]
310 },
311
312 {
313 code: `Object.assign({
314 boo: "lol",
315 // I'm a comment
316 dog: "cat"
317 }, {
318 // this is a bar
319 foo: 'bar',
320 baz: "cats"
321 })`,
322 output: `({boo: "lol",
323 // I'm a comment
324 dog: "cat", // this is a bar
325 foo: 'bar',
326 baz: "cats"})`,
327 errors: [
328 {
329 messageId: "useSpreadMessage",
330 type: "CallExpression",
331 line: 1,
332 column: 1
333 }
334 ]
335 },
336
337 // HTML comment
338 {
339 code: `const test = Object.assign({ ...bar }, {
340 <!-- html comment
341 foo: 'bar',
342 baz: "cats"
343 --> weird
344 })`,
345 output: `const test = {...bar, <!-- html comment
346 foo: 'bar',
347 baz: "cats"
348 --> weird
349 }`,
350 parserOptions: {
351 sourceType: "script"
352 },
353 errors: [
354 {
355 messageId: "useSpreadMessage",
356 type: "CallExpression",
357 line: 1,
358 column: 14
359 }
360 ]
361 },
362
363 {
364 code: `const test = Object.assign({ ...bar }, {
365 foo: 'bar', // inline comment
366 baz: "cats"
367 })`,
368 output: `const test = {...bar, foo: 'bar', // inline comment
369 baz: "cats"}`,
370 errors: [
371 {
372 messageId: "useSpreadMessage",
373 type: "CallExpression",
374 line: 1,
375 column: 14
376 }
377 ]
378 },
379
380
381 {
382 code: `const test = Object.assign({ ...bar }, {
383 /**
384 * foo
385 */
386 foo: 'bar',
387 baz: "cats"
388 })`,
389 output: `const test = {...bar, /**
390 * foo
391 */
392 foo: 'bar',
393 baz: "cats"}`,
394 errors: [
395 {
396 messageId: "useSpreadMessage",
397 type: "CallExpression",
398 line: 1,
399 column: 14
400 }
401 ]
402 },
403
404
405 /*
406 * This is a special case where Object.assign is called with a single argument
407 * and that argument is an object expression. In this case we warn and display
408 * a message to use an object literal instead.
409 */
410 {
411 code: "Object.assign({})",
412 output: "({})",
413 errors: [
414 {
415 messageId: "useLiteralMessage",
416 type: "CallExpression",
417 line: 1,
418 column: 1
419 }
420 ]
421 },
422 {
423 code: "Object.assign({ foo: bar })",
424 output: "({foo: bar})",
425 errors: [
426 {
427 messageId: "useLiteralMessage",
428 type: "CallExpression",
429 line: 1,
430 column: 1
431 }
432 ]
433 },
434
435 {
436 code: `
437 const foo = 'bar';
438 Object.assign({ foo: bar })
439 `,
440 output: `
441 const foo = 'bar';
442 ({foo: bar})
443 `,
444 errors: [
445 {
446 messageId: "useLiteralMessage",
447 type: "CallExpression",
448 line: 3,
449 column: 17
450 }
451 ]
452 },
453
454 {
455 code: `
456 foo = 'bar';
457 Object.assign({ foo: bar })
458 `,
459 output: `
460 foo = 'bar';
461 ({foo: bar})
462 `,
463 errors: [
464 {
465 messageId: "useLiteralMessage",
466 type: "CallExpression",
467 line: 3,
468 column: 17
469 }
470 ]
471 },
472
473 {
474 code: "let a = Object.assign({})",
475 output: "let a = {}",
476 errors: [
477 {
478 messageId: "useLiteralMessage",
479 type: "CallExpression",
480 line: 1,
481 column: 9
482 }
483 ]
484 },
485 {
486 code: "let a = Object.assign({}, a)",
487 output: "let a = { ...a}",
488 errors: [
489 {
490 messageId: "useSpreadMessage",
491 type: "CallExpression",
492 line: 1,
493 column: 9
494 }
495 ]
496 },
497 {
498 code: "let a = Object.assign ({}, a)",
499 output: "let a = { ...a}",
500 errors: [
501 {
502 messageId: "useSpreadMessage",
503 type: "CallExpression",
504 line: 1,
505 column: 9
506 }
507 ]
508 },
509 {
510 code: "let a = Object.assign({ a: 1 }, b)",
511 output: "let a = {a: 1, ...b}",
512 errors: [
513 {
514 messageId: "useSpreadMessage",
515 type: "CallExpression",
516 line: 1,
517 column: 9
518 }
519 ]
520 },
521 {
522 code: "Object.assign( {}, a, b, )",
523 output: "({ ...a, ...b, })",
524 errors: [
525 {
526 messageId: "useSpreadMessage",
527 type: "CallExpression",
528 line: 1,
529 column: 1
530 }
531 ]
532 },
533 {
534 code: "Object.assign({}, a ? b : {}, b => c, a = 2)",
535 output: "({ ...(a ? b : {}), ...(b => c), ...(a = 2)})",
536 errors: [
537 {
538 messageId: "useSpreadMessage",
539 type: "CallExpression",
540 line: 1,
541 column: 1
542 }
543 ]
544 },
545 {
546 code: `
547 const someVar = 'foo';
548 Object.assign({}, a ? b : {}, b => c, a = 2)
549 `,
550 output: `
551 const someVar = 'foo';
552 ({ ...(a ? b : {}), ...(b => c), ...(a = 2)})
553 `,
554 errors: [
555 {
556 messageId: "useSpreadMessage",
557 type: "CallExpression",
558 line: 3,
559 column: 17
560 }
561 ]
562 },
563 {
564 code: `
565 someVar = 'foo';
566 Object.assign({}, a ? b : {}, b => c, a = 2)
567 `,
568 output: `
569 someVar = 'foo';
570 ({ ...(a ? b : {}), ...(b => c), ...(a = 2)})
571 `,
572 errors: [
573 {
574 messageId: "useSpreadMessage",
575 type: "CallExpression",
576 line: 3,
577 column: 17
578 }
579 ]
580 },
581
582 // Cases where you don't need parens around an object literal
583 {
584 code: "[1, 2, Object.assign({}, a)]",
585 output: "[1, 2, { ...a}]",
586 errors: [
587 {
588 messageId: "useSpreadMessage",
589 type: "CallExpression",
590 line: 1,
591 column: 8
592 }
593 ]
594 },
595 {
596 code: "const foo = Object.assign({}, a)",
597 output: "const foo = { ...a}",
598 errors: [
599 {
600 messageId: "useSpreadMessage",
601 type: "CallExpression",
602 line: 1,
603 column: 13
604 }
605 ]
606 },
607 {
608 code: "function foo() { return Object.assign({}, a) }",
609 output: "function foo() { return { ...a} }",
610 errors: [
611 {
612 messageId: "useSpreadMessage",
613 type: "CallExpression",
614 line: 1,
615 column: 25
616 }
617 ]
618 },
619 {
620 code: "foo(Object.assign({}, a));",
621 output: "foo({ ...a});",
622 errors: [
623 {
624 messageId: "useSpreadMessage",
625 type: "CallExpression",
626 line: 1,
627 column: 5
628 }
629 ]
630 },
631 {
632 code: "const x = { foo: 'bar', baz: Object.assign({}, a) }",
633 output: "const x = { foo: 'bar', baz: { ...a} }",
634 errors: [
635 {
636 messageId: "useSpreadMessage",
637 type: "CallExpression",
638 line: 1,
639 column: 30
640 }
641 ]
642 },
643 {
644 code: `
645 import Foo from 'foo';
646 Object.assign({ foo: Foo });
647 `,
648 output: `
649 import Foo from 'foo';
650 ({foo: Foo});
651 `,
652 errors: [
653 {
654 messageId: "useLiteralMessage",
655 type: "CallExpression",
656 line: 3,
657 column: 17
658 }
659 ]
660 },
661 {
662 code: `
663 import Foo from 'foo';
664 Object.assign({}, Foo);
665 `,
666 output: `
667 import Foo from 'foo';
668 ({ ...Foo});
669 `,
670 errors: [
671 {
672 messageId: "useSpreadMessage",
673 type: "CallExpression",
674 line: 3,
675 column: 17
676 }
677 ]
678 },
679 {
680 code: `
681 const Foo = require('foo');
682 Object.assign({ foo: Foo });
683 `,
684 output: `
685 const Foo = require('foo');
686 ({foo: Foo});
687 `,
688 errors: [
689 {
690 messageId: "useLiteralMessage",
691 type: "CallExpression",
692 line: 3,
693 column: 17
694 }
695 ]
696 },
697 {
698 code: `
699 import { Something as somethingelse } from 'foo';
700 Object.assign({}, somethingelse);
701 `,
702 output: `
703 import { Something as somethingelse } from 'foo';
704 ({ ...somethingelse});
705 `,
706 errors: [
707 {
708 messageId: "useSpreadMessage",
709 type: "CallExpression",
710 line: 3,
711 column: 17
712 }
713 ]
714 },
715 {
716 code: `
717 import { foo } from 'foo';
718 Object.assign({ foo: Foo });
719 `,
720 output: `
721 import { foo } from 'foo';
722 ({foo: Foo});
723 `,
724 errors: [
725 {
726 messageId: "useLiteralMessage",
727 type: "CallExpression",
728 line: 3,
729 column: 17
730 }
731 ]
732 },
733 {
734 code: `
735 const Foo = require('foo');
736 Object.assign({}, Foo);
737 `,
738 output: `
739 const Foo = require('foo');
740 ({ ...Foo});
741 `,
742 errors: [
743 {
744 messageId: "useSpreadMessage",
745 type: "CallExpression",
746 line: 3,
747 column: 17
748 }
749 ]
750 },
751 {
752 code: `
753 const actions = Object.assign(
754 {
755 onChangeInput: this.handleChangeInput,
756 },
757 this.props.actions
758 );
759 `,
760 output: `
761 const actions = {
762 onChangeInput: this.handleChangeInput,
763 ...this.props.actions
764 };
765 `,
766 errors: [
767 {
768 messageId: "useSpreadMessage",
769 type: "CallExpression",
770 line: 2,
771 column: 33
772 }
773 ]
774 },
775 {
776 code: `
777 const actions = Object.assign(
778 {
779 onChangeInput: this.handleChangeInput, //
780 },
781 this.props.actions
782 );
783 `,
784 output: `
785 const actions = {
786 onChangeInput: this.handleChangeInput, //
787
788 ...this.props.actions
789 };
790 `,
791 errors: [
792 {
793 messageId: "useSpreadMessage",
794 type: "CallExpression",
795 line: 2,
796 column: 33
797 }
798 ]
799 },
800 {
801 code: `
802 const actions = Object.assign(
803 {
804 onChangeInput: this.handleChangeInput //
805 },
806 this.props.actions
807 );
808 `,
809 output: `
810 const actions = {
811 onChangeInput: this.handleChangeInput //
812 ,
813 ...this.props.actions
814 };
815 `,
816 errors: [
817 {
818 messageId: "useSpreadMessage",
819 type: "CallExpression",
820 line: 2,
821 column: 33
822 }
823 ]
824 },
825 {
826 code: `
827 const actions = Object.assign(
828 (
829 {
830 onChangeInput: this.handleChangeInput
831 }
832 ),
833 (
834 this.props.actions
835 )
836 );
837 `,
838 output: `
839 const actions = {
840
841 onChangeInput: this.handleChangeInput
842 ,
843 ...(
844 this.props.actions
845 )
846 };
847 `,
848 errors: [
849 {
850 messageId: "useSpreadMessage",
851 type: "CallExpression",
852 line: 2,
853 column: 33
854 }
855 ]
856 },
857 {
858 code: `
859 eventData = Object.assign({}, eventData, { outsideLocality: \`\${originLocality} - \${destinationLocality}\` })
860 `,
861 output: `
862 eventData = { ...eventData, outsideLocality: \`\${originLocality} - \${destinationLocality}\`}
863 `,
864 errors: [
865 {
866 messageId: "useSpreadMessage",
867 type: "CallExpression",
868 line: 2,
869 column: 29
870 }
871 ]
872 },
873
874 // https://github.com/eslint/eslint/issues/10646
875 {
876 code: "Object.assign({ });",
877 output: "({});",
878 errors: [
879 {
880 messageId: "useLiteralMessage",
881 type: "CallExpression",
882 line: 1,
883 column: 1
884 }
885 ]
886 },
887 {
888 code: "Object.assign({\n});",
889 output: "({});",
890 errors: [
891 {
892 messageId: "useLiteralMessage",
893 type: "CallExpression",
894 line: 1,
895 column: 1
896 }
897 ]
898 },
899 {
900 code: "globalThis.Object.assign({ });",
901 output: "({});",
902 env: { es2020: true },
903 errors: [
904 {
905 messageId: "useLiteralMessage",
906 type: "CallExpression",
907 line: 1,
908 column: 1
909 }
910 ]
911 },
912 {
913 code: "globalThis.Object.assign({\n});",
914 output: "({});",
915 env: { es2020: true },
916 errors: [
917 {
918 messageId: "useLiteralMessage",
919 type: "CallExpression",
920 line: 1,
921 column: 1
922 }
923 ]
924 },
925 {
926 code: `
927 function foo () { var globalThis = bar; }
928 globalThis.Object.assign({ });
929 `,
930 output: `
931 function foo () { var globalThis = bar; }
932 ({});
933 `,
934 env: { es2020: true },
935 errors: [
936 {
937 messageId: "useLiteralMessage",
938 type: "CallExpression",
939 line: 3,
940 column: 17
941 }
942 ]
943 },
944 {
945 code: `
946 const Foo = require('foo');
947 globalThis.Object.assign({ foo: Foo });
948 `,
949 output: `
950 const Foo = require('foo');
951 ({foo: Foo});
952 `,
953 env: { es2020: true },
954 errors: [
955 {
956 messageId: "useLiteralMessage",
957 type: "CallExpression",
958 line: 3,
959 column: 17
960 }
961 ]
962 },
963
964 // report Object.assign() with getters/setters if the function call has only 1 argument
965 {
966 code: "Object.assign({ get a() {}, set b(val) {} })",
967 output: "({get a() {}, set b(val) {}})",
968 errors: [
969 {
970 messageId: "useLiteralMessage",
971 type: "CallExpression",
972 line: 1,
973 column: 1
974 }
975 ]
976 },
977
978 // https://github.com/eslint/eslint/issues/13058
979 {
980 code: "const obj = Object.assign<{}, Record<string, string[]>>({}, getObject());",
981 output: "const obj = { ...getObject()};",
982 parser: require.resolve("../../fixtures/parsers/typescript-parsers/object-assign-with-generic/object-assign-with-generic-1"),
983 errors: [
984 {
985 messageId: "useSpreadMessage",
986 type: "CallExpression",
987 line: 1,
988 column: 13
989 }
990 ]
991 },
992 {
993 code: "Object.assign<{}, A>({}, foo);",
994 output: "({ ...foo});",
995 parser: require.resolve("../../fixtures/parsers/typescript-parsers/object-assign-with-generic/object-assign-with-generic-2"),
996 errors: [
997 {
998 messageId: "useSpreadMessage",
999 type: "CallExpression",
1000 line: 1,
1001 column: 1
1002 }
1003 ]
1004 }
1005 ]
1006});