diff --git a/package-lock.json b/package-lock.json index d4c9360d37..85a94eacd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "@edx/frontend-lib-special-exams": "^4.0.0", "@edx/frontend-platform": "^8.3.1", "@edx/openedx-atlas": "^0.7.0", - "@edx/react-unit-test-utils": "^4.0.0", "@fortawesome/free-brands-svg-icons": "5.15.4", "@fortawesome/free-regular-svg-icons": "5.15.4", "@fortawesome/free-solid-svg-icons": "5.15.4", @@ -70,6 +69,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.2.tgz", "integrity": "sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==", + "dev": true, "license": "MIT" }, "node_modules/@ampproject/remapping": { @@ -2602,30 +2602,6 @@ "atlas": "atlas" } }, - "node_modules/@edx/react-unit-test-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@edx/react-unit-test-utils/-/react-unit-test-utils-4.0.0.tgz", - "integrity": "sha512-QlVYhYD9L2bzx1eAtf8BbCJr00ek9rrHrG+/pW2bVSt+t0uvKHQpX1CNdMrDePv18DsMeC7IOB00t8ZIn4mi7w==", - "license": "AGPL-3.0", - "dependencies": { - "@edx/browserslist-config": "^1.1.1", - "@reduxjs/toolkit": "^1.5.1", - "@testing-library/dom": "^10.4.0", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.2.0", - "classnames": "^2.2.6", - "core-js": "3.6.5", - "lodash": "^4.17.21", - "react-dev-utils": "^12.0.1", - "react-test-renderer": "^18.3.1" - }, - "peerDependencies": { - "@edx/frontend-platform": "^8.3.1", - "@openedx/frontend-build": "^14.3.0", - "@openedx/paragon": "^22.0.0 || ^23.0.0", - "react": "^18.0.0" - } - }, "node_modules/@edx/reactifex": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@edx/reactifex/-/reactifex-2.2.0.tgz", @@ -5552,7 +5528,9 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -5571,6 +5549,7 @@ "version": "6.6.3", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz", "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", + "dev": true, "license": "MIT", "dependencies": { "@adobe/css-tools": "^4.4.0", @@ -5591,6 +5570,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -5604,12 +5584,14 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, "license": "MIT" }, "node_modules/@testing-library/react": { "version": "16.3.0", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", + "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" @@ -5705,7 +5687,9 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "license": "MIT" + "dev": true, + "license": "MIT", + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -9094,18 +9078,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-js-compat": { "version": "3.41.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", @@ -9336,6 +9308,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, "license": "MIT" }, "node_modules/cssesc": { @@ -9973,7 +9946,9 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "license": "MIT" + "dev": true, + "license": "MIT", + "peer": true }, "node_modules/dom-converter": { "version": "0.2.0", @@ -13421,6 +13396,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -15999,7 +15975,9 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -16753,6 +16731,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -18988,7 +18967,9 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -19002,7 +18983,9 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -19014,7 +18997,9 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "license": "MIT" + "dev": true, + "license": "MIT", + "peer": true }, "node_modules/process": { "version": "0.11.10", @@ -19974,19 +19959,6 @@ "react-dom": ">=16.8" } }, - "node_modules/react-shallow-renderer": { - "version": "16.15.0", - "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", - "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", - "license": "MIT", - "dependencies": { - "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-share": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/react-share/-/react-share-4.4.1.tgz", @@ -20048,26 +20020,6 @@ "react": "^16.8.3 || ^17.0.0-0 || ^18.0.0" } }, - "node_modules/react-test-renderer": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz", - "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==", - "license": "MIT", - "dependencies": { - "react-is": "^18.3.1", - "react-shallow-renderer": "^16.15.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-test-renderer/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT" - }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -20220,6 +20172,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, "license": "MIT", "dependencies": { "indent-string": "^4.0.0", @@ -21965,6 +21918,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, "license": "MIT", "dependencies": { "min-indent": "^1.0.0" diff --git a/package.json b/package.json index 853b42f36d..d3d3791dc0 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "@edx/frontend-lib-special-exams": "^4.0.0", "@edx/frontend-platform": "^8.3.1", "@edx/openedx-atlas": "^0.7.0", - "@edx/react-unit-test-utils": "^4.0.0", "@fortawesome/free-brands-svg-icons": "5.15.4", "@fortawesome/free-regular-svg-icons": "5.15.4", "@fortawesome/free-solid-svg-icons": "5.15.4", diff --git a/src/courseware/course/sequence/Unit/ContentIFrame.jsx b/src/courseware/course/sequence/Unit/ContentIFrame.jsx index 8be355bf14..bc77182506 100644 --- a/src/courseware/course/sequence/Unit/ContentIFrame.jsx +++ b/src/courseware/course/sequence/Unit/ContentIFrame.jsx @@ -1,8 +1,6 @@ import PropTypes from 'prop-types'; -import React from 'react'; import { ErrorPage } from '@edx/frontend-platform/react'; -import { StrictDict } from '@edx/react-unit-test-utils'; import { ModalDialog } from '@openedx/paragon'; import { ContentIFrameLoaderSlot } from '../../../../plugin-slots/ContentIFrameLoaderSlot'; @@ -22,10 +20,10 @@ export const IFRAME_FEATURE_POLICY = ( 'microphone *; camera *; midi *; geolocation *; encrypted-media *; clipboard-write *; autoplay *' ); -export const testIDs = StrictDict({ +export const testIDs = { contentIFrame: 'content-iframe-test-id', modalIFrame: 'modal-iframe-test-id', -}); +}; const ContentIFrame = ({ iframeUrl, diff --git a/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx b/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx index 6ef5f08a95..86f72d7df3 100644 --- a/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx +++ b/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx @@ -1,25 +1,11 @@ -import React from 'react'; +import { render, screen } from '@testing-library/react'; -import { ErrorPage } from '@edx/frontend-platform/react'; -import { ModalDialog } from '@openedx/paragon'; -import { shallow } from '@edx/react-unit-test-utils'; - -import PageLoading from '@src/generic/PageLoading'; - -import { ContentIFrameLoaderSlot } from '@src/plugin-slots/ContentIFrameLoaderSlot'; import * as hooks from './hooks'; -import ContentIFrame, { IFRAME_FEATURE_POLICY, testIDs } from './ContentIFrame'; - -jest.mock('@edx/frontend-platform/react', () => ({ ErrorPage: 'ErrorPage' })); +import ContentIFrame, { IFRAME_FEATURE_POLICY } from './ContentIFrame'; -jest.mock('@openedx/paragon', () => jest.requireActual('@edx/react-unit-test-utils') - .mockComponents({ - ModalDialog: { - Body: 'ModalDialog.Body', - }, - })); +jest.mock('@edx/frontend-platform/react', () => ({ ErrorPage: () =>
ErrorPage
})); -jest.mock('@src/generic/PageLoading', () => 'PageLoading'); +jest.mock('@src/generic/PageLoading', () => jest.fn(() =>
PageLoading
)); jest.mock('./hooks', () => ({ useIFrameBehavior: jest.fn(), @@ -67,14 +53,13 @@ const props = { title: 'test-title', }; -let el; describe('ContentIFrame Component', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('behavior', () => { beforeEach(() => { - el = shallow(); + render(); }); it('initializes iframe behavior hook', () => { expect(hooks.useIFrameBehavior).toHaveBeenCalledWith({ @@ -89,63 +74,56 @@ describe('ContentIFrame Component', () => { }); }); describe('output', () => { - let component; describe('if shouldShowContent', () => { describe('if not hasLoaded', () => { it('displays errorPage if showError', () => { - hooks.useIFrameBehavior.mockReturnValueOnce({ ...iframeBehavior, showError: true }); - el = shallow(); - expect(el.instance.findByType(ErrorPage).length).toEqual(1); + hooks.useIFrameBehavior.mockReturnValueOnce({ ...iframeBehavior, showError: true, shouldShowContent: true }); + render(); + const errorPage = screen.getByText('ErrorPage'); + expect(errorPage).toBeInTheDocument(); }); it('displays PageLoading component if not showError', () => { - el = shallow(); - [component] = el.instance.findByType(ContentIFrameLoaderSlot); - expect(component.props.loadingMessage).toEqual(props.loadingMessage); + render(); + const pageLoading = screen.getByText('PageLoading'); + expect(pageLoading).toBeInTheDocument(); }); }); describe('hasLoaded', () => { it('does not display PageLoading or ErrorPage', () => { hooks.useIFrameBehavior.mockReturnValueOnce({ ...iframeBehavior, hasLoaded: true }); - el = shallow(); - expect(el.instance.findByType(PageLoading).length).toEqual(0); - expect(el.instance.findByType(ErrorPage).length).toEqual(0); + render(); + const pageLoading = screen.queryByText('PageLoading'); + expect(pageLoading).toBeNull(); + const errorPage = screen.queryByText('ErrorPage'); + expect(errorPage).toBeNull(); }); }); it('display iframe with props from hooks', () => { - el = shallow(); - [component] = el.instance.findByTestId(testIDs.contentIFrame); - expect(component.props).toEqual({ - allow: IFRAME_FEATURE_POLICY, - allowFullScreen: true, - scrolling: 'no', - referrerPolicy: 'origin', - title: props.title, - id: props.elementId, - src: props.iframeUrl, - height: iframeBehavior.iframeHeight, - onLoad: iframeBehavior.handleIFrameLoad, - 'data-testid': testIDs.contentIFrame, - }); + render(); + const iframe = screen.getByTitle(props.title); + expect(iframe).toBeInTheDocument(); + expect(iframe).toHaveAttribute('id', props.elementId); + expect(iframe).toHaveAttribute('src', props.iframeUrl); + expect(iframe).toHaveAttribute('allow', IFRAME_FEATURE_POLICY); + expect(iframe).toHaveAttribute('allowfullscreen', ''); + expect(iframe).toHaveAttribute('scrolling', 'no'); + expect(iframe).toHaveAttribute('referrerpolicy', 'origin'); }); }); describe('if not shouldShowContent', () => { it('does not show PageLoading, ErrorPage, or unit-iframe-wrapper', () => { - el = shallow(); - expect(el.instance.findByType(PageLoading).length).toEqual(0); - expect(el.instance.findByType(ErrorPage).length).toEqual(0); - expect(el.instance.findByTestId(testIDs.contentIFrame).length).toEqual(0); + render(); + expect(screen.queryByText('PageLoading')).toBeNull(); + expect(screen.queryByText('ErrorPage')).toBeNull(); + expect(screen.queryByTitle(props.title)).toBeNull(); }); }); it('does not display modal if modalOptions returns isOpen: false', () => { - el = shallow(); - expect(el.instance.findByType(ModalDialog).length).toEqual(0); + render(); + const modal = screen.queryByRole('dialog'); + expect(modal).toBeNull(); }); describe('if modalOptions.isOpen', () => { - const testModalOpenAndHandleClose = () => { - test('Modal component isOpen, with handleModalClose from hook', () => { - expect(component.props.onClose).toEqual(modalIFrameData.handleModalClose); - }); - }; describe('fullscreen modal', () => { describe('body modal', () => { beforeEach(() => { @@ -153,16 +131,14 @@ describe('ContentIFrame Component', () => { ...modalIFrameData, modalOptions: { ...modalOptions.withBody, isFullscreen: true }, }); - el = shallow(); - [component] = el.instance.findByType(ModalDialog); + render(); }); it('displays Modal with div wrapping provided body content if modal.body is provided', () => { - const content = component.findByType(ModalDialog.Body)[0].children[0]; - expect(content.matches(shallow( -
{modalOptions.withBody.body}
, - ))).toEqual(true); + const dialog = screen.getByRole('dialog'); + expect(dialog).toBeInTheDocument(); + const modalBody = screen.getByText(modalOptions.withBody.body); + expect(modalBody).toBeInTheDocument(); }); - testModalOpenAndHandleClose(); }); describe('url modal', () => { beforeEach(() => { @@ -171,54 +147,38 @@ describe('ContentIFrame Component', () => { ...modalIFrameData, modalOptions: { ...modalOptions.withUrl, isFullscreen: true }, }); - el = shallow(); - [component] = el.instance.findByType(ModalDialog); + render(); }); - testModalOpenAndHandleClose(); it('displays Modal with iframe to provided url if modal.body is not provided', () => { - const content = component.findByType(ModalDialog.Body)[0].children[0]; - expect(content.matches(shallow( -