From 1d5f0819a0289bc32741bd7577159ac1b4cf60e0 Mon Sep 17 00:00:00 2001 From: David Pickart Date: Mon, 28 Sep 2020 17:12:54 -0500 Subject: [PATCH] Remove FlashMessage component dependency on redux-flash --- src/indicators/flash-message-container.js | 21 +++++---- src/indicators/flash-message.js | 46 +++++++++++-------- stories/indicators/flash-message.story.js | 16 ++----- .../flash-message-container.test.js | 36 +++++++++++++++ test/indicators/flash-message.test.js | 28 +++++------ 5 files changed, 94 insertions(+), 53 deletions(-) create mode 100644 test/indicators/flash-message-container.test.js diff --git a/src/indicators/flash-message-container.js b/src/indicators/flash-message-container.js index 8d7ac0e3..350a19f5 100644 --- a/src/indicators/flash-message-container.js +++ b/src/indicators/flash-message-container.js @@ -8,13 +8,13 @@ import FlashMessage from './flash-message' * A component that displays multiple flash messages generated by [redux-flash](https://github.com/LaunchPadLab/redux-flash). * Most apps will need only one of these containers at the top level. * Will pass down any additional props to the inner `FlashMessage` components. - * + * * @name FlashMessageContainer * @type Function * @param {Object} messages - The flash messages that will be displayed. * @param {Number} [limit] - Maximum number of concurrent messages to display * @example - * + * * function MyApp ({ messages }) { * return ( *
@@ -35,15 +35,20 @@ const defaultProps = { limit: 5, } -function FlashMessageContainer ({ messages, limit, ...rest }) { +function FlashMessageContainer({ messages, limit, ...rest }) { const messagesToDisplay = messages.slice(0, limit) return (
- { - messagesToDisplay.map(message => - - ) - } + {messagesToDisplay.map((message) => ( + + {message.message} + + ))}
) } diff --git a/src/indicators/flash-message.js b/src/indicators/flash-message.js index d392da9f..4ac82bdb 100644 --- a/src/indicators/flash-message.js +++ b/src/indicators/flash-message.js @@ -1,25 +1,27 @@ import React from 'react' import PropTypes from 'prop-types' -import { flashMessageType } from 'redux-flash' import classnames from 'classnames' /** * - * A component that displays a flash message generated by [redux-flash](https://github.com/LaunchPadLab/redux-flash). - * Any message props will be passed through to this component. - * + * A component that displays a flash message. + * * @name FlashMessage * @type Function - * @param {Object} message - The flash message that will be displayed. + * @param {String} children - The flash message that will be displayed. + * @param {Boolean} [isError] - A flag to indicate whether the message is an error message. * @param {Function} [onDismiss] - A callback for dismissing the flash message. The dismiss button will only be shown if this callback is provided. * @example - * - * function ManyMessages ({ messages }) { + * + * function MyView () { + * const [message, setMessage] = useState(null) * return ( *
- * { - * messages.map(message => ) - * } + * { + * message && + * {message}) + * } + * *
* ) * } @@ -27,25 +29,31 @@ import classnames from 'classnames' */ const propTypes = { - message: flashMessageType.isRequired, + children: PropTypes.node.isRequired, + isError: PropTypes.bool, onDismiss: PropTypes.func, + className: PropTypes.string, } const defaultProps = { + isError: false, onDismiss: null, + className: '', } -function FlashMessage ({ message, onDismiss }) { - const statusClass = message.isError ? 'failure' : 'success' +function FlashMessage({ children, isError, onDismiss, className, ...rest }) { + const statusClass = isError ? 'failure' : 'success' return ( -
- { - onDismiss && - - } -

{ message.message }

+ )} +

{children}

) } diff --git a/stories/indicators/flash-message.story.js b/stories/indicators/flash-message.story.js index 1eddd47d..b88e7cec 100644 --- a/stories/indicators/flash-message.story.js +++ b/stories/indicators/flash-message.story.js @@ -3,19 +3,9 @@ import { storiesOf } from '@storybook/react' import { action } from '@storybook/addon-actions' import { FlashMessage } from 'src' -const successMessage = { id: '0', message: 'Success!', isError: false, props: {} } -const failureMessage = { id: '1', message: 'Failure!', isError: true, props: {} } - storiesOf('FlashMessage', module) - .add('success', () => ( - - )) - .add('failure', () => ( - - )) + .add('success', () => Success!) + .add('failure', () => Failure!) .add('dismissable', () => ( - + Success! )) - .add('with custom prop ("hidden")', () => ( - - )) \ No newline at end of file diff --git a/test/indicators/flash-message-container.test.js b/test/indicators/flash-message-container.test.js new file mode 100644 index 00000000..3b1e9af5 --- /dev/null +++ b/test/indicators/flash-message-container.test.js @@ -0,0 +1,36 @@ +import React from 'react' +import { mount } from 'enzyme' +import { FlashMessageContainer } from '../../src' + +const successMessage = { + id: '0', + message: 'Success!', + isError: false, + props: {}, +} +const failureMessage = { + id: '1', + message: 'Failure!', + isError: true, + props: {}, +} + +test('FlashMessageContainer displays all provided redux-flash messages', () => { + const wrapper = mount( + + ) + expect(wrapper.find('div.flash-message.success').exists()).toBe(true) + expect( + wrapper + .find('div.flash-message.success > p') + .first() + .contains('Success!') + ).toBe(true) + expect(wrapper.find('div.flash-message.failure').exists()).toBe(true) + expect( + wrapper + .find('div.flash-message.failure > p') + .first() + .contains('Failure!') + ).toBe(true) +}) diff --git a/test/indicators/flash-message.test.js b/test/indicators/flash-message.test.js index cbe1ff22..65bd7766 100644 --- a/test/indicators/flash-message.test.js +++ b/test/indicators/flash-message.test.js @@ -2,24 +2,26 @@ import React from 'react' import { mount } from 'enzyme' import { FlashMessage } from '../../src/' -const successMessage = { id: '0', message: 'Success!', isError: false, props: {} } -const customMessage = { id: '0', message: 'Success!', isError: false, props: { className: 'foo', hidden: true } } - test('FlashMessage only shows dismiss button when callback is provided', () => { - const wrapper = mount( - - ) + const wrapper = mount(Success!) expect(wrapper.find('button.dismiss').exists()).toBe(false) const dismissWrapper = mount( - { /* do something */ } } /> + { + /* do something */ + }} + > + Success! + ) expect(dismissWrapper.find('button.dismiss').exists()).toBe(true) }) -test('FlashMessage accepts props from message object', () => { - const wrapper = mount( - - ) - expect(wrapper.find('div.foo').exists()).toBe(true) - expect(wrapper.find('div').prop('hidden')).toBe(true) +test('FlashMessage sets class based on isError prop', () => { + const wrapper = mount(Success!) + expect(wrapper.find('div.success').exists()).toBe(true) + expect(wrapper.find('div.failure').exists()).toBe(false) + const errorWrapper = mount(Failure!) + expect(errorWrapper.find('div.success').exists()).toBe(false) + expect(errorWrapper.find('div.failure').exists()).toBe(true) })