7e7a76633e
Build & Push / Pipeline Tests (push) Successful in 1m57s
Test / Type Check (all packages) (push) Successful in 54s
Build & Push / Build & Push Docker Image (push) Successful in 3m30s
Test / API Unit Tests (push) Successful in 1m19s
Test / Homepage Unit Tests (push) Successful in 48s
Test / Carplace Unit Tests (push) Successful in 42s
Test / Admin Unit Tests (push) Successful in 41s
Test / Dashboard Unit Tests (push) Successful in 42s
Test / API Integration Tests (push) Successful in 1m10s
180 lines
5.5 KiB
TypeScript
180 lines
5.5 KiB
TypeScript
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) => <img {...props} />,
|
|
}));
|
|
|
|
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 unified login on the default sign-in page', async () => {
|
|
vi.mocked(fetch).mockResolvedValueOnce(
|
|
jsonResponse(200, { data: { employee: { id: 'employee_1' } } }),
|
|
);
|
|
render(<SignInForm locale="en" />);
|
|
|
|
await submitForm();
|
|
|
|
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
|
|
expect(fetch).toHaveBeenCalledWith(
|
|
`${API_BASE}/auth/login`,
|
|
expect.objectContaining({ method: 'POST' }),
|
|
);
|
|
expect(fetch).not.toHaveBeenCalledWith(
|
|
`${API_BASE}/admin/auth/login`,
|
|
expect.anything(),
|
|
);
|
|
});
|
|
|
|
it('shows invalid credentials when unified login rejects the credentials', async () => {
|
|
render(<SignInForm locale="en" />);
|
|
|
|
await submitForm();
|
|
|
|
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
|
|
expect(fetch).toHaveBeenNthCalledWith(
|
|
1,
|
|
`${API_BASE}/auth/login`,
|
|
expect.objectContaining({ method: 'POST' }),
|
|
);
|
|
expect(fetch).not.toHaveBeenCalledWith(
|
|
`${API_BASE}/admin/auth/login`,
|
|
expect.anything(),
|
|
);
|
|
expect(await screen.findByText('Invalid email or password.')).toBeInTheDocument();
|
|
});
|
|
|
|
it('uses unified login 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(<SignInForm locale="en" />);
|
|
|
|
await submitForm();
|
|
|
|
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
|
|
expect(fetch).toHaveBeenCalledWith(
|
|
`${API_BASE}/auth/login`,
|
|
expect.objectContaining({ method: 'POST' }),
|
|
);
|
|
expect(fetch).not.toHaveBeenCalledWith(
|
|
`${API_BASE}/admin/auth/login`,
|
|
expect.anything(),
|
|
);
|
|
});
|
|
|
|
it('uses unified login when the admin portal is requested', async () => {
|
|
searchParams = new URLSearchParams('portal=admin');
|
|
render(<SignInForm locale="en" />);
|
|
|
|
await submitForm();
|
|
|
|
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
|
|
expect(fetch).toHaveBeenCalledWith(
|
|
`${API_BASE}/auth/login`,
|
|
expect.objectContaining({ method: 'POST' }),
|
|
);
|
|
expect(fetch).not.toHaveBeenCalledWith(
|
|
`${API_BASE}/auth/employee/login`,
|
|
expect.anything(),
|
|
);
|
|
});
|
|
|
|
it('uses unified login when the requested destination is an admin path', async () => {
|
|
searchParams = new URLSearchParams('next=/admin/dashboard');
|
|
render(<SignInForm locale="en" />);
|
|
|
|
await submitForm();
|
|
|
|
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
|
|
expect(fetch).toHaveBeenCalledWith(
|
|
`${API_BASE}/auth/login`,
|
|
expect.objectContaining({ method: 'POST' }),
|
|
);
|
|
});
|
|
|
|
it('uses unified login when the requested destination is an absolute admin URL', async () => {
|
|
searchParams = new URLSearchParams('redirect=http://localhost:3000/admin/dashboard');
|
|
render(<SignInForm locale="en" />);
|
|
|
|
await submitForm();
|
|
|
|
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
|
|
expect(fetch).toHaveBeenCalledWith(
|
|
`${API_BASE}/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(<SignInForm locale="en" authMode="admin" />);
|
|
|
|
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 unified login on the admin sign-in path', async () => {
|
|
pathname = '/en/light/admin-sign-in';
|
|
render(<SignInForm locale="en" />);
|
|
|
|
await submitForm();
|
|
|
|
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
|
|
expect(fetch).toHaveBeenCalledWith(
|
|
`${API_BASE}/auth/login`,
|
|
expect.objectContaining({ method: 'POST' }),
|
|
);
|
|
expect(fetch).not.toHaveBeenCalledWith(
|
|
`${API_BASE}/auth/employee/login`,
|
|
expect.anything(),
|
|
);
|
|
});
|
|
});
|