import { DiaryEntry } from "@/components/Nutrition/models/diaryEntry"; import { useAddDiaryEntryQuery, useEditDiaryEntryQuery, useSearchIngredientQuery } from "@/components/Nutrition/queries"; import { NutritionDiaryEntryForm } from "@/components/Nutrition/widgets/forms/NutritionDiaryEntryForm"; import { searchIngredient } from "@/components/Nutrition/api/ingredient"; import { TEST_INGREDIENT_1, TEST_INGREDIENT_2 } from "@/tests/ingredientTestdata"; import { TEST_DIARY_ENTRY_1 } from "@/tests/nutritionDiaryTestdata"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { render, screen, within } from '@testing-library/react'; import userEvent, { UserEvent } from "@testing-library/user-event"; import React from 'react'; import type { Mock } from 'vitest'; vi.mock('@/components/Nutrition/queries'); vi.mock("@/components/Nutrition/api/ingredient"); async function fillInEntry(user: UserEvent) { const autocomplete = screen.getByTestId('autocomplete'); const input = within(autocomplete).getByRole('combobox'); await user.click(autocomplete); await user.type(input, 'Bagu'); // Wait for the debounced search results to render in the dropdown // before navigating to them with the keyboard. await screen.findByText('0% fat Greek style yogurt'); // Select the first result await user.click(input); await user.keyboard('{ArrowDown}{Enter}'); const amountInput = screen.getByLabelText('amount'); await user.clear(amountInput); await user.type(amountInput, '120'); const submitButton = screen.getByRole('button', { name: 'submit' }); await user.click(submitButton); } describe('Test the NutritionDiaryEntryForm component', () => { const queryClient = new QueryClient(); let mutateAddMock = vi.fn(); let mutateEditMock = vi.fn(); let closeFnMock = vi.fn(); beforeEach(() => { mutateAddMock = vi.fn(); mutateEditMock = vi.fn(); closeFnMock = vi.fn(); (useEditDiaryEntryQuery as Mock).mockImplementation(() => ({ mutate: mutateEditMock })); (useAddDiaryEntryQuery as Mock).mockImplementation(() => ({ mutate: mutateAddMock })); (searchIngredient as Mock).mockImplementation(() => Promise.resolve([TEST_INGREDIENT_1, TEST_INGREDIENT_2])); (useSearchIngredientQuery as Mock).mockImplementation(() => searchIngredient); }); test('A new entry should be added - no meal', async () => { // Arrange const user = userEvent.setup(); // Act render( ); await fillInEntry(user); // Assert expect(screen.getByDisplayValue('0% fat Greek style yogurt')).toBeInTheDocument(); expect(screen.getByDisplayValue('120')).toBeInTheDocument(); expect(mutateEditMock).not.toHaveBeenCalled(); expect(closeFnMock).toHaveBeenCalled(); expect(mutateAddMock).toHaveBeenCalledWith( new DiaryEntry({ amount: 120, datetime: expect.any(Date), ingredientId: 101, planId: 'aaaaaaaa-0000-0000-0000-000000000123', mealId: null, weightUnitId: null, }) ); }); test('A new entry should be added - passing meal ID', async () => { // Arrange const user = userEvent.setup(); // Act render( ); await fillInEntry(user); // Assert expect(screen.getByDisplayValue('0% fat Greek style yogurt')).toBeInTheDocument(); expect(screen.getByDisplayValue('120')).toBeInTheDocument(); expect(mutateEditMock).not.toHaveBeenCalled(); expect(closeFnMock).toHaveBeenCalled(); expect(mutateAddMock).toHaveBeenCalledWith( new DiaryEntry({ amount: 120, datetime: expect.any(Date), ingredientId: 101, planId: 'aaaaaaaa-0000-0000-0000-000000000123', mealId: 'bbbbbbbb-0000-0000-0000-000000000456', weightUnitId: null, }) ); }); test('An existing diary entry should be edited', async () => { // Arrange const user = userEvent.setup(); // Act render( ); await fillInEntry(user); // Assert expect(mutateAddMock).not.toHaveBeenCalled(); expect(closeFnMock).toHaveBeenCalled(); expect(mutateEditMock).toHaveBeenCalledWith( expect.objectContaining({ id: 'dddddddd-0000-0000-0000-000000000042', amount: 120, mealId: 'bbbbbbbb-0000-0000-0000-000000000078', planId: 'aaaaaaaa-0000-0000-0000-000000000123', ingredientId: 101, }) ); }); test('An existing diary entry should be edited - passing a meal Id', async () => { // Arrange const user = userEvent.setup(); // Act render( ); await fillInEntry(user); // Assert expect(mutateAddMock).not.toHaveBeenCalled(); expect(closeFnMock).toHaveBeenCalled(); expect(mutateEditMock).toHaveBeenCalledWith( expect.objectContaining({ id: 'dddddddd-0000-0000-0000-000000000042', planId: 'aaaaaaaa-0000-0000-0000-000000000123', mealId: 'bbbbbbbb-0000-0000-0000-000000000456', amount: 120, ingredientId: 101, weightUnitId: null, }) ); }); });