# Jest tests hang or render nothing for components that call useContent

Asked by dani_h on 2025-08-06. Tags: nextjs, react, testing, jest.

I write tests first, so this is blocking me. I have a hero component that calls
`useContent('home-hero')`. In Jest with jsdom, `render(<Hero />)` produces an
empty container, and `findByRole` from testing-library times out waiting for
anything to appear.

I understand the hook fetches content, but I expected some kind of loading state
to render. Following the testing-library guidance of testing behavior over
implementation, I would rather not rewrite the component just to make it
testable. How do others isolate components from the SDK in unit tests?

## 2 answers

### Accepted answer from Yuki Tanaka (2025-08-06)

The empty render is expected once you know the mechanism: `useContent` relies
on React Suspense. While content resolves, the component suspends, and with no
`<Suspense>` boundary above it there is nothing to show, so jsdom renders
nothing and your async queries time out waiting for a fetch that never
completes offline.

For unit tests, mock the hook module and keep the component untouched:

```ts
jest.mock('@croct/plug-react', () => ({
    ...jest.requireActual('@croct/plug-react'),
    useContent: () => ({
        title: 'Test headline',
        cta: 'Sign up',
    }),
}));
```

Now the component renders synchronously with fixture content and you can assert
on behavior as usual.

If you prefer not to mock, wrap the render in the provider plus a Suspense
boundary and assert the fallback appears first, but that turns it into an
integration test with network concerns, which is rarely what you want in a
unit suite.

#### Reply from dani_h (2025-08-06)

The module mock did it, and it keeps the component API untouched, which is
what I wanted. Tests are green. Thanks!

### Answer from dario_f (2025-08-07)

Adding two options for completeness since teams draw the line differently:

1. Passing an `initial` or `fallback` value to `useContent` gives the component
   deterministic content to render without suspending forever, so some teams
   standardize on always providing one and asserting against it in tests.
2. For integration-style runs where you keep the real provider, the plug
   options include a test mode flag that swaps in a mock transport, so nothing
   hits the network but the real code paths execute.

Module mocks for unit tests, test mode for integration tests is the split that
has worked for us.
