diff --git a/src/common/hooks/useSearch.ts b/src/common/hooks/useSearch.ts index 576828a3..52fd01cb 100644 --- a/src/common/hooks/useSearch.ts +++ b/src/common/hooks/useSearch.ts @@ -6,9 +6,9 @@ import { DEFAULT_PAGES_METADATA } from '@common/constants/api.constants'; import { SearchIdentifiers, SearchSegment } from '@common/constants/search.constants'; import { generateSearchParamsState } from '@common/helpers/search.helper'; import { usePagination } from '@common/hooks/usePagination'; +import { useSearchContext } from '@common/hooks/useSearchContext'; +import { useFetchSearchData } from '@common/hooks/useFetchSearchData'; import state from '@state'; -import { useSearchContext } from './useSearchContext'; -import { useFetchSearchData } from './useFetchSearchData'; export const useSearch = () => { const { diff --git a/src/test/__tests__/common/hooks/useSearch.test.ts b/src/test/__tests__/common/hooks/useSearch.test.ts new file mode 100644 index 00000000..cfbb6c85 --- /dev/null +++ b/src/test/__tests__/common/hooks/useSearch.test.ts @@ -0,0 +1,191 @@ +import { renderHook } from '@testing-library/react'; +import { useSearchParams } from 'react-router-dom'; +import { useRecoilState, useSetRecoilState, useResetRecoilState } from 'recoil'; +import { useSearch } from '@common/hooks/useSearch'; +import { useSearchContext } from '@common/hooks/useSearchContext'; + +const selectedNavigationSegment = 'defaultSegment'; +const defaultSearchBy = 'defaultSearchBy'; +const defaultQuery = 'defaultQuery'; +const setCurrentPageNumber = jest.fn(); +const onPrevPageClick = jest.fn(); +const onNextPageClick = jest.fn(); +const getCurrentPageNumber = jest.fn().mockReturnValue(0); +const fetchData = jest.fn(); + +jest.mock('react-router-dom'); +jest.mock('recoil'); +jest.mock('@common/hooks/useSearchContext'); +jest.mock('@common/hooks/usePagination', () => ({ + usePagination: () => ({ + getCurrentPageNumber, + setCurrentPageNumber, + onPrevPageClick, + onNextPageClick, + }), +})); +jest.mock('@common/hooks/useFetchSearchData', () => ({ + useFetchSearchData: () => ({ + fetchData, + }), +})); +jest.mock('@state', () => ({ + default: { + search: { + index: '', + query: '', + limiters: {}, + message: '', + data: null, + pageMetadata: {}, + facetsBySegments: { + defaultSegment: { + query: 'defaultQuery', + searchBy: 'defaultSearchBy', + facets: {}, + }, + }, + }, + inputs: { + userValues: {}, + previewContent: {}, + }, + loadingState: { + isLoading: false, + }, + }, +})); + +describe('useSearch hook', () => { + const setIsLoading = jest.fn(); + const setSearchBy = jest.fn(); + const setQuery = jest.fn(); + const setFacets = jest.fn(); + const setMessage = jest.fn(); + const setData = jest.fn(); + const setPageMetadata = jest.fn(); + const setFacetsBySegments = jest.fn(); + const setForceRefreshSearch = jest.fn(); + const resetPreviewContent = jest.fn(); + const clearFacetsBySegments = jest.fn(); + const setSearchParams = jest.fn(); + + const mockUseSearchContext = { + hasSearchParams: true, + defaultSearchBy, + defaultQuery, + navigationSegment: { value: selectedNavigationSegment }, + hasCustomPagination: true, + searchByControlOptions: {}, + getSearchSourceData: jest.fn(), + }; + + beforeEach(() => { + (useSearchContext as jest.Mock).mockReturnValue(mockUseSearchContext); + (useSearchParams as jest.Mock).mockReturnValue([null, setSearchParams]); + + (useRecoilState as jest.Mock) + .mockReturnValueOnce(['', setSearchBy]) + .mockReturnValueOnce(['', setQuery]) + .mockReturnValueOnce([{}, setFacets]) + .mockReturnValueOnce(['', setMessage]) + .mockReturnValueOnce([null, setData]) + .mockReturnValueOnce([{}, setPageMetadata]) + .mockReturnValueOnce([ + { + newSegment: { + query: 'newQuery', + searchBy: 'newSearchBy', + facets: {}, + }, + }, + setFacetsBySegments, + ]); + (useSetRecoilState as jest.Mock).mockReturnValueOnce(setIsLoading).mockReturnValueOnce(setForceRefreshSearch); + (useResetRecoilState as jest.Mock) + .mockReturnValueOnce(resetPreviewContent) + .mockReturnValueOnce(clearFacetsBySegments); + }); + + test('initializes with default values and set up effects', () => { + renderHook(useSearch); + + expect(useSearchContext).toHaveBeenCalled(); + expect(fetchData).not.toHaveBeenCalled(); + }); + + test('submits search and updates states correctly', () => { + const updatedUseSearchContext = { ...mockUseSearchContext, hasSearchParams: false }; + (useSearchContext as jest.Mock).mockReturnValue(updatedUseSearchContext); + + const { result } = renderHook(useSearch); + + result.current.submitSearch(); + + expect(fetchData).toHaveBeenCalled(); + expect(setCurrentPageNumber).toHaveBeenCalledWith(0); + expect(resetPreviewContent).toHaveBeenCalled(); + expect(setForceRefreshSearch).toHaveBeenCalledWith(true); + }); + + test('clears values and resets states', () => { + const { result } = renderHook(useSearch); + + result.current.clearValues(); + + expect(setCurrentPageNumber).toHaveBeenCalledWith(0); + expect(setData).toHaveBeenCalledWith(null); + expect(setSearchBy).toHaveBeenCalledWith(defaultSearchBy); + expect(setQuery).toHaveBeenCalledWith(''); + expect(setMessage).toHaveBeenCalledWith(''); + expect(resetPreviewContent).toHaveBeenCalled(); + }); + + test('handles onPrevPageClick with custom pagination', async () => { + getCurrentPageNumber.mockReturnValue(1); + onPrevPageClick.mockReturnValue(0); + + const { result } = renderHook(useSearch); + + await result.current.onPrevPageClick(); + + expect(onPrevPageClick).toHaveBeenCalled(); + expect(fetchData).toHaveBeenCalled(); + }); + + test('handles onNextPageClick with custom pagination', async () => { + getCurrentPageNumber.mockReturnValue(0); + onNextPageClick.mockReturnValue(1); + + const { result } = renderHook(useSearch); + + await result.current.onNextPageClick(); + + expect(onNextPageClick).toHaveBeenCalled(); + expect(fetchData).toHaveBeenCalled(); + }); + + test('handles onChangeSegment and update states', async () => { + const newSegment = 'newSegment' as SearchSegmentValue; + + const { result } = renderHook(useSearch); + + await result.current.onChangeSegment(newSegment); + + expect(setSearchBy).toHaveBeenCalledWith('defaultSearchBy'); + expect(setQuery).toHaveBeenCalledWith('defaultQuery'); + expect(setFacets).toHaveBeenCalledWith({}); + expect(setIsLoading).toHaveBeenCalledWith(true); + expect(setCurrentPageNumber).toHaveBeenCalledWith(0); + expect(fetchData).toHaveBeenCalled(); + expect(setIsLoading).toHaveBeenCalledWith(false); + }); + + test('cleanups facetsBySegments on unmount', () => { + const { unmount } = renderHook(useSearch); + + unmount(); + + expect(clearFacetsBySegments).toHaveBeenCalled(); + }); +}); diff --git a/src/test/__tests__/common/hooks/useSearchFiltersData.test.ts b/src/test/__tests__/common/hooks/useSearchFiltersData.test.ts index 7fae0a0f..6ed578a3 100644 --- a/src/test/__tests__/common/hooks/useSearchFiltersData.test.ts +++ b/src/test/__tests__/common/hooks/useSearchFiltersData.test.ts @@ -72,14 +72,14 @@ describe('useSearchFiltersData', () => { test('onToggleFilterGroupState - updates selectedFacetsGroups', () => { const setSelectedFacetsGroups = jest.fn(); - (useRecoilState as jest.Mock).mockReturnValue([['facet1'], setSelectedFacetsGroups]); + (useRecoilState as jest.Mock).mockReturnValue([['facet_1'], setSelectedFacetsGroups]); const { result } = renderHook(() => useSearchFiltersData()); act(() => { - const updatedGroups = result.current.onToggleFilterGroupState('facet2', true); - expect(updatedGroups).toEqual(['facet1', 'facet2']); - expect(setSelectedFacetsGroups).toHaveBeenCalledWith(['facet1', 'facet2']); + const updatedGroups = result.current.onToggleFilterGroupState('facet_2', true); + expect(updatedGroups).toEqual(['facet_1', 'facet_2']); + expect(setSelectedFacetsGroups).toHaveBeenCalledWith(['facet_1', 'facet_2']); }); }); }); diff --git a/src/test/__tests__/common/services/recordNormalizing/recordProcessingCases.test.ts b/src/test/__tests__/common/services/recordNormalizing/recordProcessingCases.test.ts index 7c9170fa..5e6226cc 100644 --- a/src/test/__tests__/common/services/recordNormalizing/recordProcessingCases.test.ts +++ b/src/test/__tests__/common/services/recordNormalizing/recordProcessingCases.test.ts @@ -22,6 +22,33 @@ describe('recordProcessingCases', () => { [creatorBFLiteUri]: { container: creatorNonBFUri }, }); + describe('getLabelUri', () => { + test('returns the correct label URI', () => { + const blockKey = 'block_1'; + const groupKey = 'group_1'; + const fieldKey = 'field_1'; + const expectedLabel = 'testLabel'; + + jest.spyOn(RecordProcessingCases, 'getLabelUri').mockReturnValueOnce(expectedLabel); + + const result = RecordProcessingCases.getLabelUri(blockKey, groupKey, fieldKey); + + expect(result).toBe(expectedLabel); + }); + + test('returns an empty string if label URI is not found', () => { + const blockKey = 'block_1'; + const groupKey = 'group_1'; + const fieldKey = 'field_1'; + + jest.spyOn(RecordProcessingCases, 'getLabelUri').mockReturnValueOnce(''); + + const result = RecordProcessingCases.getLabelUri(blockKey, groupKey, fieldKey); + + expect(result).toBe(''); + }); + }); + describe('wrapWithContainer', () => { const container = 'groupContainer_1'; diff --git a/src/test/__tests__/common/services/userValues/userValueTypes/literal.test.ts b/src/test/__tests__/common/services/userValues/userValueTypes/literal.test.ts index 31a6d559..4e5dcf29 100644 --- a/src/test/__tests__/common/services/userValues/userValueTypes/literal.test.ts +++ b/src/test/__tests__/common/services/userValues/userValueTypes/literal.test.ts @@ -8,9 +8,9 @@ describe('LiteralUserValueService', () => { literalUserValueService = new LiteralUserValueService(); }); - function testGeneratedData(data: string | string[]) { + function testGeneratedData(data: string | string[], uuid?: string) { const testResult = { - uuid: 'testUuid_1', + uuid: uuid ?? '', contents: [ { label: 'test value 1', @@ -20,14 +20,14 @@ describe('LiteralUserValueService', () => { const result = literalUserValueService.generate({ data, - uuid: 'testUuid_1', + uuid, }); expect(result).toEqual(testResult); } test('generates user value for string data', () => { - testGeneratedData('test value 1'); + testGeneratedData('test value 1', 'testUuid_1'); }); test('generates user value for array data', () => {