diff --git a/package-lock.json b/package-lock.json index 07cceda..c8bde6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "@edx/frontend-component-header": "^6.4.0", "@edx/frontend-platform": "^8.3.7", "@edx/openedx-atlas": "^0.6.0", - "@edx/react-unit-test-utils": "^4.0.0", "@edx/reactifex": "^2.1.1", "@fortawesome/fontawesome-svg-core": "^1.2.25", "@fortawesome/free-brands-svg-icons": "^5.11.2", @@ -67,6 +66,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": { @@ -2256,6 +2256,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@edx/browserslist-config/-/browserslist-config-1.5.0.tgz", "integrity": "sha512-d2ggwi5j4DOBJOwhWZxBWQSDR0DhT4ke/1PbzRauICdFkuOyax+PsFjK8GUh443K2OaQpy9PGfiCzZ1Yg37AUA==", + "dev": true, "license": "AGPL-3.0" }, "node_modules/@edx/eslint-config": { @@ -2515,30 +2516,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", @@ -5576,7 +5553,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", @@ -5595,6 +5574,7 @@ "version": "6.6.4", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.4.tgz", "integrity": "sha512-xDXgLjVunjHqczScfkCJ9iyjdNOVHvvCdqHSSxwM9L0l/wHkTRum67SDc020uAlCoqktJplgO2AAQeLP1wgqDQ==", + "dev": true, "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", @@ -5614,12 +5594,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, "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -5714,7 +5696,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", @@ -9238,6 +9222,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": { @@ -9841,7 +9826,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", @@ -13165,6 +13152,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" @@ -15603,7 +15591,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" } @@ -15834,6 +15824,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" @@ -17768,7 +17759,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", @@ -17782,7 +17775,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" }, @@ -18705,6 +18700,7 @@ "version": "16.15.0", "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "dev": true, "license": "MIT", "dependencies": { "object-assign": "^4.1.1", @@ -18762,6 +18758,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz", "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==", + "dev": true, "license": "MIT", "dependencies": { "react-is": "^18.3.1", @@ -18776,6 +18773,7 @@ "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==", + "dev": true, "license": "MIT" }, "node_modules/react-transition-group": { @@ -18876,6 +18874,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", @@ -20502,6 +20501,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 04b5273..af4dccb 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "@edx/frontend-component-header": "^6.4.0", "@edx/frontend-platform": "^8.3.7", "@edx/openedx-atlas": "^0.6.0", - "@edx/react-unit-test-utils": "^4.0.0", "@edx/reactifex": "^2.1.1", "@fortawesome/fontawesome-svg-core": "^1.2.25", "@fortawesome/free-brands-svg-icons": "^5.11.2", diff --git a/src/components/BulkManagementHistoryView/BulkManagementAlerts.test.jsx b/src/components/BulkManagementHistoryView/BulkManagementAlerts.test.jsx index a229bf8..05f6d1c 100644 --- a/src/components/BulkManagementHistoryView/BulkManagementAlerts.test.jsx +++ b/src/components/BulkManagementHistoryView/BulkManagementAlerts.test.jsx @@ -1,11 +1,10 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; import selectors from 'data/selectors'; import { BulkManagementAlerts, mapStateToProps } from './BulkManagementAlerts'; +import { renderWithIntl, screen } from '../../testUtilsExtra'; -jest.unmock('@openedx/paragon'); jest.mock('data/selectors', () => ({ __esModule: true, default: { @@ -22,16 +21,16 @@ describe('BulkManagementAlerts', () => { describe('component', () => { describe('states of the warnings', () => { test('no alert shown', () => { - const el = render(); - expect(el.container.querySelectorAll('.alert').length).toEqual(0); + renderWithIntl(); + expect(document.querySelectorAll('.alert').length).toEqual(0); }); test('Just success alert shown', () => { - const el = render(); - expect(el.container.querySelectorAll('.alert-success').length).toEqual(1); + renderWithIntl(); + expect(document.querySelectorAll('.alert-success').length).toEqual(1); }); test('Just error alert shown', () => { - const el = render(); - expect(el.container.querySelectorAll('.alert-danger').length).toEqual(1); + renderWithIntl(); + expect(document.querySelectorAll('.alert-danger').length).toEqual(1); expect(screen.getByText(errorMessage)).toBeInTheDocument(); }); }); diff --git a/src/components/BulkManagementHistoryView/HistoryTable.test.jsx b/src/components/BulkManagementHistoryView/HistoryTable.test.jsx index 35369af..2a82810 100644 --- a/src/components/BulkManagementHistoryView/HistoryTable.test.jsx +++ b/src/components/BulkManagementHistoryView/HistoryTable.test.jsx @@ -8,12 +8,10 @@ import { bulkManagementColumns } from 'data/constants/app'; import { HistoryTable, mapHistoryRows, mapStateToProps } from './HistoryTable'; import ResultsSummary from './ResultsSummary'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); initializeMocks(); jest.mock('@openedx/paragon', () => ({ + ...jest.requireActual('@openedx/paragon'), DataTable: jest.fn(() =>
DataTable
), })); jest.mock('./ResultsSummary', () => jest.fn(() =>
ResultsSummary
)); diff --git a/src/components/BulkManagementHistoryView/ResultsSummary.test.jsx b/src/components/BulkManagementHistoryView/ResultsSummary.test.jsx index 34188a9..e3f95fd 100644 --- a/src/components/BulkManagementHistoryView/ResultsSummary.test.jsx +++ b/src/components/BulkManagementHistoryView/ResultsSummary.test.jsx @@ -1,10 +1,9 @@ import React from 'react'; import lms from 'data/services/lms'; -import { render, screen } from '@testing-library/react'; +import { renderWithIntl, screen } from '../../testUtilsExtra'; import ResultsSummary from './ResultsSummary'; -jest.unmock('@openedx/paragon'); jest.mock('data/services/lms', () => ({ urls: { bulkGradesUrlByRow: jest.fn((rowId) => (`www.edx.org/${rowId}`)), @@ -16,10 +15,9 @@ describe('ResultsSummary component', () => { rowId: 42, text: 'texty', }; - let el; let link; beforeEach(() => { - el = render(); + renderWithIntl(); link = screen.getByRole('link', { name: props.text }); }); test('Hyperlink has target="_blank" and rel="noopener noreferrer"', () => { @@ -31,7 +29,7 @@ describe('ResultsSummary component', () => { }); test('displays Download Icon and text', () => { expect(link).toHaveTextContent(props.text); - const span = el.container.querySelector('span[aria-hidden="true"]'); - expect(span).toBeInTheDocument(); + const icon = screen.getByRole('img', { hidden: true }); + expect(icon).toBeInTheDocument(); }); }); diff --git a/src/components/BulkManagementHistoryView/index.test.jsx b/src/components/BulkManagementHistoryView/index.test.jsx index 51b0ef0..9bf3430 100644 --- a/src/components/BulkManagementHistoryView/index.test.jsx +++ b/src/components/BulkManagementHistoryView/index.test.jsx @@ -3,10 +3,6 @@ import { render, initializeMocks, screen } from 'testUtilsExtra'; import { BulkManagementHistoryView } from '.'; import messages from './messages'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('./BulkManagementAlerts', () => jest.fn(() =>
BulkManagementAlerts
)); jest.mock('./HistoryTable', () => jest.fn(() =>
HistoryTable
)); diff --git a/src/components/EdxHeader/EdxHeader.test.jsx b/src/components/EdxHeader/EdxHeader.test.jsx index fc075bb..8d45b79 100644 --- a/src/components/EdxHeader/EdxHeader.test.jsx +++ b/src/components/EdxHeader/EdxHeader.test.jsx @@ -1,23 +1,35 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; import { getConfig } from '@edx/frontend-platform'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { render, screen } from '@testing-library/react'; import Header from '.'; -jest.unmock('@openedx/paragon'); - jest.mock('@edx/frontend-platform', () => ({ + ...jest.requireActual('@edx/frontend-platform'), getConfig: jest.fn(), })); describe('Header', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + test('has edx link with logo url', () => { const url = 'www.ourLogo.url'; const baseUrl = 'www.lms.url'; getConfig.mockReturnValue({ LOGO_URL: url, LMS_BASE_URL: baseUrl }); - render(
); - expect(screen.getByRole('link')).toHaveAttribute('href', `${baseUrl}/dashboard`); - expect(screen.getByAltText('edX logo')).toHaveAttribute('src', url); + render( + +
+ , + ); + + const link = screen.getByRole('link'); + const logo = screen.getByAltText('edX logo'); + + expect(link).toHaveAttribute('href', `${baseUrl}/dashboard`); + expect(logo).toHaveAttribute('src', url); }); }); diff --git a/src/components/GradebookFilters/AssignmentFilter/index.test.jsx b/src/components/GradebookFilters/AssignmentFilter/index.test.jsx index 86b23c4..ff0f720 100644 --- a/src/components/GradebookFilters/AssignmentFilter/index.test.jsx +++ b/src/components/GradebookFilters/AssignmentFilter/index.test.jsx @@ -4,9 +4,6 @@ import { render, screen, initializeMocks } from 'testUtilsExtra'; import useAssignmentFilterData from './hooks'; import AssignmentFilter from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() })); const handleChange = jest.fn(); diff --git a/src/components/GradebookFilters/AssignmentGradeFilter/index.test.jsx b/src/components/GradebookFilters/AssignmentGradeFilter/index.test.jsx index a929cc7..025d6f2 100644 --- a/src/components/GradebookFilters/AssignmentGradeFilter/index.test.jsx +++ b/src/components/GradebookFilters/AssignmentGradeFilter/index.test.jsx @@ -1,15 +1,12 @@ /* eslint-disable import/no-extraneous-dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; import useAssignmentGradeFilterData from './hooks'; import AssignmentFilter from '.'; +import { renderWithIntl } from '../../../testUtilsExtra'; jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() })); -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); const hookData = { handleSubmit: jest.fn(), @@ -26,7 +23,7 @@ const updateQueryParams = jest.fn(); describe('AssignmentFilter component', () => { describe('behavior', () => { it('initializes hooks', () => { - render(); + renderWithIntl(); expect(useAssignmentGradeFilterData).toHaveBeenCalledWith({ updateQueryParams }); }); }); @@ -34,7 +31,7 @@ describe('AssignmentFilter component', () => { describe('with selected assignment', () => { beforeEach(() => { jest.clearAllMocks(); - render(); + renderWithIntl(); }); it('renders a PercentGroup for both Max and Min filters', async () => { const user = userEvent.setup(); @@ -64,7 +61,7 @@ describe('AssignmentFilter component', () => { ...hookData, selectedAssignment: null, }); - render(); + renderWithIntl(); }); it('disables controls', () => { const minGrade = screen.getByRole('spinbutton', { name: /Min Grade/ }); diff --git a/src/components/GradebookFilters/AssignmentTypeFilter/index.test.jsx b/src/components/GradebookFilters/AssignmentTypeFilter/index.test.jsx index e94d9bf..d6a9678 100644 --- a/src/components/GradebookFilters/AssignmentTypeFilter/index.test.jsx +++ b/src/components/GradebookFilters/AssignmentTypeFilter/index.test.jsx @@ -1,13 +1,9 @@ import React from 'react'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import useAssignmentFilterTypeData from './hooks'; import AssignmentFilterType from '.'; - -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); +import { renderWithIntl } from '../../../testUtilsExtra'; jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() })); @@ -25,7 +21,7 @@ const updateQueryParams = jest.fn(); describe('AssignmentFilterType component', () => { beforeAll(() => { - render(); + renderWithIntl(); }); describe('render', () => { test('filter options', () => { diff --git a/src/components/GradebookFilters/CourseGradeFilter/index.test.jsx b/src/components/GradebookFilters/CourseGradeFilter/index.test.jsx index 600fe0e..b3ce1e4 100644 --- a/src/components/GradebookFilters/CourseGradeFilter/index.test.jsx +++ b/src/components/GradebookFilters/CourseGradeFilter/index.test.jsx @@ -1,13 +1,9 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { screen } from '@testing-library/react'; import useCourseGradeFilterData from './hooks'; import CourseFilter from '.'; - -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); +import { renderWithIntl } from '../../../testUtilsExtra'; jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() })); @@ -38,7 +34,7 @@ describe('CourseFilter component', () => { }); describe('with selected assignment', () => { beforeEach(() => { - render(); + renderWithIntl(); }); it('renders a PercentGroup for both Max and Min filters', () => { @@ -55,7 +51,7 @@ describe('CourseFilter component', () => { beforeEach(() => { jest.clearAllMocks(); useCourseGradeFilterData.mockReturnValueOnce({ ...hookData, isDisabled: true }); - render(); + renderWithIntl(); }); it('disables submit', () => { expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled(); diff --git a/src/components/GradebookFilters/PercentGroup.test.jsx b/src/components/GradebookFilters/PercentGroup.test.jsx index fa356d6..e00fb15 100644 --- a/src/components/GradebookFilters/PercentGroup.test.jsx +++ b/src/components/GradebookFilters/PercentGroup.test.jsx @@ -2,10 +2,6 @@ import { render, screen, initializeMocks } from 'testUtilsExtra'; import PercentGroup from './PercentGroup'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - describe('PercentGroup', () => { let props = { id: 'group id', diff --git a/src/components/GradebookFilters/SelectGroup.test.jsx b/src/components/GradebookFilters/SelectGroup.test.jsx index 85934af..fd35e4c 100644 --- a/src/components/GradebookFilters/SelectGroup.test.jsx +++ b/src/components/GradebookFilters/SelectGroup.test.jsx @@ -3,10 +3,6 @@ import { render, screen } from '@testing-library/react'; import SelectGroup from './SelectGroup'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - describe('SelectGroup', () => { let props = { id: 'group id', diff --git a/src/components/GradebookFilters/StudentGroupsFilter/index.test.jsx b/src/components/GradebookFilters/StudentGroupsFilter/index.test.jsx index 5992272..b257989 100644 --- a/src/components/GradebookFilters/StudentGroupsFilter/index.test.jsx +++ b/src/components/GradebookFilters/StudentGroupsFilter/index.test.jsx @@ -5,9 +5,6 @@ import SelectGroup from '../SelectGroup'; import { StudentGroupsFilter } from './index'; import useStudentGroupsFilterData from './hooks'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); jest.mock('../SelectGroup', () => jest.fn(() =>
SelectGroup
)); jest.mock('./hooks', () => jest.fn()); diff --git a/src/components/GradebookFilters/index.test.jsx b/src/components/GradebookFilters/index.test.jsx index 6d32e07..d0f628e 100644 --- a/src/components/GradebookFilters/index.test.jsx +++ b/src/components/GradebookFilters/index.test.jsx @@ -3,10 +3,6 @@ import { render, screen, initializeMocks } from 'testUtilsExtra'; import GradebookFilters from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - const updateQueryParams = jest.fn(); initializeMocks(); diff --git a/src/components/GradebookHeader/index.test.jsx b/src/components/GradebookHeader/index.test.jsx index 0f93f95..33dbb89 100644 --- a/src/components/GradebookHeader/index.test.jsx +++ b/src/components/GradebookHeader/index.test.jsx @@ -8,9 +8,6 @@ import { GradebookHeader } from './index'; import useGradebookHeaderData from './hooks'; import messages from './messages'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); jest.mock('data/services/lms/urls', () => ({ instructorDashboardUrl: jest.fn(), })); diff --git a/src/components/GradesView/BulkManagementControls/index.test.jsx b/src/components/GradesView/BulkManagementControls/index.test.jsx index 27fde69..95fa809 100644 --- a/src/components/GradesView/BulkManagementControls/index.test.jsx +++ b/src/components/GradesView/BulkManagementControls/index.test.jsx @@ -8,9 +8,6 @@ import { BulkManagementControls } from './index'; import useBulkManagementControlsData from './hooks'; import messages from './messages'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); jest.mock('components/NetworkButton', () => jest.fn(() =>
NetworkButton
)); jest.mock('../ImportGradesButton', () => jest.fn(() => (
ImportGradesButton
diff --git a/src/components/GradesView/EditModal/HistoryHeader.test.jsx b/src/components/GradesView/EditModal/HistoryHeader.test.jsx index 034026c..aed366b 100644 --- a/src/components/GradesView/EditModal/HistoryHeader.test.jsx +++ b/src/components/GradesView/EditModal/HistoryHeader.test.jsx @@ -3,10 +3,6 @@ import { render, screen, initializeMocks } from 'testUtilsExtra'; import HistoryHeader from './HistoryHeader'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - initializeMocks(); describe('HistoryHeader', () => { diff --git a/src/components/GradesView/EditModal/ModalHeaders.test.jsx b/src/components/GradesView/EditModal/ModalHeaders.test.jsx index c6ff0a6..63992e9 100644 --- a/src/components/GradesView/EditModal/ModalHeaders.test.jsx +++ b/src/components/GradesView/EditModal/ModalHeaders.test.jsx @@ -4,10 +4,6 @@ import { selectors } from 'data/redux/hooks'; import { render, screen, initializeMocks } from 'testUtilsExtra'; import ModalHeaders from './ModalHeaders'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('data/redux/hooks', () => ({ selectors: { app: { useModalData: jest.fn() }, diff --git a/src/components/GradesView/EditModal/OverrideTable/AdjustedGradeInput/index.test.jsx b/src/components/GradesView/EditModal/OverrideTable/AdjustedGradeInput/index.test.jsx index 30d2a7e..eebbea5 100644 --- a/src/components/GradesView/EditModal/OverrideTable/AdjustedGradeInput/index.test.jsx +++ b/src/components/GradesView/EditModal/OverrideTable/AdjustedGradeInput/index.test.jsx @@ -4,10 +4,6 @@ import { render, screen } from '@testing-library/react'; import useAdjustedGradeInputData from './hooks'; import AdjustedGradeInput from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('./hooks', () => jest.fn()); const hookProps = { diff --git a/src/components/GradesView/EditModal/OverrideTable/ReasonInput/hooks.test.jsx b/src/components/GradesView/EditModal/OverrideTable/ReasonInput/hooks.test.jsx index 6b5acec..0e6fa0b 100644 --- a/src/components/GradesView/EditModal/OverrideTable/ReasonInput/hooks.test.jsx +++ b/src/components/GradesView/EditModal/OverrideTable/ReasonInput/hooks.test.jsx @@ -16,6 +16,12 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useRef: jest.fn((val) => ({ current: val, useRef: true })), + useEffect: jest.fn((cb, prereqs) => ({ useEffect: { cb, prereqs } })), +})); + const modalData = { reasonForChange: 'test-reason-for-change' }; const setModalState = jest.fn(); selectors.app.useModalData.mockReturnValue(modalData); @@ -25,6 +31,7 @@ const ref = { current: { focus: jest.fn() }, useRef: true }; React.useRef.mockReturnValue(ref); let out; + describe('useReasonInputData hook', () => { beforeEach(() => { jest.clearAllMocks(); diff --git a/src/components/GradesView/EditModal/OverrideTable/ReasonInput/index.test.jsx b/src/components/GradesView/EditModal/OverrideTable/ReasonInput/index.test.jsx index 7f652b1..eb19ccd 100644 --- a/src/components/GradesView/EditModal/OverrideTable/ReasonInput/index.test.jsx +++ b/src/components/GradesView/EditModal/OverrideTable/ReasonInput/index.test.jsx @@ -5,9 +5,6 @@ import ReasonInput from '.'; jest.mock('./hooks', () => jest.fn()); -jest.unmock('@openedx/paragon'); -jest.unmock('react'); - const hookProps = { ref: jest.fn().mockName('hook.ref'), onChange: jest.fn().mockName('hook.onChange'), diff --git a/src/components/GradesView/EditModal/OverrideTable/ReasonInput/ref.test.jsx b/src/components/GradesView/EditModal/OverrideTable/ReasonInput/ref.test.jsx index c31fc2e..7f71d2d 100644 --- a/src/components/GradesView/EditModal/OverrideTable/ReasonInput/ref.test.jsx +++ b/src/components/GradesView/EditModal/OverrideTable/ReasonInput/ref.test.jsx @@ -4,8 +4,6 @@ import { render } from '@testing-library/react'; import useReasonInputData from './hooks'; import ReasonInput, { controlTestId } from '.'; -jest.unmock('react'); -jest.unmock('@openedx/paragon'); jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() })); const focus = jest.fn(); diff --git a/src/components/GradesView/EditModal/OverrideTable/hooks.test.js b/src/components/GradesView/EditModal/OverrideTable/hooks.test.js index 8e684f0..f4724cb 100644 --- a/src/components/GradesView/EditModal/OverrideTable/hooks.test.js +++ b/src/components/GradesView/EditModal/OverrideTable/hooks.test.js @@ -1,5 +1,4 @@ import { useIntl } from '@edx/frontend-platform/i18n'; -import { formatMessage } from 'testUtils'; import { gradeOverrideHistoryColumns as columns } from 'data/constants/app'; import { selectors } from 'data/redux/hooks'; @@ -16,6 +15,18 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useContext: jest.fn(context => context), +})); + +jest.mock('@edx/frontend-platform/i18n', () => ({ + ...jest.requireActual('@edx/frontend-platform/i18n'), + useIntl: jest.fn(() => ({ + formatMessage: (message) => message.defaultMessage, + })), +})); + selectors.grades.useHasOverrideErrors.mockReturnValue(false); const gradeOverrides = ['some', 'override', 'data']; const gradeData = { gradeOverrideHistoryResults: gradeOverrides }; @@ -44,22 +55,22 @@ describe('useOverrideTableData', () => { describe('columns', () => { test('date column', () => { const { Header, accessor } = out.columns[0]; - expect(Header).toEqual(formatMessage(messages.dateHeader)); + expect(Header).toEqual(messages.dateHeader.defaultMessage); expect(accessor).toEqual(columns.date); }); test('grader column', () => { const { Header, accessor } = out.columns[1]; - expect(Header).toEqual(formatMessage(messages.graderHeader)); + expect(Header).toEqual(messages.graderHeader.defaultMessage); expect(accessor).toEqual(columns.grader); }); test('reason column', () => { const { Header, accessor } = out.columns[2]; - expect(Header).toEqual(formatMessage(messages.reasonHeader)); + expect(Header).toEqual(messages.reasonHeader.defaultMessage); expect(accessor).toEqual(columns.reason); }); test('adjustedGrade column', () => { const { Header, accessor } = out.columns[3]; - expect(Header).toEqual(formatMessage(messages.adjustedGradeHeader)); + expect(Header).toEqual(messages.adjustedGradeHeader.defaultMessage); expect(accessor).toEqual(columns.adjustedGrade); }); }); diff --git a/src/components/GradesView/EditModal/OverrideTable/index.test.jsx b/src/components/GradesView/EditModal/OverrideTable/index.test.jsx index 712420a..dc6de4c 100644 --- a/src/components/GradesView/EditModal/OverrideTable/index.test.jsx +++ b/src/components/GradesView/EditModal/OverrideTable/index.test.jsx @@ -1,13 +1,9 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { screen } from '@testing-library/react'; import useOverrideTableData from './hooks'; import OverrideTable from '.'; - -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); +import { renderWithIntl } from '../../../../testUtilsExtra'; jest.mock('utils', () => ({ ...jest.requireActual('utils'), @@ -41,19 +37,19 @@ describe('OverrideTable component', () => { describe('hooks', () => { it('initializes hook data', () => { useOverrideTableData.mockReturnValue(hookProps); - render(); + renderWithIntl(); expect(useOverrideTableData).toHaveBeenCalled(); }); }); describe('behavior', () => { it('null render if hide', () => { useOverrideTableData.mockReturnValue({ ...hookProps, hide: true }); - render(); + renderWithIntl(); expect(screen.queryByRole('table')).toBeNull(); }); it('renders table with correct data', () => { useOverrideTableData.mockReturnValue(hookProps); - render(); + renderWithIntl(); const table = screen.getByRole('table'); expect(table).toBeInTheDocument(); expect(screen.getByText(hookProps.columns[0].Header)).toBeInTheDocument(); diff --git a/src/components/GradesView/EditModal/index.test.jsx b/src/components/GradesView/EditModal/index.test.jsx index 2dcb384..2322cfc 100644 --- a/src/components/GradesView/EditModal/index.test.jsx +++ b/src/components/GradesView/EditModal/index.test.jsx @@ -1,19 +1,15 @@ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; import useEditModalData from './hooks'; import EditModal from '.'; import messages from './messages'; +import { renderWithIntl } from '../../../testUtilsExtra'; jest.mock('./hooks', () => jest.fn()); jest.mock('./ModalHeaders', () => jest.fn(() =>
ModalHeaders
)); jest.mock('./OverrideTable', () => jest.fn(() =>
OverrideTable
)); -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - const hookProps = { onClose: jest.fn().mockName('hooks.onClose'), error: 'test-error', @@ -28,7 +24,7 @@ describe('EditModal component', () => { describe('behavior', () => { it('initializes component hooks', () => { useEditModalData.mockReturnValue(hookProps); - render(); + renderWithIntl(); expect(useEditModalData).toHaveBeenCalled(); }); }); @@ -80,7 +76,7 @@ describe('EditModal component', () => { describe('without error', () => { beforeEach(() => { useEditModalData.mockReturnValueOnce({ ...hookProps, error: undefined }); - render(); + renderWithIntl(); }); testModal(); testBody(); @@ -93,7 +89,7 @@ describe('EditModal component', () => { describe('with error', () => { beforeEach(() => { useEditModalData.mockReturnValue(hookProps); - render(); + renderWithIntl(); }); testModal(); testBody(); diff --git a/src/components/GradesView/FilterBadges/FilterBadge.test.jsx b/src/components/GradesView/FilterBadges/FilterBadge.test.jsx index 36369f4..c48681a 100644 --- a/src/components/GradesView/FilterBadges/FilterBadge.test.jsx +++ b/src/components/GradesView/FilterBadges/FilterBadge.test.jsx @@ -1,15 +1,12 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { useIntl } from '@edx/frontend-platform/i18n'; +import { screen } from '@testing-library/react'; import { formatMessage } from 'testUtils'; import { selectors } from 'data/redux/hooks'; import userEvent from '@testing-library/user-event'; import FilterBadge from './FilterBadge'; +import { renderWithIntl } from '../../../testUtilsExtra'; -jest.mock('@openedx/paragon', () => ({ - Button: () => 'Button', -})); jest.mock('data/redux/hooks', () => ({ selectors: { root: { @@ -18,14 +15,12 @@ jest.mock('data/redux/hooks', () => ({ }, })); -jest.unmock('@openedx/paragon'); -jest.unmock('react'); - const handleClose = jest.fn(); const filterName = 'test-filter-name'; const hookProps = { displayName: { + id: 'test.id', defaultMessage: 'a common name', }, isDefault: false, @@ -38,10 +33,7 @@ selectors.root.useFilterBadgeConfig.mockReturnValue(hookProps); describe('FilterBadge', () => { describe('hooks', () => { beforeEach(() => { - render(); - }); - it('initializes intl hook', () => { - expect(useIntl).toHaveBeenCalled(); + renderWithIntl(); }); it('initializes redux hooks', () => { expect(selectors.root.useFilterBadgeConfig).toHaveBeenCalledWith(filterName); @@ -53,7 +45,7 @@ describe('FilterBadge', () => { ...hookProps, isDefault: true, }); - render(); + renderWithIntl(); expect(screen.queryByText(hookProps.displayName)).toBeNull(); }); describe('hide Value', () => { @@ -62,7 +54,7 @@ describe('FilterBadge', () => { ...hookProps, hideValue: true, }); - render(); + renderWithIntl(); const user = userEvent.setup(); expect(screen.getByTestId('display-name')).toHaveTextContent(formatMessage(hookProps.displayName)); expect(screen.queryByTestId('filter-value')).toHaveTextContent(''); @@ -77,7 +69,7 @@ describe('FilterBadge', () => { ...hookProps, hideValue: false, }); - render(); + renderWithIntl(); const user = userEvent.setup(); expect(screen.getByTestId('display-name')).toHaveTextContent(formatMessage(hookProps.displayName)); expect(screen.getByTestId('filter-value')).toHaveTextContent(`: ${hookProps.value}`); diff --git a/src/components/GradesView/FilterBadges/test.jsx b/src/components/GradesView/FilterBadges/test.jsx index 71843ae..859c267 100644 --- a/src/components/GradesView/FilterBadges/test.jsx +++ b/src/components/GradesView/FilterBadges/test.jsx @@ -6,9 +6,6 @@ import userEvent from '@testing-library/user-event'; import FilterBadges from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); - const order = ['filter1', 'filter2', 'filter3']; jest.mock('data/constants/filters', () => ({ ...jest.requireActual('data/constants/filters'), diff --git a/src/components/GradesView/FilterMenuToggle/index.test.jsx b/src/components/GradesView/FilterMenuToggle/index.test.jsx index 7d6be6f..2a7ac73 100644 --- a/src/components/GradesView/FilterMenuToggle/index.test.jsx +++ b/src/components/GradesView/FilterMenuToggle/index.test.jsx @@ -1,11 +1,11 @@ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; import { formatMessage } from 'testUtils'; import { thunkActions } from 'data/redux/hooks'; import FilterMenuToggle from '.'; import messages from './messages'; +import { renderWithIntl } from '../../../testUtilsExtra'; jest.mock('data/redux/hooks', () => ({ thunkActions: { @@ -17,17 +17,13 @@ jest.mock('data/redux/hooks', () => ({ }, })); -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - const toggleFilterMenu = jest.fn().mockName('hooks.toggleFilterMenu'); thunkActions.app.filterMenu.useToggleMenu.mockReturnValue(toggleFilterMenu); describe('FilterMenuToggle component', () => { beforeEach(() => { jest.clearAllMocks(); - render(); + renderWithIntl(); }); describe('behavior', () => { it('initializes redux hooks', () => { diff --git a/src/components/GradesView/FilteredUsersLabel/index.test.jsx b/src/components/GradesView/FilteredUsersLabel/index.test.jsx index 85ceb30..71f155c 100644 --- a/src/components/GradesView/FilteredUsersLabel/index.test.jsx +++ b/src/components/GradesView/FilteredUsersLabel/index.test.jsx @@ -1,14 +1,9 @@ -import { render, screen } from '@testing-library/react'; - -import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { screen } from '@testing-library/react'; import { selectors } from 'data/redux/hooks'; import FilteredUsersLabel from '.'; - -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); +import { renderWithIntl } from '../../../testUtilsExtra'; jest.mock('data/redux/hooks', () => ({ selectors: { @@ -30,7 +25,7 @@ describe('FilteredUsersLabel component', () => { }); describe('behavior', () => { it('initializes redux hooks', () => { - render(); + renderWithIntl(); expect(selectors.grades.useUserCounts).toHaveBeenCalled(); }); }); @@ -40,11 +35,11 @@ describe('FilteredUsersLabel component', () => { ...userCounts, totalUsersCount: 0, }); - const { container } = render(); + const { container } = renderWithIntl(); expect(container.firstChild).toBeNull(); }); it('renders users count correctly', () => { - render(); + renderWithIntl(); expect(screen.getByText((text) => text.includes(userCounts.filteredUsersCount))).toBeInTheDocument(); expect(screen.getByText((text) => text.includes(userCounts.totalUsersCount))).toBeInTheDocument(); }); diff --git a/src/components/GradesView/GradebookTable/GradeButton.test.jsx b/src/components/GradesView/GradebookTable/GradeButton.test.jsx index c1da1bd..53782f0 100644 --- a/src/components/GradesView/GradebookTable/GradeButton.test.jsx +++ b/src/components/GradesView/GradebookTable/GradeButton.test.jsx @@ -26,10 +26,6 @@ jest.mock('data/redux/transforms', () => ({ }, })); -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - const props = { subsection: { attempted: false, diff --git a/src/components/GradesView/GradebookTable/LabelReplacements.test.jsx b/src/components/GradesView/GradebookTable/LabelReplacements.test.jsx index 496d307..2565f12 100644 --- a/src/components/GradesView/GradebookTable/LabelReplacements.test.jsx +++ b/src/components/GradesView/GradebookTable/LabelReplacements.test.jsx @@ -1,7 +1,8 @@ -import { render, screen } from '@testing-library/react'; -import { getLocale, IntlProvider } from '@edx/frontend-platform/i18n'; +import { screen } from '@testing-library/react'; +import { getLocale } from '@edx/frontend-platform/i18n'; import LabelReplacements from './LabelReplacements'; import messages from './messages'; +import { renderWithIntl } from '../../../testUtilsExtra'; const { TotalGradeLabelReplacement, @@ -9,10 +10,6 @@ const { MastersOnlyLabelReplacement, } = LabelReplacements; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('@edx/frontend-platform/i18n', () => ({ ...jest.requireActual('@edx/frontend-platform/i18n'), getLocale: jest.fn(), @@ -22,7 +19,7 @@ jest.mock('@edx/frontend-platform/i18n', () => ({ describe('LabelReplacements', () => { describe('TotalGradeLabelReplacement', () => { getLocale.mockImplementation(() => 'en'); - render(); + renderWithIntl(); it('displays overlay tooltip', () => { const tooltip = screen.getByText(messages.totalGradePercentage.defaultMessage); expect(tooltip).toBeInTheDocument(); @@ -30,7 +27,7 @@ describe('LabelReplacements', () => { }); describe('UsernameLabelReplacement', () => { it('renders correctly', () => { - render(); + renderWithIntl(); expect(screen.getByText(messages.usernameHeading.defaultMessage)).toBeInTheDocument(); }); }); @@ -41,7 +38,7 @@ describe('LabelReplacements', () => { defaultMessage: 'defaultMessAge', description: 'desCripTion', }; - render(); + renderWithIntl(); expect(screen.getByText(message.defaultMessage)).toBeInTheDocument(); }); }); diff --git a/src/components/GradesView/GradebookTable/hooks.test.jsx b/src/components/GradesView/GradebookTable/hooks.test.jsx index 52fcc3c..c3219ef 100644 --- a/src/components/GradesView/GradebookTable/hooks.test.jsx +++ b/src/components/GradesView/GradebookTable/hooks.test.jsx @@ -5,10 +5,6 @@ import { initializeMocks, render } from '../../../testUtilsExtra'; import * as hooks from './hooks'; import messages from './messages'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - let mockUseAllGrades; let mockUseGetHeadings; diff --git a/src/components/GradesView/GradebookTable/index.test.jsx b/src/components/GradesView/GradebookTable/index.test.jsx index 46f06ee..63c67f9 100644 --- a/src/components/GradesView/GradebookTable/index.test.jsx +++ b/src/components/GradesView/GradebookTable/index.test.jsx @@ -1,15 +1,11 @@ -import { render, screen } from '@testing-library/react'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { screen } from '@testing-library/react'; import useGradebookTableData from './hooks'; import GradebookTable from '.'; +import { renderWithIntl } from '../../../testUtilsExtra'; jest.mock('./hooks', () => jest.fn()); -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - const hookProps = { columns: [{ Header: 'Username', accessor: 'username' }, { Header: 'Email', accessor: 'email' }, { Header: 'Total Grade', accessor: 'totalGrade' }], data: [{ username: 'instructor', email: 'instructor@example.com', totalGrade: '100' }, { username: 'student', email: 'student@example.com', totalGrade: '90' }], @@ -21,7 +17,7 @@ const hookProps = { describe('GradebookTable', () => { it('renders Datatable correctly', () => { useGradebookTableData.mockReturnValue(hookProps); - render(); + renderWithIntl(); expect(useGradebookTableData).toHaveBeenCalled(); const headers = screen.getAllByRole('columnheader'); expect(headers).toHaveLength(3); @@ -40,7 +36,7 @@ describe('GradebookTable', () => { data: [], grades: [], }); - render(); + renderWithIntl(); expect(screen.getByText(hookProps.emptyContent)).toBeInTheDocument(); }); }); diff --git a/src/components/GradesView/ImportGradesButton/hooks.test.js b/src/components/GradesView/ImportGradesButton/hooks.test.js index c4439d0..74614e8 100644 --- a/src/components/GradesView/ImportGradesButton/hooks.test.js +++ b/src/components/GradesView/ImportGradesButton/hooks.test.js @@ -12,6 +12,11 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useRef: jest.fn((val) => ({ current: val, useRef: true })), +})); + let out; let submitThen; diff --git a/src/components/GradesView/ImportGradesButton/index.test.jsx b/src/components/GradesView/ImportGradesButton/index.test.jsx index 4766141..6485725 100644 --- a/src/components/GradesView/ImportGradesButton/index.test.jsx +++ b/src/components/GradesView/ImportGradesButton/index.test.jsx @@ -6,10 +6,6 @@ import { import ImportGradesButton from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - initializeMocks(); describe('ImportGradesButton component', () => { diff --git a/src/components/GradesView/ImportGradesButton/ref.test.jsx b/src/components/GradesView/ImportGradesButton/ref.test.jsx index cd9c123..7d66ff5 100644 --- a/src/components/GradesView/ImportGradesButton/ref.test.jsx +++ b/src/components/GradesView/ImportGradesButton/ref.test.jsx @@ -1,11 +1,8 @@ import React from 'react'; -import { render } from '@testing-library/react'; - import useImportGradesButtonData from './hooks'; import ImportGradesButton from '.'; +import { renderWithIntl, screen } from '../../../testUtilsExtra'; -jest.unmock('react'); -jest.unmock('@openedx/paragon'); jest.mock('components/NetworkButton', () => 'network-button'); jest.mock('./hooks', () => ({ __esModule: true, default: jest.fn() })); @@ -17,11 +14,10 @@ const props = { }; useImportGradesButtonData.mockReturnValue(props); -let el; describe('ImportGradesButton ref test', () => { it('loads ref from hook', () => { - el = render(); - const input = el.getByTestId('file-control'); + renderWithIntl(); + const input = screen.getByTestId('file-control'); expect(input).toEqual(props.fileInputRef.current); }); }); diff --git a/src/components/GradesView/ImportSuccessToast/hooks.test.js b/src/components/GradesView/ImportSuccessToast/hooks.test.js index 8530036..faa9847 100644 --- a/src/components/GradesView/ImportSuccessToast/hooks.test.js +++ b/src/components/GradesView/ImportSuccessToast/hooks.test.js @@ -19,6 +19,18 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useContext: jest.fn(context => context), +})); + +jest.mock('@edx/frontend-platform/i18n', () => ({ + ...jest.requireActual('@edx/frontend-platform/i18n'), + useIntl: jest.fn(() => ({ + formatMessage: (message) => message.defaultMessage, + })), +})); + const setView = jest.fn().mockName('hooks.setView'); const setShowToast = jest.fn().mockName('hooks.setShowImportSuccessToast'); actions.app.useSetView.mockReturnValue(setView); diff --git a/src/components/GradesView/ImportSuccessToast/index.test.jsx b/src/components/GradesView/ImportSuccessToast/index.test.jsx index 84caac7..1864504 100644 --- a/src/components/GradesView/ImportSuccessToast/index.test.jsx +++ b/src/components/GradesView/ImportSuccessToast/index.test.jsx @@ -5,10 +5,6 @@ import { render, initializeMocks, screen } from 'testUtilsExtra'; import ImportSuccessToast from '.'; import useImportSuccessToastData from './hooks'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('data/redux/hooks', () => ({ actions: { app: { diff --git a/src/components/GradesView/InterventionsReport/index.test.jsx b/src/components/GradesView/InterventionsReport/index.test.jsx index e273478..d2ccc82 100644 --- a/src/components/GradesView/InterventionsReport/index.test.jsx +++ b/src/components/GradesView/InterventionsReport/index.test.jsx @@ -4,10 +4,6 @@ import { render, screen, initializeMocks } from 'testUtilsExtra'; import InterventionsReport from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('components/NetworkButton', () => 'NetworkButton'); jest.mock('./hooks', () => jest.fn()); diff --git a/src/components/GradesView/PageButtons/hooks.test.js b/src/components/GradesView/PageButtons/hooks.test.js index 8d96bec..7fc2bbb 100644 --- a/src/components/GradesView/PageButtons/hooks.test.js +++ b/src/components/GradesView/PageButtons/hooks.test.js @@ -15,6 +15,18 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useContext: jest.fn(context => context), +})); + +jest.mock('@edx/frontend-platform/i18n', () => ({ + ...jest.requireActual('@edx/frontend-platform/i18n'), + useIntl: jest.fn(() => ({ + formatMessage: (message) => message.defaultMessage, + })), +})); + const gradeData = { nextPage: 'test-next-page', prevPage: 'test-prev-page' }; selectors.grades.useGradeData.mockReturnValue(gradeData); diff --git a/src/components/GradesView/PageButtons/index.test.jsx b/src/components/GradesView/PageButtons/index.test.jsx index 9d2f014..5408ef9 100644 --- a/src/components/GradesView/PageButtons/index.test.jsx +++ b/src/components/GradesView/PageButtons/index.test.jsx @@ -5,9 +5,6 @@ import { initializeMocks, render, screen } from 'testUtilsExtra'; import usePageButtonsData from './hooks'; import PageButtons from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('@edx/frontend-platform/i18n'); -jest.unmock('react'); jest.mock('./hooks', () => jest.fn()); const hookProps = { diff --git a/src/components/GradesView/ScoreViewInput/index.test.jsx b/src/components/GradesView/ScoreViewInput/index.test.jsx index 6126044..76e2c69 100644 --- a/src/components/GradesView/ScoreViewInput/index.test.jsx +++ b/src/components/GradesView/ScoreViewInput/index.test.jsx @@ -5,10 +5,6 @@ import userEvent from '@testing-library/user-event'; import { ScoreViewInput } from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('data/redux/hooks', () => ({ actions: { grades: { diff --git a/src/components/GradesView/SearchControls/hooks.test.js b/src/components/GradesView/SearchControls/hooks.test.js index db0c291..9629596 100644 --- a/src/components/GradesView/SearchControls/hooks.test.js +++ b/src/components/GradesView/SearchControls/hooks.test.js @@ -18,6 +18,18 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useContext: jest.fn(context => context), +})); + +jest.mock('@edx/frontend-platform/i18n', () => ({ + ...jest.requireActual('@edx/frontend-platform/i18n'), + useIntl: jest.fn(() => ({ + formatMessage: (message) => message.defaultMessage, + })), +})); + const searchValue = 'test-search-value'; selectors.app.useSearchValue.mockReturnValue(searchValue); const setSearchValue = jest.fn(); diff --git a/src/components/GradesView/SearchControls/index.test.jsx b/src/components/GradesView/SearchControls/index.test.jsx index 0f4a3a7..82b988c 100644 --- a/src/components/GradesView/SearchControls/index.test.jsx +++ b/src/components/GradesView/SearchControls/index.test.jsx @@ -4,9 +4,6 @@ import { initializeMocks, render, screen } from 'testUtilsExtra'; import useSearchControlsData from './hooks'; import SearchControls from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('@edx/frontend-platform/i18n'); -jest.unmock('react'); jest.mock('./hooks', () => jest.fn()); const hookProps = { diff --git a/src/components/GradesView/SpinnerIcon.test.jsx b/src/components/GradesView/SpinnerIcon.test.jsx index 8de8427..36ba8c0 100644 --- a/src/components/GradesView/SpinnerIcon.test.jsx +++ b/src/components/GradesView/SpinnerIcon.test.jsx @@ -4,9 +4,6 @@ import { render } from '@testing-library/react'; import { selectors } from 'data/redux/hooks'; import SpinnerIcon from './SpinnerIcon'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); jest.mock('data/redux/hooks', () => ({ selectors: { root: { useShouldShowSpinner: jest.fn() }, diff --git a/src/components/GradesView/StatusAlerts/hooks.test.js b/src/components/GradesView/StatusAlerts/hooks.test.js index 4b0e11f..cf3d5a4 100644 --- a/src/components/GradesView/StatusAlerts/hooks.test.js +++ b/src/components/GradesView/StatusAlerts/hooks.test.js @@ -1,6 +1,5 @@ import { useIntl } from '@edx/frontend-platform/i18n'; -import { formatMessage } from 'testUtils'; import { actions, selectors } from 'data/redux/hooks'; import useStatusAlertsData from './hooks'; @@ -16,6 +15,18 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useContext: jest.fn(context => context), +})); + +jest.mock('@edx/frontend-platform/i18n', () => ({ + ...jest.requireActual('@edx/frontend-platform/i18n'), + useIntl: jest.fn(() => ({ + formatMessage: (message) => message.defaultMessage, + })), +})); + const validity = { isMinValid: true, isMaxValid: true, @@ -49,7 +60,7 @@ describe('useStatusAlertsData', () => { expect(out.successBanner.show).toEqual(showSuccess); }); test('message', () => { - expect(out.successBanner.text).toEqual(formatMessage(messages.editSuccessAlert)); + expect(out.successBanner.text).toEqual(messages.editSuccessAlert.defaultMessage); }); }); describe('gradeFilter', () => { @@ -70,7 +81,7 @@ describe('useStatusAlertsData', () => { expect(out.gradeFilter.show).toEqual(true); }); test('filter message', () => { - expect(out.gradeFilter.text).toEqual(formatMessage(messages.minGradeInvalid)); + expect(out.gradeFilter.text).toEqual(messages.minGradeInvalid.defaultMessage); }); }); describe('max filter is invalid', () => { @@ -85,7 +96,7 @@ describe('useStatusAlertsData', () => { expect(out.gradeFilter.show).toEqual(true); }); test('filter message', () => { - expect(out.gradeFilter.text).toEqual(formatMessage(messages.maxGradeInvalid)); + expect(out.gradeFilter.text).toEqual(messages.maxGradeInvalid.defaultMessage); }); }); describe('both filters are invalid', () => { @@ -101,7 +112,7 @@ describe('useStatusAlertsData', () => { }); test('filter message', () => { expect(out.gradeFilter.text).toEqual( - `${formatMessage(messages.minGradeInvalid)}${formatMessage(messages.maxGradeInvalid)}`, + `${messages.minGradeInvalid.defaultMessage}${messages.maxGradeInvalid.defaultMessage}`, ); }); }); diff --git a/src/components/GradesView/StatusAlerts/index.test.jsx b/src/components/GradesView/StatusAlerts/index.test.jsx index ba31033..b5a0553 100644 --- a/src/components/GradesView/StatusAlerts/index.test.jsx +++ b/src/components/GradesView/StatusAlerts/index.test.jsx @@ -5,7 +5,6 @@ import useStatusAlertsData from './hooks'; import StatusAlerts from '.'; jest.mock('./hooks', () => jest.fn()); -jest.unmock('@openedx/paragon'); const hookProps = { successBanner: { diff --git a/src/components/GradesView/hooks.test.js b/src/components/GradesView/hooks.test.js index 7e444e0..216dd27 100644 --- a/src/components/GradesView/hooks.test.js +++ b/src/components/GradesView/hooks.test.js @@ -1,6 +1,5 @@ import { useIntl } from '@edx/frontend-platform/i18n'; -import { formatMessage } from 'testUtils'; import { actions, thunkActions } from 'data/redux/hooks'; import useGradesViewData from './hooks'; @@ -15,6 +14,18 @@ jest.mock('data/redux/hooks', () => ({ }, })); +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useContext: jest.fn(context => context), +})); + +jest.mock('@edx/frontend-platform/i18n', () => ({ + ...jest.requireActual('@edx/frontend-platform/i18n'), + useIntl: jest.fn(() => ({ + formatMessage: (message) => message.defaultMessage, + })), +})); + const fetchGrades = jest.fn(); thunkActions.grades.useFetchGrades.mockReturnValue(fetchGrades); const resetFilters = jest.fn(); @@ -39,11 +50,11 @@ describe('useGradesViewData', () => { }); describe('output', () => { test('stepHeadings', () => { - expect(out.stepHeadings.filter).toEqual(formatMessage(messages.filterStepHeading)); - expect(out.stepHeadings.gradebook).toEqual(formatMessage(messages.gradebookStepHeading)); + expect(out.stepHeadings.filter).toEqual(messages.filterStepHeading.defaultMessage); + expect(out.stepHeadings.gradebook).toEqual(messages.gradebookStepHeading.defaultMessage); }); test('mastersHint', () => { - expect(out.mastersHint).toEqual(formatMessage(messages.mastersHint)); + expect(out.mastersHint).toEqual(messages.mastersHint.defaultMessage); }); describe('handleFilterBadgeClose', () => { it('resets filters locally and in query params, and fetches grades', () => { diff --git a/src/components/GradesView/index.test.jsx b/src/components/GradesView/index.test.jsx index fafd550..bbccbf9 100644 --- a/src/components/GradesView/index.test.jsx +++ b/src/components/GradesView/index.test.jsx @@ -6,9 +6,6 @@ import { render, initializeMocks } from 'testUtilsExtra'; import useGradesViewData from './hooks'; import GradesView from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); jest.mock('./hooks', () => jest.fn()); const hookProps = { diff --git a/src/components/NetworkButton/test.jsx b/src/components/NetworkButton/test.jsx index b45f651..ae241cb 100644 --- a/src/components/NetworkButton/test.jsx +++ b/src/components/NetworkButton/test.jsx @@ -6,10 +6,6 @@ import userEvent from '@testing-library/user-event'; import { NetworkButton, mapStateToProps, buttonStates } from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('data/selectors', () => ({ root: { shouldShowSpinner: jest.fn(), diff --git a/src/components/WithSidebar/test.jsx b/src/components/WithSidebar/test.jsx index f1f481b..8dec453 100644 --- a/src/components/WithSidebar/test.jsx +++ b/src/components/WithSidebar/test.jsx @@ -4,10 +4,6 @@ import { render, screen, initializeMocks } from 'testUtilsExtra'; import { WithSidebar, mapStateToProps, mapDispatchToProps } from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock('data/selectors', () => ({ app: { filterMenu: { diff --git a/src/containers/GradebookPage/test.jsx b/src/containers/GradebookPage/test.jsx index 4adcfc7..b5853a9 100644 --- a/src/containers/GradebookPage/test.jsx +++ b/src/containers/GradebookPage/test.jsx @@ -4,10 +4,6 @@ import { render, screen, initializeMocks } from 'testUtilsExtra'; import { GradebookPage, mapStateToProps, mapDispatchToProps } from '.'; -jest.unmock('@openedx/paragon'); -jest.unmock('react'); -jest.unmock('@edx/frontend-platform/i18n'); - jest.mock( 'components/WithSidebar', // eslint-disable-next-line react/prop-types diff --git a/src/data/selectors/grades.test.js b/src/data/selectors/grades.test.js index bdd5f06..ff3d6c8 100644 --- a/src/data/selectors/grades.test.js +++ b/src/data/selectors/grades.test.js @@ -8,6 +8,11 @@ import { formatDateForDisplay } from '../actions/utils'; import * as selectors from './grades'; import exportedSelectors from './grades'; +jest.mock('@edx/frontend-platform/i18n', () => ({ + ...jest.requireActual('@edx/frontend-platform/i18n'), + getLocale: jest.fn(), +})); + const { minGrade, maxGrade } = selectors; const genericResultsRows = [ diff --git a/src/head/Head.test.jsx b/src/head/Head.test.jsx index 11bcdef..f24741e 100644 --- a/src/head/Head.test.jsx +++ b/src/head/Head.test.jsx @@ -4,10 +4,6 @@ import { initializeMocks, render, waitFor } from 'testUtilsExtra'; import Head from './Head'; -jest.unmock('@openedx/paragon'); -jest.unmock('@edx/frontend-platform/i18n'); -jest.unmock('react'); - describe('Head', () => { it('should match render title tag and favicon with the site configuration values', async () => { initializeMocks(); diff --git a/src/setupTest.js b/src/setupTest.js index e8b5b1d..56f70cb 100755 --- a/src/setupTest.js +++ b/src/setupTest.js @@ -17,102 +17,3 @@ process.env.LOGOUT_URL = `${mockConfigs.LMS_BASE_URL}/logout`; process.env.REFRESH_ACCESS_TOKEN_ENDPOINT = `${mockConfigs.LMS_BASE_URL}/refresh_access_token`; process.env.ACCESS_TOKEN_COOKIE_NAME = 'edx'; process.env.CSRF_TOKEN_API_PATH = 'TOKEN_PATH'; - -jest.mock('@edx/frontend-platform/i18n', () => { - const i18n = jest.requireActual('@edx/frontend-platform/i18n'); - const PropTypes = jest.requireActual('prop-types'); - const { formatMessage } = jest.requireActual('./testUtils'); - const formatDate = jest.fn(date => new Date(date).toLocaleDateString()).mockName('useIntl.formatDate'); - return { - ...i18n, - intlShape: PropTypes.shape({ - formatMessage: PropTypes.func, - }), - useIntl: jest.fn(() => ({ - formatMessage, - formatDate, - })), - IntlProvider: () => 'IntlProvider', - defineMessages: m => m, - FormattedMessage: () => 'FormattedMessage', - getLocale: jest.fn(), - }; -}); - -jest.mock('@edx/frontend-component-header', () => ({ - messages: ['some', 'messages'], -})); -jest.mock('@edx/frontend-component-footer', () => ({ - messages: ['some', 'messages'], -})); - -jest.mock('@openedx/paragon/icons', () => ({ - FilterAlt: 'FilterAlt', - Close: 'Close', -})); - -jest.mock('@openedx/paragon', () => jest.requireActual('testUtils').mockNestedComponents({ - Alert: 'Alert', - ActionRow: 'ActionRow', - Badge: 'Badge', - Button: 'Button', - Collapsible: { - Advanced: 'Collapsible.Advanced', - Body: 'Collapsible.Body', - Trigger: 'Collapsible.Trigger', - Visible: 'Collapsible.Visible', - }, - DataTable: { - EmptyTable: 'DataTable.EmptyTable', - Table: 'DataTable.Table', - TableControlBar: 'DataTable.TableControlBar', - TableController: 'DataTable.TableController', - TableFooter: 'DataTable.TableFooter', - }, - Form: { - Checkbox: 'Form.Checkbox', - CheckboxSet: 'Form.CheckboxSet', - Control: { - Feedback: 'Form.Control.Feedback', - }, - Group: 'Form.Group', - Label: 'Form.Label', - Radio: 'Form.Radio', - RadioSet: 'Form.RadioSet', - Switch: 'Form.Switch', - }, - FormControl: 'FormControl', - FormGroup: 'FormGroup', - FormLabel: 'FormLabel', - Hyperlink: 'Hyperlink', - Icon: 'Icon', - IconButton: 'IconButton', - Input: 'Input', - ModalDialog: { - Body: 'ModalDialog.Body', - CloseButton: 'ModalDialog.CloseButton', - Header: 'ModalDialog.Header', - Hero: 'ModalDialog.Hero', - Footer: 'ModalDialog.Footer', - }, - OverlayTrigger: 'OverlayTrigger', - Row: 'Row', - SearchField: 'SearchField', - Spinner: 'Spinner', - StatefulButton: 'StatefulButton', - Toast: 'Toast', - - useCheckboxSetValues: () => jest.fn().mockImplementation((values) => ([values, { - add: jest.fn().mockName('useCheckboxSetValues.add'), - remove: jest.fn().mockName('useCheckboxSetValues.remove'), - }])), -})); - -jest.mock('react', () => ({ - ...jest.requireActual('react'), - useRef: jest.fn((val) => ({ current: val, useRef: true })), - useCallback: jest.fn((cb, prereqs) => ({ useCallback: { cb, prereqs } })), - useEffect: jest.fn((cb, prereqs) => ({ useEffect: { cb, prereqs } })), - useMemo: jest.fn((cb, prereqs) => cb(prereqs)), - useContext: jest.fn(context => context), -})); diff --git a/src/testUtilsExtra.jsx b/src/testUtilsExtra.jsx index d89b7fb..7be26ea 100644 --- a/src/testUtilsExtra.jsx +++ b/src/testUtilsExtra.jsx @@ -143,3 +143,9 @@ export * from '@testing-library/react'; export { customRender as render, }; + +export const renderWithIntl = (component) => render( + + {component} + , +);