diff --git a/package.json b/package.json index 3c6a61133..3d31e16cb 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "build": "fedx-scripts webpack", "i18n_extract": "fedx-scripts formatjs extract", "lint": "fedx-scripts eslint --ext .js --ext .jsx .", + "lint:fix": "npm run lint -- --fix", "snapshot": "fedx-scripts jest --updateSnapshot", "start": "fedx-scripts webpack-dev-server --progress", "test": "TZ=UTC fedx-scripts jest --coverage --passWithNoTests" diff --git a/src/index.jsx b/src/index.jsx index cef8bc4d8..520486ea4 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -15,7 +15,7 @@ import FooterSlot from '@openedx/frontend-slot-footer'; import configureStore from './data/configureStore'; import AccountSettingsPage, { NotFoundPage } from './account-settings'; -import IdVerificationPage from './id-verification'; +import IdVerificationPageSlot from './plugin-slots/IdVerificationPageSlot'; import messages from './i18n'; import './index.scss'; @@ -40,7 +40,10 @@ subscribe(APP_READY, () => { > } /> } /> - } /> + } + /> } /> } /> } /> diff --git a/src/plugin-slots/IdVerificationPageSlot/README.md b/src/plugin-slots/IdVerificationPageSlot/README.md new file mode 100644 index 000000000..94400bd30 --- /dev/null +++ b/src/plugin-slots/IdVerificationPageSlot/README.md @@ -0,0 +1,45 @@ +# Footer Slot + +### Slot ID: `id_verification_page_plugin` + +## Description + +This slot is used to replace/modify the IDV Page. + +The implementation of the `IdVerificationPageSlot` component lives in `src/plugin-slots/IdVerificationPageSlot/index.jsx`. + +## Example + +The following `env.config.jsx` will replace the default IDV Page. + +![Screenshot of Default IDV Page](./images/default_id-verification-page.png) + +```jsx +import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework'; + +const config = { + pluginSlots: { + id_verification_page_plugin: { + plugins: [ + { + // Insert a custom IDV Page + op: PLUGIN_OPERATIONS.Insert, + widget: { + id: 'id_verification_page_plugin', + type: DIRECT_PLUGIN, + RenderWidget: () => ( +
+

This is the new IDV page

+ Go Home +
+ ), + }, + }, + ], + }, + }, +}; + +export default config; + +``` diff --git a/src/plugin-slots/IdVerificationPageSlot/images/custom_id-verification-page.png b/src/plugin-slots/IdVerificationPageSlot/images/custom_id-verification-page.png new file mode 100644 index 000000000..a3d8d00ea Binary files /dev/null and b/src/plugin-slots/IdVerificationPageSlot/images/custom_id-verification-page.png differ diff --git a/src/plugin-slots/IdVerificationPageSlot/images/default_id-verification-page.png b/src/plugin-slots/IdVerificationPageSlot/images/default_id-verification-page.png new file mode 100644 index 000000000..8741fe7ab Binary files /dev/null and b/src/plugin-slots/IdVerificationPageSlot/images/default_id-verification-page.png differ diff --git a/src/plugin-slots/IdVerificationPageSlot/index.jsx b/src/plugin-slots/IdVerificationPageSlot/index.jsx new file mode 100644 index 000000000..d207e8e09 --- /dev/null +++ b/src/plugin-slots/IdVerificationPageSlot/index.jsx @@ -0,0 +1,10 @@ +import { PluginSlot } from '@openedx/frontend-plugin-framework'; +import IdVerificationPage from '../../id-verification'; + +const IdVerificationPageSlot = () => ( + + + +); + +export default IdVerificationPageSlot; diff --git a/src/plugin-slots/README.md b/src/plugin-slots/README.md index a38ecda48..1b7f8c2df 100644 --- a/src/plugin-slots/README.md +++ b/src/plugin-slots/README.md @@ -1,3 +1,4 @@ # `frontend-app-account` Plugin Slots * [`footer_slot`](./FooterSlot/) +* [`id_verification_page_plugin`](./IdVerificationPageSlot/) diff --git a/src/setupTest.js b/src/setupTest.js index 95b3726d1..e2e601f96 100755 --- a/src/setupTest.js +++ b/src/setupTest.js @@ -1,3 +1,11 @@ import 'core-js/stable'; import 'regenerator-runtime/runtime'; import '@testing-library/jest-dom'; + +import MockedPluginSlot from './tests/MockedPluginSlot'; + +jest.mock('@openedx/frontend-plugin-framework', () => ({ + ...jest.requireActual('@openedx/frontend-plugin-framework'), + Plugin: () => 'Plugin', + PluginSlot: MockedPluginSlot, +})); diff --git a/src/tests/MockedPluginSlot.jsx b/src/tests/MockedPluginSlot.jsx new file mode 100644 index 000000000..e86952ee0 --- /dev/null +++ b/src/tests/MockedPluginSlot.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const MockedPluginSlot = ({ children, id }) => ( +
+ PluginSlot_{id} + { children &&
{children}
} +
+); + +MockedPluginSlot.displayName = 'PluginSlot'; + +MockedPluginSlot.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]), + id: PropTypes.string, +}; + +MockedPluginSlot.defaultProps = { + children: undefined, + id: undefined, +}; + +export default MockedPluginSlot; diff --git a/src/tests/MockedPluginSlot.test.jsx b/src/tests/MockedPluginSlot.test.jsx new file mode 100644 index 000000000..b830b68fb --- /dev/null +++ b/src/tests/MockedPluginSlot.test.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import MockedPluginSlot from './MockedPluginSlot'; + +describe('MockedPluginSlot', () => { + it('renders mock plugin with "PluginSlot" text', () => { + render(); + + const component = screen.getByText('PluginSlot_test_plugin'); + expect(component).toBeInTheDocument(); + }); + + it('renders as the slot children directly if there is content within', () => { + render( +
+ + How much wood could a woodchuck chuck if a woodchuck could chuck wood? + +
, + ); + + const component = screen.getByRole('article'); + expect(component).toBeInTheDocument(); + + // Direct children + const quote = component.querySelector(':scope > q'); + expect(quote.getAttribute('role')).toBe('note'); + }); + + it('renders mock plugin with a data-testid ', () => { + render( + + I am selling these fine leather jackets. + , + ); + + const component = screen.getByTestId('guybrush'); + expect(component).toBeInTheDocument(); + + const quote = component.querySelector('[role=note]'); + expect(quote).toBeInTheDocument(); + }); +});