5722912413
- useSupplier(id) : GET /api/suppliers/{id} en Hydra (embed contacts/adresses/ribs
+ scalaires compta si accounting.view), archive()/restore() via PATCH isArchived seul
- supplierConsultation : mappers purs de l'embed (addressType, bennes, triageProvider,
volumeForecast ; gating compta par omission de cle), helpers de permissions
- page [id]/index.vue : lecture seule, bloc principal + onglets (Information/Contacts/
Adresses/Comptabilite selon permission/4 coquilles A venir), Modifier/Archiver/Restaurer,
fleche retour repertoire ; miroir de l'ecran Consultation client (M1)
- tests Vitest : supplierConsultation (mappers + permissions) + useSupplier (GET/PATCH)
96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
// Mocks des composables auto-importes par Nuxt (indisponibles sous happy-dom).
|
|
const mockGet = vi.hoisted(() => vi.fn())
|
|
const mockPatch = vi.hoisted(() => vi.fn())
|
|
|
|
vi.stubGlobal('useApi', () => ({
|
|
get: mockGet,
|
|
post: vi.fn(),
|
|
put: vi.fn(),
|
|
patch: mockPatch,
|
|
delete: vi.fn(),
|
|
}))
|
|
|
|
const { useSupplier } = await import('../useSupplier')
|
|
|
|
const SAMPLE = { '@id': '/api/suppliers/85', id: 85, companyName: 'DOD59393F 862875', isArchived: false }
|
|
|
|
describe('useSupplier', () => {
|
|
beforeEach(() => {
|
|
mockGet.mockReset()
|
|
mockPatch.mockReset()
|
|
mockGet.mockResolvedValue(SAMPLE)
|
|
mockPatch.mockResolvedValue({ ...SAMPLE, isArchived: true })
|
|
})
|
|
|
|
it('charge le detail via GET /suppliers/{id} en Hydra, sans toast', async () => {
|
|
const { supplier, load } = useSupplier(85)
|
|
await load()
|
|
|
|
expect(mockGet).toHaveBeenCalledWith(
|
|
'/suppliers/85',
|
|
{},
|
|
expect.objectContaining({
|
|
headers: { Accept: 'application/ld+json' },
|
|
toast: false,
|
|
}),
|
|
)
|
|
expect(supplier.value).toEqual(SAMPLE)
|
|
})
|
|
|
|
it('bascule loading pendant le chargement et le retombe a false', async () => {
|
|
const { loading, load } = useSupplier(85)
|
|
const promise = load()
|
|
expect(loading.value).toBe(true)
|
|
await promise
|
|
expect(loading.value).toBe(false)
|
|
})
|
|
|
|
it('marque error et laisse supplier null si le GET echoue (404...)', async () => {
|
|
mockGet.mockRejectedValueOnce(new Error('not found'))
|
|
const { supplier, error, load } = useSupplier(99)
|
|
await load()
|
|
expect(error.value).toBe(true)
|
|
expect(supplier.value).toBeNull()
|
|
})
|
|
|
|
it('archive() PATCHe { isArchived: true } sans toast puis RECHARGE le detail complet', async () => {
|
|
// 1er GET = chargement initial, 2e GET = rechargement post-archivage.
|
|
mockGet.mockResolvedValueOnce(SAMPLE)
|
|
mockGet.mockResolvedValueOnce({ ...SAMPLE, isArchived: true })
|
|
const { supplier, load, archive } = useSupplier(85)
|
|
await load()
|
|
await archive()
|
|
|
|
expect(mockPatch).toHaveBeenCalledWith(
|
|
'/suppliers/85',
|
|
{ isArchived: true },
|
|
expect.objectContaining({ toast: false }),
|
|
)
|
|
// Le detail est re-fetch (le PATCH ne renvoie pas l'embed complet).
|
|
expect(mockGet).toHaveBeenCalledTimes(2)
|
|
expect(supplier.value?.isArchived).toBe(true)
|
|
})
|
|
|
|
it('restore() PATCHe { isArchived: false } (payload isArchived SEUL)', async () => {
|
|
const { load, restore } = useSupplier(85)
|
|
await load()
|
|
await restore()
|
|
|
|
expect(mockPatch).toHaveBeenCalledWith(
|
|
'/suppliers/85',
|
|
{ isArchived: false },
|
|
expect.objectContaining({ toast: false }),
|
|
)
|
|
})
|
|
|
|
it('propage l\'erreur (ex: 403 sans permission archive, 409 conflit homonyme) au lieu de l\'avaler', async () => {
|
|
const forbidden = { response: { status: 403 } }
|
|
mockPatch.mockRejectedValueOnce(forbidden)
|
|
const { load, archive } = useSupplier(85)
|
|
await load()
|
|
await expect(archive()).rejects.toBe(forbidden)
|
|
})
|
|
})
|