9ca9cb1d42
- Page /clients (route à plat) : MalioDataTable 6 colonnes (contact, téléphone formaté, codes catégories, badges sites), toggle « Voir les archivés » (état local), boutons Ajouter (manage) / Exporter (view, download xlsx), clic ligne vers le détail, empty state. - Composable useClientsRepository (wrapper de usePaginatedList) + util formatPhoneFR + clé i18n showArchived. - Contrat back : la liste client:read expose désormais les codes catégories (category:read) et les sites agrégés des adresses (site:read + Client::getSites) ; jointures anti N+1 dans createListQueryBuilder. Tests back + front.
80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import type { HydraCollection } from '~/shared/utils/api'
|
|
import type { Client } from '../useClientsRepository'
|
|
|
|
// `useApi` est un auto-import Nuxt : on le stubbe globalement pour intercepter
|
|
// les appels declenches par usePaginatedList (que useClientsRepository enveloppe)
|
|
// et controler les reponses. Meme pattern que useCategoriesAdmin.spec.ts.
|
|
const mockGet = vi.hoisted(() => vi.fn())
|
|
vi.stubGlobal('useApi', () => ({
|
|
get: mockGet,
|
|
post: vi.fn(),
|
|
put: vi.fn(),
|
|
patch: vi.fn(),
|
|
delete: vi.fn(),
|
|
}))
|
|
|
|
// Import APRES le stub pour que useApi soit bien resolu au top-level du module.
|
|
const { useClientsRepository } = await import('../useClientsRepository')
|
|
|
|
/** Envelope Hydra minimale (la liste reelle des membres importe peu ici). */
|
|
function makeHydra(total: number): HydraCollection<Client> {
|
|
return { totalItems: total, member: [] }
|
|
}
|
|
|
|
describe('useClientsRepository', () => {
|
|
beforeEach(() => {
|
|
mockGet.mockReset()
|
|
// 25 items → 3 pages a 10/page : permet de tester la navigation page 2.
|
|
mockGet.mockResolvedValue(makeHydra(25))
|
|
})
|
|
|
|
it('charge /clients sans includeArchived par defaut (clients actifs)', async () => {
|
|
const repo = useClientsRepository()
|
|
await repo.fetch()
|
|
|
|
expect(repo.includeArchived.value).toBe(false)
|
|
expect(mockGet).toHaveBeenLastCalledWith(
|
|
'/clients',
|
|
{ page: 1, itemsPerPage: 10 },
|
|
expect.objectContaining({ toast: false }),
|
|
)
|
|
})
|
|
|
|
it('pousse le filtre serveur includeArchived=true quand le toggle est actif', async () => {
|
|
const repo = useClientsRepository()
|
|
await repo.fetch()
|
|
await repo.setIncludeArchived(true)
|
|
|
|
expect(repo.includeArchived.value).toBe(true)
|
|
expect(mockGet).toHaveBeenLastCalledWith(
|
|
'/clients',
|
|
{ includeArchived: true, page: 1, itemsPerPage: 10 },
|
|
expect.objectContaining({ toast: false }),
|
|
)
|
|
})
|
|
|
|
it('retombe en page 1 lorsqu on bascule le toggle archives', async () => {
|
|
const repo = useClientsRepository()
|
|
await repo.fetch()
|
|
await repo.goToPage(2)
|
|
expect(repo.currentPage.value).toBe(2)
|
|
|
|
await repo.setIncludeArchived(true)
|
|
expect(repo.currentPage.value).toBe(1)
|
|
})
|
|
|
|
it('retire le filtre (query propre) quand le toggle repasse a false', async () => {
|
|
const repo = useClientsRepository()
|
|
await repo.setIncludeArchived(true)
|
|
await repo.setIncludeArchived(false)
|
|
|
|
expect(repo.includeArchived.value).toBe(false)
|
|
expect(mockGet).toHaveBeenLastCalledWith(
|
|
'/clients',
|
|
{ page: 1, itemsPerPage: 10 },
|
|
expect.objectContaining({ toast: false }),
|
|
)
|
|
})
|
|
})
|