All questions

Cleanest way to mock Croct hooks in Vitest so component tests stay offline

Asked by Ines Beltran on

IBInes Beltran

hi, trying to keep our component tests fully offline. Minimal repro:

// Hero.tsximport {useContent} from '@croct/plug-react';
export function Hero() {    const {title} = useContent('home-hero');
    return <h1>{title}</h1>;}

In jsdom the hook never resolves, so render(<Hero />) inside a Suspense boundary just sits on the fallback forever and findByText times out. What is the standard way people mock this in Vitest? I would rather not rewrite the component to take content as a prop just for tests.

Was this helpful?

2 answers

FOFelix OrtegaAccepted answer

For unit tests, mock the module. vi.mock makes useContent return fixture content synchronously, so the Suspense path never kicks in and the test is deterministic and offline:

import {render, screen} from '@testing-library/react';import {vi} from 'vitest';import {Hero} from './Hero';
vi.mock('@croct/plug-react', () => ({    useContent: () => ({title: 'Fixture title'}),}));
test('renders the hero title', () => {    render(<Hero />);
    expect(screen.getByText('Fixture title')).toBeInTheDocument();});

No provider, no Suspense boundary, no network. If different tests need different content, swap the factory for vi.fn() and set the return value per test.

This is the right altitude for component tests: you are testing your rendering logic, not the SDK's fetching behavior.

Was this helpful?
IBInes Beltran

perfect, the per-test vi.fn() variant is what we ended up with. all green and zero network calls, thanks!

Nnils_bergman

Adding the option for tests that keep the real provider (integration-style runs):

  1. Pass an initial or fallback value to useContent in the component. The hook then renders immediately with that value instead of suspending, which also makes jsdom happy.
  2. The plug options include a test mode flag (default false) that swaps in a mock transport, so even a mounted provider sends nothing over the wire.

We use module mocks for unit tests like Felix showed, and the test flag for the handful of tests that exercise the provider wiring itself. Both have their place.

Was this helpful?
Still have questions?