From 4194f507a2b7436fb869954eac0fabc517aa6d07 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 15 Nov 2023 13:42:04 +0100 Subject: [PATCH] catalog-react: refactor useEntityListProvider tests Signed-off-by: Vincenzo Scamporlino --- .../src/hooks/useEntityListProvider.test.tsx | 131 +++++++++++------- 1 file changed, 78 insertions(+), 53 deletions(-) diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index edbfb65c0c..1a8d7b5c30 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -31,14 +31,13 @@ import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { catalogApiRef } from '../api'; import { starredEntitiesApiRef, MockStarredEntitiesApi } from '../apis'; -import { EntityKindPicker, UserListPicker } from '../components'; import { EntityKindFilter, EntityTypeFilter, EntityUserFilter, } from '../filters'; -import { UserListFilterKind } from '../types'; import { EntityListProvider, useEntityList } from './useEntityListProvider'; +import { useMountEffect } from '@react-hookz/web'; const entities: Entity[] = [ { @@ -77,43 +76,53 @@ const mockIdentityApi: Partial = { }), getCredentials: async () => ({ token: undefined }), }; -const mockCatalogApi: Partial = { - getEntities: jest.fn().mockImplementation(async () => ({ items: entities })), - getEntityByRef: async () => undefined, +const mockCatalogApi: Partial> = { + getEntities: jest.fn().mockResolvedValue({ items: entities }), + queryEntities: jest.fn().mockResolvedValue({ + items: entities, + pageInfo: { prevCursor: 'prevCursor', nextCursor: 'nextCursor' }, + totalItems: 10, + }), + getEntityByRef: jest.fn().mockResolvedValue(undefined), }; -const wrapper = ({ - userFilter, - location, - children, -}: PropsWithChildren<{ - userFilter?: UserListFilterKind; - location?: string; -}>) => { - return ( - - - - - - - ); -}; +const createWrapper = + (options: { location?: string; enablePagination: boolean }) => + (props: PropsWithChildren) => { + const InitialFiltersWrapper = ({ children }: PropsWithChildren) => { + const { updateFilters } = useEntityList(); + + useMountEffect(() => { + updateFilters({ kind: new EntityKindFilter('component') }); + }); + + return <>{children}; + }; + + return ( + + + + {props.children} + + + + ); + }; describe('', () => { const origReplaceState = window.history.replaceState; + const enablePagination = false; + beforeEach(() => { window.history.replaceState = jest.fn(); }); @@ -125,16 +134,17 @@ describe('', () => { jest.clearAllMocks(); }); - it('resolves backend filters', async () => { + it('should send backend filters', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ enablePagination }), }); await waitFor(() => { - expect(result.current.backendEntities.length).toBeGreaterThan(0); + expect(result.current.backendEntities.length).toBe(2); }); - expect(result.current.backendEntities.length).toBe(2); + expect(result.current.entities.length).toBe(2); + expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); expect(mockCatalogApi.getEntities).toHaveBeenCalledWith({ filter: { kind: 'component' }, }); @@ -142,17 +152,12 @@ describe('', () => { it('resolves frontend filters', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ enablePagination }), initialProps: { userFilter: 'all', }, }); - await waitFor(() => { - expect(result.current.backendEntities.length).toBeGreaterThan(0); - }); - expect(result.current.backendEntities.length).toBe(2); - act(() => result.current.updateFilters({ user: EntityUserFilter.owned(ownershipEntityRefs), @@ -171,8 +176,10 @@ describe('', () => { filters: { kind: 'component', type: 'service' }, }); const { result } = renderHook(() => useEntityList(), { - wrapper: ({ children }) => - wrapper({ location: `/catalog?${query}`, children }), + wrapper: createWrapper({ + location: `/catalog?${query}`, + enablePagination, + }), }); await waitFor(() => { @@ -186,7 +193,7 @@ describe('', () => { it('does not fetch when only frontend filters change', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ enablePagination }), }); await waitFor(() => { @@ -202,13 +209,18 @@ describe('', () => { await waitFor(() => { expect(result.current.entities.length).toBe(1); - expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); }); + + await expect(() => + waitFor(() => { + expect(mockCatalogApi.getEntities).not.toHaveBeenCalledTimes(1); + }), + ).rejects.toThrow(); }); it('debounces multiple filter changes', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ enablePagination }), }); await waitFor(() => { @@ -218,18 +230,20 @@ describe('', () => { expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); await act(async () => { - result.current.updateFilters({ kind: new EntityKindFilter('component') }); + result.current.updateFilters({ kind: new EntityKindFilter('api') }); result.current.updateFilters({ type: new EntityTypeFilter('service') }); }); await waitFor(() => { - expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(2); + expect(mockCatalogApi.getEntities).toHaveBeenNthCalledWith(2, { + filter: { kind: 'api', 'spec.type': ['service'] }, + }); }); }); it('returns an error on catalogApi failure', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ enablePagination }), }); await waitFor(() => { @@ -237,7 +251,7 @@ describe('', () => { }); expect(result.current.backendEntities.length).toBe(2); - mockCatalogApi.getEntities = jest.fn().mockRejectedValue('error'); + mockCatalogApi.getEntities!.mockRejectedValueOnce('error'); act(() => { result.current.updateFilters({ kind: new EntityKindFilter('api') }); }); @@ -245,4 +259,15 @@ describe('', () => { expect(result.current.error).toBeDefined(); }); }); + + it('returns an empty pageInfo', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ enablePagination }), + }); + await waitFor(() => { + expect(mockCatalogApi.getEntities).toHaveBeenCalled(); + }); + + expect(result.current.pageInfo).toBeUndefined(); + }); });