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 }) => (
{children}
);
};
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(, { 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(, { wrapper: createWrapper() });
expect(screen.getByText('Bem-vindo')).toBeInTheDocument();
});
it('deve renderizar checkbox "Manter-me conectado"', () => {
render(, { wrapper: createWrapper() });
expect(screen.getByText(/manter-me conectado/i)).toBeInTheDocument();
});
it('deve renderizar link "Esqueceu sua senha"', () => {
render(, { wrapper: createWrapper() });
const link = screen.getByText(/esqueceu sua senha/i);
expect(link).toBeInTheDocument();
});
});
describe('Validação', () => {
it('deve validar campos obrigatórios', async () => {
render(, { 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(, { 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(, { 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(, { 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(, { 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(, { 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(, { 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(, { 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();
});
});
});