From 8a7964b6aa72ac529d50683db593053c92e3e891 Mon Sep 17 00:00:00 2001 From: Arkadiusz Celer Date: Wed, 3 Mar 2021 13:03:53 +0100 Subject: [PATCH 1/3] created ErrorBoundary --- .../UI/ErrorBoundary/ErrorBoundary.css | 68 +++++++++++++++++++ .../UI/ErrorBoundary/ErrorBoundary.tsx | 53 +++++++++++++++ src/components/UI/index.tsx | 3 +- src/tests/components/ErrorBoundary.test.tsx | 35 ++++++++++ stories/components/ErrorBoundary.stories.tsx | 14 ++++ 5 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/components/UI/ErrorBoundary/ErrorBoundary.css create mode 100644 src/components/UI/ErrorBoundary/ErrorBoundary.tsx create mode 100644 src/tests/components/ErrorBoundary.test.tsx create mode 100644 stories/components/ErrorBoundary.stories.tsx diff --git a/src/components/UI/ErrorBoundary/ErrorBoundary.css b/src/components/UI/ErrorBoundary/ErrorBoundary.css new file mode 100644 index 0000000..aea01b7 --- /dev/null +++ b/src/components/UI/ErrorBoundary/ErrorBoundary.css @@ -0,0 +1,68 @@ +.a6y-react-auth-error-boundary, .a6y-react-auth-error-boundary * { + font-size: 12px; + letter-spacing: normal; + line-height: 16px; + font-weight: normal; +} + +.a6y-react-auth-error-boundary-primary { + padding: 10px 15px; +} + +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-info, +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-info * { + color: #2563EB; + background-color: #93C5FD; + border: 1px solid #2563EB; +} + +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-success, +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-success * { + color: #059669; + background-color: #D1FAE5; + border: 1px solid #059669; +} + +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-warning, +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-warning * { + color: #D97706; + background-color: #FEF3C7; + border: 1px solid #D97706; +} + +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-error, +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-error * { + color: #DC2626; + background-color: #FEE2E2; + border: 1px solid #DC2626; +} +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-validation, +.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-validation * { + color: #D63301; + background-color: #FFCCBA; + border: 1px solid #D63301; +} + +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-info, +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-info * { + color: #2563EB; +} + +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-success, +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-success * { + color: #059669; +} + +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-warning, +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-warning * { + color: #D97706; +} + +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-error, +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-error * { + color: #DC2626; +} +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-validation, +.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-validation * { + color: #D63301; +} \ No newline at end of file diff --git a/src/components/UI/ErrorBoundary/ErrorBoundary.tsx b/src/components/UI/ErrorBoundary/ErrorBoundary.tsx new file mode 100644 index 0000000..98b5a40 --- /dev/null +++ b/src/components/UI/ErrorBoundary/ErrorBoundary.tsx @@ -0,0 +1,53 @@ +import React from 'react' +import './ErrorBoundary.css' + +/** + * @typedef IErrorBoundaryProps + * + * @props {string} [className] - the CSS classname + * @props {boolean} showError - state which determines if an error message will be displayed + * @props {React.ReactNode} children - the error message it can be string or react child with string + * @props {string} [style] - the CSS style for error message 'primary' | 'secondary' + * @props {string} [status] - the status of message 'success' | 'warning' | 'error' | 'validation' + */ + +export interface IErrorBoundaryProps { + className?: string + showError: boolean + children: React.ReactNode + style?: 'primary' | 'secondary' + status?: 'success' | 'warning' | 'error' | 'validation' +} + +/** + * Renders component with API error or Web App error messages + * + * @param {string} [className] - the CSS classname + * @param {boolean} showError - state which determines if an error message will be displayed + * @param {React.ReactNode} children - the error message it can be string or react child with string + * @param {string} [style] - the CSS style for error message 'primary' | 'secondary' + * @param {string} [status] - the status of message 'success' | 'warning' | 'error' | 'validation' + * + * @example + * + * Error message or React child with message + * + */ + +const ErrorBoundary = ({ + className = 'a6y-react-auth-error-boundary', + showError = false, + children = 'Ups! Something were wrong', + style = 'primary', + status = 'error', +}: IErrorBoundaryProps): JSX.Element => { + const classNames = require('classnames') + const ErrorBoundaryClass = classNames({ + [`${className}`]: true, + [`${className}-${style}`]: showError, + [`${className}-${status}`]: showError, + }) + return
{showError && children}
+} + +export default ErrorBoundary diff --git a/src/components/UI/index.tsx b/src/components/UI/index.tsx index 954b2a6..f3feadb 100644 --- a/src/components/UI/index.tsx +++ b/src/components/UI/index.tsx @@ -1,5 +1,6 @@ import Button from './Button/Button' import Input from './Input/Input' import Link from './Link/Link' +import ErrorBoundary from './ErrorBoundary/ErrorBoundary' -export { Button, Input, Link } +export { Button, Input, Link, ErrorBoundary } diff --git a/src/tests/components/ErrorBoundary.test.tsx b/src/tests/components/ErrorBoundary.test.tsx new file mode 100644 index 0000000..14fd347 --- /dev/null +++ b/src/tests/components/ErrorBoundary.test.tsx @@ -0,0 +1,35 @@ +import React from 'react' +import { render } from '@testing-library/react' +import { ErrorBoundary } from '../../components/UI' + +const ErrorText = 'Error message' +const ErrorChild =
{ErrorText}
+ +describe(`ErrorBoundary component test`, () => { + it('should component rendered properly with status [false]', () => { + const rendered = render( + {ErrorText}, + ) + expect(rendered).toBeDefined + }) + it('should component rendered properly with status [true]', () => { + const rendered = render( + {ErrorText}, + ) + expect(rendered).toBeDefined + }) + it('should component rendered properly with status [true] and with H1 tag', () => { + const rendered = render( + +

{ErrorText}

+
, + ) + expect(rendered).toBeDefined + }) + it('should component rendered properly with status [true] and with react child', () => { + const rendered = render( + {ErrorChild}, + ) + expect(rendered).toBeDefined + }) +}) diff --git a/stories/components/ErrorBoundary.stories.tsx b/stories/components/ErrorBoundary.stories.tsx new file mode 100644 index 0000000..4527384 --- /dev/null +++ b/stories/components/ErrorBoundary.stories.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import { Meta } from '@storybook/react' +import ErrorBoundary from '../../src/components/UI/ErrorBoundary/ErrorBoundary' + +export const ErrorBoundaryComponent: React.VFC = args => ( + + Error message + +) + +export default { + title: 'Components/ErrorBoundary', + component: ErrorBoundary, +} as Meta From 4c8b774a8e7ab336efd0fae66e3337a57a9d48d2 Mon Sep 17 00:00:00 2001 From: Arkadiusz Celer Date: Wed, 3 Mar 2021 13:08:04 +0100 Subject: [PATCH 2/3] added ErrorBoundary to SignIn and SignUp components --- src/components/SignIn/SignIn.tsx | 7 ++++++- src/components/SignUp/SignUp.tsx | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/SignIn/SignIn.tsx b/src/components/SignIn/SignIn.tsx index d5a58b8..0211581 100644 --- a/src/components/SignIn/SignIn.tsx +++ b/src/components/SignIn/SignIn.tsx @@ -1,20 +1,25 @@ import React from 'react' import EmailPasswordForm from '../EmailPasswordForm' import FormLinks from '../FormLinks' +import { ErrorBoundary } from '../UI' import './SignIn.css' export interface Props { className?: string onClick?: () => void - apiError?: unknown + apiError?: string } const SignIn = ({ className = 'a6y-react-auth-sign-in-cmp', onClick, + apiError, }: Props): JSX.Element => { return (
+ + {apiError} +
diff --git a/src/components/SignUp/SignUp.tsx b/src/components/SignUp/SignUp.tsx index 836d92a..e1c11b0 100644 --- a/src/components/SignUp/SignUp.tsx +++ b/src/components/SignUp/SignUp.tsx @@ -1,19 +1,24 @@ import React from 'react' import EmailPasswordForm from '../EmailPasswordForm' import FormLinks from '../FormLinks' +import { ErrorBoundary } from '../UI' import './SignUp.css' export interface Props { className?: string onClick?: () => void - apiError?: unknown + apiError?: string } const SignUp = ({ className = 'a6y-react-auth-sign-up-cmp', + apiError, }: Props): JSX.Element => { return (
+ + {apiError} +
From 5f786d14ac4a62b195df4f3782f933a4e70a6fe0 Mon Sep 17 00:00:00 2001 From: Arkadiusz Celer Date: Wed, 3 Mar 2021 14:23:40 +0100 Subject: [PATCH 3/3] changed className --- .../UI/ErrorBoundary/ErrorBoundary.css | 54 ++++--------------- .../UI/ErrorBoundary/ErrorBoundary.tsx | 21 ++++---- 2 files changed, 22 insertions(+), 53 deletions(-) diff --git a/src/components/UI/ErrorBoundary/ErrorBoundary.css b/src/components/UI/ErrorBoundary/ErrorBoundary.css index aea01b7..0323a85 100644 --- a/src/components/UI/ErrorBoundary/ErrorBoundary.css +++ b/src/components/UI/ErrorBoundary/ErrorBoundary.css @@ -1,68 +1,34 @@ -.a6y-react-auth-error-boundary, .a6y-react-auth-error-boundary * { +.a6y-react-auth__error-boundary, .a6y-react-auth__error-boundary * { font-size: 12px; letter-spacing: normal; line-height: 16px; font-weight: normal; } -.a6y-react-auth-error-boundary-primary { +.a6y-react-auth__error-boundary--primary { padding: 10px 15px; } -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-info, -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-info * { - color: #2563EB; - background-color: #93C5FD; - border: 1px solid #2563EB; -} - -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-success, -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-success * { - color: #059669; - background-color: #D1FAE5; - border: 1px solid #059669; -} - -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-warning, -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-warning * { +.a6y-react-auth__error-boundary--primary.a6y-react-auth__error-boundary--warning, +.a6y-react-auth__error-boundary--primary.a6y-react-auth__error-boundary--warning * { color: #D97706; background-color: #FEF3C7; border: 1px solid #D97706; } -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-error, -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-error * { +.a6y-react-auth__error-boundary--primary.a6y-react-auth__error-boundary--error, +.a6y-react-auth__error-boundary--primary.a6y-react-auth__error-boundary--error * { color: #DC2626; background-color: #FEE2E2; border: 1px solid #DC2626; } -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-validation, -.a6y-react-auth-error-boundary-primary.a6y-react-auth-error-boundary-validation * { - color: #D63301; - background-color: #FFCCBA; - border: 1px solid #D63301; -} -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-info, -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-info * { - color: #2563EB; -} - -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-success, -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-success * { - color: #059669; -} - -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-warning, -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-warning * { +.a6y-react-auth__error-boundary--secondary.a6y-react-auth__error-boundary--warning, +.a6y-react-auth__error-boundary--secondary.a6y-react-auth__error-boundary--warning * { color: #D97706; } -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-error, -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-error * { +.a6y-react-auth__error-boundary--secondary.a6y-react-auth__error-boundary--error, +.a6y-react-auth__error-boundary--secondary.a6y-react-auth__error-boundary--error * { color: #DC2626; -} -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-validation, -.a6y-react-auth-error-boundary-secondary.a6y-react-auth-error-boundary-validation * { - color: #D63301; } \ No newline at end of file diff --git a/src/components/UI/ErrorBoundary/ErrorBoundary.tsx b/src/components/UI/ErrorBoundary/ErrorBoundary.tsx index 98b5a40..ee1527c 100644 --- a/src/components/UI/ErrorBoundary/ErrorBoundary.tsx +++ b/src/components/UI/ErrorBoundary/ErrorBoundary.tsx @@ -8,7 +8,7 @@ import './ErrorBoundary.css' * @props {boolean} showError - state which determines if an error message will be displayed * @props {React.ReactNode} children - the error message it can be string or react child with string * @props {string} [style] - the CSS style for error message 'primary' | 'secondary' - * @props {string} [status] - the status of message 'success' | 'warning' | 'error' | 'validation' + * @props {string} [status] - the status of message 'warning' | 'error' */ export interface IErrorBoundaryProps { @@ -16,7 +16,7 @@ export interface IErrorBoundaryProps { showError: boolean children: React.ReactNode style?: 'primary' | 'secondary' - status?: 'success' | 'warning' | 'error' | 'validation' + status?: 'warning' | 'error' } /** @@ -26,16 +26,16 @@ export interface IErrorBoundaryProps { * @param {boolean} showError - state which determines if an error message will be displayed * @param {React.ReactNode} children - the error message it can be string or react child with string * @param {string} [style] - the CSS style for error message 'primary' | 'secondary' - * @param {string} [status] - the status of message 'success' | 'warning' | 'error' | 'validation' + * @param {string} [status] - the status of message 'warning' | 'error' * * @example - * + * * Error message or React child with message * */ const ErrorBoundary = ({ - className = 'a6y-react-auth-error-boundary', + className = 'a6y-react-auth__error-boundary', showError = false, children = 'Ups! Something were wrong', style = 'primary', @@ -43,11 +43,14 @@ const ErrorBoundary = ({ }: IErrorBoundaryProps): JSX.Element => { const classNames = require('classnames') const ErrorBoundaryClass = classNames({ - [`${className}`]: true, - [`${className}-${style}`]: showError, - [`${className}-${status}`]: showError, + [`${className}--${style}`]: showError && style ? true : false, + [`${className}--${status}`]: showError && status ? true : false, }) - return
{showError && children}
+ return ( +
+ {showError && children} +
+ ) } export default ErrorBoundary