{"id":16820,"library":"flipper-test-utils","title":"Flipper Test Utilities","description":"flipper-test-utils is a library providing common testing utilities specifically designed for developing and testing Flipper plugins and components within the Flipper ecosystem. It is an integral part of the larger Flipper monorepo maintained by Facebook, currently at version 0.273.0. The package has a rapid release cadence, with updates typically aligning with the main Flipper desktop application releases (often weekly or bi-weekly). Its primary purpose is to facilitate isolated and integrated testing of Flipper plugins by offering functionalities like component rendering (often re-exporting or wrapping `@testing-library/react` utilities), mocking the Flipper client API, and providing helper functions for common testing scenarios. This allows developers to thoroughly test their plugins' UI, data interactions, and Flipper host communications without needing a full Flipper desktop environment.","status":"active","version":"0.273.0","language":"javascript","source_language":"en","source_url":"https://github.com/facebook/flipper","tags":["javascript","Flipper","typescript"],"install":[{"cmd":"npm install flipper-test-utils","lang":"bash","label":"npm"},{"cmd":"yarn add flipper-test-utils","lang":"bash","label":"yarn"},{"cmd":"pnpm add flipper-test-utils","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for UI component testing, often re-exported or wrapped.","package":"@testing-library/react","optional":false},{"reason":"Provides the Flipper Desktop plugin SDK and components, essential for plugin definition and API interaction.","package":"flipper-plugin","optional":false},{"reason":"Supplies shared utilities and types across Flipper packages.","package":"flipper-common","optional":false},{"reason":"Frontend library for building Flipper plugin UIs.","package":"react","optional":false}],"imports":[{"note":"While often wrapping `@testing-library/react`, `flipper-test-utils` exports its own `render` for Flipper-specific setup.","wrong":"import { render } from '@testing-library/react';","symbol":"render","correct":"import { render } from 'flipper-test-utils';"},{"note":"This utility is crucial for mocking the Flipper client API within your tests, providing a controlled environment for plugin interactions.","wrong":"import { FlipperLib } from 'flipper-plugin'; // Then try to mock FlipperLib manually","symbol":"createStubFlipperLib","correct":"import { createStubFlipperLib } from 'flipper-test-utils';"},{"note":"A general object containing various helpers and constants for Flipper tests, common in many testing libraries. Specific contents may vary by version.","symbol":"TestUtils","correct":"import { TestUtils } from 'flipper-test-utils';"},{"note":"While not directly from `flipper-test-utils`, `act` is essential for React component testing to ensure updates are flushed and to avoid warnings.","symbol":"act","correct":"import { act } from 'react-dom/test-utils';"}],"quickstart":{"code":"import React from 'react';\nimport { render, createStubFlipperLib } from 'flipper-test-utils';\nimport { act } from 'react-dom/test-utils'; // Essential for React 18+ tests\nimport { FlipperPlugin, Flipper } from 'flipper-plugin';\n\ninterface MyPluginClient {\n  getGreeting(): Promise<string>;\n}\n\n// Define a simple Flipper plugin component\nclass MyFlipperPlugin extends FlipperPlugin<any, any, any> {\n  static id = 'MyFlipperPlugin';\n  static title = 'My Flipper Plugin';\n\n  constructor(flipper: Flipper) {\n    super(flipper);\n  }\n\n  render() {\n    return (\n      <div>\n        <h1>Hello from My Flipper Plugin!</h1>\n        <GreetingFetcher client={this.client} />\n      </div>\n    );\n  }\n}\n\n// A component that uses the Flipper client\nfunction GreetingFetcher({ client }: { client: MyPluginClient }) {\n  const [greeting, setGreeting] = React.useState('Loading...');\n\n  React.useEffect(() => {\n    const fetchGreeting = async () => {\n      const message = await client.getGreeting();\n      setGreeting(message);\n    };\n    fetchGreeting();\n  }, [client]);\n\n  return <p>{greeting}</p>;\n}\n\ndescribe('MyFlipperPlugin', () => {\n  it('renders correctly and fetches a greeting', async () => {\n    const stubFlipperLib = createStubFlipperLib();\n\n    // Mock the client's method directly on the stub\n    stubFlipperLib.pluginClient.getGreeting = async () => 'Hello World!';\n\n    let rendered;\n    await act(async () => {\n      rendered = render(\n        <MyFlipperPlugin flipper={stubFlipperLib} />, \n        { wrapper: ({ children }) => <div>{children}</div> } // Provide a simple wrapper if needed\n      );\n    });\n\n    expect(rendered.getByText('Hello from My Flipper Plugin!')).toBeInTheDocument();\n    // Wait for the async effect to complete\n    await rendered.findByText('Hello World!'); \n    expect(rendered.getByText('Hello World!')).toBeInTheDocument();\n  });\n});\n","lang":"typescript","description":"Demonstrates how to render a Flipper plugin component and mock its Flipper client interactions for testing."},"warnings":[{"fix":"Always test against the Flipper Desktop application version you target. Regularly consult the main Flipper CHANGELOG.md for migration guides and API adjustments, and update `flipper-test-utils` along with `flipper-plugin` and `flipper-common`.","message":"As `flipper-test-utils` is deeply integrated into the Flipper monorepo, its APIs can experience breaking changes aligning with major or even minor Flipper desktop application updates. Referencing the main Flipper changelog is crucial for staying up-to-date, as this sub-package's dedicated changelog may not detail all related breaking changes.","severity":"breaking","affected_versions":">=0.x"},{"fix":"Import `act` from `react-dom/test-utils` and wrap your `render` calls, state updates, and assertions that trigger React lifecycle methods within `await act(async () => { /* ... */ });` blocks.","message":"When testing React components that update state or use effects, ensure your test code that triggers these updates and assertions is wrapped in `act()`. Failure to do so can lead to `Act(...)` warnings and inconsistent test results, especially with React 18+.","severity":"gotcha","affected_versions":">=0.x (React Testing Library based)"},{"fix":"Ensure that `jest`, `@testing-library/react`, `react`, and `react-dom` are installed as `devDependencies` in your project and are compatible with the version of `flipper-test-utils` you are using.","message":"`flipper-test-utils` assumes certain peer dependencies like `jest`, `@testing-library/react`, and `react`. While not always explicitly listed as direct dependencies in `package.json`, their absence or incompatible versions can lead to runtime errors during testing.","severity":"gotcha","affected_versions":">=0.x"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Run `npm install flipper-test-utils` or `yarn add flipper-test-utils` to install it. Ensure your `tsconfig.json` includes `node_modules/@types` if using custom type roots.","cause":"The package is not installed, or TypeScript cannot locate its declarations.","error":"Cannot find module 'flipper-test-utils' or its corresponding type declarations."},{"fix":"Ensure you are using `import { render } from 'flipper-test-utils';` (ESM syntax) and that your test runner (e.g., Jest) is configured to handle ESM modules correctly. Avoid `const { render } = require('flipper-test-utils');` if the package primarily uses ESM named exports.","cause":"This usually indicates an issue with CommonJS (`require`) trying to import an ESM-style named export, or incorrect named vs. default import.","error":"TypeError: (0 , _flipper_test_utils.render) is not a function"},{"fix":"Wrap the code that causes state updates or re-renders (including the initial `render` call, user interactions, or awaiting async operations) within `await act(async () => { /* ... */ });`.","cause":"A React component updated its state or props, causing a re-render outside of React's `act()` utility in your test. This can lead to unpredictable test behavior.","error":"Warning: An update to TestComponent inside a test was not wrapped in act(...)."}],"ecosystem":"npm","meta_description":null}