From b54e8ffc8546027e8ceba2d6dca7d1c99ca045eb Mon Sep 17 00:00:00 2001 From: Victor Navarro Date: Wed, 11 Jun 2025 06:28:54 -0600 Subject: [PATCH] test: deprecate react-unit-test-utils part-2 (#428) --- .../FilePreview/Banners/ErrorBanner.test.jsx | 56 +++++------ .../Banners/LoadingBanner.test.jsx | 23 +++-- .../__snapshots__/ErrorBanner.test.jsx.snap | 42 --------- .../__snapshots__/LoadingBanner.test.jsx.snap | 12 --- .../BaseRenderers/ImageRenderer.test.jsx | 40 ++++++-- .../__snapshots__/ImageRenderer.test.jsx.snap | 11 --- src/components/FilePreview/FileInfo.test.jsx | 35 ++++--- .../FilePreview/FileRenderer.test.jsx | 94 ++++++++++++------- .../__snapshots__/FileInfo.test.jsx.snap | 34 ------- .../__snapshots__/FileRenderer.test.jsx.snap | 33 ------- 10 files changed, 153 insertions(+), 227 deletions(-) delete mode 100644 src/components/FilePreview/Banners/__snapshots__/ErrorBanner.test.jsx.snap delete mode 100644 src/components/FilePreview/Banners/__snapshots__/LoadingBanner.test.jsx.snap delete mode 100644 src/components/FilePreview/BaseRenderers/__snapshots__/ImageRenderer.test.jsx.snap delete mode 100644 src/components/FilePreview/__snapshots__/FileInfo.test.jsx.snap delete mode 100644 src/components/FilePreview/__snapshots__/FileRenderer.test.jsx.snap diff --git a/src/components/FilePreview/Banners/ErrorBanner.test.jsx b/src/components/FilePreview/Banners/ErrorBanner.test.jsx index f1f5897..990c938 100644 --- a/src/components/FilePreview/Banners/ErrorBanner.test.jsx +++ b/src/components/FilePreview/Banners/ErrorBanner.test.jsx @@ -1,10 +1,10 @@ -import React from 'react'; -import { shallow } from '@edx/react-unit-test-utils'; - +import { render, screen } from '@testing-library/react'; import ErrorBanner from './ErrorBanner'; - import messages from '../messages'; +jest.unmock('@openedx/paragon'); +jest.unmock('react'); + describe('Error Banner component', () => { const children =

Abitary Child

; @@ -25,39 +25,29 @@ describe('Error Banner component', () => { children, }; - let el; - beforeEach(() => { - el = shallow(); - }); - - test('snapshot', () => { - expect(el.snapshot).toMatchSnapshot(); - }); - - describe('component', () => { - test('children node', () => { - const childElement = el.instance.children[1]; - const child = shallow(children); - - expect(childElement.type).toEqual(child.type); - expect(childElement.children[0].el).toEqual(child.children[0].el); + describe('behavior', () => { + it('renders children content', () => { + render(); + const childText = screen.getByText('Abitary Child'); + expect(childText).toBeInTheDocument(); }); - test('verify actions', () => { - const { actions } = el.instance.findByType('Alert')[0].props; - expect(actions).toHaveLength(props.actions.length); - - actions.forEach((action, index) => { - expect(action.type).toEqual('Button'); - expect(action.props.onClick).toEqual(props.actions[index].onClick); - // action message - expect(action.props.children.props).toEqual(props.actions[index].message); - }); + it('renders the correct number of action buttons', () => { + render(); + const buttons = screen.getAllByText('FormattedMessage'); + expect(buttons).toHaveLength(3); }); - test('verify heading', () => { - const heading = el.instance.findByType('FormattedMessage')[0]; - expect(heading.props).toEqual(props.headingMessage); + it('renders error heading with correct message', () => { + render(); + const heading = screen.getAllByText('FormattedMessage')[0]; + expect(heading).toBeInTheDocument(); + }); + + it('renders with danger variant', () => { + render(); + const alert = screen.getByRole('alert'); + expect(alert).toHaveClass('alert-danger'); }); }); }); diff --git a/src/components/FilePreview/Banners/LoadingBanner.test.jsx b/src/components/FilePreview/Banners/LoadingBanner.test.jsx index c05c6e8..f0abfb3 100644 --- a/src/components/FilePreview/Banners/LoadingBanner.test.jsx +++ b/src/components/FilePreview/Banners/LoadingBanner.test.jsx @@ -1,11 +1,22 @@ -import React from 'react'; -import { shallow } from '@edx/react-unit-test-utils'; - +import { render, screen } from '@testing-library/react'; import LoadingBanner from './LoadingBanner'; +jest.unmock('@openedx/paragon'); +jest.unmock('react'); + describe('Loading Banner component', () => { - test('snapshot', () => { - const el = shallow(); - expect(el.snapshot).toMatchSnapshot(); + describe('behavior', () => { + it('renders an info alert', () => { + render(); + const alert = screen.getByRole('alert'); + expect(alert).toHaveClass('alert-info'); + }); + + it('renders a spinner', () => { + const { container } = render(); + const spinner = container.querySelector('.pgn__spinner'); + expect(spinner).toBeInTheDocument(); + expect(spinner).toHaveClass('spinner-border'); + }); }); }); diff --git a/src/components/FilePreview/Banners/__snapshots__/ErrorBanner.test.jsx.snap b/src/components/FilePreview/Banners/__snapshots__/ErrorBanner.test.jsx.snap deleted file mode 100644 index 1a7ecc9..0000000 --- a/src/components/FilePreview/Banners/__snapshots__/ErrorBanner.test.jsx.snap +++ /dev/null @@ -1,42 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Error Banner component snapshot 1`] = ` - - - , - , - ] - } - variant="danger" -> - - - -

- Abitary Child -

-
-`; diff --git a/src/components/FilePreview/Banners/__snapshots__/LoadingBanner.test.jsx.snap b/src/components/FilePreview/Banners/__snapshots__/LoadingBanner.test.jsx.snap deleted file mode 100644 index d6a2a51..0000000 --- a/src/components/FilePreview/Banners/__snapshots__/LoadingBanner.test.jsx.snap +++ /dev/null @@ -1,12 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Loading Banner component snapshot 1`] = ` - - - -`; diff --git a/src/components/FilePreview/BaseRenderers/ImageRenderer.test.jsx b/src/components/FilePreview/BaseRenderers/ImageRenderer.test.jsx index 8e6d87e..d558318 100644 --- a/src/components/FilePreview/BaseRenderers/ImageRenderer.test.jsx +++ b/src/components/FilePreview/BaseRenderers/ImageRenderer.test.jsx @@ -1,21 +1,43 @@ import React from 'react'; -import { shallow } from '@edx/react-unit-test-utils'; +import { render, screen } from '@testing-library/react'; import ImageRenderer from './ImageRenderer'; +jest.unmock('@openedx/paragon'); +jest.unmock('react'); + describe('Image Renderer Component', () => { const props = { url: 'some_url.jpg', + fileName: 'test-image.jpg', + onError: jest.fn().mockName('this.props.onError'), + onSuccess: jest.fn().mockName('this.props.onSuccess'), }; - props.onError = jest.fn().mockName('this.props.onError'); - props.onSuccess = jest.fn().mockName('this.props.onSuccess'); - - let el; - beforeEach(() => { - el = shallow(); + it('renders an image with the correct src and alt attributes', () => { + render(); + const imgElement = screen.getByRole('img'); + expect(imgElement).toBeInTheDocument(); + expect(imgElement).toHaveAttribute('src', props.url); + expect(imgElement).toHaveAttribute('alt', props.fileName); + expect(imgElement).toHaveClass('image-renderer'); }); - test('snapshot', () => { - expect(el.snapshot).toMatchSnapshot(); + + it('calls onSuccess when image loads successfully', () => { + render(); + + const imgElement = screen.getByRole('img'); + imgElement.dispatchEvent(new Event('load')); + + expect(props.onSuccess).toHaveBeenCalled(); + }); + + it('calls onError when image fails to load', () => { + render(); + + const imgElement = screen.getByRole('img'); + imgElement.dispatchEvent(new Event('error')); + + expect(props.onError).toHaveBeenCalled(); }); }); diff --git a/src/components/FilePreview/BaseRenderers/__snapshots__/ImageRenderer.test.jsx.snap b/src/components/FilePreview/BaseRenderers/__snapshots__/ImageRenderer.test.jsx.snap deleted file mode 100644 index 3e9712c..0000000 --- a/src/components/FilePreview/BaseRenderers/__snapshots__/ImageRenderer.test.jsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Image Renderer Component snapshot 1`] = ` - -`; diff --git a/src/components/FilePreview/FileInfo.test.jsx b/src/components/FilePreview/FileInfo.test.jsx index 5c3627f..1fa500f 100644 --- a/src/components/FilePreview/FileInfo.test.jsx +++ b/src/components/FilePreview/FileInfo.test.jsx @@ -1,25 +1,30 @@ -import React from 'react'; -import { shallow } from '@edx/react-unit-test-utils'; - -import { Popover } from '@openedx/paragon'; +import { render, screen, fireEvent } from '@testing-library/react'; import FileInfo from './FileInfo'; -describe('File Preview Card component', () => { +jest.unmock('@openedx/paragon'); +jest.unmock('react'); + +describe('FileInfo component', () => { const children = (

some Children

); const props = { onClick: jest.fn().mockName('this.props.onClick') }; - let el; + beforeEach(() => { - el = shallow({children}); + jest.clearAllMocks(); }); - test('snapshot', () => { - expect(el.snapshot).toMatchSnapshot(); - }); - describe('Component', () => { - test('overlay with passed children', () => { - const { overlay } = el.instance.props; - expect(overlay.type).toEqual(Popover); - expect(overlay.props.children).toEqual({children}); + + describe('Component rendering', () => { + it('renders the FileInfo button with correct text', () => { + render({children}); + + expect(screen.getByText('FormattedMessage')).toBeInTheDocument(); + }); + + it('calls onClick when button is clicked', () => { + render({children}); + + fireEvent.click(screen.getByText('FormattedMessage')); + expect(props.onClick).toHaveBeenCalledTimes(1); }); }); }); diff --git a/src/components/FilePreview/FileRenderer.test.jsx b/src/components/FilePreview/FileRenderer.test.jsx index f3fb79c..acbf995 100644 --- a/src/components/FilePreview/FileRenderer.test.jsx +++ b/src/components/FilePreview/FileRenderer.test.jsx @@ -1,18 +1,12 @@ -import React from 'react'; -import { shallow } from '@edx/react-unit-test-utils'; - +import { render, screen } from '@testing-library/react'; import { formatMessage } from 'testUtils'; import { keyStore } from 'utils'; import { ErrorStatuses } from 'data/constants/requests'; - import { FileRenderer } from './FileRenderer'; import * as hooks from './hooks'; -jest.mock('./FileCard', () => 'FileCard'); -jest.mock('./Banners', () => ({ - ErrorBanner: () => 'ErrorBanner', - LoadingBanner: () => 'LoadingBanner', -})); +jest.unmock('@openedx/paragon'); +jest.unmock('react'); const hookKeys = keyStore(hooks); @@ -20,34 +14,70 @@ const props = { file: { downloadUrl: 'file download url', name: 'filename.txt', + description: 'A text file', }, intl: { formatMessage }, }; describe('FileRenderer', () => { describe('component', () => { - describe('snapshot', () => { - test('isLoading, no Error', () => { - const hookProps = { - Renderer: () => 'Renderer', - isloading: true, - errorStatus: null, - error: null, - rendererProps: { prop: 'hooks.rendererProps' }, - }; - jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps); - expect(shallow().snapshot).toMatchSnapshot(); - }); - test('is not loading, with error', () => { - const hookProps = { - Renderer: () => 'Renderer', - isloading: false, - errorStatus: ErrorStatuses.serverError, - error: { prop: 'hooks.errorProps' }, - rendererProps: { prop: 'hooks.rendererProps' }, - }; - jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps); - expect(shallow().snapshot).toMatchSnapshot(); - }); + it('renders loading banner when isLoading is true', () => { + const hookProps = { + Renderer: () =>
Renderer Component
, + isLoading: true, + errorStatus: null, + error: null, + rendererProps: { prop: 'hooks.rendererProps' }, + }; + jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps); + render(); + + expect(screen.getByText('filename.txt')).toBeInTheDocument(); + expect(screen.getByTestId('mock-renderer')).toBeInTheDocument(); + const spinner = document.querySelector('.spinner-border'); + expect(spinner).toBeInTheDocument(); + }); + it('renders error banner when there is an error status', () => { + const errorProps = { + headingMessage: { id: 'error.heading', defaultMessage: 'Error Heading' }, + children: 'Error Message', + actions: [{ id: 'retry', onClick: jest.fn(), message: { id: 'retry', defaultMessage: 'Retry' } }], + }; + + const hookProps = { + Renderer: () =>
Renderer Component
, + isLoading: false, + errorStatus: ErrorStatuses.serverError, + error: errorProps, + rendererProps: { prop: 'hooks.rendererProps' }, + }; + jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps); + + render(); + + expect(screen.getByText('filename.txt')).toBeInTheDocument(); + expect(screen.getByText('Error Message')).toBeInTheDocument(); + expect(document.querySelector('.alert-heading')).toBeInTheDocument(); + expect(document.querySelector('.btn.btn-outline-primary')).toBeInTheDocument(); + }); + + it('renders renderer component when not loading and no error', () => { + const hookProps = { + Renderer: () =>
Renderer Component
, + isLoading: false, + errorStatus: null, + error: null, + rendererProps: { prop: 'hooks.rendererProps' }, + }; + jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps); + + render(); + + expect(screen.getByText('filename.txt')).toBeInTheDocument(); + expect(screen.getByTestId('mock-renderer')).toBeInTheDocument(); + expect(screen.getByText('Renderer Component')).toBeInTheDocument(); + + const spinner = document.querySelector('.spinner-border'); + expect(spinner).not.toBeInTheDocument(); }); }); }); diff --git a/src/components/FilePreview/__snapshots__/FileInfo.test.jsx.snap b/src/components/FilePreview/__snapshots__/FileInfo.test.jsx.snap deleted file mode 100644 index cda256b..0000000 --- a/src/components/FilePreview/__snapshots__/FileInfo.test.jsx.snap +++ /dev/null @@ -1,34 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`File Preview Card component snapshot 1`] = ` - - -

- some Children -

-
- - } - placement="right-end" - trigger="focus" -> - -
-`; diff --git a/src/components/FilePreview/__snapshots__/FileRenderer.test.jsx.snap b/src/components/FilePreview/__snapshots__/FileRenderer.test.jsx.snap deleted file mode 100644 index b6bc460..0000000 --- a/src/components/FilePreview/__snapshots__/FileRenderer.test.jsx.snap +++ /dev/null @@ -1,33 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`FileRenderer component snapshot is not loading, with error 1`] = ` - - - -`; - -exports[`FileRenderer component snapshot isLoading, no Error 1`] = ` - - - -`;