diff --git a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx index dad4740d6c..a7493152de 100644 --- a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx +++ b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, withLogCollector, } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { createTranslationRef, TranslationRef } from './TranslationRef'; import { useTranslationRef } from './useTranslationRef'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports @@ -95,12 +95,11 @@ describe('useTranslationRef', () => { wrapper: makeWrapper(translationApi), }); - await act(async () => {}); - - const { t } = result.current; - - expect(t('key1')).toBe('en1'); - expect(t('key2')).toBe('en2'); + await waitFor(() => { + const { t } = result.current; + expect(t('key1')).toBe('en1'); + expect(t('key2')).toBe('en2'); + }); }); it('should switch between languages', async () => { @@ -124,19 +123,21 @@ describe('useTranslationRef', () => { wrapper: makeWrapper(translationApi), }); - const { t } = result.current; + await waitFor(() => { + const { t } = result.current; - expect(t('key1')).toBe('default1'); - expect(t('key2')).toBe('default2'); + expect(t('key1')).toBe('default1'); + expect(t('key2')).toBe('default2'); + }); languageApi.setLanguage('de'); - await act(async () => {}); + await waitFor(() => { + const { t: t2 } = result.current; - const { t: t2 } = result.current; - - expect(t2('key1')).toBe('de1'); - expect(t2('key2')).toBe('de2'); + expect(t2('key1')).toBe('de1'); + expect(t2('key2')).toBe('de2'); + }); }); it('should load default resource', async () => { @@ -163,12 +164,12 @@ describe('useTranslationRef', () => { wrapper: makeWrapper(translationApi), }); - await act(async () => {}); + await waitFor(() => { + const { t } = result.current; - const { t } = result.current; - - expect(t('key1')).toBe('de1'); - expect(t('key2')).toBe('de2'); + expect(t('key1')).toBe('de1'); + expect(t('key2')).toBe('de2'); + }); }); it('should log once and then ignore loading errors', async () => { diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 45566528bc..079b010ec6 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -18,7 +18,7 @@ import { configApiRef, errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TestApiProvider, MockConfigApi } from '@backstage/test-utils'; import { TextField } from '@material-ui/core'; -import { act, render, screen, waitFor } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; @@ -121,8 +121,6 @@ describe('', () => { }, ); - await act(async () => {}); - const title = await screen.findByText('My title'); const description = await screen.findByText('body', { selector: 'strong', @@ -169,7 +167,6 @@ describe('', () => { wrapper: Wrapper, }, ); - await act(async () => {}); await userEvent.type(await screen.findByLabelText('name'), '-changed'); await userEvent.type(await screen.findByLabelText('owner'), '-changed'); @@ -244,7 +241,6 @@ spec: wrapper: Wrapper, }, ); - await act(async () => {}); await userEvent.click( await screen.findByRole('button', { name: /Create PR/i }), @@ -281,7 +277,6 @@ spec: wrapper: Wrapper, }, ); - await act(async () => {}); await waitFor(() => { expect(catalogApi.getEntities).toHaveBeenCalledTimes(1); diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index a3366506f8..d77655ebcc 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -171,7 +171,6 @@ describe('', () => { wrapper: ({ children }) => wrapper({ location: `/catalog?${query}`, children }), }); - await act(async () => {}); await waitFor(() => { expect(result.current.queryParameters).toBeTruthy(); diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx index 6c76e8eb24..e3010a0f4a 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx @@ -60,9 +60,9 @@ describe('useStarredEntities', () => { wrapper, }); - await act(async () => {}); - - expect(result.current.starredEntities.size).toBe(0); + await waitFor(() => { + expect(result.current.starredEntities.size).toBe(0); + }); }); it('should return a set with the current items', async () => { @@ -75,11 +75,11 @@ describe('useStarredEntities', () => { wrapper, }); - await act(async () => {}); - - for (const item of expectedIds) { - expect(result.current.starredEntities.has(item)).toBeTruthy(); - } + await waitFor(() => { + for (const item of expectedIds) { + expect(result.current.starredEntities.has(item)).toBeTruthy(); + } + }); }); it('should listen to changes when the storage is set elsewhere', async () => { @@ -87,8 +87,6 @@ describe('useStarredEntities', () => { wrapper, }); - await act(async () => {}); - expect(result.current.starredEntities.size).toBe(0); expect(result.current.isStarredEntity(mockEntity)).toBeFalsy(); diff --git a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts index ace954ec2d..40ab619180 100644 --- a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts +++ b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts @@ -16,7 +16,7 @@ import { useCustomResources } from './useCustomResources'; import { Entity } from '@backstage/catalog-model'; -import { act, renderHook, waitFor } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { generateAuth } from './auth'; @@ -103,11 +103,11 @@ describe('useCustomResources', () => { expect(result.current.loading).toEqual(true); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + }); expectMocksCalledCorrectly(); }); @@ -121,16 +121,13 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - expect(result.current.error).toBeUndefined(); - await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + expectMocksCalledCorrectly(2); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); }); it('should return error when getObjectsByEntity throws', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -143,13 +140,13 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers), ); - await act(async () => {}); + await waitFor(() => { + expect(result.current.error).toBe('some error'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); - expect(result.current.error).toBe('some error'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - expectMocksCalledCorrectly(); + expectMocksCalledCorrectly(); + }); }); describe('when retrying', () => { @@ -166,19 +163,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset error after getCustomObjectsByEntity has failed and then succeeded', async () => { @@ -192,19 +187,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset data after generateAuth succeeded then failed', async () => { @@ -220,19 +213,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); it('should reset data after getCustomObjectsByEntity succeeded then failed', async () => { @@ -246,19 +237,17 @@ describe('useCustomResources', () => { useCustomResources(entity, customResourceMatchers, 100), ); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); }); }); diff --git a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts index 9fa642e071..e88432f980 100644 --- a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts +++ b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts @@ -16,7 +16,7 @@ import { useKubernetesObjects } from './useKubernetesObjects'; import { Entity } from '@backstage/catalog-model'; -import { act, renderHook, waitFor } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { generateAuth } from './auth'; @@ -92,14 +92,12 @@ describe('useKubernetesObjects', () => { expect(result.current.loading).toEqual(true); await waitFor(() => { + expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + + expectMocksCalledCorrectly(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - - expectMocksCalledCorrectly(); }); it('should update on an interval', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -112,14 +110,12 @@ describe('useKubernetesObjects', () => { expect(result.current.error).toBeUndefined(); await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + expectMocksCalledCorrectly(2); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - - expectMocksCalledCorrectly(2); }); it('should return error when getObjectsByEntity throws', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -130,13 +126,13 @@ describe('useKubernetesObjects', () => { }); const { result } = renderHook(() => useKubernetesObjects(entity)); - await act(async () => {}); + await waitFor(() => { + expect(result.current.error).toBe('some error'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); - expect(result.current.error).toBe('some error'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - expectMocksCalledCorrectly(); + expectMocksCalledCorrectly(); + }); }); describe('when retrying', () => { @@ -151,19 +147,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset error after getObjectsByEntity has failed and then succeeded', async () => { @@ -175,19 +169,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); await waitFor(() => { expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); }); it('should reset data after generateAuth succeeded then failed', async () => { @@ -201,19 +193,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); it('should reset data after getObjectsByEntity succeeded then failed', async () => { @@ -225,19 +215,17 @@ describe('useKubernetesObjects', () => { const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await act(async () => {}); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - await waitFor(() => { - expect(result.current.error).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); }); - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); }); }); diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx index 440eb6a6fa..69acd34dc3 100644 --- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx +++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { act, renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { WebsiteListResponse } from '@backstage/plugin-lighthouse-common'; import { lighthouseApiRef } from '../api'; @@ -78,8 +78,9 @@ describe('useWebsiteForEntity', () => { it('returns the lighthouse information for the website url in annotations', async () => { const { result } = subject(); - await act(async () => {}); - expect(result.current?.value).toBe(website); + await waitFor(() => { + expect(result.current?.value).toBe(website); + }); }); describe('where there is an error', () => { @@ -93,9 +94,10 @@ describe('useWebsiteForEntity', () => { it('posts the error to the error api and returns the error to the caller', async () => { const { result } = subject(); - await act(async () => {}); - expect(result.current?.error).toBe(error); - expect(mockErrorApi.post).toHaveBeenCalledWith(error); + await waitFor(() => { + expect(result.current?.error).toBe(error); + expect(mockErrorApi.post).toHaveBeenCalledWith(error); + }); }); }); @@ -110,9 +112,10 @@ describe('useWebsiteForEntity', () => { it('does not post the error to the error api and returns the error to the caller', async () => { const { result } = subject(); - await act(async () => {}); - expect(result.current?.error).toBe(error); - expect(mockErrorApi.post).not.toHaveBeenCalledWith(error); + await waitFor(() => { + expect(result.current?.error).toBe(error); + expect(mockErrorApi.post).not.toHaveBeenCalledWith(error); + }); }); }); }); diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index cb02f94ac5..eac5a171ba 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -16,7 +16,7 @@ import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; import { useGetEntities } from './useGetEntities'; import { CatalogApi } from '@backstage/catalog-client'; -import { act, renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { getEntityRelations } from '@backstage/plugin-catalog-react'; const givenParentGroup = 'team.squad1'; @@ -66,11 +66,14 @@ describe('useGetEntities', () => { describe('given aggregated relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - renderHook(({ entity }) => useGetEntities(entity, 'aggregated'), { - initialProps: { entity: _entity }, - }); + const { result } = renderHook( + ({ entity }) => useGetEntities(entity, 'aggregated'), + { + initialProps: { entity: _entity }, + }, + ); - await act(async () => {}); + await waitFor(() => expect(result.current.loading).toBe(false)); }; beforeEach(() => { @@ -204,11 +207,14 @@ describe('useGetEntities', () => { describe('given direct relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - renderHook(({ entity }) => useGetEntities(entity, 'direct'), { - initialProps: { entity: _entity }, - }); + const { result } = renderHook( + ({ entity }) => useGetEntities(entity, 'direct'), + { + initialProps: { entity: _entity }, + }, + ); - await act(async () => {}); + await waitFor(() => expect(result.current.loading).toBe(false)); }; it('given group entity should return directly owned entities', async () => { diff --git a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx index dda09a0e04..ce0d49802b 100644 --- a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx +++ b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx @@ -119,8 +119,8 @@ describe('', () => { }); await waitFor(() => { expect(result.current.backendPlaylists.length).toBe(2); + expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); }); - expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); }); it('resolves frontend filters', async () => { @@ -155,14 +155,12 @@ describe('', () => { wrapper: ({ children }) => wrapper({ location: `/playlist?${query}`, children }), }); - await act(async () => {}); await waitFor(() => { - expect(result.current.queryParameters).toBeTruthy(); - }); - expect(result.current.queryParameters).toEqual({ - personal: 'all', - owners: ['user:default/guest'], + expect(result.current.queryParameters).toEqual({ + personal: 'all', + owners: ['user:default/guest'], + }); }); }); diff --git a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx index 3d61c11b79..884512963f 100644 --- a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { ApiProvider } from '@backstage/core-app-api'; import { MockConfigApi, TestApiRegistry } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { searchApiRef } from '../../api'; import { SearchContextProvider, useSearch } from '../../context'; @@ -77,9 +77,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should set non-empty array value', async () => { @@ -95,9 +95,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set undefined value', async () => { @@ -121,9 +121,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set null value', async () => { @@ -147,9 +147,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set empty string value', async () => { @@ -173,9 +173,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set empty array value', async () => { @@ -199,9 +199,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not affect unrelated filters', async () => { @@ -225,9 +225,9 @@ describe('SearchFilter.hooks', () => { }, ); - await act(async () => {}); - - expect(result.current.filters.unrelatedField).toEqual('unrelatedValue'); + await waitFor(() => { + expect(result.current.filters.unrelatedField).toEqual('unrelatedValue'); + }); }); }); diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index 7ac2d6d11b..5aa217553f 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -89,9 +89,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); - - expect(result.current).toEqual(true); + await waitFor(() => { + expect(result.current).toEqual(true); + }); }); describe('Uses initial state values', () => { @@ -100,17 +100,17 @@ describe('SearchContext', () => { wrapper, }); - await act(async () => {}); - - expect(result.current).toEqual( - expect.objectContaining({ - term: '', - types: [], - filters: {}, - pageLimit: undefined, - pageCursor: undefined, - }), - ); + await waitFor(() => { + expect(result.current).toEqual( + expect.objectContaining({ + term: '', + types: [], + filters: {}, + pageLimit: undefined, + pageCursor: undefined, + }), + ); + }); }); it('Uses provided initial state values', async () => { @@ -118,9 +118,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); - - expect(result.current).toEqual(expect.objectContaining(initialState)); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); }); it('Uses page limit provided via config api', async () => { @@ -139,11 +139,11 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current).toEqual( - expect.objectContaining({ ...initialState, pageLimit: 100 }), - ); + await waitFor(() => { + expect(result.current).toEqual( + expect.objectContaining({ ...initialState, pageLimit: 100 }), + ); + }); }); }); @@ -161,10 +161,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.term).toEqual('first term'); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setTerm(''); @@ -186,10 +186,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.term).toEqual('first term'); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setTerm('second term'); @@ -212,10 +212,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.filters).toEqual({ foo: 'bar' }); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setFilters({}); @@ -238,10 +238,10 @@ describe('SearchContext', () => { }), }); - await act(async () => {}); - - expect(result.current.filters).toEqual({ foo: 'bar' }); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); + await waitFor(() => { + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); await act(async () => { result.current.setFilters({ foo: 'test' }); @@ -257,7 +257,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const term = 'term'; @@ -277,7 +279,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const types = ['type']; @@ -297,7 +301,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const filters = { filter: 'filter' }; @@ -317,7 +323,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const pageLimit = 30; @@ -338,7 +346,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const pageCursor = 'SOMEPAGE'; @@ -364,7 +374,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); expect(result.current.fetchNextPage).toBeDefined(); expect(result.current.fetchPreviousPage).toBeUndefined(); @@ -391,7 +403,9 @@ describe('SearchContext', () => { wrapper: ({ children }) => wrapper({ children, initialState }), }); - await act(async () => {}); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); expect(result.current.fetchNextPage).toBeUndefined(); expect(result.current.fetchPreviousPage).toBeDefined(); diff --git a/plugins/techdocs-react/src/context.test.tsx b/plugins/techdocs-react/src/context.test.tsx index e66630b04e..bcab445729 100644 --- a/plugins/techdocs-react/src/context.test.tsx +++ b/plugins/techdocs-react/src/context.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderHook, act } from '@testing-library/react'; +import { renderHook, act, waitFor } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; @@ -140,9 +140,9 @@ describe('useTechDocsReaderPage', () => { namespace: mockEntityMetadata.metadata.namespace?.toLocaleLowerCase(), }; const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); - await act(async () => {}); - - expect(result.current.entityRef).toStrictEqual(lowercaseEntityRef); + await waitFor(() => { + expect(result.current.entityRef).toStrictEqual(lowercaseEntityRef); + }); }); it('entityRef is not modified when legacyUseCaseSensitiveTripletPaths is true', async () => { @@ -159,23 +159,23 @@ describe('useTechDocsReaderPage', () => { config: { techdocs: { legacyUseCaseSensitiveTripletPaths: true } }, }), }); - await act(async () => {}); - - expect(result.current.entityRef).toStrictEqual(caseSensitiveEntityRef); + await waitFor(() => { + expect(result.current.entityRef).toStrictEqual(caseSensitiveEntityRef); + }); }); it('entityRef provided as analytics context', async () => { renderHook(() => useAnalytics().captureEvent('action', 'subject'), { wrapper, }); - await act(async () => {}); - - expect(analyticsApiMock.getEvents()[0]).toMatchObject({ - action: 'action', - subject: 'subject', - context: { - entityRef: 'component:default/test', - }, + await waitFor(() => { + expect(analyticsApiMock.getEvents()[0]).toMatchObject({ + action: 'action', + subject: 'subject', + context: { + entityRef: 'component:default/test', + }, + }); }); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx index 43dabaa7c7..670653ce6b 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { act, renderHook } from '@testing-library/react'; +import { renderHook, waitFor } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; @@ -97,11 +97,11 @@ describe('context', () => { it('should return expected entity values', async () => { const { result } = renderHook(() => useEntityMetadata(), { wrapper }); - await act(async () => {}); - - expect(result.current.value).toBeDefined(); - expect(result.current.error).toBeUndefined(); - expect(result.current.value).toMatchObject(mockEntityMetadata); + await waitFor(() => { + expect(result.current.value).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.value).toMatchObject(mockEntityMetadata); + }); }); }); @@ -115,11 +115,11 @@ describe('context', () => { it('should return expected techdocs metadata values', async () => { const { result } = renderHook(() => useTechDocsMetadata(), { wrapper }); - await act(async () => {}); - - expect(result.current.value).toBeDefined(); - expect(result.current.error).toBeUndefined(); - expect(result.current.value).toMatchObject(mockTechDocsMetadata); + await waitFor(() => { + expect(result.current.value).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.value).toMatchObject(mockTechDocsMetadata); + }); }); }); }); diff --git a/plugins/techdocs/src/reader/components/useReaderState.test.tsx b/plugins/techdocs/src/reader/components/useReaderState.test.tsx index d8851a805d..60898ab288 100644 --- a/plugins/techdocs/src/reader/components/useReaderState.test.tsx +++ b/plugins/techdocs/src/reader/components/useReaderState.test.tsx @@ -299,16 +299,16 @@ describe('useReaderState', () => { contentReload: expect.any(Function), }); - await act(async () => {}); - - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( @@ -357,42 +357,45 @@ describe('useReaderState', () => { contentReload: expect.any(Function), }); - await waitFor(() => expect(result.current.state).toBe('INITIAL_BUILD'), { - timeout: 2000, + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'INITIAL_BUILD', + path: '/example', + content: undefined, + contentErrorMessage: 'NotFoundError: Page Not Found', + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); + }, + { + timeout: 2000, + }, + ); + + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); - expect(result.current).toEqual({ - state: 'INITIAL_BUILD', - path: '/example', - content: undefined, - contentErrorMessage: 'NotFoundError: Page Not Found', - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), - }); - - await waitFor(() => expect(result.current.state).toBe('CHECKING')); - - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); - - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); @@ -444,43 +447,42 @@ describe('useReaderState', () => { }); // the content is returned but the sync is in progress - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); }); // the sync takes longer than 1 seconds so the refreshing state starts - await waitFor(() => - expect(result.current.state).toBe('CONTENT_STALE_REFRESHING'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_STALE_REFRESHING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_STALE_REFRESHING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); }); // the content is updated but not yet displayed - await waitFor(() => - expect(result.current.state).toBe('CONTENT_STALE_READY'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_STALE_READY', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_STALE_READY', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); }); // reload the content @@ -489,30 +491,35 @@ describe('useReaderState', () => { }); // the new content refresh is triggered - await waitFor(() => expect(result.current.state).toBe('CHECKING')); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); // the new content is loaded - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH'), { - timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + }, + { + timeout: 2000, + }, + ); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( @@ -556,58 +563,63 @@ describe('useReaderState', () => { }); // show the content - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH')); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); // navigate rerender({ path: '/new' }); - await waitFor(() => expect(result.current.state).toBe('CHECKING')); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: 'my content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: 'my content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); - await waitFor(() => expect(result.current.state).toBe('CONTENT_FRESH'), { - timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/new', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/new', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + }, + { + timeout: 2000, + }, + ); // navigate rerender({ path: '/missing' }); - await waitFor(() => - expect(result.current.state).toBe('CONTENT_NOT_FOUND'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_NOT_FOUND', - path: '/missing', - content: undefined, - contentErrorMessage: 'NotFoundError: Some error description', - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_NOT_FOUND', + path: '/missing', + content: undefined, + contentErrorMessage: 'NotFoundError: Some error description', + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( @@ -650,17 +662,16 @@ describe('useReaderState', () => { }); // the content loading threw an error - await waitFor(() => - expect(result.current.state).toBe('CONTENT_NOT_FOUND'), - ); - expect(result.current).toEqual({ - state: 'CONTENT_NOT_FOUND', - path: '/example', - content: undefined, - contentErrorMessage: 'NotFoundError: Some error description', - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), + await waitFor(() => { + expect(result.current).toEqual({ + state: 'CONTENT_NOT_FOUND', + path: '/example', + content: undefined, + contentErrorMessage: 'NotFoundError: Some error description', + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); }); expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(