diff --git a/src/screens/OrganizationFunds/FundModal.test.tsx b/src/screens/OrganizationFunds/FundModal.spec.tsx similarity index 85% rename from src/screens/OrganizationFunds/FundModal.test.tsx rename to src/screens/OrganizationFunds/FundModal.spec.tsx index c74b0434c3..7296f31661 100644 --- a/src/screens/OrganizationFunds/FundModal.test.tsx +++ b/src/screens/OrganizationFunds/FundModal.spec.tsx @@ -21,11 +21,12 @@ import { toast } from 'react-toastify'; import { MOCKS, MOCKS_ERROR } from './OrganizationFundsMocks'; import type { InterfaceFundModal } from './FundModal'; import FundModal from './FundModal'; +import { vi } from 'vitest'; -jest.mock('react-toastify', () => ({ +vi.mock('react-toastify', () => ({ toast: { - success: jest.fn(), - error: jest.fn(), + success: vi.fn(), + error: vi.fn(), }, })); @@ -38,7 +39,7 @@ const translations = JSON.parse( const fundProps: InterfaceFundModal[] = [ { isOpen: true, - hide: jest.fn(), + hide: vi.fn(), fund: { _id: 'fundId', name: 'Fund 1', @@ -54,13 +55,13 @@ const fundProps: InterfaceFundModal[] = [ lastName: 'Doe', }, }, - refetchFunds: jest.fn(), + refetchFunds: vi.fn(), orgId: 'orgId', mode: 'create', }, { isOpen: true, - hide: jest.fn(), + hide: vi.fn(), fund: { _id: 'fundId', name: 'Fund 1', @@ -76,7 +77,7 @@ const fundProps: InterfaceFundModal[] = [ lastName: 'Doe', }, }, - refetchFunds: jest.fn(), + refetchFunds: vi.fn(), orgId: 'orgId', mode: 'edit', }, @@ -104,6 +105,7 @@ const renderFundModal = ( describe('PledgeModal', () => { afterEach(() => { cleanup(); + vi.clearAllMocks(); }); it('should populate form fields with correct values in edit mode', async () => { @@ -184,6 +186,37 @@ describe('PledgeModal', () => { }); }); + it('should not update the fund when no fields are changed', async () => { + renderFundModal(link1, fundProps[1]); + + // Simulate no change to the fields + const fundNameInput = screen.getByLabelText(translations.fundName); + fireEvent.change(fundNameInput, { target: { value: 'Fund 1' } }); + + const fundIdInput = screen.getByLabelText(translations.fundId); + fireEvent.change(fundIdInput, { target: { value: '1111' } }); + + const taxDeductibleSwitch = screen.getByTestId('setTaxDeductibleSwitch'); + fireEvent.click(taxDeductibleSwitch); + fireEvent.click(taxDeductibleSwitch); + + const defaultSwitch = screen.getByTestId('setDefaultSwitch'); + fireEvent.click(defaultSwitch); + fireEvent.click(defaultSwitch); + + const archivedSwitch = screen.getByTestId('archivedSwitch'); + fireEvent.click(archivedSwitch); + fireEvent.click(archivedSwitch); + + fireEvent.click(screen.getByTestId('createFundFormSubmitBtn')); + + await waitFor(() => { + expect(toast.success).not.toHaveBeenCalled(); + expect(fundProps[1].refetchFunds).not.toHaveBeenCalled(); + expect(fundProps[1].hide).not.toHaveBeenCalled(); + }); + }); + it('should update fund', async () => { renderFundModal(link1, fundProps[1]); diff --git a/src/screens/OrganizationFunds/FundModal.tsx b/src/screens/OrganizationFunds/FundModal.tsx index de4329e55c..b33270b30f 100644 --- a/src/screens/OrganizationFunds/FundModal.tsx +++ b/src/screens/OrganizationFunds/FundModal.tsx @@ -139,7 +139,9 @@ const FundModal: React.FC = ({ if (isDefault != fund?.isDefault) { updatedFields.isDefault = isDefault; } - + if (Object.keys(updatedFields).length === 0) { + return; + } await updateFund({ variables: { id: fund?._id, @@ -157,9 +159,7 @@ const FundModal: React.FC = ({ hide(); toast.success(t('fundUpdated') as string); } catch (error: unknown) { - if (error instanceof Error) { - toast.error(error.message); - } + toast.error((error as Error).message); } }; diff --git a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx b/src/screens/OrganizationFunds/OrganizationFunds.spec.tsx similarity index 85% rename from src/screens/OrganizationFunds/OrganizationFunds.test.tsx rename to src/screens/OrganizationFunds/OrganizationFunds.spec.tsx index c6983e1d6d..b259b7da65 100644 --- a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx +++ b/src/screens/OrganizationFunds/OrganizationFunds.spec.tsx @@ -11,7 +11,7 @@ import { import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; -import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { MemoryRouter, Route, Routes, useParams } from 'react-router-dom'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; @@ -20,11 +20,12 @@ import { MOCKS, MOCKS_ERROR, NO_FUNDS } from './OrganizationFundsMocks'; import type { ApolloLink } from '@apollo/client'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { vi } from 'vitest'; -jest.mock('react-toastify', () => ({ +vi.mock('react-toastify', () => ({ toast: { - success: jest.fn(), - error: jest.fn(), + success: vi.fn(), + error: vi.fn(), }, })); @@ -67,21 +68,22 @@ const renderOrganizationFunds = (link: ApolloLink): RenderResult => { describe('OrganizationFunds Screen =>', () => { beforeEach(() => { - jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useParams: () => ({ orgId: 'orgId' }), - })); - }); - - afterEach(() => { - jest.clearAllMocks(); + vi.mock('react-router-dom', async () => { + const actual = await vi.importActual('react-router-dom'); + return { + ...actual, + useParams: vi.fn(), + }; + }); }); afterEach(() => { + vi.clearAllMocks(); cleanup(); }); it('should render the Campaign Pledge screen', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); await waitFor(() => { expect(screen.getByTestId('searchByName')).toBeInTheDocument(); @@ -89,29 +91,34 @@ describe('OrganizationFunds Screen =>', () => { }); it('should redirect to fallback URL if URL params are undefined', async () => { + vi.mocked(useParams).mockReturnValue({}); render( - } /> } /> + } /> , ); + await waitFor(() => { + expect(window.location.pathname).toBe('/'); + }); await waitFor(() => { expect(screen.getByTestId('paramsError')).toBeInTheDocument(); }); }); it('open and close Create Fund modal', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); const createFundBtn = await screen.findByTestId('createFundBtn'); @@ -128,6 +135,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('open and close update fund modal', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); await waitFor(() => { @@ -150,6 +158,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('Search the Funds list by name', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); const searchField = await screen.findByTestId('searchByName'); fireEvent.change(searchField, { @@ -163,6 +172,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('should render the Fund screen with error', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link2); await waitFor(() => { expect(screen.getByTestId('errorMsg')).toBeInTheDocument(); @@ -170,6 +180,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('renders the empty fund component', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link3); await waitFor(() => expect(screen.getByText(translations.noFundsFound)).toBeInTheDocument(), @@ -177,6 +188,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('Sort the Pledges list by Latest created Date', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); const sortBtn = await screen.findByTestId('filter'); @@ -198,6 +210,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('Sort the Pledges list by Earliest created Date', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); const sortBtn = await screen.findByTestId('filter'); @@ -219,6 +232,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('Click on Fund Name', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); const fundName = await screen.findAllByTestId('fundName'); @@ -231,6 +245,7 @@ describe('OrganizationFunds Screen =>', () => { }); it('Click on View Campaign', async () => { + vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' }); renderOrganizationFunds(link1); const viewBtn = await screen.findAllByTestId('viewBtn');