Initial commit
This commit is contained in:
364
hooks/__tests__/useDashboard.test.tsx
Normal file
364
hooks/__tests__/useDashboard.test.tsx
Normal file
@@ -0,0 +1,364 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react'
|
||||
import { useDashboard } from '../useDashboard'
|
||||
import { clientService, chantierService, devisService, factureService } from '../../services/api'
|
||||
|
||||
// Mock des services
|
||||
jest.mock('../../services/api')
|
||||
|
||||
const mockClientService = clientService as jest.Mocked<typeof clientService>
|
||||
const mockChantierService = chantierService as jest.Mocked<typeof chantierService>
|
||||
const mockDevisService = devisService as jest.Mocked<typeof devisService>
|
||||
const mockFactureService = factureService as jest.Mocked<typeof factureService>
|
||||
|
||||
const mockClients = [
|
||||
{ id: '1', nom: 'Client', prenom: 'Un', email: 'client1@test.com' },
|
||||
{ id: '2', nom: 'Client', prenom: 'Deux', email: 'client2@test.com' },
|
||||
]
|
||||
|
||||
const mockChantiers = [
|
||||
{
|
||||
id: '1',
|
||||
nom: 'Chantier 1',
|
||||
client: mockClients[0],
|
||||
statut: 'EN_COURS',
|
||||
dateDebut: '2024-01-01',
|
||||
montantPrevu: 10000,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
nom: 'Chantier 2',
|
||||
client: mockClients[1],
|
||||
statut: 'PLANIFIE',
|
||||
dateDebut: '2024-01-15',
|
||||
montantPrevu: 15000,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
nom: 'Chantier 3',
|
||||
client: mockClients[0],
|
||||
statut: 'TERMINE',
|
||||
dateDebut: '2024-01-10',
|
||||
montantPrevu: 8000,
|
||||
},
|
||||
]
|
||||
|
||||
const mockDevis = [
|
||||
{
|
||||
id: '1',
|
||||
numero: 'D2024-001',
|
||||
client: mockClients[0],
|
||||
statut: 'ENVOYE',
|
||||
dateEmission: '2024-01-01',
|
||||
dateValidite: '2024-12-31',
|
||||
montantTTC: 5000,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
numero: 'D2024-002',
|
||||
client: mockClients[1],
|
||||
statut: 'ACCEPTE',
|
||||
dateEmission: '2024-01-05',
|
||||
dateValidite: '2024-12-31',
|
||||
montantTTC: 7000,
|
||||
},
|
||||
]
|
||||
|
||||
const mockFactures = [
|
||||
{
|
||||
id: '1',
|
||||
numero: 'F2024-001',
|
||||
client: mockClients[0],
|
||||
statut: 'PAYEE',
|
||||
dateEmission: '2024-01-01',
|
||||
dateEcheance: '2024-01-31',
|
||||
montantTTC: 10000,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
numero: 'F2024-002',
|
||||
client: mockClients[1],
|
||||
statut: 'ENVOYEE',
|
||||
dateEmission: '2024-01-10',
|
||||
dateEcheance: '2024-01-01', // En retard
|
||||
montantTTC: 5000,
|
||||
},
|
||||
]
|
||||
|
||||
describe('Hook useDashboard', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
jest.spyOn(console, 'log').mockImplementation(() => {})
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('devrait initialiser avec les valeurs par défaut', () => {
|
||||
mockClientService.getAll.mockImplementation(() => new Promise(() => {}))
|
||||
mockChantierService.getAll.mockImplementation(() => new Promise(() => {}))
|
||||
mockDevisService.getAll.mockImplementation(() => new Promise(() => {}))
|
||||
mockFactureService.getAll.mockImplementation(() => new Promise(() => {}))
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
expect(result.current.stats).toBeNull()
|
||||
expect(result.current.chantiersRecents).toEqual([])
|
||||
expect(result.current.facturesEnRetard).toEqual([])
|
||||
expect(result.current.devisEnAttente).toEqual([])
|
||||
expect(result.current.loading).toBe(true)
|
||||
expect(result.current.error).toBeNull()
|
||||
})
|
||||
|
||||
it('devrait charger les données avec succès', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue(mockChantiers)
|
||||
mockDevisService.getAll.mockResolvedValue(mockDevis)
|
||||
mockFactureService.getAll.mockResolvedValue(mockFactures)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.stats).toEqual({
|
||||
totalClients: 2,
|
||||
totalChantiers: 3,
|
||||
chantiersEnCours: 1,
|
||||
chantiersPlanifies: 1,
|
||||
chantiersTermines: 1,
|
||||
totalDevis: 2,
|
||||
devisAcceptes: 1,
|
||||
devisEnAttente: 1,
|
||||
totalFactures: 2,
|
||||
facturesPayees: 1,
|
||||
facturesEnRetard: 1,
|
||||
chiffreAffaires: 10000,
|
||||
chiffreAffairesMois: expect.any(Number),
|
||||
chiffreAffairesAnnee: expect.any(Number),
|
||||
})
|
||||
})
|
||||
|
||||
it('devrait calculer les chantiers récents', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue(mockChantiers)
|
||||
mockDevisService.getAll.mockResolvedValue(mockDevis)
|
||||
mockFactureService.getAll.mockResolvedValue(mockFactures)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.chantiersRecents).toHaveLength(3)
|
||||
expect(result.current.chantiersRecents[0]).toEqual({
|
||||
id: '2',
|
||||
nom: 'Chantier 2',
|
||||
client: 'Client Deux',
|
||||
statut: 'PLANIFIE',
|
||||
dateDebut: '2024-01-15',
|
||||
montantPrevu: 15000,
|
||||
})
|
||||
})
|
||||
|
||||
it('devrait calculer les factures en retard', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue(mockChantiers)
|
||||
mockDevisService.getAll.mockResolvedValue(mockDevis)
|
||||
mockFactureService.getAll.mockResolvedValue(mockFactures)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.facturesEnRetard).toHaveLength(1)
|
||||
expect(result.current.facturesEnRetard[0]).toEqual({
|
||||
id: '2',
|
||||
numero: 'F2024-002',
|
||||
client: 'Client Deux',
|
||||
montantTTC: 5000,
|
||||
dateEcheance: '2024-01-01',
|
||||
joursRetard: expect.any(Number),
|
||||
})
|
||||
})
|
||||
|
||||
it('devrait calculer les devis en attente', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue(mockChantiers)
|
||||
mockDevisService.getAll.mockResolvedValue(mockDevis)
|
||||
mockFactureService.getAll.mockResolvedValue(mockFactures)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.devisEnAttente).toHaveLength(1)
|
||||
expect(result.current.devisEnAttente[0]).toEqual({
|
||||
id: '1',
|
||||
numero: 'D2024-001',
|
||||
client: 'Client Un',
|
||||
montantTTC: 5000,
|
||||
dateEmission: '2024-01-01',
|
||||
dateValidite: '2024-12-31',
|
||||
joursRestants: expect.any(Number),
|
||||
})
|
||||
})
|
||||
|
||||
it('devrait gérer les erreurs partielles', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockRejectedValue(new Error('Erreur chantiers'))
|
||||
mockDevisService.getAll.mockResolvedValue(mockDevis)
|
||||
mockFactureService.getAll.mockResolvedValue(mockFactures)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.error).toBeNull()
|
||||
expect(result.current.stats?.totalClients).toBe(2)
|
||||
expect(result.current.stats?.totalChantiers).toBe(0)
|
||||
expect(result.current.chantiersRecents).toEqual([])
|
||||
})
|
||||
|
||||
it('devrait gérer les erreurs complètes', async () => {
|
||||
mockClientService.getAll.mockRejectedValue(new Error('Erreur clients'))
|
||||
mockChantierService.getAll.mockRejectedValue(new Error('Erreur chantiers'))
|
||||
mockDevisService.getAll.mockRejectedValue(new Error('Erreur devis'))
|
||||
mockFactureService.getAll.mockRejectedValue(new Error('Erreur factures'))
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.error).toBeNull()
|
||||
expect(result.current.stats?.totalClients).toBe(0)
|
||||
expect(result.current.stats?.totalChantiers).toBe(0)
|
||||
expect(result.current.chantiersRecents).toEqual([])
|
||||
})
|
||||
|
||||
it('devrait permettre de rafraîchir les données', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue(mockChantiers)
|
||||
mockDevisService.getAll.mockResolvedValue(mockDevis)
|
||||
mockFactureService.getAll.mockResolvedValue(mockFactures)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(mockClientService.getAll).toHaveBeenCalledTimes(1)
|
||||
|
||||
// Rafraîchir
|
||||
result.current.refresh()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockClientService.getAll).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
|
||||
it('devrait gérer les données non-array', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(null as any)
|
||||
mockChantierService.getAll.mockResolvedValue(undefined as any)
|
||||
mockDevisService.getAll.mockResolvedValue({} as any)
|
||||
mockFactureService.getAll.mockResolvedValue('invalid' as any)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.stats?.totalClients).toBe(0)
|
||||
expect(result.current.stats?.totalChantiers).toBe(0)
|
||||
expect(result.current.stats?.totalDevis).toBe(0)
|
||||
expect(result.current.stats?.totalFactures).toBe(0)
|
||||
})
|
||||
|
||||
it('devrait calculer correctement le chiffre d\'affaires mensuel', async () => {
|
||||
const today = new Date()
|
||||
const thisMonth = today.getMonth()
|
||||
const thisYear = today.getFullYear()
|
||||
|
||||
const facturesThisMonth = [
|
||||
{
|
||||
id: '1',
|
||||
numero: 'F2024-001',
|
||||
client: mockClients[0],
|
||||
statut: 'PAYEE',
|
||||
dateEmission: new Date(thisYear, thisMonth, 1).toISOString(),
|
||||
dateEcheance: new Date(thisYear, thisMonth, 31).toISOString(),
|
||||
montantTTC: 10000,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
numero: 'F2024-002',
|
||||
client: mockClients[1],
|
||||
statut: 'PAYEE',
|
||||
dateEmission: new Date(thisYear, thisMonth - 1, 1).toISOString(), // Mois précédent
|
||||
dateEcheance: new Date(thisYear, thisMonth - 1, 31).toISOString(),
|
||||
montantTTC: 5000,
|
||||
},
|
||||
]
|
||||
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue([])
|
||||
mockDevisService.getAll.mockResolvedValue([])
|
||||
mockFactureService.getAll.mockResolvedValue(facturesThisMonth)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.stats?.chiffreAffairesMois).toBe(10000)
|
||||
})
|
||||
|
||||
it('devrait limiter les chantiers récents à 5', async () => {
|
||||
const manyChantiers = Array.from({ length: 10 }, (_, i) => ({
|
||||
id: `${i + 1}`,
|
||||
nom: `Chantier ${i + 1}`,
|
||||
client: mockClients[0],
|
||||
statut: 'EN_COURS',
|
||||
dateDebut: new Date(2024, 0, i + 1).toISOString(),
|
||||
montantPrevu: 10000,
|
||||
}))
|
||||
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue(manyChantiers)
|
||||
mockDevisService.getAll.mockResolvedValue([])
|
||||
mockFactureService.getAll.mockResolvedValue([])
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false)
|
||||
})
|
||||
|
||||
expect(result.current.chantiersRecents).toHaveLength(5)
|
||||
})
|
||||
|
||||
it('devrait fournir un alias isLoading', async () => {
|
||||
mockClientService.getAll.mockResolvedValue(mockClients)
|
||||
mockChantierService.getAll.mockResolvedValue(mockChantiers)
|
||||
mockDevisService.getAll.mockResolvedValue(mockDevis)
|
||||
mockFactureService.getAll.mockResolvedValue(mockFactures)
|
||||
|
||||
const { result } = renderHook(() => useDashboard())
|
||||
|
||||
expect(result.current.isLoading).toBe(result.current.loading)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user