Best JavaScript code snippet using storybook-root
ESLintRulesOfHooks-test.js
Source:ESLintRulesOfHooks-test.js
...28 valid: [29 `30 // Valid because components can use hooks.31 function ComponentWithHook() {32 useHook();33 }34 `,35 `36 // Valid because components can use hooks.37 function createComponentWithHook() {38 return function ComponentWithHook() {39 useHook();40 };41 }42 `,43 `44 // Valid because hooks can use hooks.45 function useHookWithHook() {46 useHook();47 }48 `,49 `50 // Valid because hooks can use hooks.51 function createHook() {52 return function useHookWithHook() {53 useHook();54 }55 }56 `,57 `58 // Valid because components can call functions.59 function ComponentWithNormalFunction() {60 doSomething();61 }62 `,63 `64 // Valid because functions can call functions.65 function normalFunctionWithNormalFunction() {66 doSomething();67 }68 `,69 `70 // Valid because functions can call functions.71 function normalFunctionWithConditionalFunction() {72 if (cond) {73 doSomething();74 }75 }76 `,77 `78 // Valid because functions can call functions.79 function functionThatStartsWithUseButIsntAHook() {80 if (cond) {81 userFetch();82 }83 }84 `,85 `86 // Valid although unconditional return doesn't make sense and would fail other rules.87 // We could make it invalid but it doesn't matter.88 function useUnreachable() {89 return;90 useHook();91 }92 `,93 `94 // Valid because hooks can call hooks.95 function useHook() { useState(); }96 const whatever = function useHook() { useState(); };97 const useHook1 = () => { useState(); };98 let useHook2 = () => useState();99 useHook2 = () => { useState(); };100 ({useHook: () => { useState(); }});101 ({useHook() { useState(); }});102 const {useHook3 = () => { useState(); }} = {};103 ({useHook = () => { useState(); }} = {});104 Namespace.useHook = () => { useState(); };105 `,106 `107 // Valid because hooks can call hooks.108 function useHook() {109 useHook1();110 useHook2();111 }112 `,113 `114 // Valid because hooks can call hooks.115 function createHook() {116 return function useHook() {117 useHook1();118 useHook2();119 };120 }121 `,122 `123 // Valid because hooks can call hooks.124 function useHook() {125 useState() && a;126 }127 `,128 `129 // Valid because hooks can call hooks.130 function useHook() {131 return useHook1() + useHook2();132 }133 `,134 `135 // Valid because hooks can call hooks.136 function useHook() {137 return useHook1(useHook2());138 }139 `,140 `141 // Valid because hooks can be used in anonymous arrow-function arguments142 // to forwardRef.143 const FancyButton = React.forwardRef((props, ref) => {144 useHook();145 return <button {...props} ref={ref} />146 });147 `,148 `149 // Valid because hooks can be used in anonymous function arguments to150 // forwardRef.151 const FancyButton = React.forwardRef(function (props, ref) {152 useHook();153 return <button {...props} ref={ref} />154 });155 `,156 `157 // Valid because hooks can be used in anonymous function arguments to158 // forwardRef.159 const FancyButton = forwardRef(function (props, ref) {160 useHook();161 return <button {...props} ref={ref} />162 });163 `,164 `165 // Valid because hooks can be used in anonymous function arguments to166 // React.memo.167 const MemoizedFunction = React.memo(props => {168 useHook();169 return <button {...props} />170 });171 `,172 `173 // Valid because hooks can be used in anonymous function arguments to174 // memo.175 const MemoizedFunction = memo(function (props) {176 useHook();177 return <button {...props} />178 });179 `,180 `181 // Valid because classes can call functions.182 // We don't consider these to be hooks.183 class C {184 m() {185 this.useHook();186 super.useHook();187 }188 }189 `,190 `191 // Valid -- this is a regression test.192 jest.useFakeTimers();193 beforeEach(() => {194 jest.useRealTimers();195 })196 `,197 `198 // Valid because they're not matching use[A-Z].199 fooState();200 use();201 _use();202 _useState();203 use_hook();204 // also valid because it's not matching the PascalCase namespace205 jest.useFakeTimer()206 `,207 `208 // Regression test for some internal code.209 // This shows how the "callback rule" is more relaxed,210 // and doesn't kick in unless we're confident we're in211 // a component or a hook.212 function makeListener(instance) {213 each(pixelsWithInferredEvents, pixel => {214 if (useExtendedSelector(pixel.id) && extendedButton) {215 foo();216 }217 });218 }219 `,220 `221 // This is valid because "use"-prefixed functions called in222 // unnamed function arguments are not assumed to be hooks.223 React.unknownFunction((foo, bar) => {224 if (foo) {225 useNotAHook(bar)226 }227 });228 `,229 `230 // This is valid because "use"-prefixed functions called in231 // unnamed function arguments are not assumed to be hooks.232 unknownFunction(function(foo, bar) {233 if (foo) {234 useNotAHook(bar)235 }236 });237 `,238 `239 // Regression test for incorrectly flagged valid code.240 function RegressionTest() {241 const foo = cond ? a : b;242 useState();243 }244 `,245 `246 // Valid because exceptions abort rendering247 function RegressionTest() {248 if (page == null) {249 throw new Error('oh no!');250 }251 useState();252 }253 `,254 `255 // Valid because the loop doesn't change the order of hooks calls.256 function RegressionTest() {257 const res = [];258 const additionalCond = true;259 for (let i = 0; i !== 10 && additionalCond; ++i ) {260 res.push(i);261 }262 React.useLayoutEffect(() => {});263 }264 `,265 `266 // Is valid but hard to compute by brute-forcing267 function MyComponent() {268 // 40 conditions269 if (c) {} else {}270 if (c) {} else {}271 if (c) {} else {}272 if (c) {} else {}273 if (c) {} else {}274 if (c) {} else {}275 if (c) {} else {}276 if (c) {} else {}277 if (c) {} else {}278 if (c) {} else {}279 if (c) {} else {}280 if (c) {} else {}281 if (c) {} else {}282 if (c) {} else {}283 if (c) {} else {}284 if (c) {} else {}285 if (c) {} else {}286 if (c) {} else {}287 if (c) {} else {}288 if (c) {} else {}289 if (c) {} else {}290 if (c) {} else {}291 if (c) {} else {}292 if (c) {} else {}293 if (c) {} else {}294 if (c) {} else {}295 if (c) {} else {}296 if (c) {} else {}297 if (c) {} else {}298 if (c) {} else {}299 if (c) {} else {}300 if (c) {} else {}301 if (c) {} else {}302 if (c) {} else {}303 if (c) {} else {}304 if (c) {} else {}305 if (c) {} else {}306 if (c) {} else {}307 if (c) {} else {}308 if (c) {} else {}309 // 10 hooks310 useHook();311 useHook();312 useHook();313 useHook();314 useHook();315 useHook();316 useHook();317 useHook();318 useHook();319 useHook();320 }321 `,322 `323 // Valid because the neither the condition nor the loop affect the hook call.324 function App(props) {325 const someObject = {propA: true};326 for (const propName in someObject) {327 if (propName === true) {328 } else {329 }330 }331 const [myState, setMyState] = useState(null);332 }333 `,334 ],335 invalid: [336 {337 code: `338 // Invalid because it's dangerous and might not warn otherwise.339 // This *must* be invalid.340 function ComponentWithConditionalHook() {341 if (cond) {342 useConditionalHook();343 }344 }345 `,346 errors: [conditionalError('useConditionalHook')],347 },348 {349 code: `350 Hook.use();351 Hook._use();352 Hook.useState();353 Hook._useState();354 Hook.use42();355 Hook.useHook();356 Hook.use_hook();357 `,358 errors: [359 topLevelError('Hook.useState'),360 topLevelError('Hook.use42'),361 topLevelError('Hook.useHook'),362 ],363 },364 {365 code: `366 class C {367 m() {368 This.useHook();369 Super.useHook();370 }371 }372 `,373 errors: [classError('This.useHook'), classError('Super.useHook')],374 },375 {376 code: `377 // This is a false positive (it's valid) that unfortunately 378 // we cannot avoid. Prefer to rename it to not start with "use"379 class Foo extends Component {380 render() {381 if (cond) {382 FooStore.useFeatureFlag();383 }384 }385 }386 `,387 errors: [classError('FooStore.useFeatureFlag')],388 },389 {390 code: `391 // Invalid because it's dangerous and might not warn otherwise.392 // This *must* be invalid.393 function ComponentWithConditionalHook() {394 if (cond) {395 Namespace.useConditionalHook();396 }397 }398 `,399 errors: [conditionalError('Namespace.useConditionalHook')],400 },401 {402 code: `403 // Invalid because it's dangerous and might not warn otherwise.404 // This *must* be invalid.405 function createComponent() {406 return function ComponentWithConditionalHook() {407 if (cond) {408 useConditionalHook();409 }410 }411 }412 `,413 errors: [conditionalError('useConditionalHook')],414 },415 {416 code: `417 // Invalid because it's dangerous and might not warn otherwise.418 // This *must* be invalid.419 function useHookWithConditionalHook() {420 if (cond) {421 useConditionalHook();422 }423 }424 `,425 errors: [conditionalError('useConditionalHook')],426 },427 {428 code: `429 // Invalid because it's dangerous and might not warn otherwise.430 // This *must* be invalid.431 function createHook() {432 return function useHookWithConditionalHook() {433 if (cond) {434 useConditionalHook();435 }436 }437 }438 `,439 errors: [conditionalError('useConditionalHook')],440 },441 {442 code: `443 // Invalid because it's dangerous and might not warn otherwise.444 // This *must* be invalid.445 function ComponentWithTernaryHook() {446 cond ? useTernaryHook() : null;447 }448 `,449 errors: [conditionalError('useTernaryHook')],450 },451 {452 code: `453 // Invalid because it's a common misunderstanding.454 // We *could* make it valid but the runtime error could be confusing.455 function ComponentWithHookInsideCallback() {456 useEffect(() => {457 useHookInsideCallback();458 });459 }460 `,461 errors: [genericError('useHookInsideCallback')],462 },463 {464 code: `465 // Invalid because it's a common misunderstanding.466 // We *could* make it valid but the runtime error could be confusing.467 function createComponent() {468 return function ComponentWithHookInsideCallback() {469 useEffect(() => {470 useHookInsideCallback();471 });472 }473 }474 `,475 errors: [genericError('useHookInsideCallback')],476 },477 {478 code: `479 // Invalid because it's a common misunderstanding.480 // We *could* make it valid but the runtime error could be confusing.481 const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {482 useEffect(() => {483 useHookInsideCallback();484 });485 return <button {...props} ref={ref} />486 });487 `,488 errors: [genericError('useHookInsideCallback')],489 },490 {491 code: `492 // Invalid because it's a common misunderstanding.493 // We *could* make it valid but the runtime error could be confusing.494 const ComponentWithHookInsideCallback = React.memo(props => {495 useEffect(() => {496 useHookInsideCallback();497 });498 return <button {...props} />499 });500 `,501 errors: [genericError('useHookInsideCallback')],502 },503 {504 code: `505 // Invalid because it's a common misunderstanding.506 // We *could* make it valid but the runtime error could be confusing.507 function ComponentWithHookInsideCallback() {508 function handleClick() {509 useState();510 }511 }512 `,513 errors: [functionError('useState', 'handleClick')],514 },515 {516 code: `517 // Invalid because it's a common misunderstanding.518 // We *could* make it valid but the runtime error could be confusing.519 function createComponent() {520 return function ComponentWithHookInsideCallback() {521 function handleClick() {522 useState();523 }524 }525 }526 `,527 errors: [functionError('useState', 'handleClick')],528 },529 {530 code: `531 // Invalid because it's dangerous and might not warn otherwise.532 // This *must* be invalid.533 function ComponentWithHookInsideLoop() {534 while (cond) {535 useHookInsideLoop();536 }537 }538 `,539 errors: [loopError('useHookInsideLoop')],540 },541 {542 code: `543 // Invalid because it's dangerous and might not warn otherwise.544 // This *must* be invalid.545 function renderItem() {546 useState();547 }548 function List(props) {549 return props.items.map(renderItem);550 }551 `,552 errors: [functionError('useState', 'renderItem')],553 },554 {555 code: `556 // Currently invalid because it violates the convention and removes the "taint"557 // from a hook. We *could* make it valid to avoid some false positives but let's558 // ensure that we don't break the "renderItem" and "normalFunctionWithConditionalHook"559 // cases which must remain invalid.560 function normalFunctionWithHook() {561 useHookInsideNormalFunction();562 }563 `,564 errors: [565 functionError('useHookInsideNormalFunction', 'normalFunctionWithHook'),566 ],567 },568 {569 code: `570 // Invalid because it's dangerous and might not warn otherwise.571 // This *must* be invalid.572 function normalFunctionWithConditionalHook() {573 if (cond) {574 useHookInsideNormalFunction();575 }576 }577 `,578 errors: [579 functionError(580 'useHookInsideNormalFunction',581 'normalFunctionWithConditionalHook'582 ),583 ],584 },585 {586 code: `587 // Invalid because it's dangerous and might not warn otherwise.588 // This *must* be invalid.589 function useHookInLoops() {590 while (a) {591 useHook1();592 if (b) return;593 useHook2();594 }595 while (c) {596 useHook3();597 if (d) return;598 useHook4();599 }600 }601 `,602 errors: [603 loopError('useHook1'),604 loopError('useHook2'),605 loopError('useHook3'),606 loopError('useHook4'),607 ],608 },609 {610 code: `611 // Invalid because it's dangerous and might not warn otherwise.612 // This *must* be invalid.613 function useHookInLoops() {614 while (a) {615 useHook1();616 if (b) continue;617 useHook2();618 }619 }620 `,621 errors: [loopError('useHook1'), loopError('useHook2', true)],622 },623 {624 code: `625 // Invalid because it's dangerous and might not warn otherwise.626 // This *must* be invalid.627 function useLabeledBlock() {628 label: {629 if (a) break label;630 useHook();631 }632 }633 `,634 errors: [conditionalError('useHook')],635 },636 {637 code: `638 // Currently invalid.639 // These are variations capturing the current heuristic--640 // we only allow hooks in PascalCase or useFoo functions.641 // We *could* make some of these valid. But before doing it,642 // consider specific cases documented above that contain reasoning.643 function a() { useState(); }644 const whatever = function b() { useState(); };645 const c = () => { useState(); };646 let d = () => useState();647 e = () => { useState(); };648 ({f: () => { useState(); }});649 ({g() { useState(); }});650 const {j = () => { useState(); }} = {};651 ({k = () => { useState(); }} = {});652 `,653 errors: [654 functionError('useState', 'a'),655 functionError('useState', 'b'),656 functionError('useState', 'c'),657 functionError('useState', 'd'),658 functionError('useState', 'e'),659 functionError('useState', 'f'),660 functionError('useState', 'g'),661 functionError('useState', 'j'),662 functionError('useState', 'k'),663 ],664 },665 {666 code: `667 // Invalid because it's dangerous and might not warn otherwise.668 // This *must* be invalid.669 function useHook() {670 if (a) return;671 useState();672 }673 `,674 errors: [conditionalError('useState', true)],675 },676 {677 code: `678 // Invalid because it's dangerous and might not warn otherwise.679 // This *must* be invalid.680 function useHook() {681 if (a) return;682 if (b) {683 console.log('true');684 } else {685 console.log('false');686 }687 useState();688 }689 `,690 errors: [conditionalError('useState', true)],691 },692 {693 code: `694 // Invalid because it's dangerous and might not warn otherwise.695 // This *must* be invalid.696 function useHook() {697 if (b) {698 console.log('true');699 } else {700 console.log('false');701 }702 if (a) return;703 useState();704 }705 `,706 errors: [conditionalError('useState', true)],707 },708 {709 code: `710 // Invalid because it's dangerous and might not warn otherwise.711 // This *must* be invalid.712 function useHook() {713 a && useHook1();714 b && useHook2();715 }716 `,717 errors: [conditionalError('useHook1'), conditionalError('useHook2')],718 },719 {720 code: `721 // Invalid because it's dangerous and might not warn otherwise.722 // This *must* be invalid.723 function useHook() {724 try {725 f();726 useState();727 } catch {}728 }729 `,730 errors: [731 // NOTE: This is an error since `f()` could possibly throw.732 conditionalError('useState'),733 ],734 },735 {736 code: `737 // Invalid because it's dangerous and might not warn otherwise.738 // This *must* be invalid.739 function useHook({ bar }) {740 let foo1 = bar && useState();741 let foo2 = bar || useState();742 let foo3 = bar ?? useState();743 }744 `,745 errors: [746 conditionalError('useState'),747 conditionalError('useState'),748 conditionalError('useState'),749 ],750 },751 {752 code: `753 // Invalid because it's dangerous and might not warn otherwise.754 // This *must* be invalid.755 const FancyButton = React.forwardRef((props, ref) => {756 if (props.fancy) {757 useCustomHook();758 }759 return <button ref={ref}>{props.children}</button>;760 });761 `,762 errors: [conditionalError('useCustomHook')],763 },764 {765 code: `766 // Invalid because it's dangerous and might not warn otherwise.767 // This *must* be invalid.768 const FancyButton = forwardRef(function(props, ref) {769 if (props.fancy) {770 useCustomHook();771 }772 return <button ref={ref}>{props.children}</button>;773 });774 `,775 errors: [conditionalError('useCustomHook')],776 },777 {778 code: `779 // Invalid because it's dangerous and might not warn otherwise.780 // This *must* be invalid.781 const MemoizedButton = memo(function(props) {782 if (props.fancy) {783 useCustomHook();784 }785 return <button>{props.children}</button>;786 });787 `,788 errors: [conditionalError('useCustomHook')],789 },790 {791 code: `792 // This is invalid because "use"-prefixed functions used in named793 // functions are assumed to be hooks.794 React.unknownFunction(function notAComponent(foo, bar) {795 useProbablyAHook(bar)796 });797 `,798 errors: [functionError('useProbablyAHook', 'notAComponent')],799 },800 {801 code: `802 // Invalid because it's dangerous.803 // Normally, this would crash, but not if you use inline requires.804 // This *must* be invalid.805 // It's expected to have some false positives, but arguably806 // they are confusing anyway due to the use*() convention807 // already being associated with Hooks.808 useState();809 if (foo) {810 const foo = React.useCallback(() => {});811 }812 useCustomHook();813 `,814 errors: [815 topLevelError('useState'),816 topLevelError('React.useCallback'),817 topLevelError('useCustomHook'),818 ],819 },820 {821 code: `822 // Technically this is a false positive.823 // We *could* make it valid (and it used to be).824 //825 // However, top-level Hook-like calls can be very dangerous826 // in environments with inline requires because they can mask827 // the runtime error by accident.828 // So we prefer to disallow it despite the false positive.829 const {createHistory, useBasename} = require('history-2.1.2');830 const browserHistory = useBasename(createHistory)({831 basename: '/',832 });833 `,834 errors: [topLevelError('useBasename')],835 },836 {837 code: `838 class ClassComponentWithFeatureFlag extends React.Component {839 render() {840 if (foo) {841 useFeatureFlag();842 }843 }844 }845 `,846 errors: [classError('useFeatureFlag')],847 },848 {849 code: `850 class ClassComponentWithHook extends React.Component {851 render() {852 React.useState();853 }854 }855 `,856 errors: [classError('React.useState')],857 },858 {859 code: `860 (class {useHook = () => { useState(); }});861 `,862 errors: [classError('useState')],863 },864 {865 code: `866 (class {useHook() { useState(); }});867 `,868 errors: [classError('useState')],869 },870 {871 code: `872 (class {h = () => { useState(); }});873 `,874 errors: [classError('useState')],875 },876 {877 code: `878 (class {i() { useState(); }});879 `,880 errors: [classError('useState')],...
require-hook.test.ts
Source:require-hook.test.ts
1import { TSESLint } from '@typescript-eslint/utils';2import dedent from 'dedent';3import rule from '../require-hook';4import { espreeParser } from './test-utils';5const ruleTester = new TSESLint.RuleTester({6 parser: espreeParser,7 parserOptions: {8 ecmaVersion: 2017,9 },10});11ruleTester.run('require-hook', rule, {12 valid: [13 'describe()',14 'describe("just a title")',15 dedent`16 describe('a test', () =>17 test('something', () => {18 expect(true).toBe(true);19 }));20 `,21 dedent`22 test('it', () => {23 //24 });25 `,26 dedent`27 const { myFn } = require('../functions');28 test('myFn', () => {29 expect(myFn()).toBe(1);30 });31 `,32 {33 code: dedent`34 import { myFn } from '../functions';35 test('myFn', () => {36 expect(myFn()).toBe(1);37 });38 `,39 parserOptions: { sourceType: 'module' },40 },41 dedent`42 class MockLogger {43 log() {}44 }45 test('myFn', () => {46 expect(myFn()).toBe(1);47 });48 `,49 dedent`50 const { myFn } = require('../functions');51 describe('myFn', () => {52 it('returns one', () => {53 expect(myFn()).toBe(1);54 });55 });56 `,57 dedent`58 describe('some tests', () => {59 it('is true', () => {60 expect(true).toBe(true);61 });62 });63 `,64 dedent`65 describe('some tests', () => {66 it('is true', () => {67 expect(true).toBe(true);68 });69 describe('more tests', () => {70 it('is false', () => {71 expect(true).toBe(false);72 });73 });74 });75 `,76 dedent`77 describe('some tests', () => {78 let consoleLogSpy;79 beforeEach(() => {80 consoleLogSpy = jest.spyOn(console, 'log'); 81 });82 it('prints a message', () => {83 printMessage('hello world');84 expect(consoleLogSpy).toHaveBeenCalledWith('hello world');85 });86 });87 `,88 dedent`89 let consoleErrorSpy = null; 90 beforeEach(() => {91 consoleErrorSpy = jest.spyOn(console, 'error');92 });93 `,94 dedent`95 let consoleErrorSpy = undefined; 96 beforeEach(() => {97 consoleErrorSpy = jest.spyOn(console, 'error');98 });99 `,100 dedent`101 describe('some tests', () => {102 beforeEach(() => {103 setup();104 });105 });106 `,107 dedent`108 beforeEach(() => {109 initializeCityDatabase();110 });111 afterEach(() => {112 clearCityDatabase();113 });114 test('city database has Vienna', () => {115 expect(isCity('Vienna')).toBeTruthy();116 });117 test('city database has San Juan', () => {118 expect(isCity('San Juan')).toBeTruthy();119 });120 `,121 dedent`122 describe('cities', () => {123 beforeEach(() => {124 initializeCityDatabase();125 });126 test('city database has Vienna', () => {127 expect(isCity('Vienna')).toBeTruthy();128 });129 test('city database has San Juan', () => {130 expect(isCity('San Juan')).toBeTruthy();131 });132 afterEach(() => {133 clearCityDatabase();134 });135 });136 `,137 {138 code: dedent`139 enableAutoDestroy(afterEach);140 141 describe('some tests', () => {142 it('is false', () => {143 expect(true).toBe(true);144 });145 });146 `,147 options: [{ allowedFunctionCalls: ['enableAutoDestroy'] }],148 },149 ],150 invalid: [151 {152 code: 'setup();',153 errors: [154 {155 messageId: 'useHook',156 line: 1,157 column: 1,158 },159 ],160 },161 {162 code: dedent`163 describe('some tests', () => {164 setup();165 });166 `,167 errors: [168 {169 messageId: 'useHook',170 line: 2,171 column: 3,172 },173 ],174 },175 {176 code: dedent`177 let { setup } = require('./test-utils');178 describe('some tests', () => {179 setup();180 });181 `,182 errors: [183 {184 messageId: 'useHook',185 line: 1,186 column: 1,187 },188 {189 messageId: 'useHook',190 line: 4,191 column: 3,192 },193 ],194 },195 {196 code: dedent`197 describe('some tests', () => {198 setup();199 it('is true', () => {200 expect(true).toBe(true);201 });202 describe('more tests', () => {203 setup();204 it('is false', () => {205 expect(true).toBe(false);206 });207 });208 });209 `,210 errors: [211 {212 messageId: 'useHook',213 line: 2,214 column: 3,215 },216 {217 messageId: 'useHook',218 line: 9,219 column: 5,220 },221 ],222 },223 {224 code: dedent`225 let consoleErrorSpy = jest.spyOn(console, 'error');226 describe('when loading cities from the api', () => {227 let consoleWarnSpy = jest.spyOn(console, 'warn');228 });229 `,230 errors: [231 {232 messageId: 'useHook',233 line: 1,234 column: 1,235 },236 {237 messageId: 'useHook',238 line: 4,239 column: 3,240 },241 ],242 },243 {244 code: dedent`245 let consoleErrorSpy = null;246 describe('when loading cities from the api', () => {247 let consoleWarnSpy = jest.spyOn(console, 'warn');248 });249 `,250 errors: [251 {252 messageId: 'useHook',253 line: 4,254 column: 3,255 },256 ],257 },258 {259 code: 'let value = 1',260 errors: [261 {262 messageId: 'useHook',263 line: 1,264 column: 1,265 },266 ],267 },268 {269 code: "let consoleErrorSpy, consoleWarnSpy = jest.spyOn(console, 'error');",270 errors: [271 {272 messageId: 'useHook',273 line: 1,274 column: 1,275 },276 ],277 },278 {279 code: "let consoleErrorSpy = jest.spyOn(console, 'error'), consoleWarnSpy;",280 errors: [281 {282 messageId: 'useHook',283 line: 1,284 column: 1,285 },286 ],287 },288 {289 code: dedent`290 import { database, isCity } from '../database';291 import { loadCities } from '../api';292 jest.mock('../api');293 const initializeCityDatabase = () => {294 database.addCity('Vienna');295 database.addCity('San Juan');296 database.addCity('Wellington');297 };298 const clearCityDatabase = () => {299 database.clear();300 };301 initializeCityDatabase();302 test('that persists cities', () => {303 expect(database.cities.length).toHaveLength(3);304 });305 test('city database has Vienna', () => {306 expect(isCity('Vienna')).toBeTruthy();307 });308 test('city database has San Juan', () => {309 expect(isCity('San Juan')).toBeTruthy();310 });311 describe('when loading cities from the api', () => {312 let consoleWarnSpy = jest.spyOn(console, 'warn');313 loadCities.mockResolvedValue(['Wellington', 'London']);314 it('does not duplicate cities', async () => {315 await database.loadCities();316 expect(database.cities).toHaveLength(4);317 });318 it('logs any duplicates', async () => {319 await database.loadCities();320 expect(consoleWarnSpy).toHaveBeenCalledWith(321 'Ignored duplicate cities: Wellington',322 );323 });324 });325 clearCityDatabase();326 `,327 parserOptions: { sourceType: 'module' },328 errors: [329 {330 messageId: 'useHook',331 line: 16,332 column: 1,333 },334 {335 messageId: 'useHook',336 line: 31,337 column: 3,338 },339 {340 messageId: 'useHook',341 line: 33,342 column: 3,343 },344 {345 messageId: 'useHook',346 line: 50,347 column: 1,348 },349 ],350 },351 {352 code: dedent`353 enableAutoDestroy(afterEach);354 355 describe('some tests', () => {356 it('is false', () => {357 expect(true).toBe(true);358 });359 });360 `,361 options: [{ allowedFunctionCalls: ['someOtherName'] }],362 errors: [363 {364 messageId: 'useHook',365 line: 1,366 column: 1,367 },368 ],369 },370 ],371});372new TSESLint.RuleTester({373 parser: require.resolve('@typescript-eslint/parser'),374}).run('require-hook: typescript edition', rule, {375 valid: [376 dedent`377 import { myFn } from '../functions';378 // todo: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56545379 declare module 'eslint' {380 namespace ESLint {381 interface LintResult {382 fatalErrorCount: number;383 }384 }385 }386 test('myFn', () => {387 expect(myFn()).toBe(1);388 });389 `,390 ],391 invalid: [392 {393 code: dedent`394 import { setup } from '../test-utils';395 // todo: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56545396 declare module 'eslint' {397 namespace ESLint {398 interface LintResult {399 fatalErrorCount: number;400 }401 }402 }403 describe('some tests', () => {404 setup();405 });406 `,407 errors: [408 {409 messageId: 'useHook',410 line: 13,411 column: 3,412 },413 ],414 },415 ],...
Using AI Code Generation
1import React from 'react';2import { storiesOf } from '@storybook/react';3import { useHook } from 'storybook-root-decorator';4const MyComponent = () => {5 const [state, setState] = useHook('state', { count: 0 });6 return (7 <p>Count: {state.count}</p>8 <button onClick={() => setState({ count: state.count + 1 })}>+1</button>9 );10};11storiesOf('MyComponent', module).add('default', () => <MyComponent />);12MIT © [anubhavsrivastava](
Using AI Code Generation
1import { useHook } from 'storybook-root-decorator';2import { useHook } from 'storybook-root-decorator';3import { useHook } from 'storybook-root-decorator';4import { useHook } from 'storybook-root-decorator';5import { useHook } from 'storybook-root-decorator';6import { withHook } from 'storybook-root-decorator';7MIT © [tjallen](
Using AI Code Generation
1import { useHook } from 'storybook-root-decorator';2import { useState } from 'react';3export default function Test() {4 const [state, setState] = useState('test');5 useHook(() => {6 console.log('test');7 });8 return (9 {state}10 <button onClick={() => setState('test2')}>click</button>11 );12}13MIT © [saihaj](
Using AI Code Generation
1import { useHook } from 'storybook-root-decorator';2import { useMyHook } from './myHook';3const MyComponent = () => {4 const myHook = useHook(useMyHook);5 return <div>{myHook}</div>;6};7import { addDecorator, addParameters } from '@storybook/react';8import { withRootDecorator } from 'storybook-root-decorator';9import { useGlobalHook } from './myHook';10addDecorator(withRootDecorator({ useGlobalHook }));11import { useGlobalHook } from 'storybook-root-decorator';12import { useMyHook } from './myHook';13const MyComponent = () => {14 const myHook = useGlobalHook(useMyHook);15 return <div>{myHook}</div>;16};17import { addDecorator, addParameters } from '@storybook/react';18import { withRootDecorator } from 'storybook-root-decorator';19import { useGlobalHook } from './myHook';20addDecorator(withRootDecorator({ useGlobalHook }));21import { useGlobalHook } from 'storybook-root-decorator';22import { useMyHook } from './myHook';23const MyComponent = () => {24 const myHook = useGlobalHook(useMyHook);25 return <div>{myHook}</div>;26};27import { addDecorator, addParameters } from '@storybook/react';28import { withRootDecorator } from 'storybook-root-decorator';29import { useGlobalHook } from './myHook';30addDecorator(withRootDecorator({ useGlobalHook }));31import { useGlobalHook } from 'storybook-root-decorator';32import { useMyHook } from './myHook';33const MyComponent = () => {34 const myHook = useGlobalHook(useMyHook);35 return <div>{myHook}</div>;
Using AI Code Generation
1import { useHook } from 'storybook-root-decorator';2import { withKnobs, text } from '@storybook/addon-knobs';3import { action } from '@storybook/addon-actions';4import { useAddToCart } from './useAddToCart';5import { useCart } from './useCart';6export default {7};8export const Default = () => {9 const cart = useHook(useCart);10 const addToCart = useHook(useAddToCart);11 const product = {12 name: text('Product Name', 'Product 1'),13 };14 const handleAddToCart = () => {15 addToCart(product);16 action('Product added to cart')(product);17 };18 return (19 <p>Cart: {cart.length}</p>20 <button onClick={handleAddToCart}>Add to cart</button>21 );22};23import { useHook } from 'storybook-root-decorator';24import { useCart } from './useCart';25export default {26};27export const Default = () => {28 const cart = useHook(useCart);29 return <div>Cart: {cart.length}</div>;30};31import { useHook } from 'storybook-root-decorator';32import { withKnobs, text } from '@storybook/addon-knobs';33import { action } from '@storybook/addon-actions';34import { useCheckout } from './useCheckout';35export default {36};37export const Default = () => {38 const checkout = useHook(useCheckout);39 const handleCheckout = async () => {40 const url = await checkout();41 action('Checkout URL')(url);42 };
Using AI Code Generation
1import { useHook } from 'storybook-root-decorator';2import { withKnobs, text } from '@storybook/addon-knobs';3import { action } from '@storybook/addon-actions';4import { useAddToCart } from './useAddToCart';5import { useCart } from './useCart';6export default {7};8export const Default = () => {9 const cart = useHook(useCart);10 const addToCart = useHook(useAddToCart);11 const product = {12 name: text('Product Name', 'Product 1'),13 };14 const handleAddToCart = () => {15 addToCart(product);16 action('Product added to cart')(product);17 };18 return (19 <p>Cart: {cart.length}</p>20 <button onClick={handleAddToCart}>Add to cart</button>21 );22};23import { useHook } from 'storybook-root-decorator';24import { useCart } from './useCart';25export default {26};27export const Default = () => {28 const cart = useHook(useCart);29 return <div>Cart: {cart.length}</div>;30};31import { useHook } from 'storybook-root-decorator';32import { withKnobs, text } from '@storybook/addon-knobs';33import { action } from '@storybook/addon-actions';34import { useCheckout } from './useCheckout';35export default {36};37export const Default = () => {38 const checkout = useHook(useCheckout);39 const handleCheckout = async () => {40 const url = await checkout();41 action('Checkout URL')(url);42 };
Using AI Code Generation
1import { useHook } from 'storybook-addon-root-decorator';2import { useTheme } from '@material-ui/core/styles';3import { ThemeProvider } from 'styled-components';4import { theme } from '../src/themes/theme';5import { GlobalStyle } from '../src/themes/globalStyles';6 useHook];
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!