/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import { ErrorCategory, getRuleForCategory, } from 'babel-plugin-react-compiler/src/CompilerError'; import {normalizeIndent, makeTestCaseError, testRule} from './shared-utils'; import {allRules} from '../src/rules/ReactCompilerRule'; testRule( 'rules-of-hooks', allRules[getRuleForCategory(ErrorCategory.Hooks).name].rule, { valid: [ { name: 'Basic example', code: normalizeIndent` function Component() { useHook(); return
Hello world
; } `, }, { name: 'Violation with Flow suppression', code: ` // Valid since error already suppressed with flow. function useHook() { if (cond) { // $FlowFixMe[react-rule-hook] useConditionalHook(); } } `, }, { // OK because invariants are only meant for the compiler team's consumption name: '[Invariant] Defined after use', code: normalizeIndent` function Component(props) { let y = function () { m(x); }; let x = { a }; m(x); return y; } `, }, { name: "Classes don't throw", code: normalizeIndent` class Foo { #bar() {} } `, }, ], invalid: [ { name: 'Simple violation', code: normalizeIndent` function useConditional() { if (cond) { useConditionalHook(); } } `, errors: [ makeTestCaseError( 'Hooks must always be called in a consistent order', ), ], }, { name: 'Multiple diagnostics within the same function are surfaced', code: normalizeIndent` function useConditional() { cond ?? useConditionalHook(); props.cond && useConditionalHook(); return
Hello world
; }`, errors: [ makeTestCaseError( 'Hooks must always be called in a consistent order', ), makeTestCaseError( 'Hooks must always be called in a consistent order', ), ], }, ], }, );