import { QueryClientProvider } from "@tanstack/react-query"; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from "@testing-library/user-event"; import { SlotEntry } from "@/components/Routines/models/SlotEntry"; import { SlotEntryRepetitionUnitField, SlotEntryRoundingField, SlotEntryTypeField, SlotEntryWeightUnitField } from "@/components/Routines/widgets/forms/SlotEntryForm"; import type { Mock } from 'vitest'; import { editSlotEntry } from "@/components/Routines/api/slotEntry"; import { getRoutineRepUnits, getRoutineWeightUnits } from "@/components/Routines/api/workoutUnits"; import { editProfile, getProfile } from "@/components/User/api/profile"; import { getTestQueryClient } from "@/tests/queryClient"; import { testProfileDataVerified } from "@/tests/userTestdata"; import { testDayLegs, testRepetitionUnits, testWeightUnits } from "@/tests/workoutRoutinesTestData"; import { DEBOUNCE_ROUTINE_FORMS } from "@/core/lib/consts"; vi.mock("@/components/Routines/api/slotEntry"); vi.mock("@/components/Routines/api/workoutUnits"); vi.mock("@/components/User/api/profile"); let user: ReturnType; const mockEditSlotEntry = editSlotEntry as Mock; describe('SlotEntryTypeField', () => { beforeEach(() => { user = userEvent.setup(); vi.resetAllMocks(); }); test('correctly updates the slot entry on change', async () => { render( ); const dropdown = screen.getByRole('combobox', { name: 'routines.set.type' }); await user.click(dropdown); // One in the options menu, one in the selected value expect(screen.queryAllByText(/routines\.set\.normalSet/)).toHaveLength(2); expect(screen.getByText(/routines\.set\.dropSet/)).toBeInTheDocument(); expect(screen.getByText(/routines\.set\.myo/)).toBeInTheDocument(); expect(screen.getByText(/routines\.set\.partial/)).toBeInTheDocument(); expect(screen.getByText(/routines\.set\.forced/)).toBeInTheDocument(); expect(screen.getByText(/routines\.set\.tut/)).toBeInTheDocument(); expect(screen.getByText(/routines\.set\.iso/)).toBeInTheDocument(); expect(screen.getByText(/routines\.set\.jump/)).toBeInTheDocument(); const myoOption = screen.getByRole('option', { name: /routines\.set\.myo/ }); await user.click(myoOption); expect(mockEditSlotEntry).toHaveBeenCalledWith(SlotEntry.clone(testDayLegs.slots[0].entries[0], { type: 'myo' })); }); }); describe('SlotEntryRepetitionUnitField', () => { const testSlotEntry = testDayLegs.slots[0].entries[0]; beforeEach(() => { vi.resetAllMocks(); user = userEvent.setup(); (getRoutineRepUnits as Mock).mockResolvedValue(testRepetitionUnits); }); test('correctly updates the slot entry on change', async () => { render( ); await waitFor(() => { expect(getRoutineRepUnits).toHaveBeenCalled(); }); await waitFor(async () => { const dropdown = screen.getByRole('combobox', { name: 'unit' }); await user.click(dropdown); }); const minutesOption = screen.getByRole('option', { name: 'Minutes' }); await user.click(minutesOption); expect(mockEditSlotEntry).toHaveBeenCalledWith(SlotEntry.clone(testSlotEntry, { repetitionUnitId: 3 })); }); }); describe('SlotEntryWeightUnitField', () => { const testSlotEntry = testDayLegs.slots[0].entries[0]; beforeEach(() => { vi.resetAllMocks(); user = userEvent.setup(); (getRoutineWeightUnits as Mock).mockResolvedValue(testWeightUnits); (getProfile as Mock).mockResolvedValue(testProfileDataVerified); }); test('correctly updates the slot entry on change', async () => { render( ); await waitFor(() => { expect(getRoutineWeightUnits).toHaveBeenCalled(); expect(getProfile).toHaveBeenCalled(); }); await waitFor(async () => { const dropdown = screen.getByRole('combobox', { name: 'unit' }); await user.click(dropdown); }); const platesOption = screen.getByRole('option', { name: 'Plates' }); await user.click(platesOption); expect(mockEditSlotEntry).toHaveBeenCalledWith(SlotEntry.clone(testSlotEntry, { weightUnitId: 3 })); }); }); describe('SlotEntryRoundingField', () => { const mockEditProfile = editProfile as Mock; const testSlotEntry = testDayLegs.slots[0].entries[0]; beforeEach(() => { vi.resetAllMocks(); (editProfile as Mock).mockResolvedValue(testProfileDataVerified); (getProfile as Mock).mockResolvedValue(testProfileDataVerified); user = userEvent.setup(); }); test('correctly updates the weight rounding for the slot entry', async () => { // Arrange render( ); // Act const inputElement = screen.getByRole('textbox', { name: 'weight' }); await user.click(inputElement); await user.clear(inputElement); await user.type(inputElement, '33'); await user.tab(); // Assert await waitFor(() => { expect(mockEditSlotEntry).toHaveBeenCalledWith(SlotEntry.clone(testSlotEntry, { weightRounding: 33 })); expect(mockEditProfile).not.toHaveBeenCalled(); }, { timeout: DEBOUNCE_ROUTINE_FORMS + 100 }); }); test('correctly updates the weight rounding for the slot entry and the user profile', async () => { // Arrange render( ); // Act const inputElement = await screen.findByRole('textbox', { name: 'weight' }); await user.click(inputElement); await user.clear(inputElement); await user.type(inputElement, '34'); await user.tab(); // Assert await waitFor(() => { expect(mockEditProfile).toHaveBeenCalledWith({ "weightRounding": 34 }); expect(mockEditSlotEntry).not.toHaveBeenCalled(); }, { timeout: DEBOUNCE_ROUTINE_FORMS + 100 }); }); test('correctly updates the reps rounding for the slot entry', async () => { // Arrange render( ); // Act const inputElement = screen.getByRole('textbox', { name: 'routines.reps' }); await user.click(inputElement); await user.clear(inputElement); await user.type(inputElement, '33'); await user.tab(); // Assert await waitFor(() => { expect(mockEditSlotEntry).toHaveBeenCalledWith(SlotEntry.clone(testSlotEntry, { repetitionRounding: 33 })); expect(mockEditProfile).not.toHaveBeenCalled(); }, { timeout: DEBOUNCE_ROUTINE_FORMS + 100 }); }); });