import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
import {render, waitFor} from '@testing-library/react';
import {type ReactNode, StrictMode} from 'react';
import {beforeEach, describe, expect, it, vi} from 'vitest';
import {GitHubOAuthCallback} from '@/features/auth/components/github-oauth-callback';
const replaceMock = vi.fn();
const setUserMock = vi.fn();
const exchangeGitHubCodeMock = vi.fn();
vi.mock('next/navigation', () => ({
useRouter: () => ({
replace: replaceMock,
}),
useSearchParams: () => new URLSearchParams('code=github-code-123'),
}));
vi.mock('@/components/providers/auth-provider', () => ({
useAuth: () => ({
setUser: setUserMock,
}),
}));
vi.mock('@/features/auth/api/auth', () => ({
exchangeGitHubCode: (code: string) => exchangeGitHubCodeMock(code),
}));
function createQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
mutations: {
retry: false,
},
},
});
}
function renderWithProviders(ui: ReactNode) {
const queryClient = createQueryClient();
return render(
{ui}
,
);
}
describe('GitHubOAuthCallback', () => {
beforeEach(() => {
replaceMock.mockReset();
setUserMock.mockReset();
exchangeGitHubCodeMock.mockReset();
exchangeGitHubCodeMock.mockResolvedValue({
id: 1,
username: 'github-user',
role: 1,
status: 1,
});
});
it('exchanges the same GitHub code only once', async () => {
const view = renderWithProviders();
await waitFor(() => {
expect(exchangeGitHubCodeMock).toHaveBeenCalledTimes(1);
});
view.rerender(
,
);
await waitFor(() => {
expect(replaceMock).toHaveBeenCalledWith('/');
});
expect(exchangeGitHubCodeMock).toHaveBeenCalledTimes(1);
expect(exchangeGitHubCodeMock).toHaveBeenCalledWith('github-code-123');
expect(setUserMock).toHaveBeenCalledTimes(1);
});
});