From 276cea70d1d1d3f4872a5e3c190b07cda3570c1c Mon Sep 17 00:00:00 2001 From: Jerry Jiang Date: Mon, 26 Aug 2024 15:25:16 -0500 Subject: [PATCH 1/4] chore(content-uploader): migrate upload state --- .../{UploadState.js => UploadState.js.flow} | 30 +-- src/elements/content-uploader/UploadState.tsx | 113 ++++++++++++ .../__tests__/UploadState.test.js | 75 -------- .../__tests__/UploadState.test.tsx | 72 ++++++++ .../__snapshots__/UploadState.test.js.snap | 171 ------------------ 5 files changed, 203 insertions(+), 258 deletions(-) rename src/elements/content-uploader/{UploadState.js => UploadState.js.flow} (91%) create mode 100644 src/elements/content-uploader/UploadState.tsx delete mode 100644 src/elements/content-uploader/__tests__/UploadState.test.js create mode 100644 src/elements/content-uploader/__tests__/UploadState.test.tsx delete mode 100644 src/elements/content-uploader/__tests__/__snapshots__/UploadState.test.js.snap diff --git a/src/elements/content-uploader/UploadState.js b/src/elements/content-uploader/UploadState.js.flow similarity index 91% rename from src/elements/content-uploader/UploadState.js rename to src/elements/content-uploader/UploadState.js.flow index b960e4e3f2..d0939dc776 100644 --- a/src/elements/content-uploader/UploadState.js +++ b/src/elements/content-uploader/UploadState.js.flow @@ -1,19 +1,17 @@ -/** - * @flow - * @file Upload state component - */ - import * as React from 'react'; import classNames from 'classnames'; import { FormattedMessage } from 'react-intl'; -import ErrorEmptyState from '../../icons/states/ErrorEmptyState'; +import { HatWand } from '@box/blueprint-web-assets/illustrations/Medium'; + import UploadEmptyState from '../../icons/states/UploadEmptyState'; import UploadSuccessState from '../../icons/states/UploadSuccessState'; -import messages from '../common/messages'; import UploadStateContent from './UploadStateContent'; -import { VIEW_ERROR, VIEW_UPLOAD_EMPTY, VIEW_UPLOAD_IN_PROGRESS, VIEW_UPLOAD_SUCCESS } from '../../constants'; import type { View } from '../../common/types/core'; +import { VIEW_ERROR, VIEW_UPLOAD_EMPTY, VIEW_UPLOAD_IN_PROGRESS, VIEW_UPLOAD_SUCCESS } from '../../constants'; + +import messages from '../common/messages'; + import './UploadState.scss'; type Props = { @@ -22,16 +20,24 @@ type Props = { isFolderUploadEnabled: boolean, isOver: boolean, isTouch: boolean, - onSelect: Function, - view: View, + onSelect: () => void, + view: View }; -const UploadState = ({ canDrop, hasItems, isOver, isTouch, view, onSelect, isFolderUploadEnabled }: Props) => { +const UploadState = ({ + canDrop, + hasItems, + isOver, + isTouch, + view, + onSelect, + isFolderUploadEnabled, +}: Props) => { let icon; let content; switch (view) { case VIEW_ERROR: - icon = ; + icon = ; content = } />; break; case VIEW_UPLOAD_EMPTY: diff --git a/src/elements/content-uploader/UploadState.tsx b/src/elements/content-uploader/UploadState.tsx new file mode 100644 index 0000000000..12c11146cd --- /dev/null +++ b/src/elements/content-uploader/UploadState.tsx @@ -0,0 +1,113 @@ +import * as React from 'react'; +import classNames from 'classnames'; +import { FormattedMessage } from 'react-intl'; +import { HatWand } from '@box/blueprint-web-assets/illustrations/Medium'; + +import UploadEmptyState from '../../icons/states/UploadEmptyState'; +import UploadSuccessState from '../../icons/states/UploadSuccessState'; +import UploadStateContent from './UploadStateContent'; +import type { View } from '../../common/types/core'; + +import { VIEW_ERROR, VIEW_UPLOAD_EMPTY, VIEW_UPLOAD_IN_PROGRESS, VIEW_UPLOAD_SUCCESS } from '../../constants'; + +import messages from '../common/messages'; + +import './UploadState.scss'; + +export interface UploadStateProps { + canDrop: boolean; + hasItems: boolean; + isFolderUploadEnabled: boolean; + isOver: boolean; + isTouch: boolean; + onSelect: () => void; + view: View; +} + +const UploadState = ({ + canDrop, + hasItems, + isOver, + isTouch, + view, + onSelect, + isFolderUploadEnabled, +}: UploadStateProps) => { + let icon; + let content; + switch (view) { + case VIEW_ERROR: + icon = ; + content = } />; + break; + case VIEW_UPLOAD_EMPTY: + icon = ; + /* eslint-disable no-nested-ternary */ + content = + canDrop && hasItems ? ( + } /> + ) : isTouch ? ( + } + onChange={onSelect} + useButton + /> + ) : ( + } + folderInputLabel={ + isFolderUploadEnabled && + } + message={ + isFolderUploadEnabled ? ( + + ) : ( + + ) + } + onChange={onSelect} + /> + ); + /* eslint-enable no-nested-ternary */ + break; + case VIEW_UPLOAD_IN_PROGRESS: + icon = ; + content = } />; + break; + case VIEW_UPLOAD_SUCCESS: + icon = ; + content = ( + } + folderInputLabel={ + isFolderUploadEnabled && + } + message={} + onChange={onSelect} + useButton={isTouch} + /> + ); + break; + default: + break; + /* eslint-enable jsx-a11y/label-has-for */ + } + + const className = classNames('bcu-upload-state', { + 'bcu-is-droppable': isOver && canDrop, + 'bcu-is-not-droppable': isOver && !canDrop, + 'bcu-has-items': hasItems, + }); + + return ( +
+
+ {icon} + {content} +
+
+
+ ); +}; + +export default UploadState; diff --git a/src/elements/content-uploader/__tests__/UploadState.test.js b/src/elements/content-uploader/__tests__/UploadState.test.js deleted file mode 100644 index 331c0f2043..0000000000 --- a/src/elements/content-uploader/__tests__/UploadState.test.js +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from 'react'; -import noop from 'lodash/noop'; -import { shallow } from 'enzyme'; -import UploadState from '../UploadState'; -import { VIEW_ERROR, VIEW_UPLOAD_EMPTY, VIEW_UPLOAD_IN_PROGRESS, VIEW_UPLOAD_SUCCESS } from '../../../constants'; - -describe('elements/content-uploader/UploadState', () => { - const getWrapper = props => - shallow( - , - ); - - test('should render VIEW_ERROR correctly', () => { - const wrapper = getWrapper({ - view: VIEW_ERROR, - }); - - expect(wrapper).toMatchSnapshot(); - }); - - test('should render VIEW_UPLOAD_EMPTY correctly', () => { - const wrapper = getWrapper({ - view: VIEW_UPLOAD_EMPTY, - }); - - expect(wrapper).toMatchSnapshot(); - }); - - test('should render VIEW_UPLOAD_EMPTY correctly when folder upload is enabled', () => { - const wrapper = getWrapper({ - view: VIEW_UPLOAD_EMPTY, - isFolderUploadEnabled: true, - }); - - expect(wrapper).toMatchSnapshot(); - }); - - test('should render VIEW_UPLOAD_IN_PROGRESS correctly', () => { - const wrapper = getWrapper({ - view: VIEW_UPLOAD_IN_PROGRESS, - }); - - expect(wrapper).toMatchSnapshot(); - }); - - test('should render VIEW_UPLOAD_SUCCESS correctly', () => { - const wrapper = getWrapper({ - view: VIEW_UPLOAD_SUCCESS, - }); - - expect(wrapper).toMatchSnapshot(); - }); - - test('should render VIEW_UPLOAD_SUCCESS correctly when folder upload is enabled', () => { - const wrapper = getWrapper({ - view: VIEW_UPLOAD_SUCCESS, - isFolderUploadEnabled: true, - }); - - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/src/elements/content-uploader/__tests__/UploadState.test.tsx b/src/elements/content-uploader/__tests__/UploadState.test.tsx new file mode 100644 index 0000000000..dd528bc7d5 --- /dev/null +++ b/src/elements/content-uploader/__tests__/UploadState.test.tsx @@ -0,0 +1,72 @@ +import * as React from 'react'; +import { render, screen } from '../../../test-utils/testing-library'; + +import UploadState, { UploadStateProps } from '../UploadState'; + +import { VIEW_ERROR, VIEW_UPLOAD_EMPTY, VIEW_UPLOAD_IN_PROGRESS, VIEW_UPLOAD_SUCCESS } from '../../../constants'; + +describe('elements/content-uploader/UploadState', () => { + const getWrapper = (props: Partial) => + render( + , + ); + + test.each` + view | iconClassName + ${VIEW_ERROR} | ${'upload-error-state'} + ${VIEW_UPLOAD_EMPTY} | ${'upload-empty-state'} + ${VIEW_UPLOAD_IN_PROGRESS} | ${'upload-empty-state'} + ${VIEW_UPLOAD_SUCCESS} | ${'upload-success-state'} + `('should render icon correctly based on the view', ({ view, iconClassName }) => { + const { container } = getWrapper({ view }); + expect(container.querySelector(`.${iconClassName}`)).toBeInTheDocument(); + }); + + test('should render upload_empty view correctly when canDrop and hasItems set to true', () => { + getWrapper({ view: VIEW_UPLOAD_EMPTY, canDrop: true, hasItems: true }); + expect(screen.getByText('Drag and drop to add additional files')).toBeInTheDocument(); + }); + + test('should render upload_empty view correctly when isTouch set to true', () => { + getWrapper({ view: VIEW_UPLOAD_EMPTY, isTouch: true }); + expect(screen.getByText('Select files from your device')).toBeInTheDocument(); + }); + + test('should render content for upload_empty view correctly when isFolderUploadEnabled set to false', () => { + getWrapper({ view: VIEW_UPLOAD_EMPTY }); + expect(screen.getByText('Browse your device')).toBeInTheDocument(); + expect(screen.getByText('Drag and drop files')).toBeInTheDocument(); + }); + + test('should render content for upload_empty view correctly when isFolderUploadEnabled set to true', () => { + getWrapper({ view: VIEW_UPLOAD_EMPTY, isFolderUploadEnabled: true }); + expect(screen.getByText('Select Folders')).toBeInTheDocument(); + expect(screen.getByText('Drag and drop files and folders')).toBeInTheDocument(); + }); + + test('should render content for upload_in_progress view correctly when isFolderUploadEnabled set to true', () => { + getWrapper({ view: VIEW_UPLOAD_IN_PROGRESS }); + expect(screen.getByText('Drag and drop to add additional files')).toBeInTheDocument(); + }); + + test('should render content for upload_success view correctly when isFolderUploadEnabled set to false', () => { + getWrapper({ view: VIEW_UPLOAD_SUCCESS }); + expect(screen.getByText('Select More Files')).toBeInTheDocument(); + expect(screen.getByText('Success! Your files have been uploaded.')).toBeInTheDocument(); + }); + + test('should render content for upload_success view correctly when isFolderUploadEnabled set to true', () => { + getWrapper({ view: VIEW_UPLOAD_SUCCESS, isFolderUploadEnabled: true }); + expect(screen.getByText('Select More Folders')).toBeInTheDocument(); + expect(screen.getByText('Success! Your files have been uploaded.')).toBeInTheDocument(); + }); +}); diff --git a/src/elements/content-uploader/__tests__/__snapshots__/UploadState.test.js.snap b/src/elements/content-uploader/__tests__/__snapshots__/UploadState.test.js.snap deleted file mode 100644 index 34d338071a..0000000000 --- a/src/elements/content-uploader/__tests__/__snapshots__/UploadState.test.js.snap +++ /dev/null @@ -1,171 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`elements/content-uploader/UploadState should render VIEW_ERROR correctly 1`] = ` -
-
- - - } - /> -
-
-
-`; - -exports[`elements/content-uploader/UploadState should render VIEW_UPLOAD_EMPTY correctly 1`] = ` -
-
- - - } - folderInputLabel={false} - message={ - - } - onChange={[Function]} - /> -
-
-
-`; - -exports[`elements/content-uploader/UploadState should render VIEW_UPLOAD_EMPTY correctly when folder upload is enabled 1`] = ` -
-
- - - } - folderInputLabel={ - - } - message={ - - } - onChange={[Function]} - /> -
-
-
-`; - -exports[`elements/content-uploader/UploadState should render VIEW_UPLOAD_IN_PROGRESS correctly 1`] = ` -
-
- - - } - /> -
-
-
-`; - -exports[`elements/content-uploader/UploadState should render VIEW_UPLOAD_SUCCESS correctly when folder upload is enabled 1`] = ` -
-
- - - } - folderInputLabel={ - - } - message={ - - } - onChange={[Function]} - useButton={false} - /> -
-
-
-`; - -exports[`elements/content-uploader/UploadState should render VIEW_UPLOAD_SUCCESS correctly 1`] = ` -
-
- - - } - folderInputLabel={false} - message={ - - } - onChange={[Function]} - useButton={false} - /> -
-
-
-`; From 583d70afcba14affa0aacb19e3e21bda9f26daad Mon Sep 17 00:00:00 2001 From: Jerry Jiang Date: Tue, 3 Sep 2024 11:32:50 -0500 Subject: [PATCH 2/4] chore(content-uploader): add aria-label to svgs --- src/elements/content-uploader/UploadState.js.flow | 2 +- src/elements/content-uploader/UploadState.tsx | 2 +- .../content-uploader/__tests__/UploadState.test.tsx | 8 ++++---- src/icons/states/UploadEmptyState.tsx | 1 + src/icons/states/UploadSuccessState.tsx | 1 + .../__snapshots__/UploadEmptyState.test.tsx.snap | 2 ++ 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/elements/content-uploader/UploadState.js.flow b/src/elements/content-uploader/UploadState.js.flow index d0939dc776..532a3c3829 100644 --- a/src/elements/content-uploader/UploadState.js.flow +++ b/src/elements/content-uploader/UploadState.js.flow @@ -37,7 +37,7 @@ const UploadState = ({ let content; switch (view) { case VIEW_ERROR: - icon = ; + icon = ; content = } />; break; case VIEW_UPLOAD_EMPTY: diff --git a/src/elements/content-uploader/UploadState.tsx b/src/elements/content-uploader/UploadState.tsx index 12c11146cd..186cdf12ac 100644 --- a/src/elements/content-uploader/UploadState.tsx +++ b/src/elements/content-uploader/UploadState.tsx @@ -37,7 +37,7 @@ const UploadState = ({ let content; switch (view) { case VIEW_ERROR: - icon = ; + icon = ; content = } />; break; case VIEW_UPLOAD_EMPTY: diff --git a/src/elements/content-uploader/__tests__/UploadState.test.tsx b/src/elements/content-uploader/__tests__/UploadState.test.tsx index dd528bc7d5..7bafbaa0bb 100644 --- a/src/elements/content-uploader/__tests__/UploadState.test.tsx +++ b/src/elements/content-uploader/__tests__/UploadState.test.tsx @@ -21,14 +21,14 @@ describe('elements/content-uploader/UploadState', () => { ); test.each` - view | iconClassName + view | iconAriaLabel ${VIEW_ERROR} | ${'upload-error-state'} ${VIEW_UPLOAD_EMPTY} | ${'upload-empty-state'} ${VIEW_UPLOAD_IN_PROGRESS} | ${'upload-empty-state'} ${VIEW_UPLOAD_SUCCESS} | ${'upload-success-state'} - `('should render icon correctly based on the view', ({ view, iconClassName }) => { - const { container } = getWrapper({ view }); - expect(container.querySelector(`.${iconClassName}`)).toBeInTheDocument(); + `('should render icon correctly based on the view', ({ view, iconAriaLabel }) => { + getWrapper({ view }); + expect(screen.getByLabelText(iconAriaLabel)).toBeInTheDocument(); }); test('should render upload_empty view correctly when canDrop and hasItems set to true', () => { diff --git a/src/icons/states/UploadEmptyState.tsx b/src/icons/states/UploadEmptyState.tsx index 3162fdd4e9..2ea433de56 100644 --- a/src/icons/states/UploadEmptyState.tsx +++ b/src/icons/states/UploadEmptyState.tsx @@ -7,6 +7,7 @@ import { Icon } from '../iconTypes'; const UploadEmptyState = ({ className = '', color = bdlBoxBlue, height = 55, title, width = 46 }: Icon) => ( ( Date: Tue, 3 Sep 2024 13:25:15 -0500 Subject: [PATCH 3/4] chore(content-uploader): update test --- i18n/en-US.properties | 6 ++++++ src/elements/common/messages.js | 15 +++++++++++++++ src/elements/content-uploader/UploadState.js.flow | 11 ++++++----- src/elements/content-uploader/UploadState.tsx | 11 ++++++----- .../__tests__/UploadState.test.tsx | 14 +++++++------- src/icons/states/UploadEmptyState.tsx | 1 - src/icons/states/UploadSuccessState.tsx | 1 - .../__snapshots__/UploadEmptyState.test.tsx.snap | 2 -- 8 files changed, 40 insertions(+), 21 deletions(-) diff --git a/i18n/en-US.properties b/i18n/en-US.properties index fa8c759b73..a7fad33ac9 100644 --- a/i18n/en-US.properties +++ b/i18n/en-US.properties @@ -778,12 +778,16 @@ be.upload = Upload be.uploadEmptyFileInput = Browse your device # Message shown for upload link for uploading more folders when there are no items to upload be.uploadEmptyFolderInput = Select Folders +# Label for upload empty state. +be.uploadEmptyState = Empty state # Message shown when there are no items to upload and folder upload is disabled be.uploadEmptyWithFolderUploadDisabled = Drag and drop files # Message shown when there are no items to upload and folder upload is enabled be.uploadEmptyWithFolderUploadEnabled = Drag and drop files and folders # Message shown when there is a network error when uploading be.uploadError = A network error has occurred while trying to upload. +# Label for upload error state. +be.uploadErrorState = Error state # Message shown when too many files are uploaded at once be.uploadErrorTooManyFiles = You can only upload up to {fileLimit} file(s) at a time. # Message shown when user drag and drops files onto uploads in progress @@ -798,6 +802,8 @@ be.uploadSuccess = Success! Your files have been uploaded. be.uploadSuccessFileInput = Select More Files # Message shown for upload link for uploading more folders after a successful upload be.uploadSuccessFolderInput = Select More Folders +# Label for upload success state. +be.uploadSuccessState = Success state # Cancel upload button tooltip be.uploadsCancelButtonTooltip = Cancel this upload # Default error message shown when upload fails diff --git a/src/elements/common/messages.js b/src/elements/common/messages.js index 8747044643..0a3821b351 100644 --- a/src/elements/common/messages.js +++ b/src/elements/common/messages.js @@ -142,6 +142,21 @@ const messages = defineMessages({ description: 'Label for upload action.', defaultMessage: 'Upload', }, + uploadEmptyState: { + id: 'be.uploadEmptyState', + description: 'Label for upload empty state.', + defaultMessage: 'Empty state', + }, + uploadErrorState: { + id: 'be.uploadErrorState', + description: 'Label for upload error state.', + defaultMessage: 'Error state', + }, + uploadSuccessState: { + id: 'be.uploadSuccessState', + description: 'Label for upload success state.', + defaultMessage: 'Success state', + }, add: { id: 'be.add', description: 'Label for add action', diff --git a/src/elements/content-uploader/UploadState.js.flow b/src/elements/content-uploader/UploadState.js.flow index 532a3c3829..e2e259f425 100644 --- a/src/elements/content-uploader/UploadState.js.flow +++ b/src/elements/content-uploader/UploadState.js.flow @@ -1,6 +1,6 @@ import * as React from 'react'; import classNames from 'classnames'; -import { FormattedMessage } from 'react-intl'; +import { useIntl, FormattedMessage } from 'react-intl'; import { HatWand } from '@box/blueprint-web-assets/illustrations/Medium'; import UploadEmptyState from '../../icons/states/UploadEmptyState'; @@ -33,15 +33,16 @@ const UploadState = ({ onSelect, isFolderUploadEnabled, }: Props) => { + const intl = useIntl(); let icon; let content; switch (view) { case VIEW_ERROR: - icon = ; + icon = ; content = } />; break; case VIEW_UPLOAD_EMPTY: - icon = ; + icon = } />; /* eslint-disable no-nested-ternary */ content = canDrop && hasItems ? ( @@ -71,11 +72,11 @@ const UploadState = ({ /* eslint-enable no-nested-ternary */ break; case VIEW_UPLOAD_IN_PROGRESS: - icon = ; + icon = } />; content = } />; break; case VIEW_UPLOAD_SUCCESS: - icon = ; + icon = } />; content = ( } diff --git a/src/elements/content-uploader/UploadState.tsx b/src/elements/content-uploader/UploadState.tsx index 186cdf12ac..75a75302ae 100644 --- a/src/elements/content-uploader/UploadState.tsx +++ b/src/elements/content-uploader/UploadState.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import classNames from 'classnames'; -import { FormattedMessage } from 'react-intl'; +import { useIntl, FormattedMessage } from 'react-intl'; import { HatWand } from '@box/blueprint-web-assets/illustrations/Medium'; import UploadEmptyState from '../../icons/states/UploadEmptyState'; @@ -33,15 +33,16 @@ const UploadState = ({ onSelect, isFolderUploadEnabled, }: UploadStateProps) => { + const intl = useIntl(); let icon; let content; switch (view) { case VIEW_ERROR: - icon = ; + icon = ; content = } />; break; case VIEW_UPLOAD_EMPTY: - icon = ; + icon = } />; /* eslint-disable no-nested-ternary */ content = canDrop && hasItems ? ( @@ -71,11 +72,11 @@ const UploadState = ({ /* eslint-enable no-nested-ternary */ break; case VIEW_UPLOAD_IN_PROGRESS: - icon = ; + icon = } />; content = } />; break; case VIEW_UPLOAD_SUCCESS: - icon = ; + icon = } />; content = ( } diff --git a/src/elements/content-uploader/__tests__/UploadState.test.tsx b/src/elements/content-uploader/__tests__/UploadState.test.tsx index 7bafbaa0bb..aff1729cd1 100644 --- a/src/elements/content-uploader/__tests__/UploadState.test.tsx +++ b/src/elements/content-uploader/__tests__/UploadState.test.tsx @@ -21,14 +21,14 @@ describe('elements/content-uploader/UploadState', () => { ); test.each` - view | iconAriaLabel - ${VIEW_ERROR} | ${'upload-error-state'} - ${VIEW_UPLOAD_EMPTY} | ${'upload-empty-state'} - ${VIEW_UPLOAD_IN_PROGRESS} | ${'upload-empty-state'} - ${VIEW_UPLOAD_SUCCESS} | ${'upload-success-state'} - `('should render icon correctly based on the view', ({ view, iconAriaLabel }) => { + view | iconName + ${VIEW_ERROR} | ${'Error state'} + ${VIEW_UPLOAD_EMPTY} | ${'Empty state'} + ${VIEW_UPLOAD_IN_PROGRESS} | ${'Empty state'} + ${VIEW_UPLOAD_SUCCESS} | ${'Success state'} + `('should render icon correctly based on the view', ({ view, iconName }) => { getWrapper({ view }); - expect(screen.getByLabelText(iconAriaLabel)).toBeInTheDocument(); + expect(screen.getByRole('img', { name: iconName })).toBeInTheDocument(); }); test('should render upload_empty view correctly when canDrop and hasItems set to true', () => { diff --git a/src/icons/states/UploadEmptyState.tsx b/src/icons/states/UploadEmptyState.tsx index 2ea433de56..3162fdd4e9 100644 --- a/src/icons/states/UploadEmptyState.tsx +++ b/src/icons/states/UploadEmptyState.tsx @@ -7,7 +7,6 @@ import { Icon } from '../iconTypes'; const UploadEmptyState = ({ className = '', color = bdlBoxBlue, height = 55, title, width = 46 }: Icon) => ( ( Date: Tue, 3 Sep 2024 14:45:26 -0500 Subject: [PATCH 4/4] chore(content-uploader): resolve nits --- src/elements/content-uploader/UploadState.tsx | 43 ++++++++----------- .../__tests__/ItemAction.test.tsx | 16 +++---- .../__tests__/ItemRemove.test.tsx | 8 ++-- .../OverallUploadsProgressBar.test.tsx | 24 +++++------ .../__tests__/UploadInput.test.tsx | 14 +++--- .../__tests__/UploadState.test.tsx | 18 ++++---- .../__tests__/UploadsManagerAction.test.tsx | 8 ++-- 7 files changed, 62 insertions(+), 69 deletions(-) diff --git a/src/elements/content-uploader/UploadState.tsx b/src/elements/content-uploader/UploadState.tsx index 75a75302ae..a41ba5988a 100644 --- a/src/elements/content-uploader/UploadState.tsx +++ b/src/elements/content-uploader/UploadState.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import classNames from 'classnames'; -import { useIntl, FormattedMessage } from 'react-intl'; +import { useIntl } from 'react-intl'; import { HatWand } from '@box/blueprint-web-assets/illustrations/Medium'; import UploadEmptyState from '../../icons/states/UploadEmptyState'; @@ -33,38 +33,34 @@ const UploadState = ({ onSelect, isFolderUploadEnabled, }: UploadStateProps) => { - const intl = useIntl(); + const { formatMessage } = useIntl(); let icon; let content; switch (view) { case VIEW_ERROR: - icon = ; - content = } />; + icon = ; + content = ; break; case VIEW_UPLOAD_EMPTY: - icon = } />; + icon = ; /* eslint-disable no-nested-ternary */ content = canDrop && hasItems ? ( - } /> + ) : isTouch ? ( } + fileInputLabel={formatMessage(messages.uploadNoDragDrop)} onChange={onSelect} useButton /> ) : ( } - folderInputLabel={ - isFolderUploadEnabled && - } + fileInputLabel={formatMessage(messages.uploadEmptyFileInput)} + folderInputLabel={isFolderUploadEnabled && formatMessage(messages.uploadEmptyFolderInput)} message={ - isFolderUploadEnabled ? ( - - ) : ( - - ) + isFolderUploadEnabled + ? formatMessage(messages.uploadEmptyWithFolderUploadEnabled) + : formatMessage(messages.uploadEmptyWithFolderUploadDisabled) } onChange={onSelect} /> @@ -72,18 +68,16 @@ const UploadState = ({ /* eslint-enable no-nested-ternary */ break; case VIEW_UPLOAD_IN_PROGRESS: - icon = } />; - content = } />; + icon = ; + content = ; break; case VIEW_UPLOAD_SUCCESS: - icon = } />; + icon = ; content = ( } - folderInputLabel={ - isFolderUploadEnabled && - } - message={} + fileInputLabel={formatMessage(messages.uploadSuccessFileInput)} + folderInputLabel={isFolderUploadEnabled && formatMessage(messages.uploadSuccessFolderInput)} + message={formatMessage(messages.uploadSuccess)} onChange={onSelect} useButton={isTouch} /> @@ -91,7 +85,6 @@ const UploadState = ({ break; default: break; - /* eslint-enable jsx-a11y/label-has-for */ } const className = classNames('bcu-upload-state', { diff --git a/src/elements/content-uploader/__tests__/ItemAction.test.tsx b/src/elements/content-uploader/__tests__/ItemAction.test.tsx index ab2e728bdc..92a5812355 100644 --- a/src/elements/content-uploader/__tests__/ItemAction.test.tsx +++ b/src/elements/content-uploader/__tests__/ItemAction.test.tsx @@ -30,7 +30,7 @@ describe('elements/content-uploader/ItemAction', () => { onUpgradeCTAClick: jest.fn(), }; - const getWrapper = (props: Partial) => render(); + const renderComponent = (props: Partial) => render(); test.each` status @@ -40,7 +40,7 @@ describe('elements/content-uploader/ItemAction', () => { ${STATUS_ERROR} ${STATUS_PENDING} `('should render correctly with $status', ({ status }: Pick) => { - getWrapper({ status }); + renderComponent({ status }); expect(screen.getByRole('button')).toBeInTheDocument(); }); @@ -51,7 +51,7 @@ describe('elements/content-uploader/ItemAction', () => { `( 'should render correctly with $status and resumable uploads enabled', ({ status, label }: Pick & { label: string }) => { - getWrapper({ status, isResumableUploadsEnabled: true }); + renderComponent({ status, isResumableUploadsEnabled: true }); expect(screen.getByRole('img', { name: label })).toBeInTheDocument(); }, ); @@ -64,7 +64,7 @@ describe('elements/content-uploader/ItemAction', () => { `( 'should render correctly with $status and resumable uploads enabled', ({ status }: Pick) => { - getWrapper({ status, isResumableUploadsEnabled: true }); + renderComponent({ status, isResumableUploadsEnabled: true }); expect(screen.getByRole('status', { name: 'loading' })).toBeInTheDocument(); }, ); @@ -76,23 +76,23 @@ describe('elements/content-uploader/ItemAction', () => { `( 'should render correctly with $status and resumable uploads disabled', ({ status, label }: Pick & { label: string }) => { - getWrapper({ status, isResumableUploadsEnabled: false }); + renderComponent({ status, isResumableUploadsEnabled: false }); expect(screen.getByRole('img', { name: label })).toBeInTheDocument(); }, ); test('should render correctly with STATUS_PENDING and resumable uploads disabled', () => { - getWrapper({ status: STATUS_PENDING, isResumableUploadsEnabled: false }); + renderComponent({ status: STATUS_PENDING, isResumableUploadsEnabled: false }); expect(screen.getByRole('button', { name: 'Cancel this upload' })).toBeInTheDocument(); }); test('should render correctly with STATUS_ERROR and item is folder', () => { - getWrapper({ status: STATUS_ERROR, isFolder: true }); + renderComponent({ status: STATUS_ERROR, isFolder: true }); expect(screen.queryByRole('button')).not.toBeInTheDocument(); }); test('should render CTA button to upgrade when upload file size exceeded error is received', () => { - getWrapper({ + renderComponent({ status: STATUS_ERROR, error: { ...defaultError, code: ERROR_CODE_UPLOAD_FILE_SIZE_LIMIT_EXCEEDED }, onUpgradeCTAClick: jest.fn(), diff --git a/src/elements/content-uploader/__tests__/ItemRemove.test.tsx b/src/elements/content-uploader/__tests__/ItemRemove.test.tsx index d8ee19742e..1446c8d102 100644 --- a/src/elements/content-uploader/__tests__/ItemRemove.test.tsx +++ b/src/elements/content-uploader/__tests__/ItemRemove.test.tsx @@ -6,25 +6,25 @@ import ItemRemove, { ItemRemoveProps } from '../ItemRemove'; import { STATUS_IN_PROGRESS, STATUS_STAGED } from '../../../constants'; describe('elements/content-uploader/ItemRemove', () => { - const getWrapper = (props: Partial) => + const renderComponent = (props: Partial) => render(); test('should have aria-label "Remove" and no aria-describedby', () => { - getWrapper({}); + renderComponent({}); const button = screen.getByRole('button'); expect(button).toHaveAttribute('aria-label', 'Remove'); expect(button).not.toHaveAttribute('aria-describedby'); }); test('should render disabled button when status is STATUS_STAGED', () => { - getWrapper({ status: STATUS_STAGED }); + renderComponent({ status: STATUS_STAGED }); const button = screen.getByRole('button'); expect(button).toBeDisabled(); }); test('should call onClick when button is clicked', () => { const mockOnClick = jest.fn(); - getWrapper({ onClick: mockOnClick }); + renderComponent({ onClick: mockOnClick }); fireEvent.click(screen.getByRole('button')); expect(mockOnClick).toHaveBeenCalledTimes(1); diff --git a/src/elements/content-uploader/__tests__/OverallUploadsProgressBar.test.tsx b/src/elements/content-uploader/__tests__/OverallUploadsProgressBar.test.tsx index 40cd3a7c82..6a41ba73be 100644 --- a/src/elements/content-uploader/__tests__/OverallUploadsProgressBar.test.tsx +++ b/src/elements/content-uploader/__tests__/OverallUploadsProgressBar.test.tsx @@ -16,7 +16,7 @@ describe('elements/content-uploader/OverallUploadsProgressBar', () => { percent: 2, view: VIEW_UPLOAD_EMPTY, }; - const getWrapper = (props: OverallUploadsProgressBarProps = defaultProps) => + const renderComponent = (props: OverallUploadsProgressBarProps = defaultProps) => render( { ); test('should render correctly when view is VIEW_UPLOAD_EMPTY', () => { - getWrapper(); + renderComponent(); expect( screen.getByRole('button', { name: 'Drop files on this page to upload them into this folder.' }), ).toBeInTheDocument(); @@ -39,55 +39,55 @@ describe('elements/content-uploader/OverallUploadsProgressBar', () => { }); test('should render correctly when view is VIEW_UPLOAD_SUCCESS', () => { - getWrapper({ ...defaultProps, view: VIEW_UPLOAD_SUCCESS }); + renderComponent({ ...defaultProps, view: VIEW_UPLOAD_SUCCESS }); expect(screen.getByRole('button', { name: 'Completed' })).toBeInTheDocument(); expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); test('should render correctly when view is VIEW_ERROR', () => { - getWrapper({ ...defaultProps, view: VIEW_ERROR }); + renderComponent({ ...defaultProps, view: VIEW_ERROR }); expect(screen.getByRole('button', { name: 'Some Uploads Failed' })).toBeInTheDocument(); expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); test('should render correctly when view is VIEW_UPLOAD_IN_PROGRESS', () => { - getWrapper({ ...defaultProps, view: VIEW_UPLOAD_IN_PROGRESS }); + renderComponent({ ...defaultProps, view: VIEW_UPLOAD_IN_PROGRESS }); expect(screen.getByRole('button', { name: 'Uploading' })).toBeInTheDocument(); expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); test('should render correctly when isVisible is false', () => { - getWrapper({ ...defaultProps, isVisible: false, view: VIEW_UPLOAD_SUCCESS }); + renderComponent({ ...defaultProps, isVisible: false, view: VIEW_UPLOAD_SUCCESS }); expect(screen.getByRole('button', { hidden: true })).toHaveAttribute('aria-hidden', 'true'); }); test('should render correctly when isDragging is true', () => { - getWrapper({ ...defaultProps, view: VIEW_UPLOAD_SUCCESS, isDragging: true }); + renderComponent({ ...defaultProps, view: VIEW_UPLOAD_SUCCESS, isDragging: true }); expect(screen.getByRole('button')).toBeInTheDocument(); }); test('should render correctly when isResumeVisible is false', () => { - getWrapper({ ...defaultProps, isResumeVisible: false }); + renderComponent({ ...defaultProps, isResumeVisible: false }); expect(screen.getByRole('button')).toBeInTheDocument(); }); test('should render correctly when isResumeVisible is true and hasMultipleFailedUploads is false', () => { - getWrapper({ ...defaultProps, isResumeVisible: true, hasMultipleFailedUploads: false }); + renderComponent({ ...defaultProps, isResumeVisible: true, hasMultipleFailedUploads: false }); expect(screen.getByText('Resume')).toBeInTheDocument(); }); test('should render correctly when isResumeVisible is true and hasMultipleFailedUploads is true', () => { - getWrapper({ ...defaultProps, isResumeVisible: true, hasMultipleFailedUploads: true }); + renderComponent({ ...defaultProps, isResumeVisible: true, hasMultipleFailedUploads: true }); expect(screen.getByText('Resume All')).toBeInTheDocument(); }); test('should be invisible for assistive technologies when hidden', () => { - getWrapper({ ...defaultProps, isVisible: false }); + renderComponent({ ...defaultProps, isVisible: false }); expect(screen.getByRole('button', { hidden: true })).toHaveAttribute('aria-hidden', 'true'); }); test('should be visible for assistive technologies when displayed', () => { - getWrapper({ ...defaultProps, isVisible: true }); + renderComponent({ ...defaultProps, isVisible: true }); expect(screen.getByRole('button')).toHaveAttribute('aria-hidden', 'false'); }); }); diff --git a/src/elements/content-uploader/__tests__/UploadInput.test.tsx b/src/elements/content-uploader/__tests__/UploadInput.test.tsx index c528f1bf0c..12c3bc494f 100644 --- a/src/elements/content-uploader/__tests__/UploadInput.test.tsx +++ b/src/elements/content-uploader/__tests__/UploadInput.test.tsx @@ -5,10 +5,10 @@ import { render, screen } from '@testing-library/react'; import UploadInput from '../UploadInput'; describe('elements/content-uploader/UploadInput', () => { - const getWrapper = props => render(); + const renderComponent = props => render(); test('should render correctly when inputLabel is available', () => { - getWrapper({ + renderComponent({ inputLabelClass: 'inputLabelClass', inputLabel: 'yo', }); @@ -18,12 +18,12 @@ describe('elements/content-uploader/UploadInput', () => { }); test('should render correctly when inputLabel is not available', () => { - const { container } = getWrapper({}); + const { container } = renderComponent({}); expect(container).toBeEmptyDOMElement(); }); test('should render correctly when isFolderUpload is true', () => { - getWrapper({ + renderComponent({ inputLabel: 'yo', isFolderUpload: true, }); @@ -33,7 +33,7 @@ describe('elements/content-uploader/UploadInput', () => { }); test('should render correctly when isFolderUpload is false', () => { - getWrapper({ + renderComponent({ inputLabel: 'yo', isFolderUpload: false, }); @@ -43,7 +43,7 @@ describe('elements/content-uploader/UploadInput', () => { }); test('should render correctly when isMultiple is true', () => { - getWrapper({ + renderComponent({ inputLabel: 'yo', isMultiple: true, }); @@ -53,7 +53,7 @@ describe('elements/content-uploader/UploadInput', () => { }); test('should render correctly when isMultiple is false', () => { - getWrapper({ + renderComponent({ inputLabel: 'yo', isMultiple: false, }); diff --git a/src/elements/content-uploader/__tests__/UploadState.test.tsx b/src/elements/content-uploader/__tests__/UploadState.test.tsx index aff1729cd1..55e0c1a990 100644 --- a/src/elements/content-uploader/__tests__/UploadState.test.tsx +++ b/src/elements/content-uploader/__tests__/UploadState.test.tsx @@ -6,7 +6,7 @@ import UploadState, { UploadStateProps } from '../UploadState'; import { VIEW_ERROR, VIEW_UPLOAD_EMPTY, VIEW_UPLOAD_IN_PROGRESS, VIEW_UPLOAD_SUCCESS } from '../../../constants'; describe('elements/content-uploader/UploadState', () => { - const getWrapper = (props: Partial) => + const renderComponent = (props: Partial) => render( { ${VIEW_UPLOAD_IN_PROGRESS} | ${'Empty state'} ${VIEW_UPLOAD_SUCCESS} | ${'Success state'} `('should render icon correctly based on the view', ({ view, iconName }) => { - getWrapper({ view }); + renderComponent({ view }); expect(screen.getByRole('img', { name: iconName })).toBeInTheDocument(); }); test('should render upload_empty view correctly when canDrop and hasItems set to true', () => { - getWrapper({ view: VIEW_UPLOAD_EMPTY, canDrop: true, hasItems: true }); + renderComponent({ view: VIEW_UPLOAD_EMPTY, canDrop: true, hasItems: true }); expect(screen.getByText('Drag and drop to add additional files')).toBeInTheDocument(); }); test('should render upload_empty view correctly when isTouch set to true', () => { - getWrapper({ view: VIEW_UPLOAD_EMPTY, isTouch: true }); + renderComponent({ view: VIEW_UPLOAD_EMPTY, isTouch: true }); expect(screen.getByText('Select files from your device')).toBeInTheDocument(); }); test('should render content for upload_empty view correctly when isFolderUploadEnabled set to false', () => { - getWrapper({ view: VIEW_UPLOAD_EMPTY }); + renderComponent({ view: VIEW_UPLOAD_EMPTY }); expect(screen.getByText('Browse your device')).toBeInTheDocument(); expect(screen.getByText('Drag and drop files')).toBeInTheDocument(); }); test('should render content for upload_empty view correctly when isFolderUploadEnabled set to true', () => { - getWrapper({ view: VIEW_UPLOAD_EMPTY, isFolderUploadEnabled: true }); + renderComponent({ view: VIEW_UPLOAD_EMPTY, isFolderUploadEnabled: true }); expect(screen.getByText('Select Folders')).toBeInTheDocument(); expect(screen.getByText('Drag and drop files and folders')).toBeInTheDocument(); }); test('should render content for upload_in_progress view correctly when isFolderUploadEnabled set to true', () => { - getWrapper({ view: VIEW_UPLOAD_IN_PROGRESS }); + renderComponent({ view: VIEW_UPLOAD_IN_PROGRESS }); expect(screen.getByText('Drag and drop to add additional files')).toBeInTheDocument(); }); test('should render content for upload_success view correctly when isFolderUploadEnabled set to false', () => { - getWrapper({ view: VIEW_UPLOAD_SUCCESS }); + renderComponent({ view: VIEW_UPLOAD_SUCCESS }); expect(screen.getByText('Select More Files')).toBeInTheDocument(); expect(screen.getByText('Success! Your files have been uploaded.')).toBeInTheDocument(); }); test('should render content for upload_success view correctly when isFolderUploadEnabled set to true', () => { - getWrapper({ view: VIEW_UPLOAD_SUCCESS, isFolderUploadEnabled: true }); + renderComponent({ view: VIEW_UPLOAD_SUCCESS, isFolderUploadEnabled: true }); expect(screen.getByText('Select More Folders')).toBeInTheDocument(); expect(screen.getByText('Success! Your files have been uploaded.')).toBeInTheDocument(); }); diff --git a/src/elements/content-uploader/__tests__/UploadsManagerAction.test.tsx b/src/elements/content-uploader/__tests__/UploadsManagerAction.test.tsx index 32bacd0f54..e33513855d 100644 --- a/src/elements/content-uploader/__tests__/UploadsManagerAction.test.tsx +++ b/src/elements/content-uploader/__tests__/UploadsManagerAction.test.tsx @@ -4,17 +4,17 @@ import { render, screen, fireEvent } from '../../../test-utils/testing-library'; import UploadsManagerAction, { UploadsManagerActionProps } from '../UploadsManagerAction'; describe('elements/content-uploader/UploadsManagerAction', () => { - const getWrapper = (props: Partial) => + const renderComponent = (props: Partial) => render(); test('should render correctly with hasMultipleFailedUploads as true', () => { - getWrapper({ hasMultipleFailedUploads: true }); + renderComponent({ hasMultipleFailedUploads: true }); expect(screen.getByText('Resume All')).toBeInTheDocument(); }); test('should render correctly with hasMultipleFailedUploads as false', () => { - getWrapper({ hasMultipleFailedUploads: false }); + renderComponent({ hasMultipleFailedUploads: false }); expect(screen.getByText('Resume')).toBeInTheDocument(); expect(screen.queryByText('Resume All')).not.toBeInTheDocument(); @@ -22,7 +22,7 @@ describe('elements/content-uploader/UploadsManagerAction', () => { test('should call onClick when resume button is clicked', () => { const handleResumeClick = jest.fn(); - getWrapper({ onClick: handleResumeClick }); + renderComponent({ onClick: handleResumeClick }); fireEvent.click(screen.getByText('Resume')); expect(handleResumeClick).toHaveBeenCalledTimes(1);