lightsoutAlpha

mocking-component-dependencies

a mocked hook, store or child component that hides coverage instead of a boundary

Agent checkadvisory by defaultreacttests

The argument

Mocking Component Dependencies

Hooks mock like utility functions — and the wrapper must forward parameters with matching types when the hook takes any (see Mock Typing Rules):

const mockUseProjects = jest.fn<(params: { workspaceId: number }) => { data: Project[] }>();

jest.mock('@/features/projects/hooks/useProjects', () => ({
	useProjects: (params: { workspaceId: number }) => mockUseProjects(params),
}));

Zustand-style stores: mockUseAppStore.mockReturnValue(value) works only when the component calls the store once. When it reads multiple slices, run the real selectors against a mock state instead:

const setupFeaturePanel = ({ isActive = true, label = 'Panel' }: { isActive?: boolean; label?: string } = {}) => {
	mockUseAppStore.mockImplementation((selector) => selector({ isActive, label }));
	render(<FeaturePanel />);
};

Child components: mock a child only if it is itself a boundary (its own module, or imported from another feature). Render real internal children (under this module's own common/) so they are covered through this boundary's tests — mocking an internal child leaves it with no coverage at all. When you do mock a boundary child, keep it minimal: just enough to verify props and conditional rendering.

The proof

failsrc/projects/ProjectPanel.unit.test.tsx
import { expect, describe, test, jest } from '@jest/globals';
import { render, screen } from '@testing-library/react';
import { ProjectPanel } from './ProjectPanel';

// An internal child under this module's own common/ — mocking it leaves it
// with no coverage at all, and the wrapper drops the props it is handed.
jest.mock('./common/components/ProjectRow', () => ({
	ProjectRow: () => <div />,
}));

const setupProjectPanel = () => {
	render(<ProjectPanel workspaceId={1} />);
};

describe('ProjectPanel', () => {
	test('lists the projects the hook returned', () => {
		setupProjectPanel();

		const panel = screen.getByRole('list');

		expect(panel).toBeInTheDocument();
	});
});
passsrc/projects/ProjectPanel.unit.test.tsx
import { expect, describe, test, jest } from '@jest/globals';
import { render, screen } from '@testing-library/react';
import { ProjectPanel } from './ProjectPanel';

// Mocked Imports
// -------------------------
const mockUseProjects = jest.fn<(params: { workspaceId: number }) => { data: Array<{ name: string }> }>();

jest.mock('@/features/projects/hooks/useProjects', () => ({
	useProjects: (params: { workspaceId: number }) => mockUseProjects(params),
}));
// -------------------------

const setupProjectPanel = ({ names = ['Apollo'] }: { names?: string[] } = {}) => {
	mockUseProjects.mockReturnValue({ data: names.map((name) => ({ name })) });
	render(<ProjectPanel workspaceId={1} />);
};

describe('ProjectPanel', () => {
	test('lists the projects the hook returned', () => {
		setupProjectPanel({ names: ['Apollo'] });

		const project = screen.getByText('Apollo');

		expect(project).toBeInTheDocument();
	});
});

Turn it down

Both lines go in your lightsout.config.json.

"standards-checks": { "mocking-component-dependencies": "advisory" }
"standards-checks": { "mocking-component-dependencies": "off" }