rtl 13 fixes for tests with type issues

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-10-13 09:21:51 +02:00
parent d60fbcb553
commit 0935b0d60f
33 changed files with 862 additions and 963 deletions
@@ -15,7 +15,7 @@
*/
import React from 'react';
import { renderHook } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react';
import { ThemeProvider } from '@material-ui/core';
@@ -95,12 +95,9 @@ describe('context', () => {
});
it('should return expected entity values', async () => {
const { result, waitForNextUpdate } = renderHook(
() => useEntityMetadata(),
{ wrapper },
);
const { result } = renderHook(() => useEntityMetadata(), { wrapper });
await waitForNextUpdate();
await act(async () => {});
expect(result.current.value).toBeDefined();
expect(result.current.error).toBeUndefined();
@@ -116,12 +113,9 @@ describe('context', () => {
});
it('should return expected techdocs metadata values', async () => {
const { result, waitForNextUpdate } = renderHook(
() => useTechDocsMetadata(),
{ wrapper },
);
const { result } = renderHook(() => useTechDocsMetadata(), { wrapper });
await waitForNextUpdate();
await act(async () => {});
expect(result.current.value).toBeDefined();
expect(result.current.error).toBeUndefined();
@@ -16,7 +16,7 @@
import { NotFoundError } from '@backstage/errors';
import { TestApiProvider } from '@backstage/test-utils';
import { act, renderHook } from '@testing-library/react';
import { act, renderHook, waitFor } from '@testing-library/react';
import React from 'react';
import { techdocsStorageApiRef } from '../../api';
import {
@@ -284,47 +284,45 @@ describe('useReaderState', () => {
return 'cached';
});
await act(async () => {
const { result, waitForValueToChange } = await renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
const { result } = renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
await waitForValueToChange(() => result.current.state);
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(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
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),
});
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
});
it('should reload initially missing content', async () => {
@@ -336,6 +334,7 @@ describe('useReaderState', () => {
});
techdocsStorageApi.syncEntityDocs.mockImplementation(
async (_, logHandler) => {
await 'a tick';
logHandler?.call(this, 'Line 1');
logHandler?.call(this, 'Line 2');
await new Promise(resolve => setTimeout(resolve, 1100));
@@ -343,75 +342,73 @@ describe('useReaderState', () => {
},
);
await act(async () => {
const { result, waitForValueToChange } = await renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
const { result } = renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
await waitForValueToChange(() => result.current.state, {
timeout: 2000,
});
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 waitForValueToChange(() => result.current.state);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
await waitForValueToChange(() => result.current.state);
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);
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledTimes(1);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
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('INITIAL_BUILD'), {
timeout: 2000,
});
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),
});
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2);
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledTimes(1);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
});
it('should handle stale content', async () => {
@@ -423,6 +420,7 @@ describe('useReaderState', () => {
});
techdocsStorageApi.syncEntityDocs.mockImplementation(
async (_, logHandler) => {
await 'a tick';
logHandler?.call(this, 'Line 1');
logHandler?.call(this, 'Line 2');
await new Promise(resolve => setTimeout(resolve, 1100));
@@ -430,101 +428,105 @@ describe('useReaderState', () => {
},
);
await act(async () => {
const { result, waitForValueToChange } = await renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
const { result } = renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
// the content is returned but the sync is in progress
await waitForValueToChange(() => result.current.state);
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 waitForValueToChange(() => result.current.state);
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 waitForValueToChange(() => result.current.state);
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
result.current.contentReload();
// the new content refresh is triggered
await waitForValueToChange(() => result.current.state);
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 waitForValueToChange(() => result.current.state, {
timeout: 2000,
});
expect(result.current).toEqual({
state: 'CONTENT_FRESH',
path: '/example',
content: 'my new content',
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2);
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
// 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),
});
// 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),
});
// 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),
});
// reload the content
await act(async () => {
result.current.contentReload();
});
// 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),
});
// 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),
});
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2);
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
});
it('should handle navigation', async () => {
@@ -537,93 +539,93 @@ describe('useReaderState', () => {
.mockRejectedValueOnce(new NotFoundError('Some error description'));
techdocsStorageApi.syncEntityDocs.mockResolvedValue('cached');
await act(async () => {
const { result, waitForValueToChange, rerender } = await renderHook(
({ path }: { path: string }) =>
useReaderState('Component', 'default', 'backstage', path),
{ initialProps: { path: '/example' }, wrapper: Wrapper as any },
);
const { result, rerender } = renderHook(
({ path }: { path: string }) =>
useReaderState('Component', 'default', 'backstage', path),
{ initialProps: { path: '/example' }, wrapper: Wrapper as any },
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
// show the content
await waitForValueToChange(() => result.current.state);
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 waitForValueToChange(() => result.current.state);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: 'my content',
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
await waitForValueToChange(() => result.current.state, {
timeout: 2000,
});
expect(result.current).toEqual({
state: 'CONTENT_FRESH',
path: '/new',
content: 'my new content',
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
// navigate
rerender({ path: '/missing' });
await waitForValueToChange(() => result.current.state);
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(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/new',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
// 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),
});
// 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.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),
});
// 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),
});
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/new',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
});
it('should handle content error', async () => {
@@ -632,47 +634,47 @@ describe('useReaderState', () => {
);
techdocsStorageApi.syncEntityDocs.mockResolvedValue('cached');
await act(async () => {
const { result, waitForValueToChange } = await renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
const { result } = renderHook(
() => useReaderState('Component', 'default', 'backstage', '/example'),
{ wrapper: Wrapper },
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
// the content loading threw an error
await waitForValueToChange(() => result.current.state);
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(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
expect(result.current).toEqual({
state: 'CHECKING',
path: '/example',
content: undefined,
contentErrorMessage: undefined,
syncErrorMessage: undefined,
buildLog: [],
contentReload: expect.any(Function),
});
// 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),
});
expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith(
{ kind: 'Component', namespace: 'default', name: 'backstage' },
'/example',
);
expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith(
{
kind: 'Component',
namespace: 'default',
name: 'backstage',
},
expect.any(Function),
);
});
});
});