import { SignInForm } from '@/components/auth/SignInForm'; import { API_BASE } from '@/lib/api'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { beforeEach, describe, expect, it, vi } from 'vitest'; let searchParams = new URLSearchParams(); let pathname = '/en/light/sign-in'; vi.mock('next/navigation', () => ({ usePathname: () => pathname, useSearchParams: () => searchParams, })); vi.mock('next/image', () => ({ default: ({ priority, unoptimized, ...props }: any) => , })); function jsonResponse(status: number, body: unknown) { return { ok: status >= 200 && status < 300, status, json: vi.fn().mockResolvedValue(body), } as unknown as Response; } async function submitForm() { const user = userEvent.setup(); await user.type(screen.getByLabelText(/Email/), 'owner@example.com'); await user.type(screen.getByLabelText(/Password/), 'password123'); await user.click(screen.getByRole('button', { name: 'Sign in' })); } describe('SignInForm auth routing', () => { beforeEach(() => { searchParams = new URLSearchParams(); pathname = '/en/light/sign-in'; vi.stubGlobal('fetch', vi.fn().mockResolvedValue( jsonResponse(401, { error: 'invalid_credentials' }), )); }); it('uses employee login only on the default sign-in page', async () => { vi.mocked(fetch).mockResolvedValueOnce( jsonResponse(200, { data: { employee: { id: 'employee_1' } } }), ); render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1)); expect(fetch).toHaveBeenCalledWith( `${API_BASE}/auth/employee/login`, expect.objectContaining({ method: 'POST' }), ); expect(fetch).not.toHaveBeenCalledWith( `${API_BASE}/admin/auth/login`, expect.anything(), ); }); it('falls back to admin login when default employee login rejects the credentials', async () => { vi.mocked(fetch) .mockResolvedValueOnce(jsonResponse(401, { error: 'invalid_credentials' })) .mockResolvedValueOnce(jsonResponse(401, { error: 'totp_required' })); render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(2)); expect(fetch).toHaveBeenNthCalledWith( 1, `${API_BASE}/auth/employee/login`, expect.objectContaining({ method: 'POST' }), ); expect(fetch).toHaveBeenNthCalledWith( 2, `${API_BASE}/admin/auth/login`, expect.objectContaining({ method: 'POST' }), ); expect(await screen.findByText('Authentication code')).toBeInTheDocument(); }); it('uses employee login only when the requested destination is a dashboard path', async () => { vi.mocked(fetch).mockResolvedValueOnce( jsonResponse(200, { data: { employee: { id: 'employee_1' } } }), ); searchParams = new URLSearchParams('redirect=/dashboard/billing'); render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1)); expect(fetch).toHaveBeenCalledWith( `${API_BASE}/auth/employee/login`, expect.objectContaining({ method: 'POST' }), ); expect(fetch).not.toHaveBeenCalledWith( `${API_BASE}/admin/auth/login`, expect.anything(), ); }); it('uses admin login only when the admin portal is requested', async () => { searchParams = new URLSearchParams('portal=admin'); render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1)); expect(fetch).toHaveBeenCalledWith( `${API_BASE}/admin/auth/login`, expect.objectContaining({ method: 'POST' }), ); expect(fetch).not.toHaveBeenCalledWith( `${API_BASE}/auth/employee/login`, expect.anything(), ); }); it('uses admin login when the requested destination is an admin path', async () => { searchParams = new URLSearchParams('next=/admin/dashboard'); render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1)); expect(fetch).toHaveBeenCalledWith( `${API_BASE}/admin/auth/login`, expect.objectContaining({ method: 'POST' }), ); }); it('uses admin login when the requested destination is an absolute admin URL', async () => { searchParams = new URLSearchParams('redirect=http://localhost:3000/admin/dashboard'); render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1)); expect(fetch).toHaveBeenCalledWith( `${API_BASE}/admin/auth/login`, expect.objectContaining({ method: 'POST' }), ); expect(fetch).not.toHaveBeenCalledWith( `${API_BASE}/auth/employee/login`, expect.anything(), ); }); it('uses admin login when the page forces admin auth mode', async () => { render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1)); expect(fetch).toHaveBeenCalledWith( `${API_BASE}/admin/auth/login`, expect.objectContaining({ method: 'POST' }), ); expect(fetch).not.toHaveBeenCalledWith( `${API_BASE}/auth/employee/login`, expect.anything(), ); }); it('uses admin login on the admin sign-in path', async () => { pathname = '/en/light/admin-sign-in'; render(); await submitForm(); await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1)); expect(fetch).toHaveBeenCalledWith( `${API_BASE}/admin/auth/login`, expect.objectContaining({ method: 'POST' }), ); expect(fetch).not.toHaveBeenCalledWith( `${API_BASE}/auth/employee/login`, expect.anything(), ); }); });