main
js 985 lines 26.3 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 'use strict';
9
10 // NOTE: Extracted from https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
11
12 /**
13 * A string template tag that removes padding from the left side of multi-line strings
14 */
15 function normalizeIndent(strings) {
16 const codeLines = strings[0].split('\n');
17 const leftPadding = codeLines[1].match(/\s+/)[0];
18 return codeLines.map(line => line.slice(leftPadding.length)).join('\n');
19 }
20
21 module.exports.tests = {
22 valid: [
23 {
24 code: normalizeIndent`
25 // Valid because components can use hooks.
26 function ComponentWithHook() {
27 useHook();
28 }
29 `,
30 },
31 {
32 code: normalizeIndent`
33 // Valid because components can use hooks.
34 function createComponentWithHook() {
35 return function ComponentWithHook() {
36 useHook();
37 };
38 }
39 `,
40 },
41 {
42 code: normalizeIndent`
43 // Valid because hooks can use hooks.
44 function useHookWithHook() {
45 useHook();
46 }
47 `,
48 },
49 {
50 code: normalizeIndent`
51 // Valid because hooks can use hooks.
52 function createHook() {
53 return function useHookWithHook() {
54 useHook();
55 }
56 }
57 `,
58 },
59 {
60 code: normalizeIndent`
61 // Valid because components can call functions.
62 function ComponentWithNormalFunction() {
63 doSomething();
64 }
65 `,
66 },
67 {
68 code: normalizeIndent`
69 // Valid because functions can call functions.
70 function normalFunctionWithNormalFunction() {
71 doSomething();
72 }
73 `,
74 },
75 {
76 code: normalizeIndent`
77 // Valid because functions can call functions.
78 function normalFunctionWithConditionalFunction() {
79 if (cond) {
80 doSomething();
81 }
82 }
83 `,
84 },
85 {
86 code: normalizeIndent`
87 // Valid because functions can call functions.
88 function functionThatStartsWithUseButIsntAHook() {
89 if (cond) {
90 userFetch();
91 }
92 }
93 `,
94 },
95 {
96 code: normalizeIndent`
97 // Valid although unconditional return doesn't make sense and would fail other rules.
98 // We could make it invalid but it doesn't matter.
99 function useUnreachable() {
100 return;
101 useHook();
102 }
103 `,
104 },
105 {
106 code: normalizeIndent`
107 // Valid because hooks can call hooks.
108 function useHook() { useState(); }
109 const whatever = function useHook() { useState(); };
110 const useHook1 = () => { useState(); };
111 let useHook2 = () => useState();
112 useHook2 = () => { useState(); };
113 ({useHook: () => { useState(); }});
114 ({useHook() { useState(); }});
115 const {useHook3 = () => { useState(); }} = {};
116 ({useHook = () => { useState(); }} = {});
117 Namespace.useHook = () => { useState(); };
118 `,
119 },
120 {
121 code: normalizeIndent`
122 // Valid because hooks can call hooks.
123 function useHook() {
124 useHook1();
125 useHook2();
126 }
127 `,
128 },
129 {
130 code: normalizeIndent`
131 // Valid because hooks can call hooks.
132 function createHook() {
133 return function useHook() {
134 useHook1();
135 useHook2();
136 };
137 }
138 `,
139 },
140 {
141 code: normalizeIndent`
142 // Valid because hooks can call hooks.
143 function useHook() {
144 useState() && a;
145 }
146 `,
147 },
148 {
149 code: normalizeIndent`
150 // Valid because hooks can call hooks.
151 function useHook() {
152 return useHook1() + useHook2();
153 }
154 `,
155 },
156 {
157 code: normalizeIndent`
158 // Valid because hooks can call hooks.
159 function useHook() {
160 return useHook1(useHook2());
161 }
162 `,
163 },
164 {
165 code: normalizeIndent`
166 // Valid because hooks can be used in anonymous arrow-function arguments
167 // to forwardRef.
168 const FancyButton = React.forwardRef((props, ref) => {
169 useHook();
170 return <button {...props} ref={ref} />
171 });
172 `,
173 },
174 {
175 code: normalizeIndent`
176 // Valid because hooks can be used in anonymous function arguments to
177 // forwardRef.
178 const FancyButton = React.forwardRef(function (props, ref) {
179 useHook();
180 return <button {...props} ref={ref} />
181 });
182 `,
183 },
184 {
185 code: normalizeIndent`
186 // Valid because hooks can be used in anonymous function arguments to
187 // forwardRef.
188 const FancyButton = forwardRef(function (props, ref) {
189 useHook();
190 return <button {...props} ref={ref} />
191 });
192 `,
193 },
194 {
195 code: normalizeIndent`
196 // Valid because hooks can be used in anonymous function arguments to
197 // React.memo.
198 const MemoizedFunction = React.memo(props => {
199 useHook();
200 return <button {...props} />
201 });
202 `,
203 },
204 {
205 code: normalizeIndent`
206 // Valid because hooks can be used in anonymous function arguments to
207 // memo.
208 const MemoizedFunction = memo(function (props) {
209 useHook();
210 return <button {...props} />
211 });
212 `,
213 },
214 {
215 code: normalizeIndent`
216 // Valid because classes can call functions.
217 // We don't consider these to be hooks.
218 class C {
219 m() {
220 this.useHook();
221 super.useHook();
222 }
223 }
224 `,
225 },
226 {
227 code: normalizeIndent`
228 // Valid -- this is a regression test.
229 jest.useFakeTimers();
230 beforeEach(() => {
231 jest.useRealTimers();
232 })
233 `,
234 },
235 {
236 code: normalizeIndent`
237 // Valid because they're not matching use[A-Z].
238 fooState();
239 _use();
240 _useState();
241 use_hook();
242 // also valid because it's not matching the PascalCase namespace
243 jest.useFakeTimer()
244 `,
245 },
246 {
247 code: normalizeIndent`
248 // Regression test for some internal code.
249 // This shows how the "callback rule" is more relaxed,
250 // and doesn't kick in unless we're confident we're in
251 // a component or a hook.
252 function makeListener(instance) {
253 each(pixelsWithInferredEvents, pixel => {
254 if (useExtendedSelector(pixel.id) && extendedButton) {
255 foo();
256 }
257 });
258 }
259 `,
260 },
261 {
262 code: normalizeIndent`
263 // This is valid because "use"-prefixed functions called in
264 // unnamed function arguments are not assumed to be hooks.
265 React.unknownFunction((foo, bar) => {
266 if (foo) {
267 useNotAHook(bar)
268 }
269 });
270 `,
271 },
272 {
273 code: normalizeIndent`
274 // This is valid because "use"-prefixed functions called in
275 // unnamed function arguments are not assumed to be hooks.
276 unknownFunction(function(foo, bar) {
277 if (foo) {
278 useNotAHook(bar)
279 }
280 });
281 `,
282 },
283 {
284 code: normalizeIndent`
285 // Regression test for incorrectly flagged valid code.
286 function RegressionTest() {
287 const foo = cond ? a : b;
288 useState();
289 }
290 `,
291 },
292 {
293 code: normalizeIndent`
294 // Valid because exceptions abort rendering
295 function RegressionTest() {
296 if (page == null) {
297 throw new Error('oh no!');
298 }
299 useState();
300 }
301 `,
302 },
303 {
304 code: normalizeIndent`
305 // Valid because the loop doesn't change the order of hooks calls.
306 function RegressionTest() {
307 const res = [];
308 const additionalCond = true;
309 for (let i = 0; i !== 10 && additionalCond; ++i ) {
310 res.push(i);
311 }
312 React.useLayoutEffect(() => {});
313 }
314 `,
315 },
316 {
317 code: normalizeIndent`
318 // Is valid but hard to compute by brute-forcing
319 function MyComponent() {
320 // 40 conditions
321 if (c) {} else {}
322 if (c) {} else {}
323 if (c) {} else {}
324 if (c) {} else {}
325 if (c) {} else {}
326 if (c) {} else {}
327 if (c) {} else {}
328 if (c) {} else {}
329 if (c) {} else {}
330 if (c) {} else {}
331 if (c) {} else {}
332 if (c) {} else {}
333 if (c) {} else {}
334 if (c) {} else {}
335 if (c) {} else {}
336 if (c) {} else {}
337 if (c) {} else {}
338 if (c) {} else {}
339 if (c) {} else {}
340 if (c) {} else {}
341 if (c) {} else {}
342 if (c) {} else {}
343 if (c) {} else {}
344 if (c) {} else {}
345 if (c) {} else {}
346 if (c) {} else {}
347 if (c) {} else {}
348 if (c) {} else {}
349 if (c) {} else {}
350 if (c) {} else {}
351 if (c) {} else {}
352 if (c) {} else {}
353 if (c) {} else {}
354 if (c) {} else {}
355 if (c) {} else {}
356 if (c) {} else {}
357 if (c) {} else {}
358 if (c) {} else {}
359 if (c) {} else {}
360 if (c) {} else {}
361
362 // 10 hooks
363 useHook();
364 useHook();
365 useHook();
366 useHook();
367 useHook();
368 useHook();
369 useHook();
370 useHook();
371 useHook();
372 useHook();
373 }
374 `,
375 },
376 {
377 code: normalizeIndent`
378 // Valid because the neither the conditions before or after the hook affect the hook call
379 // Failed prior to implementing BigInt because pathsFromStartToEnd and allPathsFromStartToEnd were too big and had rounding errors
380 const useSomeHook = () => {};
381
382 const SomeName = () => {
383 const filler = FILLER ?? FILLER ?? FILLER;
384 const filler2 = FILLER ?? FILLER ?? FILLER;
385 const filler3 = FILLER ?? FILLER ?? FILLER;
386 const filler4 = FILLER ?? FILLER ?? FILLER;
387 const filler5 = FILLER ?? FILLER ?? FILLER;
388 const filler6 = FILLER ?? FILLER ?? FILLER;
389 const filler7 = FILLER ?? FILLER ?? FILLER;
390 const filler8 = FILLER ?? FILLER ?? FILLER;
391
392 useSomeHook();
393
394 if (anyConditionCanEvenBeFalse) {
395 return null;
396 }
397
398 return (
399 <React.Fragment>
400 {FILLER ? FILLER : FILLER}
401 {FILLER ? FILLER : FILLER}
402 {FILLER ? FILLER : FILLER}
403 {FILLER ? FILLER : FILLER}
404 {FILLER ? FILLER : FILLER}
405 {FILLER ? FILLER : FILLER}
406 {FILLER ? FILLER : FILLER}
407 {FILLER ? FILLER : FILLER}
408 {FILLER ? FILLER : FILLER}
409 {FILLER ? FILLER : FILLER}
410 {FILLER ? FILLER : FILLER}
411 {FILLER ? FILLER : FILLER}
412 {FILLER ? FILLER : FILLER}
413 {FILLER ? FILLER : FILLER}
414 {FILLER ? FILLER : FILLER}
415 {FILLER ? FILLER : FILLER}
416 {FILLER ? FILLER : FILLER}
417 {FILLER ? FILLER : FILLER}
418 {FILLER ? FILLER : FILLER}
419 {FILLER ? FILLER : FILLER}
420 {FILLER ? FILLER : FILLER}
421 {FILLER ? FILLER : FILLER}
422 {FILLER ? FILLER : FILLER}
423 {FILLER ? FILLER : FILLER}
424 {FILLER ? FILLER : FILLER}
425 {FILLER ? FILLER : FILLER}
426 {FILLER ? FILLER : FILLER}
427 {FILLER ? FILLER : FILLER}
428 {FILLER ? FILLER : FILLER}
429 {FILLER ? FILLER : FILLER}
430 {FILLER ? FILLER : FILLER}
431 {FILLER ? FILLER : FILLER}
432 {FILLER ? FILLER : FILLER}
433 {FILLER ? FILLER : FILLER}
434 {FILLER ? FILLER : FILLER}
435 {FILLER ? FILLER : FILLER}
436 {FILLER ? FILLER : FILLER}
437 {FILLER ? FILLER : FILLER}
438 {FILLER ? FILLER : FILLER}
439 {FILLER ? FILLER : FILLER}
440 {FILLER ? FILLER : FILLER}
441 {FILLER ? FILLER : FILLER}
442 </React.Fragment>
443 );
444 };
445 `,
446 },
447 {
448 code: normalizeIndent`
449 // Valid because the neither the condition nor the loop affect the hook call.
450 function App(props) {
451 const someObject = {propA: true};
452 for (const propName in someObject) {
453 if (propName === true) {
454 } else {
455 }
456 }
457 const [myState, setMyState] = useState(null);
458 }
459 `,
460 },
461 ],
462 invalid: [
463 {
464 code: normalizeIndent`
465 // Invalid because it's dangerous and might not warn otherwise.
466 // This *must* be invalid.
467 function ComponentWithConditionalHook() {
468 if (cond) {
469 useConditionalHook();
470 }
471 }
472 `,
473 errors: [],
474 },
475 {
476 code: normalizeIndent`
477 Hook.useState();
478 Hook._useState();
479 Hook.use42();
480 Hook.useHook();
481 Hook.use_hook();
482 `,
483 errors: [],
484 },
485 {
486 code: normalizeIndent`
487 class C {
488 m() {
489 This.useHook();
490 Super.useHook();
491 }
492 }
493 `,
494 errors: [],
495 },
496 {
497 code: normalizeIndent`
498 // This is a false positive (it's valid) that unfortunately
499 // we cannot avoid. Prefer to rename it to not start with "use"
500 class Foo extends Component {
501 render() {
502 if (cond) {
503 FooStore.useFeatureFlag();
504 }
505 }
506 }
507 `,
508 errors: [],
509 },
510 {
511 code: normalizeIndent`
512 // Invalid because it's dangerous and might not warn otherwise.
513 // This *must* be invalid.
514 function ComponentWithConditionalHook() {
515 if (cond) {
516 Namespace.useConditionalHook();
517 }
518 }
519 `,
520 errors: [],
521 },
522 {
523 code: normalizeIndent`
524 // Invalid because it's dangerous and might not warn otherwise.
525 // This *must* be invalid.
526 function createComponent() {
527 return function ComponentWithConditionalHook() {
528 if (cond) {
529 useConditionalHook();
530 }
531 }
532 }
533 `,
534 errors: [],
535 },
536 {
537 code: normalizeIndent`
538 // Invalid because it's dangerous and might not warn otherwise.
539 // This *must* be invalid.
540 function useHookWithConditionalHook() {
541 if (cond) {
542 useConditionalHook();
543 }
544 }
545 `,
546 errors: [],
547 },
548 {
549 code: normalizeIndent`
550 // Invalid because it's dangerous and might not warn otherwise.
551 // This *must* be invalid.
552 function createHook() {
553 return function useHookWithConditionalHook() {
554 if (cond) {
555 useConditionalHook();
556 }
557 }
558 }
559 `,
560 errors: [],
561 },
562 {
563 code: normalizeIndent`
564 // Invalid because it's dangerous and might not warn otherwise.
565 // This *must* be invalid.
566 function ComponentWithTernaryHook() {
567 cond ? useTernaryHook() : null;
568 }
569 `,
570 errors: [],
571 },
572 {
573 code: normalizeIndent`
574 // Invalid because it's a common misunderstanding.
575 // We *could* make it valid but the runtime error could be confusing.
576 function ComponentWithHookInsideCallback() {
577 useEffect(() => {
578 useHookInsideCallback();
579 });
580 }
581 `,
582 errors: [],
583 },
584 {
585 code: normalizeIndent`
586 // Invalid because it's a common misunderstanding.
587 // We *could* make it valid but the runtime error could be confusing.
588 function createComponent() {
589 return function ComponentWithHookInsideCallback() {
590 useEffect(() => {
591 useHookInsideCallback();
592 });
593 }
594 }
595 `,
596 errors: [],
597 },
598 {
599 code: normalizeIndent`
600 // Invalid because it's a common misunderstanding.
601 // We *could* make it valid but the runtime error could be confusing.
602 const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {
603 useEffect(() => {
604 useHookInsideCallback();
605 });
606 return <button {...props} ref={ref} />
607 });
608 `,
609 errors: [],
610 },
611 {
612 code: normalizeIndent`
613 // Invalid because it's a common misunderstanding.
614 // We *could* make it valid but the runtime error could be confusing.
615 const ComponentWithHookInsideCallback = React.memo(props => {
616 useEffect(() => {
617 useHookInsideCallback();
618 });
619 return <button {...props} />
620 });
621 `,
622 errors: [],
623 },
624 {
625 code: normalizeIndent`
626 // Invalid because it's a common misunderstanding.
627 // We *could* make it valid but the runtime error could be confusing.
628 function ComponentWithHookInsideCallback() {
629 function handleClick() {
630 useState();
631 }
632 }
633 `,
634 errors: [],
635 },
636 {
637 code: normalizeIndent`
638 // Invalid because it's a common misunderstanding.
639 // We *could* make it valid but the runtime error could be confusing.
640 function createComponent() {
641 return function ComponentWithHookInsideCallback() {
642 function handleClick() {
643 useState();
644 }
645 }
646 }
647 `,
648 errors: [],
649 },
650 {
651 code: normalizeIndent`
652 // Invalid because it's dangerous and might not warn otherwise.
653 // This *must* be invalid.
654 function ComponentWithHookInsideLoop() {
655 while (cond) {
656 useHookInsideLoop();
657 }
658 }
659 `,
660 errors: [],
661 },
662 {
663 code: normalizeIndent`
664 // Invalid because it's dangerous and might not warn otherwise.
665 // This *must* be invalid.
666 function renderItem() {
667 useState();
668 }
669
670 function List(props) {
671 return props.items.map(renderItem);
672 }
673 `,
674 errors: [],
675 },
676 {
677 code: normalizeIndent`
678 // Currently invalid because it violates the convention and removes the "taint"
679 // from a hook. We *could* make it valid to avoid some false positives but let's
680 // ensure that we don't break the "renderItem" and "normalFunctionWithConditionalHook"
681 // cases which must remain invalid.
682 function normalFunctionWithHook() {
683 useHookInsideNormalFunction();
684 }
685 `,
686 errors: [],
687 },
688 {
689 code: normalizeIndent`
690 // These are neither functions nor hooks.
691 function _normalFunctionWithHook() {
692 useHookInsideNormalFunction();
693 }
694 function _useNotAHook() {
695 useHookInsideNormalFunction();
696 }
697 `,
698 errors: [],
699 },
700 {
701 code: normalizeIndent`
702 // Invalid because it's dangerous and might not warn otherwise.
703 // This *must* be invalid.
704 function normalFunctionWithConditionalHook() {
705 if (cond) {
706 useHookInsideNormalFunction();
707 }
708 }
709 `,
710 errors: [],
711 },
712 {
713 code: normalizeIndent`
714 // Invalid because it's dangerous and might not warn otherwise.
715 // This *must* be invalid.
716 function useHookInLoops() {
717 while (a) {
718 useHook1();
719 if (b) return;
720 useHook2();
721 }
722 while (c) {
723 useHook3();
724 if (d) return;
725 useHook4();
726 }
727 }
728 `,
729 errors: [],
730 },
731 {
732 code: normalizeIndent`
733 // Invalid because it's dangerous and might not warn otherwise.
734 // This *must* be invalid.
735 function useHookInLoops() {
736 while (a) {
737 useHook1();
738 if (b) continue;
739 useHook2();
740 }
741 }
742 `,
743 errors: [],
744 },
745 {
746 code: normalizeIndent`
747 // Invalid because it's dangerous and might not warn otherwise.
748 // This *must* be invalid.
749 function useLabeledBlock() {
750 label: {
751 if (a) break label;
752 useHook();
753 }
754 }
755 `,
756 errors: [],
757 },
758 {
759 code: normalizeIndent`
760 // Currently invalid.
761 // These are variations capturing the current heuristic--
762 // we only allow hooks in PascalCase or useFoo functions.
763 // We *could* make some of these valid. But before doing it,
764 // consider specific cases documented above that contain reasoning.
765 function a() { useState(); }
766 const whatever = function b() { useState(); };
767 const c = () => { useState(); };
768 let d = () => useState();
769 e = () => { useState(); };
770 ({f: () => { useState(); }});
771 ({g() { useState(); }});
772 const {j = () => { useState(); }} = {};
773 ({k = () => { useState(); }} = {});
774 `,
775 errors: [],
776 },
777 {
778 code: normalizeIndent`
779 // Invalid because it's dangerous and might not warn otherwise.
780 // This *must* be invalid.
781 function useHook() {
782 if (a) return;
783 useState();
784 }
785 `,
786 errors: [],
787 },
788 {
789 code: normalizeIndent`
790 // Invalid because it's dangerous and might not warn otherwise.
791 // This *must* be invalid.
792 function useHook() {
793 if (a) return;
794 if (b) {
795 console.log('true');
796 } else {
797 console.log('false');
798 }
799 useState();
800 }
801 `,
802 errors: [],
803 },
804 {
805 code: normalizeIndent`
806 // Invalid because it's dangerous and might not warn otherwise.
807 // This *must* be invalid.
808 function useHook() {
809 if (b) {
810 console.log('true');
811 } else {
812 console.log('false');
813 }
814 if (a) return;
815 useState();
816 }
817 `,
818 errors: [],
819 },
820 {
821 code: normalizeIndent`
822 // Invalid because it's dangerous and might not warn otherwise.
823 // This *must* be invalid.
824 function useHook() {
825 a && useHook1();
826 b && useHook2();
827 }
828 `,
829 errors: [],
830 },
831 {
832 code: normalizeIndent`
833 // Invalid because it's dangerous and might not warn otherwise.
834 // This *must* be invalid.
835 function useHook() {
836 try {
837 f();
838 useState();
839 } catch {}
840 }
841 `,
842 errors: [],
843 },
844 {
845 code: normalizeIndent`
846 // Invalid because it's dangerous and might not warn otherwise.
847 // This *must* be invalid.
848 function useHook({ bar }) {
849 let foo1 = bar && useState();
850 let foo2 = bar || useState();
851 let foo3 = bar ?? useState();
852 }
853 `,
854 errors: [],
855 },
856 {
857 code: normalizeIndent`
858 // Invalid because it's dangerous and might not warn otherwise.
859 // This *must* be invalid.
860 const FancyButton = React.forwardRef((props, ref) => {
861 if (props.fancy) {
862 useCustomHook();
863 }
864 return <button ref={ref}>{props.children}</button>;
865 });
866 `,
867 errors: [],
868 },
869 {
870 code: normalizeIndent`
871 // Invalid because it's dangerous and might not warn otherwise.
872 // This *must* be invalid.
873 const FancyButton = forwardRef(function(props, ref) {
874 if (props.fancy) {
875 useCustomHook();
876 }
877 return <button ref={ref}>{props.children}</button>;
878 });
879 `,
880 errors: [],
881 },
882 {
883 code: normalizeIndent`
884 // Invalid because it's dangerous and might not warn otherwise.
885 // This *must* be invalid.
886 const MemoizedButton = memo(function(props) {
887 if (props.fancy) {
888 useCustomHook();
889 }
890 return <button>{props.children}</button>;
891 });
892 `,
893 errors: [],
894 },
895 {
896 code: normalizeIndent`
897 // This is invalid because "use"-prefixed functions used in named
898 // functions are assumed to be hooks.
899 React.unknownFunction(function notAComponent(foo, bar) {
900 useProbablyAHook(bar)
901 });
902 `,
903 errors: [],
904 },
905 {
906 code: normalizeIndent`
907 // Invalid because it's dangerous.
908 // Normally, this would crash, but not if you use inline requires.
909 // This *must* be invalid.
910 // It's expected to have some false positives, but arguably
911 // they are confusing anyway due to the use*() convention
912 // already being associated with Hooks.
913 useState();
914 if (foo) {
915 const foo = React.useCallback(() => {});
916 }
917 useCustomHook();
918 `,
919 errors: [],
920 },
921 {
922 code: normalizeIndent`
923 // Technically this is a false positive.
924 // We *could* make it valid (and it used to be).
925 //
926 // However, top-level Hook-like calls can be very dangerous
927 // in environments with inline requires because they can mask
928 // the runtime error by accident.
929 // So we prefer to disallow it despite the false positive.
930
931 const {createHistory, useBasename} = require('history-2.1.2');
932 const browserHistory = useBasename(createHistory)({
933 basename: '/',
934 });
935 `,
936 errors: [],
937 },
938 {
939 code: normalizeIndent`
940 class ClassComponentWithFeatureFlag extends React.Component {
941 render() {
942 if (foo) {
943 useFeatureFlag();
944 }
945 }
946 }
947 `,
948 errors: [],
949 },
950 {
951 code: normalizeIndent`
952 class ClassComponentWithHook extends React.Component {
953 render() {
954 React.useState();
955 }
956 }
957 `,
958 errors: [],
959 },
960 {
961 code: normalizeIndent`
962 (class {useHook = () => { useState(); }});
963 `,
964 errors: [],
965 },
966 {
967 code: normalizeIndent`
968 (class {useHook() { useState(); }});
969 `,
970 errors: [],
971 },
972 {
973 code: normalizeIndent`
974 (class {h = () => { useState(); }});
975 `,
976 errors: [],
977 },
978 {
979 code: normalizeIndent`
980 (class {i() { useState(); }});
981 `,
982 errors: [],
983 },
984 ],
985 };