diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js index 7d6f8b87cbc2b..ef8e3c7ee6781 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js @@ -19,6 +19,16 @@ ESLintTester.setDefaultConfig({ }, }); +/** + * A string template tag that removes padding from the left side of multi-line strings + * @param {Array} strings array of code strings (only one expected) + */ +function normalizeIndent(strings) { + const codeLines = strings[0].split('\n'); + const leftPadding = codeLines[1].match(/\s+/)[0]; + return codeLines.map(line => line.substr(leftPadding.length)).join('\n'); +} + // *************************************************** // For easier local testing, you can add to any case: // { @@ -31,385 +41,449 @@ ESLintTester.setDefaultConfig({ const tests = { valid: [ - ` - // Valid because components can use hooks. - function ComponentWithHook() { - useHook(); - } - `, - ` - // Valid because components can use hooks. - function createComponentWithHook() { - return function ComponentWithHook() { + { + code: normalizeIndent` + // Valid because components can use hooks. + function ComponentWithHook() { useHook(); - }; - } - `, - ` - // Valid because hooks can use hooks. - function useHookWithHook() { - useHook(); - } - `, - ` - // Valid because hooks can use hooks. - function createHook() { - return function useHookWithHook() { + } + `, + }, + { + code: normalizeIndent` + // Valid because components can use hooks. + function createComponentWithHook() { + return function ComponentWithHook() { + useHook(); + }; + } + `, + }, + { + code: normalizeIndent` + // Valid because hooks can use hooks. + function useHookWithHook() { useHook(); } - } - `, - ` - // Valid because components can call functions. - function ComponentWithNormalFunction() { - doSomething(); - } - `, - ` - // Valid because functions can call functions. - function normalFunctionWithNormalFunction() { - doSomething(); - } - `, - ` - // Valid because functions can call functions. - function normalFunctionWithConditionalFunction() { - if (cond) { + `, + }, + { + code: normalizeIndent` + // Valid because hooks can use hooks. + function createHook() { + return function useHookWithHook() { + useHook(); + } + } + `, + }, + { + code: normalizeIndent` + // Valid because components can call functions. + function ComponentWithNormalFunction() { + doSomething(); + } + `, + }, + { + code: normalizeIndent` + // Valid because functions can call functions. + function normalFunctionWithNormalFunction() { doSomething(); } - } - `, - ` - // Valid because functions can call functions. - function functionThatStartsWithUseButIsntAHook() { - if (cond) { - userFetch(); - } - } - `, - ` - // Valid although unconditional return doesn't make sense and would fail other rules. - // We could make it invalid but it doesn't matter. - function useUnreachable() { - return; - useHook(); - } - `, - ` - // Valid because hooks can call hooks. - function useHook() { useState(); } - const whatever = function useHook() { useState(); }; - const useHook1 = () => { useState(); }; - let useHook2 = () => useState(); - useHook2 = () => { useState(); }; - ({useHook: () => { useState(); }}); - ({useHook() { useState(); }}); - const {useHook3 = () => { useState(); }} = {}; - ({useHook = () => { useState(); }} = {}); - Namespace.useHook = () => { useState(); }; - `, - ` - // Valid because hooks can call hooks. - function useHook() { - useHook1(); - useHook2(); - } - `, - ` - // Valid because hooks can call hooks. - function createHook() { - return function useHook() { + `, + }, + { + code: normalizeIndent` + // Valid because functions can call functions. + function normalFunctionWithConditionalFunction() { + if (cond) { + doSomething(); + } + } + `, + }, + { + code: normalizeIndent` + // Valid because functions can call functions. + function functionThatStartsWithUseButIsntAHook() { + if (cond) { + userFetch(); + } + } + `, + }, + { + code: normalizeIndent` + // Valid although unconditional return doesn't make sense and would fail other rules. + // We could make it invalid but it doesn't matter. + function useUnreachable() { + return; + useHook(); + } + `, + }, + { + code: normalizeIndent` + // Valid because hooks can call hooks. + function useHook() { useState(); } + const whatever = function useHook() { useState(); }; + const useHook1 = () => { useState(); }; + let useHook2 = () => useState(); + useHook2 = () => { useState(); }; + ({useHook: () => { useState(); }}); + ({useHook() { useState(); }}); + const {useHook3 = () => { useState(); }} = {}; + ({useHook = () => { useState(); }} = {}); + Namespace.useHook = () => { useState(); }; + `, + }, + { + code: normalizeIndent` + // Valid because hooks can call hooks. + function useHook() { useHook1(); useHook2(); - }; - } - `, - ` - // Valid because hooks can call hooks. - function useHook() { - useState() && a; - } - `, - ` - // Valid because hooks can call hooks. - function useHook() { - return useHook1() + useHook2(); - } - `, - ` - // Valid because hooks can call hooks. - function useHook() { - return useHook1(useHook2()); - } - `, - ` - // Valid because hooks can be used in anonymous arrow-function arguments - // to forwardRef. - const FancyButton = React.forwardRef((props, ref) => { - useHook(); - return