import { describe, it, expect, vi, beforeEach } from 'vitest'; import axios from 'axios'; import { recipesApi } from './api'; vi.mock('axios'); describe('Recipes API Service', () => { const mockAxios = axios as any; beforeEach(() => { vi.clearAllMocks(); mockAxios.create = vi.fn(() => mockAxios); }); describe('getAll', () => { it('should fetch all recipes with default params', async () => { const mockRecipes = { data: [ { id: '1', title: 'Recipe 1' }, { id: '2', title: 'Recipe 2' }, ], total: 2, page: 1, pageSize: 20, }; mockAxios.get = vi.fn().mockResolvedValue({ data: mockRecipes }); const result = await recipesApi.getAll(); expect(mockAxios.get).toHaveBeenCalledWith('/recipes', { params: undefined }); expect(result).toEqual(mockRecipes); }); it('should fetch recipes with search params', async () => { const mockRecipes = { data: [{ id: '1', title: 'Pasta Recipe' }], total: 1, page: 1, pageSize: 20, }; mockAxios.get = vi.fn().mockResolvedValue({ data: mockRecipes }); await recipesApi.getAll({ search: 'pasta', page: 1, limit: 10 }); expect(mockAxios.get).toHaveBeenCalledWith('/recipes', { params: { search: 'pasta', page: 1, limit: 10 }, }); }); }); describe('getById', () => { it('should fetch single recipe by id', async () => { const mockRecipe = { data: { id: '1', title: 'Test Recipe', description: 'Test' }, }; mockAxios.get = vi.fn().mockResolvedValue({ data: mockRecipe }); const result = await recipesApi.getById('1'); expect(mockAxios.get).toHaveBeenCalledWith('/recipes/1'); expect(result).toEqual(mockRecipe); }); }); describe('create', () => { it('should create new recipe', async () => { const newRecipe = { title: 'New Recipe', description: 'New Description' }; const mockResponse = { data: { id: '1', ...newRecipe } }; mockAxios.post = vi.fn().mockResolvedValue({ data: mockResponse }); const result = await recipesApi.create(newRecipe); expect(mockAxios.post).toHaveBeenCalledWith('/recipes', newRecipe); expect(result).toEqual(mockResponse); }); }); describe('update', () => { it('should update existing recipe', async () => { const updatedRecipe = { title: 'Updated Recipe' }; const mockResponse = { data: { id: '1', ...updatedRecipe } }; mockAxios.put = vi.fn().mockResolvedValue({ data: mockResponse }); const result = await recipesApi.update('1', updatedRecipe); expect(mockAxios.put).toHaveBeenCalledWith('/recipes/1', updatedRecipe); expect(result).toEqual(mockResponse); }); }); describe('delete', () => { it('should delete recipe', async () => { const mockResponse = { data: { message: 'Recipe deleted' } }; mockAxios.delete = vi.fn().mockResolvedValue({ data: mockResponse }); const result = await recipesApi.delete('1'); expect(mockAxios.delete).toHaveBeenCalledWith('/recipes/1'); expect(result).toEqual(mockResponse); }); }); describe('uploadImage', () => { it('should upload image with multipart form data', async () => { const mockFile = new File(['content'], 'test.jpg', { type: 'image/jpeg' }); const mockResponse = { data: { url: '/uploads/recipes/test.jpg' } }; mockAxios.post = vi.fn().mockResolvedValue({ data: mockResponse }); const result = await recipesApi.uploadImage('1', mockFile); expect(mockAxios.post).toHaveBeenCalledWith( '/recipes/1/images', expect.any(FormData), { headers: { 'Content-Type': 'multipart/form-data' } } ); expect(result).toEqual(mockResponse); }); }); describe('importFromUrl', () => { it('should import recipe from URL', async () => { const url = 'https://example.com/recipe'; const mockResponse = { success: true, recipe: { title: 'Imported Recipe' }, }; mockAxios.post = vi.fn().mockResolvedValue({ data: mockResponse }); const result = await recipesApi.importFromUrl(url); expect(mockAxios.post).toHaveBeenCalledWith('/recipes/import', { url }); expect(result).toEqual(mockResponse); }); }); });