diff --git a/src/components/GradesView/ImportSuccessToast/__snapshots__/index.test.jsx.snap b/src/components/GradesView/ImportSuccessToast/__snapshots__/index.test.jsx.snap new file mode 100644 index 0000000..e3c7721 --- /dev/null +++ b/src/components/GradesView/ImportSuccessToast/__snapshots__/index.test.jsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ImportSuccessToast component render snapshot 1`] = ` + + test-description + +`; diff --git a/src/components/GradesView/ImportSuccessToast/hooks.js b/src/components/GradesView/ImportSuccessToast/hooks.js new file mode 100644 index 0000000..75db550 --- /dev/null +++ b/src/components/GradesView/ImportSuccessToast/hooks.js @@ -0,0 +1,39 @@ +import { useIntl } from '@edx/frontend-platform/i18n'; + +import { actions, selectors } from 'data/redux/hooks'; +import { views } from 'data/constants/app'; +import messages from './messages'; + +/** + * + * Toast component triggered by successful grade upload. + * Provides a link to view the Bulk Management History tab. + */ +export const useImportSuccessToastData = () => { + const { formatMessage } = useIntl(); + + const show = selectors.app.useShowImportSuccessToast(); + const setAppView = actions.app.useSetView(); + const setShow = actions.app.useSetShowImportSuccessToast(); + + const onClose = () => { + setShow(false); + }; + + const handleShowHistoryView = () => { + setAppView(views.bulkManagementHistory); + setShow(false); + }; + + return { + action: { + label: formatMessage(messages.showHistoryViewBtn), + onClick: handleShowHistoryView, + }, + onClose, + show, + description: formatMessage(messages.description), + }; +}; + +export default useImportSuccessToastData; diff --git a/src/components/GradesView/ImportSuccessToast/hooks.test.js b/src/components/GradesView/ImportSuccessToast/hooks.test.js new file mode 100644 index 0000000..8530036 --- /dev/null +++ b/src/components/GradesView/ImportSuccessToast/hooks.test.js @@ -0,0 +1,58 @@ +import { useIntl } from '@edx/frontend-platform/i18n'; + +import { formatMessage } from 'testUtils'; +import { views } from 'data/constants/app'; +import { actions, selectors } from 'data/redux/hooks'; + +import useImportSuccessToastData from './hooks'; +import messages from './messages'; + +jest.mock('data/redux/hooks', () => ({ + actions: { + app: { + useSetView: jest.fn(), + useSetShowImportSuccessToast: jest.fn(), + }, + }, + selectors: { + app: { useShowImportSuccessToast: jest.fn() }, + }, +})); + +const setView = jest.fn().mockName('hooks.setView'); +const setShowToast = jest.fn().mockName('hooks.setShowImportSuccessToast'); +actions.app.useSetView.mockReturnValue(setView); +actions.app.useSetShowImportSuccessToast.mockReturnValue(setShowToast); +const showImportSuccessToast = 'test-show-import-success-toast'; +selectors.app.useShowImportSuccessToast.mockReturnValue(showImportSuccessToast); + +let out; +describe('ImportSuccessToast component', () => { + beforeAll(() => { + out = useImportSuccessToastData(); + }); + describe('behavior', () => { + it('initializes intl hook', () => { + expect(useIntl).toHaveBeenCalledWith(); + }); + it('initializes redux hooks', () => { + expect(selectors.app.useShowImportSuccessToast).toHaveBeenCalled(); + expect(actions.app.useSetView).toHaveBeenCalled(); + expect(actions.app.useSetShowImportSuccessToast).toHaveBeenCalled(); + }); + }); + describe('output', () => { + test('action label', () => { + expect(out.action.label).toEqual(formatMessage(messages.showHistoryViewBtn)); + }); + test('action click event', () => { + out.action.onClick(); + expect(setView).toHaveBeenCalledWith(views.bulkManagementHistory); + expect(setShowToast).toHaveBeenCalledWith(false); + }); + test('onClose', () => { + out.onClose(); + expect(setShowToast).toHaveBeenCalledWith(false); + }); + }); +}); diff --git a/src/components/GradesView/ImportSuccessToast/index.jsx b/src/components/GradesView/ImportSuccessToast/index.jsx new file mode 100644 index 0000000..f9f80f3 --- /dev/null +++ b/src/components/GradesView/ImportSuccessToast/index.jsx @@ -0,0 +1,28 @@ +import React from 'react'; + +import { Toast } from '@edx/paragon'; + +import useImportSuccessToastData from './hooks'; + +/** + * + * Toast component triggered by successful grade upload. + * Provides a link to view the Bulk Management History tab. + */ +export const ImportSuccessToast = () => { + const { + action, + onClose, + show, + description, + } = useImportSuccessToastData(); + return ( + + {description} + + ); +}; + +ImportSuccessToast.propTypes = {}; + +export default ImportSuccessToast; diff --git a/src/components/GradesView/ImportSuccessToast/index.test.jsx b/src/components/GradesView/ImportSuccessToast/index.test.jsx new file mode 100644 index 0000000..d9c7c55 --- /dev/null +++ b/src/components/GradesView/ImportSuccessToast/index.test.jsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { shallow } from 'enzyme'; + +import useImportSuccessToastData from './hooks'; +import ImportSuccessToast from '.'; + +jest.mock('./hooks', () => jest.fn()); + +const hookProps = { + action: 'test-action', + onClose: jest.fn().mockName('hooks.onClose'), + show: 'test-show', + description: 'test-description', +}; +useImportSuccessToastData.mockReturnValue(hookProps); + +let el; +describe('ImportSuccessToast component', () => { + beforeAll(() => { + el = shallow(); + }); + describe('behavior', () => { + it('initializes component hook', () => { + expect(useImportSuccessToastData).toHaveBeenCalled(); + }); + }); + describe('render', () => { + test('snapshot', () => { + expect(el).toMatchSnapshot(); + }); + test('Toast', () => { + expect(el.type()).toEqual('Toast'); + expect(el.props().action).toEqual(hookProps.action); + expect(el.props().onClose).toEqual(hookProps.onClose); + expect(el.props().show).toEqual(hookProps.show); + expect(el.text()).toEqual(hookProps.description); + }); + }); +}); diff --git a/src/components/GradesView/ImportSuccessToast/messages.js b/src/components/GradesView/ImportSuccessToast/messages.js new file mode 100644 index 0000000..90791f6 --- /dev/null +++ b/src/components/GradesView/ImportSuccessToast/messages.js @@ -0,0 +1,16 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + description: { + id: 'gradebook.GradesView.ImportSuccessToast.description', + defaultMessage: 'Import Successful! Grades will be updated momentarily.', + description: 'A message congratulating a successful Import of grades', + }, + showHistoryViewBtn: { + id: 'gradebook.GradesView.ImportSuccessToast.showHistoryViewBtn', + defaultMessage: 'View Activity Log', + description: 'The text on a button that loads a view of the Bulk Management Activity Log', + }, +}); + +export default messages;