import React, { type ReactElement } from 'react';
import { render, type RenderOptions } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { I18nextProvider } from 'react-i18next';
import i18n from '../i18n'; // Adjust path to your i18n config
/**
* Test conventions — distilled from the SmartStack.app corpus (see the
* `/test-conventions` skill, references/frontend-vitest.md). Apply them in every
* `*.test.tsx`:
*
* • `vi.mock(...)` is HOISTED — declare each mock ABOVE the import of the module
* it mocks (the page/hook under test), never after.
* • For unit component/hook tests, MOCK `react-i18next`
* (`useTranslation: () => ({ t: (k) => k, i18n: {…} })`) instead of relying on
* a real instance — avoids the NO_I18NEXT_INSTANCE warning and lets assertions
* match on the i18n key. (The provider below is for integration-style page tests.)
* • Testing Library queries: `getByRole` / `findByRole` / `queryByTestId`.
* • Router: `MemoryRouter` with `initialEntries` — never `BrowserRouter`.
* • Random ids: `crypto.randomUUID()` — never a hardcoded literal.
* • API is mocked with MSW (see `msw/handlers.ts` + `server.use(...)` per test) —
* this harness keeps the MSW approach rather than mocking the api client.
*/
/**
* AuthContext mock for tests.
* Provides a default authenticated user with admin permissions.
*/
const mockAuthContext = {
user: {
id: 'test-user-id',
email: 'test-admin@smartstack.io',
name: 'Test Admin',
role: 'Administrator',
},
isAuthenticated: true,
isLoading: false,
login: async () => {},
logout: async () => {},
hasPermission: () => true,
refreshPermissions: async () => {},
};
/**
* Wraps components with all necessary providers for testing.
* Includes: MemoryRouter, React Query, i18n.
*/
function AllProviders({ children }: { children: React.ReactNode }) {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false, staleTime: Infinity } },
});
return (
{children}
);
}
/**
* Custom render function that wraps components with test providers.
* Use this instead of @testing-library/react's render.
*
* @example
* import { renderWithProviders, screen } from '@/test/test-utils';
* renderWithProviders();
* expect(screen.getByText('Hello')).toBeInTheDocument();
*/
function renderWithProviders(
ui: ReactElement,
options?: Omit
) {
return render(ui, { wrapper: AllProviders, ...options });
}
// Re-export everything from testing-library
export * from '@testing-library/react';
export { renderWithProviders };
export { mockAuthContext };