diff --git a/src/common/components/DownloadAllocationWorksheetModal/DownloadAllocationWorksheetModal.test.js b/src/common/components/DownloadAllocationWorksheetModal/DownloadAllocationWorksheetModal.test.js new file mode 100644 index 00000000..0c6a6d28 --- /dev/null +++ b/src/common/components/DownloadAllocationWorksheetModal/DownloadAllocationWorksheetModal.test.js @@ -0,0 +1,103 @@ +import { + QueryClient, + QueryClientProvider, +} from 'react-query'; + +import { + render, + screen, + waitFor, +} from '@folio/jest-config-stripes/testing-library/react'; +import userEvent from '@folio/jest-config-stripes/testing-library/user-event'; +import { exportToCsv } from '@folio/stripes/components'; +import { useOkapiKy } from '@folio/stripes/core'; +import { useShowCallout } from '@folio/stripes-acq-components'; + +import { fetchFinanceData } from '../../utils'; +import { DownloadAllocationWorksheetModal } from './DownloadAllocationWorksheetModal'; +import { useWorksheetFiscalYears } from './useWorksheetFiscalYears'; + +jest.mock('@folio/stripes/components', () => ({ + ...jest.requireActual('@folio/stripes/components'), + exportToCsv: jest.fn(), +})); +jest.mock('@folio/stripes-acq-components', () => ({ + ...jest.requireActual('@folio/stripes-acq-components'), + useShowCallout: jest.fn(), +})); +jest.mock('../../utils', () => ({ + fetchFinanceData: jest.fn(), +})); +jest.mock('./useWorksheetFiscalYears', () => ({ + useWorksheetFiscalYears: jest.fn(), +})); + +const queryClient = new QueryClient(); +const renderComponent = (props) => render( + + + , +); + +const fiscalYears = [{ id: 'fy1', code: 'FY2021' }]; + +describe('DownloadAllocationWorksheetModal', () => { + const toggleMock = jest.fn(); + const showCalloutMock = jest.fn(); + const kyMock = { get: jest.fn() }; + + beforeEach(() => { + fetchFinanceData.mockReturnValue(() => ({ fyFinanceData: [{ fiscalYearId: 'fy1' }] })); + useOkapiKy.mockReturnValue(kyMock); + useShowCallout.mockReturnValue(showCalloutMock); + useWorksheetFiscalYears + .mockImplementationOnce((_, options) => { + options?.onSuccess?.({ fiscalYears }); + + return { isFetching: false, fiscalYears }; + }) + .mockReturnValue({ isFetching: false, fiscalYears }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should render modal with fiscal year selection', () => { + renderComponent({ open: true, toggle: toggleMock }); + + expect(screen.getByText('ui-finance.selectFiscalYear')).toBeInTheDocument(); + expect(screen.getByText('ui-finance.fiscalyear')).toBeInTheDocument(); + expect(screen.getByText('stripes-core.button.confirm')).toBeInTheDocument(); + }); + + it('should call toggle on cancel', async () => { + renderComponent({ open: true, toggle: toggleMock }); + + await userEvent.click(screen.getByRole('button', { name: 'stripes-components.cancel' })); + + expect(toggleMock).toHaveBeenCalled(); + }); + + it('should enable confirm button when fiscal year is selected', () => { + renderComponent({ open: true, toggle: toggleMock }); + + expect(screen.getByText('stripes-core.button.confirm')).not.toBeDisabled(); + }); + + it('should call showCallout and toggle on successful confirm', async () => { + kyMock.get.mockResolvedValue({ + json: jest.fn().mockResolvedValue({ fyFinanceData: [] }), + }); + + renderComponent({ open: true, toggle: toggleMock }); + + await userEvent.click(screen.getByRole('button', { name: 'stripes-core.button.confirm' })); + + await waitFor(() => { + expect(exportToCsv).toHaveBeenCalled(); + expect(showCalloutMock).toHaveBeenCalledWith({ messageId: 'ui-finance.allocation.worksheet.download.start' }); + expect(toggleMock).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/common/hooks/useGroupUpcomingFiscalYears/useGroupUpcomingFiscalYears.test.js b/src/common/hooks/useGroupUpcomingFiscalYears/useGroupUpcomingFiscalYears.test.js new file mode 100644 index 00000000..91d4564d --- /dev/null +++ b/src/common/hooks/useGroupUpcomingFiscalYears/useGroupUpcomingFiscalYears.test.js @@ -0,0 +1,67 @@ +import { + QueryClient, + QueryClientProvider, +} from 'react-query'; + +import { + renderHook, + waitFor, +} from '@folio/jest-config-stripes/testing-library/react'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { + getGroupLedgers, + getLedgersCurrentFiscalYears, +} from '../../../Groups/GroupDetails/utils'; +import { FISCAL_YEARS_API } from '../../const'; +import { useGroupUpcomingFiscalYears } from './useGroupUpcomingFiscalYears'; + +jest.mock('../../../Groups/GroupDetails/utils', () => ({ + getGroupLedgers: jest.fn(), + getLedgersCurrentFiscalYears: jest.fn(), +})); + +const queryClient = new QueryClient(); +const wrapper = ({ children }) => ( + + {children} + +); + +describe('useGroupUpcomingFiscalYears', () => { + const kyMock = { + get: jest.fn(() => ({ + json: jest.fn().mockResolvedValue({ fiscalYears: [], totalRecords: 0 }), + })), + extend: jest.fn(() => kyMock), + }; + + beforeEach(() => { + useOkapiKy.mockReturnValue(kyMock); + getGroupLedgers.mockReturnValue(() => Promise.resolve({ ledgers: [{ id: 'ledger1' }] })); + getLedgersCurrentFiscalYears.mockReturnValue(() => Promise.resolve([{ series: 'FY', periodStart: '2022-01-01' }])); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should return default data when groupId is not provided', async () => { + const { result } = renderHook(() => useGroupUpcomingFiscalYears(), { wrapper }); + + await waitFor(() => expect(result.current.isLoading).toBe(false)); + + expect(result.current.fiscalYears).toEqual([]); + expect(result.current.totalRecords).toBeUndefined(); + }); + + it('should fetch and return fiscal years data', async () => { + const { result } = renderHook(() => useGroupUpcomingFiscalYears('groupId'), { wrapper }); + + await waitFor(() => expect(result.current.isLoading).toBe(false)); + + expect(result.current.fiscalYears).toEqual([]); + expect(result.current.totalRecords).toBe(0); + expect(kyMock.get).toHaveBeenCalledWith(FISCAL_YEARS_API, expect.any(Object)); + }); +}); diff --git a/src/common/hooks/useLedgerUpcomingFiscalYears/useLedgerUpcomingFiscalYears.test.js b/src/common/hooks/useLedgerUpcomingFiscalYears/useLedgerUpcomingFiscalYears.test.js new file mode 100644 index 00000000..0ecdc9bf --- /dev/null +++ b/src/common/hooks/useLedgerUpcomingFiscalYears/useLedgerUpcomingFiscalYears.test.js @@ -0,0 +1,63 @@ +import { + QueryClient, + QueryClientProvider, +} from 'react-query'; + +import { + renderHook, + waitFor, +} from '@folio/jest-config-stripes/testing-library/react'; +import { useOkapiKy } from '@folio/stripes/core'; + +import { FISCAL_YEARS_API } from '../../const'; +import { useLedgerCurrentFiscalYear } from '../useLedgerCurrentFiscalYear'; +import { useLedgerUpcomingFiscalYears } from './useLedgerUpcomingFiscalYears'; + +jest.mock('../useLedgerCurrentFiscalYear', () => ({ + useLedgerCurrentFiscalYear: jest.fn(), +})); + +const currentFiscalYear = { + id: 'fiscal-year-id', + series: 'FY', + periodStart: '2023-10-05T00:00:00Z', +}; +const fiscalYears = [{ id: 'fy1' }, { id: 'fy2' }]; + +const kyMock = { + get: jest.fn(() => ({ + json: () => Promise.resolve({ fiscalYears }), + })), +}; + +const queryClient = new QueryClient(); +const wrapper = ({ children }) => ( + + {children} + +); + +describe('useLedgerUpcomingFiscalYears', () => { + beforeEach(() => { + useLedgerCurrentFiscalYear.mockReturnValue({ currentFiscalYear }); + useOkapiKy.mockReturnValue(kyMock); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should fetch fiscal years for the ledger', async () => { + const { result } = renderHook(() => useLedgerUpcomingFiscalYears('ledgerId'), { wrapper }); + + await waitFor(() => expect(result.current.isLoading).toBeFalsy()); + + expect(kyMock.get).toHaveBeenCalledWith(FISCAL_YEARS_API, { + searchParams: expect.objectContaining({ + query: `series==${currentFiscalYear.series} and periodStart >= ${currentFiscalYear.periodStart} sortby periodStart/sort.descending series/sort.ascending`, + }), + signal: expect.any(AbortSignal), + }); + expect(result.current.fiscalYears).toEqual(fiscalYears); + }); +}); diff --git a/src/common/utils/fetchFinanceData.test.js b/src/common/utils/fetchFinanceData.test.js new file mode 100644 index 00000000..f6fdce55 --- /dev/null +++ b/src/common/utils/fetchFinanceData.test.js @@ -0,0 +1,19 @@ +import { FINANCE_DATA_API } from '../const'; +import { fetchFinanceData } from './fetchFinanceData'; + +const httpClient = { + get: jest.fn(() => ({ + json: jest.fn(() => Promise.resolve({})), + })), +}; + +describe('fetchFinanceData', () => { + it('should fetch finance data by specific query', async () => { + const fetcher = fetchFinanceData(httpClient); + const options = { query: 'financeDataQuery' }; + + await fetcher(options); + + expect(httpClient.get).toHaveBeenCalledWith(FINANCE_DATA_API, options); + }); +});