diff --git a/src/pages-and-resources/discussions/app-list/FeatureList.test.jsx b/src/pages-and-resources/discussions/app-list/FeatureList.test.jsx new file mode 100644 index 000000000..89b40ab03 --- /dev/null +++ b/src/pages-and-resources/discussions/app-list/FeatureList.test.jsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { + render, queryAllByText, queryByText, getByRole, +} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import FeaturesList from './FeaturesList'; +import messages from './messages'; + +describe('FeaturesList', () => { + const app = { + documentationUrl: 'http://example.com', + featureIds: ['discussion-page', 'embedded-course-sections', 'wcag-2.1'], + hasFullSupport: false, + id: 'legacy', + }; + const features = [ + { id: 'lti' }, + { id: 'wcag-2.1' }, + { id: 'discussion-page' }, + { id: 'embedded-course-sections' }, + ]; + let container; + + beforeEach(() => { + const wrapper = render( + + + , + ); + container = wrapper.container; + }); + + test('displays show app features message', () => { + expect(queryByText(container, messages['supportedFeatureList-mobile-show'].defaultMessage)).toBeInTheDocument(); + }); + + test('displays hide available feature message on expand', () => { + const button = getByRole(container, 'button'); + userEvent.click(button); + expect(queryByText(container, messages['supportedFeatureList-mobile-hide'].defaultMessage)).toBeInTheDocument(); + }); + + test('displays a row for each available feature', () => { + const button = getByRole(container, 'button'); + userEvent.click(button); + features.forEach((feature) => { + const featureNodes = queryAllByText( + container, feature.id, + ); + expect(featureNodes.map(node => node.closest('div'))).toHaveLength(1); + }); + }); + + test('A check icon is shown with each supported feature', () => { + const button = getByRole(container, 'button'); + userEvent.click(button); + features.forEach((feature) => { + const featureElement = queryByText(container, feature.id); + if (app.featureIds.includes(feature.id)) { + expect(featureElement.querySelector('svg')).toHaveAttribute('id', 'check-icon'); + } + }); + }); + + test('A dash icon is shown with each unsupported feature', () => { + const button = getByRole(container, 'button'); + userEvent.click(button); + features.forEach((feature) => { + const featureElement = queryByText(container, feature.id); + if (!app.featureIds.includes(feature.id)) { + expect(featureElement.querySelector('svg')).toHaveAttribute('id', 'remove-icon'); + } + }); + }); +}); diff --git a/src/pages-and-resources/discussions/app-list/FeaturesList.jsx b/src/pages-and-resources/discussions/app-list/FeaturesList.jsx index 5ba1ef9cc..876ddc1e3 100644 --- a/src/pages-and-resources/discussions/app-list/FeaturesList.jsx +++ b/src/pages-and-resources/discussions/app-list/FeaturesList.jsx @@ -1,19 +1,19 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faCheck } from '@fortawesome/free-solid-svg-icons'; -import { Remove } from '@edx/paragon/icons'; +import { Remove, Check } from '@edx/paragon/icons'; import { Collapsible } from '@edx/paragon'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import messages from './messages'; const SupportedFeature = ( - + ); const NonSupportedFeature = ( - + + + ); function FeaturesList({ app, features, intl }) { @@ -46,7 +46,10 @@ function FeaturesList({ app, features, intl }) { export default injectIntl(FeaturesList); FeaturesList.propTypes = { - app: PropTypes.arrayOf(PropTypes.object).isRequired, + app: PropTypes.shape({ + id: PropTypes.string.isRequired, + featureIds: PropTypes.array.isRequired, + }).isRequired, features: PropTypes.arrayOf(PropTypes.object).isRequired, intl: intlShape.isRequired, };