211 lines
6.4 KiB
TypeScript
211 lines
6.4 KiB
TypeScript
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
import AuthLogin from './AuthLogin';
|
|
import { useAuth } from '../hooks/useAuth';
|
|
|
|
// Mock do hook useAuth
|
|
jest.mock('../hooks/useAuth');
|
|
|
|
const createWrapper = () => {
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: { retry: false },
|
|
mutations: { retry: false },
|
|
},
|
|
});
|
|
|
|
return ({ children }: { children: React.ReactNode }) => (
|
|
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
);
|
|
};
|
|
|
|
describe('AuthLogin Component', () => {
|
|
const mockLoginMutation = {
|
|
mutate: jest.fn(),
|
|
isPending: false,
|
|
isError: false,
|
|
isSuccess: false,
|
|
error: null,
|
|
};
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
(useAuth as jest.Mock).mockReturnValue({
|
|
loginMutation: mockLoginMutation,
|
|
});
|
|
});
|
|
|
|
describe('Renderização', () => {
|
|
it('deve renderizar formulário de login', () => {
|
|
render(<AuthLogin title="Login" />, { wrapper: createWrapper() });
|
|
|
|
expect(screen.getByLabelText(/usuário/i)).toBeInTheDocument();
|
|
expect(screen.getByLabelText(/senha/i)).toBeInTheDocument();
|
|
expect(
|
|
screen.getByRole('button', { name: /sign in/i })
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
it('deve renderizar título quando fornecido', () => {
|
|
render(<AuthLogin title="Bem-vindo" />, { wrapper: createWrapper() });
|
|
expect(screen.getByText('Bem-vindo')).toBeInTheDocument();
|
|
});
|
|
|
|
it('deve renderizar checkbox "Manter-me conectado"', () => {
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
expect(screen.getByText(/manter-me conectado/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('deve renderizar link "Esqueceu sua senha"', () => {
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
const link = screen.getByText(/esqueceu sua senha/i);
|
|
expect(link).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Validação', () => {
|
|
it('deve validar campos obrigatórios', async () => {
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
const submitButton = screen.getByRole('button', { name: /sign in/i });
|
|
fireEvent.click(submitButton);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/usuário é obrigatório/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('deve validar senha mínima', async () => {
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
const usernameInput = screen.getByLabelText(/usuário/i);
|
|
const passwordInput = screen.getByLabelText(/senha/i);
|
|
const submitButton = screen.getByRole('button', { name: /sign in/i });
|
|
|
|
fireEvent.change(usernameInput, { target: { value: 'testuser' } });
|
|
fireEvent.change(passwordInput, { target: { value: '123' } });
|
|
fireEvent.click(submitButton);
|
|
|
|
await waitFor(() => {
|
|
expect(
|
|
screen.getByText(/senha deve ter no mínimo 4 caracteres/i)
|
|
).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Submissão', () => {
|
|
it('deve submeter formulário com credenciais válidas', async () => {
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
const usernameInput = screen.getByLabelText(/usuário/i);
|
|
const passwordInput = screen.getByLabelText(/senha/i);
|
|
const submitButton = screen.getByRole('button', { name: /sign in/i });
|
|
|
|
fireEvent.change(usernameInput, { target: { value: 'testuser' } });
|
|
fireEvent.change(passwordInput, { target: { value: 'password123' } });
|
|
fireEvent.click(submitButton);
|
|
|
|
await waitFor(() => {
|
|
expect(mockLoginMutation.mutate).toHaveBeenCalledWith({
|
|
username: 'testuser',
|
|
password: 'password123',
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Estados de Loading e Erro', () => {
|
|
it('deve desabilitar botão durante loading', () => {
|
|
const loadingMutation = {
|
|
...mockLoginMutation,
|
|
isPending: true,
|
|
};
|
|
|
|
(useAuth as jest.Mock).mockReturnValue({
|
|
loginMutation: loadingMutation,
|
|
});
|
|
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
const submitButton = screen.getByRole('button', { name: /logging in/i });
|
|
expect(submitButton).toBeDisabled();
|
|
});
|
|
|
|
it('deve mostrar mensagem de erro quando login falha', () => {
|
|
const errorMutation = {
|
|
...mockLoginMutation,
|
|
isError: true,
|
|
error: {
|
|
response: {
|
|
data: { message: 'Credenciais inválidas' },
|
|
},
|
|
},
|
|
};
|
|
|
|
(useAuth as jest.Mock).mockReturnValue({
|
|
loginMutation: errorMutation,
|
|
});
|
|
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
expect(screen.getByText(/credenciais inválidas/i)).toBeInTheDocument();
|
|
});
|
|
|
|
// 🐛 TESTE QUE REVELA BUG: Erro não limpa durante nova tentativa
|
|
it('🐛 BUG: deve esconder erro durante nova tentativa de login', () => {
|
|
const errorAndLoadingMutation = {
|
|
...mockLoginMutation,
|
|
isError: true,
|
|
isPending: true, // Está tentando novamente
|
|
error: {
|
|
response: {
|
|
data: { message: 'Credenciais inválidas' },
|
|
},
|
|
},
|
|
};
|
|
|
|
(useAuth as jest.Mock).mockReturnValue({
|
|
loginMutation: errorAndLoadingMutation,
|
|
});
|
|
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
// ❌ ESTE TESTE VAI FALHAR - erro ainda aparece durante loading!
|
|
expect(
|
|
screen.queryByText(/credenciais inválidas/i)
|
|
).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('🐛 Bugs Identificados', () => {
|
|
// 🐛 BUG: Link "Esqueceu senha" vai para home
|
|
it('🐛 BUG: link "Esqueceu senha" deve ir para /forgot-password', () => {
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
const link = screen.getByText(/esqueceu sua senha/i).closest('a');
|
|
|
|
// ❌ ESTE TESTE VAI FALHAR - href é "/"
|
|
expect(link).toHaveAttribute('href', '/forgot-password');
|
|
});
|
|
|
|
// 🐛 BUG: Checkbox não funciona
|
|
it('🐛 BUG: checkbox "Manter-me conectado" deve ser controlado', () => {
|
|
render(<AuthLogin />, { wrapper: createWrapper() });
|
|
|
|
const checkbox = screen.getByRole('checkbox', {
|
|
name: /manter-me conectado/i,
|
|
});
|
|
|
|
// Checkbox está sempre marcado
|
|
expect(checkbox).toBeChecked();
|
|
|
|
// Tenta desmarcar
|
|
fireEvent.click(checkbox);
|
|
|
|
// ❌ ESTE TESTE VAI FALHAR - checkbox não muda de estado!
|
|
expect(checkbox).not.toBeChecked();
|
|
});
|
|
});
|
|
});
|