import { describe, it, expect, vi, beforeEach } from 'vitest'
import { screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import Inscription from '../../pages/Inscription'
import { renderWithProviders } from '../renderWithProviders'
import { registerApi, verifyCodeApi } from '../../services/auth'
vi.mock('../../services/auth', () => ({
registerApi: vi.fn(),
verifyCodeApi: vi.fn(),
}))
// Remplit et soumet le formulaire d'inscription (étape 1).
async function remplirEtSoumettre() {
await userEvent.type(screen.getByLabelText(/adresse email/i), 'jean@example.com')
await userEvent.type(screen.getByLabelText(/^nom/i), 'Dupont')
await userEvent.type(screen.getByLabelText(/prénom/i), 'Jean')
await userEvent.type(screen.getByLabelText(/^mot de passe/i), 'MotDePasse123!')
await userEvent.click(screen.getByRole('checkbox', { name: /conditions d'utilisation/i }))
await userEvent.click(screen.getByRole('button', { name: /s'inscrire/i }))
}
// Saisit le code à 4 chiffres de l'étape de vérification.
async function saisirCode(code) {
const inputs = screen.getAllByRole('textbox')
for (let i = 0; i < 4; i++) {
await userEvent.type(inputs[i], code[i])
}
}
describe('Inscription', () => {
beforeEach(() => {
vi.clearAllMocks()
})
it("affiche le formulaire d'inscription", () => {
renderWithProviders(, { route: '/inscription' })
expect(screen.getByRole('heading', { name: /s'inscrire/i })).toBeInTheDocument()
expect(screen.getByLabelText(/adresse email/i)).toBeInTheDocument()
expect(screen.getByLabelText(/^nom/i)).toBeInTheDocument()
expect(screen.getByLabelText(/prénom/i)).toBeInTheDocument()
expect(screen.getByLabelText(/^mot de passe/i)).toBeInTheDocument()
})
it("désactive le bouton tant que les conditions ne sont pas acceptées", async () => {
renderWithProviders(, { route: '/inscription' })
const bouton = screen.getByRole('button', { name: /s'inscrire/i })
expect(bouton).toBeDisabled()
await userEvent.click(screen.getByRole('checkbox', { name: /conditions d'utilisation/i }))
expect(bouton).toBeEnabled()
})
it("passe à l'étape de vérification après une inscription réussie", async () => {
registerApi.mockResolvedValue({ message: 'ok' })
renderWithProviders(, { route: '/inscription' })
await remplirEtSoumettre()
expect(registerApi).toHaveBeenCalledWith({
email: 'jean@example.com',
firstname: 'Jean',
lastname: 'Dupont',
password: 'MotDePasse123!',
birthdate: '',
gender: '',
marketingOptIn: false,
})
expect(await screen.findByRole('heading', { name: /vérifiez votre email/i })).toBeInTheDocument()
expect(screen.getByText('jean@example.com')).toBeInTheDocument()
})
it("transmet la date de naissance et le genre saisis", async () => {
registerApi.mockResolvedValue({ message: 'ok' })
renderWithProviders(, { route: '/inscription' })
await userEvent.type(screen.getByLabelText(/adresse email/i), 'jean@example.com')
await userEvent.type(screen.getByLabelText(/^nom/i), 'Dupont')
await userEvent.type(screen.getByLabelText(/prénom/i), 'Jean')
await userEvent.type(screen.getByLabelText(/date de naissance/i), '1990-05-14')
await userEvent.selectOptions(screen.getByLabelText(/genre/i), 'Femme')
await userEvent.type(screen.getByLabelText(/^mot de passe/i), 'MotDePasse123!')
await userEvent.click(screen.getByRole('checkbox', { name: /conditions d'utilisation/i }))
await userEvent.click(screen.getByRole('button', { name: /s'inscrire/i }))
expect(registerApi).toHaveBeenCalledWith(
expect.objectContaining({ birthdate: '1990-05-14', gender: 'Femme' })
)
})
it("transmet le consentement marketing quand il est coché", async () => {
registerApi.mockResolvedValue({ message: 'ok' })
renderWithProviders(, { route: '/inscription' })
const marketing = screen.getByRole('checkbox', { name: /offres et actualités/i })
expect(marketing).not.toBeChecked()
await userEvent.type(screen.getByLabelText(/adresse email/i), 'jean@example.com')
await userEvent.type(screen.getByLabelText(/^nom/i), 'Dupont')
await userEvent.type(screen.getByLabelText(/prénom/i), 'Jean')
await userEvent.type(screen.getByLabelText(/^mot de passe/i), 'MotDePasse123!')
await userEvent.click(marketing)
await userEvent.click(screen.getByRole('checkbox', { name: /conditions d'utilisation/i }))
await userEvent.click(screen.getByRole('button', { name: /s'inscrire/i }))
expect(registerApi).toHaveBeenCalledWith(
expect.objectContaining({ marketingOptIn: true })
)
})
it("n'exige pas le consentement marketing pour s'inscrire", async () => {
renderWithProviders(, { route: '/inscription' })
const bouton = screen.getByRole('button', { name: /s'inscrire/i })
await userEvent.click(screen.getByRole('checkbox', { name: /conditions d'utilisation/i }))
expect(screen.getByRole('checkbox', { name: /offres et actualités/i })).not.toBeChecked()
expect(bouton).toBeEnabled()
})
it("affiche l'erreur de l'API si l'inscription échoue", async () => {
registerApi.mockRejectedValue(new Error('Cet email est déjà utilisé.'))
renderWithProviders(, { route: '/inscription' })
await remplirEtSoumettre()
expect(await screen.findByText('Cet email est déjà utilisé.')).toBeInTheDocument()
expect(screen.queryByRole('heading', { name: /vérifiez votre email/i })).not.toBeInTheDocument()
})
it('connecte et redirige vers /saisir-code-unique quand le code est valide', async () => {
registerApi.mockResolvedValue({ message: 'ok' })
verifyCodeApi.mockResolvedValue({
token: 'jwt-token',
user: { id: 1, email: 'jean@example.com', role: 'CLIENT' },
})
renderWithProviders(, {
route: '/inscription',
routes: { '/saisir-code-unique':
Page Saisir Code
},
})
await remplirEtSoumettre()
await screen.findByRole('heading', { name: /vérifiez votre email/i })
await saisirCode('1234')
await userEvent.click(screen.getByRole('button', { name: /valider le code/i }))
expect(verifyCodeApi).toHaveBeenCalledWith({ email: 'jean@example.com', code: '1234' })
expect(await screen.findByText('Page Saisir Code')).toBeInTheDocument()
expect(localStorage.getItem('token')).toBe('jwt-token')
})
it("affiche l'erreur et vide les champs quand le code est invalide", async () => {
registerApi.mockResolvedValue({ message: 'ok' })
verifyCodeApi.mockRejectedValue(new Error('Code invalide.'))
renderWithProviders(, { route: '/inscription' })
await remplirEtSoumettre()
await screen.findByRole('heading', { name: /vérifiez votre email/i })
await saisirCode('0000')
await userEvent.click(screen.getByRole('button', { name: /valider le code/i }))
expect(await screen.findByText('Code invalide.')).toBeInTheDocument()
for (const input of screen.getAllByRole('textbox')) {
expect(input).toHaveValue('')
}
})
})