import { describe, it, expect, vi, beforeEach } from 'vitest' import { useComposants } from '~/composables/useComposants' import { mockComponentFromApi, wrapCollection } from '../fixtures/mockData' // --------------------------------------------------------------------------- // Mocks // --------------------------------------------------------------------------- const mockGet = vi.fn() const mockPost = vi.fn() const mockPatch = vi.fn() const mockDel = vi.fn() vi.mock('~/composables/useApi', () => ({ useApi: () => ({ get: mockGet, post: mockPost, patch: mockPatch, put: vi.fn(), delete: mockDel, postFormData: vi.fn(), }), })) vi.mock('~/composables/useToast', () => ({ useToast: () => ({ showSuccess: vi.fn(), showError: vi.fn(), showInfo: vi.fn(), showToast: vi.fn(), toasts: { value: [] }, clearAll: vi.fn(), }), })) vi.mock('~/composables/useConstructeurs', () => ({ useConstructeurs: () => ({ ensureConstructeurs: vi.fn().mockResolvedValue([]), }), })) beforeEach(() => { vi.clearAllMocks() const { clearComposantsCache } = useComposants() clearComposantsCache() }) // --------------------------------------------------------------------------- // createComposant // --------------------------------------------------------------------------- describe('createComposant', () => { it('sends all fields in creation payload', async () => { const created = { ...mockComponentFromApi, id: 'comp-new' } mockPost.mockResolvedValue({ success: true, data: created }) const { createComposant } = useComposants() const result = await createComposant({ name: 'Moteur principal', reference: 'COMP-MOT-001', description: 'Un moteur', typeComposantId: 'tc-moteur', }) expect(result.success).toBe(true) // normalizeRelationIds converts typeComposantId to typeComposant IRI expect(mockPost).toHaveBeenCalledWith('/composants', expect.objectContaining({ name: 'Moteur principal', reference: 'COMP-MOT-001', description: 'Un moteur', typeComposant: '/api/model_types/tc-moteur', })) // typeComposantId should be removed by normalizeRelationIds const payload = mockPost.mock.calls[0]![1] expect(payload).not.toHaveProperty('typeComposantId') }) it('adds created composant to cache', async () => { const created = { ...mockComponentFromApi, id: 'comp-new', name: 'Nouveau composant' } mockPost.mockResolvedValue({ success: true, data: created }) const { createComposant, composants, total } = useComposants() expect(composants.value).toHaveLength(0) expect(total.value).toBe(0) await createComposant({ name: 'Nouveau composant' }) expect(composants.value).toHaveLength(1) expect(composants.value[0]!.id).toBe('comp-new') expect(total.value).toBe(1) }) }) // --------------------------------------------------------------------------- // updateComposant // --------------------------------------------------------------------------- describe('updateComposant', () => { it('patches and updates cache', async () => { // Seed the cache with one composant const original = { ...mockComponentFromApi, id: 'comp-001', name: 'Ancien nom' } mockPost.mockResolvedValue({ success: true, data: original }) const { createComposant, updateComposant, composants } = useComposants() await createComposant({ name: 'Ancien nom' }) expect(composants.value).toHaveLength(1) // Now update const updated = { ...original, name: 'Nouveau nom' } mockPatch.mockResolvedValue({ success: true, data: updated }) const result = await updateComposant('comp-001', { name: 'Nouveau nom' }) expect(result.success).toBe(true) expect(mockPatch).toHaveBeenCalledWith('/composants/comp-001', expect.objectContaining({ name: 'Nouveau nom', })) expect(composants.value[0]!.name).toBe('Nouveau nom') }) }) // --------------------------------------------------------------------------- // deleteComposant // --------------------------------------------------------------------------- describe('deleteComposant', () => { it('removes composant from cache on success', async () => { // Seed cache const item = { ...mockComponentFromApi, id: 'comp-del', name: 'A supprimer' } mockPost.mockResolvedValue({ success: true, data: item }) const { createComposant, deleteComposant, composants, total } = useComposants() await createComposant({ name: 'A supprimer' }) expect(composants.value).toHaveLength(1) expect(total.value).toBe(1) mockDel.mockResolvedValue({ success: true }) const result = await deleteComposant('comp-del') expect(result.success).toBe(true) expect(composants.value).toHaveLength(0) expect(total.value).toBe(0) }) it('keeps composant in cache on failure', async () => { // Seed cache const item = { ...mockComponentFromApi, id: 'comp-keep', name: 'Garder' } mockPost.mockResolvedValue({ success: true, data: item }) const { createComposant, deleteComposant, composants, total } = useComposants() await createComposant({ name: 'Garder' }) expect(composants.value).toHaveLength(1) mockDel.mockResolvedValue({ success: false, error: 'Server error' }) const result = await deleteComposant('comp-keep') expect(result.success).toBe(false) expect(composants.value).toHaveLength(1) expect(composants.value[0]!.id).toBe('comp-keep') }) })