diff --git a/tdrive/frontend/src/app/atoms/button/button.tsx b/tdrive/frontend/src/app/atoms/button/button.tsx index 8f8b4613..791fdfc8 100644 --- a/tdrive/frontend/src/app/atoms/button/button.tsx +++ b/tdrive/frontend/src/app/atoms/button/button.tsx @@ -12,6 +12,7 @@ interface ButtonProps extends React.ButtonHTMLAttributes { loading?: boolean; disabled?: boolean; children?: React.ReactNode; + testClassId?: string; } export const Button = (props: ButtonProps) => { @@ -65,10 +66,12 @@ export const Button = (props: ButtonProps) => { ' inline-flex items-center px-4 py-2 border font-medium rounded-md focus:outline-none ' + className + ' ' + - props.className + props.className + + ' ' + + `testid:${props.testClassId}` } disabled={disabled} - {..._.omit(props, 'loading', 'children', 'className', 'icon', 'iconSize')} + {..._.omit(props, 'loading', 'children', 'className', 'icon', 'iconSize', 'testClassId')} > {props.loading && ( <> diff --git a/tdrive/frontend/src/app/atoms/input/input-checkbox-slider.tsx b/tdrive/frontend/src/app/atoms/input/input-checkbox-slider.tsx index dc658dc7..9b549de0 100644 --- a/tdrive/frontend/src/app/atoms/input/input-checkbox-slider.tsx +++ b/tdrive/frontend/src/app/atoms/input/input-checkbox-slider.tsx @@ -1,9 +1,11 @@ +import _ from "lodash"; import { isUndefined } from "lodash"; interface CheckboxSliderProps extends React.InputHTMLAttributes { checked?: boolean; disabled?: boolean; noFocusBorder?: boolean; + testClassId?: string; } /** Just classes up a checkbox to look like a slider. Deviates from onChange etc for * compatibility with `InputHTMLAttributes`, to expose eg. id to use with htmlFor. @@ -15,13 +17,17 @@ export const CheckboxSlider = (props: CheckboxSliderProps) => { return ( ) } diff --git a/tdrive/frontend/src/app/atoms/input/input-text.tsx b/tdrive/frontend/src/app/atoms/input/input-text.tsx index 41d78753..764875f8 100644 --- a/tdrive/frontend/src/app/atoms/input/input-text.tsx +++ b/tdrive/frontend/src/app/atoms/input/input-text.tsx @@ -17,6 +17,7 @@ interface InputProps inputClassName?: string; className?: string; inputRef?: React.Ref; + testClassId?: string; } export type ThemeName = 'plain' | 'outline' | 'blue' | 'rose'; @@ -66,7 +67,8 @@ export const Input = (props: InputProps) => { @@ -74,8 +76,8 @@ export const Input = (props: InputProps) => { } type="text" - className={inputClassName + ' ' + props.inputClassName + ' ' + props.className} - {..._.omit(props, 'label', 'inputClassName', 'inputRef', 'className', 'size')} + className={`${inputClassName} ${props.inputClassName} ${props.className} testid:${props.testClassId}`} + {..._.omit(props, 'label', 'inputClassName', 'inputRef', 'className', 'size', 'testClassId')} /> ))} diff --git a/tdrive/frontend/src/app/atoms/link/index.tsx b/tdrive/frontend/src/app/atoms/link/index.tsx index d5aac855..08814268 100644 --- a/tdrive/frontend/src/app/atoms/link/index.tsx +++ b/tdrive/frontend/src/app/atoms/link/index.tsx @@ -8,6 +8,7 @@ export default function A( href?: string; children: React.ReactNode; noColor?: boolean; + testClassId?: string; }, ) { const colors = props.noColor ? '' : 'hover:text-blue-700 active:text-blue-800 text-blue-500'; @@ -27,8 +28,8 @@ export default function A( return ( {props.children} diff --git a/tdrive/frontend/src/app/atoms/modal/confirm.tsx b/tdrive/frontend/src/app/atoms/modal/confirm.tsx index 08327344..f585e4d7 100644 --- a/tdrive/frontend/src/app/atoms/modal/confirm.tsx +++ b/tdrive/frontend/src/app/atoms/modal/confirm.tsx @@ -42,13 +42,15 @@ export const ConfirmModal = (props: ConfirmModalProps) => { className="ml-2" theme={props.buttonOkTheme || "danger"} onClick={dialogCloseHandler(true)} - > + testClassId="confirm-modal-button-confirm" + > {Languages.t(props.buttonOkLabel)} diff --git a/tdrive/frontend/src/app/components/buttons/button-with-timeout.jsx b/tdrive/frontend/src/app/components/buttons/button-with-timeout.jsx index 4d33b9c3..b206f90f 100755 --- a/tdrive/frontend/src/app/components/buttons/button-with-timeout.jsx +++ b/tdrive/frontend/src/app/components/buttons/button-with-timeout.jsx @@ -62,6 +62,7 @@ export default class ButtonWithTimeout extends React.Component { (this.props.className ? this.props.className : '') } onClick={this.props.onClick} + testClassId={this.props.testClassId} > {this.props.value} diff --git a/tdrive/frontend/src/app/components/buttons/button.jsx b/tdrive/frontend/src/app/components/buttons/button.jsx index a4c260b0..2339e988 100755 --- a/tdrive/frontend/src/app/components/buttons/button.jsx +++ b/tdrive/frontend/src/app/components/buttons/button.jsx @@ -27,7 +27,7 @@ export default class Button extends React.Component { @@ -514,6 +525,7 @@ export default memo( setChecked(_.pickBy({ ...checked, [child.id]: v }, _.identity)) } onBuildContextMenu={() => onBuildContextMenu(details, child)} + testClassId="browser-folder-row" /> ) : ( diff --git a/tdrive/frontend/src/app/views/client/body/drive/components/access-level-dropdown.tsx b/tdrive/frontend/src/app/views/client/body/drive/components/access-level-dropdown.tsx index d1e40444..825cba64 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/components/access-level-dropdown.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/components/access-level-dropdown.tsx @@ -26,6 +26,7 @@ export const AccessLevelDropdown = ({ className, size, noRedWhenLevelNone, + testClassId, }: { disabled?: boolean; level: DriveFileAccessLevel | null; @@ -35,6 +36,7 @@ export const AccessLevelDropdown = ({ hiddenLevels?: DriveFileAccessLevelOrRemove[] | string[]; size?: SelectSize, noRedWhenLevelNone?: boolean, + testClassId?: string, }) => { const createOption = (level: DriveFileAccessLevelOrRemove) => !hiddenLevels?.includes(level) && ; @@ -42,7 +44,7 @@ export const AccessLevelDropdown = ({ { placeholder="https://example.com" className="w-full mt-4" onChange={e => setLink(e.target.value)} + testClassId="create-link-input" /> diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx index 11dc578e..4ee05ea9 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx @@ -82,11 +82,13 @@ export const CreateModal = ({ icon={} text={Languages.t('components.create_modal.create_folder')} onClick={() => setState({ ...state, type: 'folder' })} + testClassId="create-folder-option" /> } text={Languages.t('components.create_modal.create_link')} onClick={() => setState({ ...state, type: 'link' })} + testClassId="create-link-option" /> {(applications || []) @@ -132,6 +134,7 @@ export const CreateModal = ({ onClick={() => addFromUrl(app.emptyFile.url, app.emptyFile.filename || app.emptyFile.name) } + testClassId={app.emptyFile.name} /> ); })} @@ -167,11 +170,11 @@ export const CreateModal = ({ ); }; -const CreateModalOption = (props: { icon: ReactNode; text: string; onClick: () => void }) => { +const CreateModalOption = (props: { testClassId?: string; icon: ReactNode; text: string; onClick: () => void }) => { return (
{props.icon}
diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/properties/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/properties/index.tsx index 7048cf26..eeebcbc2 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/properties/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/properties/index.tsx @@ -105,6 +105,7 @@ const PropertiesModalContent = ({ id, onClose, inPublicSharing }: { id: string; } }} placeholder={Languages.t('components.PropertiesModalContent_place_holder')} + testClassId="properties-modal-input-update-name" /> } /> @@ -115,6 +116,7 @@ const PropertiesModalContent = ({ id, onClose, inPublicSharing }: { id: string; theme="primary" loading={loading} onClick={doSave} + testClassId="properties-modal-button-update-name" > {Languages.t('components.PropertiesModalContent_update_button')} diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/copy-link-button.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/copy-link-button.tsx index 7ff176be..8536a93d 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/copy-link-button.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/copy-link-button.tsx @@ -26,7 +26,8 @@ export const CopyLinkButton = (props: { disabled={!haveTextToCopy} theme={didJustCompleteACopy ? "green" : "primary"} className="justify-center w-64" - > + testClassId="copy-link-button" + > { didJustCompleteACopy ? : diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx index 82a6fdae..c6bce1bf 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/expiry-editor-row.tsx @@ -130,6 +130,7 @@ export const ExpiryEditorRow = (props: { else if (e.key == 'Enter') confirmSaveExpiry(currentEditedValue); }} + testClassId="expiry-editor-row-expired-date" /> @@ -153,7 +155,8 @@ export const ExpiryEditorRow = (props: { } else confirmSaveExpiry(0); }} - /> + testClassId="expiry-editor-row-checkbox" + /> } /> + testClassId="public-link-access-level-dropdown" + /> } /> ); @@ -101,7 +102,8 @@ const SwitchToAdvancedSettingsRow = (props: { if (!props.disabled) props.onShowAdvancedScreen(true); }} - > + testClassId="public-link-access-advance-switcher" + > {Languages.t("components.public-link-security-change")} } @@ -126,58 +128,58 @@ const PublicLinkModalContent = (props: { return ( - {Languages.t('components.public-link-security-title') + ' '} - {item?.name} - - } - > -
- { - item && update(changePublicLink(item, { level })); - }} - /> - + {Languages.t('components.public-link-security-title') + ' '} + {item?.name} + + } + > +
+ { + item && update(changePublicLink(item, { level })); + }} /> -
+ +
-
- -
+
+ +
- { props.onShowAdvancedScreen(false); }} - > - - {Languages.t('components.public-link-security-title') + ' '} - {item?.name} - - } - > -
{Languages.t('components.public-link-security')}
-
- { - item && await update(changePublicLink(item, { password: password || '' })); - }} - onChangeExpiration={async (expiration: number) => { - item && await update(changePublicLink(item, { expiration })); - }} - /> -
-
-
-
+ { props.onShowAdvancedScreen(false); }} + > + + {Languages.t('components.public-link-security-title') + ' '} + {item?.name} + + } + > +
{Languages.t('components.public-link-security')}
+
+ { + item && await update(changePublicLink(item, { password: password || '' })); + }} + onChangeExpiration={async (expiration: number) => { + item && await update(changePublicLink(item, { expiration })); + }} + /> +
+
+
+ ); } \ No newline at end of file diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx index 1c911d87..02d8a92c 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/password-editor-row.tsx @@ -112,6 +112,7 @@ return <> else if (e.key == 'Enter') confirmSavePassword(currentEditedPassword); }} + testClassId="pasword-editor-row-editting-password" /> @@ -135,7 +137,8 @@ return <> } else confirmSavePassword(""); }} - /> + testClassId="password-editor-row-checkbox" + /> } /> @@ -145,9 +148,8 @@ return <> text={Languages.t("components.public-link-security_password_removal_body")} buttonOkTheme='primary' buttonOkLabel='components.public-link-security_password_removal_confirm' - onClose={() => setIsConfirmingPasswordRemoval(false)} onOk={() => savePassword("")} - /> + /> ; } \ No newline at end of file diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/public-link-access-options.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/public-link-access-options.tsx index 6be0a35e..355b047e 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/public-link-access-options.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/public-link/public-link-access-options.tsx @@ -14,13 +14,13 @@ export const PublicLinkAccessOptions = (props: { password={props.password} onChangePassword={props.onChangePassword} isLinkExpired={!!props.expiration && props.expiration < Date.now()} - /> + /> + /> ); diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/selector/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/selector/index.tsx index 8afdd75a..3f815c88 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/selector/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/selector/index.tsx @@ -138,6 +138,7 @@ const SelectorModalContent = (key: any) => { setState({ ...state, open: false }); setLoading(false); }} + testClassId="selector-modal-button" > {selected.length === 0 ? ( <>{Languages.t('components.SelectorModalContent_no_items')} diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/internal-users-access.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/internal-users-access.tsx index f798fbc2..8576a542 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/internal-users-access.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/update-access/internal-users-access.tsx @@ -113,6 +113,7 @@ export const InternalUsersAccessManager = ({ }} value={searchString} inputRef={inputElement} + testClassId="access-management-search-users" /> )} /> @@ -125,6 +126,7 @@ export const InternalUsersAccessManager = ({ hiddenLevels={['remove']} level={level} onChange={level => setLevel(level)} + testClassId="access-management-dropdown" />
@@ -179,7 +181,8 @@ export const InternalUsersAccessManager = ({ size="sm" className='text-center' onClick={onCloseModal} - > + testClassId="access-management-public-link-security-field-confirm-edit" + > {Languages.t('components.public-link-security_field_confirm_edit')} @@ -209,7 +212,8 @@ const UserAccessLevel = (props: { ? @@ -218,7 +222,8 @@ const UserAccessLevel = (props: { noRedWhenLevelNone={true} level={(item && getUserAccessLevel(item, props.userId)) || "none"} onChange={level => item && update(changeUserAccess(item, props.userId, level === 'remove' ? false : level))} - /> + testClassId="user-access-dropdown" + /> } /> ); diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx index f3817033..94f15fe4 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx @@ -74,11 +74,13 @@ export const UploadModal = ({ icon={} text={Languages.t('components.create_modal.upload_files')} onClick={() => selectFromDevice()} + testClassId="upload-file-from-device" /> } text={Languages.t('components.create_modal.upload_folders')} onClick={() => selectFolderFromDevice()} + testClassId="upload-folder-from-device" /> @@ -88,11 +90,11 @@ export const UploadModal = ({ ); }; -const CreateModalOption = (props: { icon: ReactNode; text: string; onClick: () => void }) => { +const CreateModalOption = (props: { icon: ReactNode; text: string; onClick: () => void; testClassId?: string; }) => { return (
{props.icon}
diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/versions/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/versions/index.tsx index de338da6..bfa41594 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/versions/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/versions/index.tsx @@ -64,6 +64,7 @@ const VersionModalContent = ({ id }: { id: string }) => { await uploadVersion(file); await refresh(id); }} + testClassId="version-modal-upload-zone" > {access !== 'read' && (
{ theme="primary" onClick={() => uploadZoneRef.current?.open()} loading={loading} + testClassId="button-create-version" > {Languages.t('components.VersionModalContent_create')} @@ -113,6 +115,7 @@ const VersionModalContent = ({ id }: { id: string }) => { diff --git a/tdrive/frontend/src/app/views/client/common/search.tsx b/tdrive/frontend/src/app/views/client/common/search.tsx index 3acf915b..98868c5b 100644 --- a/tdrive/frontend/src/app/views/client/common/search.tsx +++ b/tdrive/frontend/src/app/views/client/common/search.tsx @@ -44,6 +44,7 @@ export default (): JSX.Element => { readOnly placeholder={Languages.t('scenes.client.main_view.main_header.search_input')} onClick={() => setOpen()} + testClassId="header-search-input" /> )} /> diff --git a/tdrive/frontend/src/app/views/client/side-bar/actions.tsx b/tdrive/frontend/src/app/views/client/side-bar/actions.tsx index 587e3816..1a4c5536 100644 --- a/tdrive/frontend/src/app/views/client/side-bar/actions.tsx +++ b/tdrive/frontend/src/app/views/client/side-bar/actions.tsx @@ -33,6 +33,7 @@ export const CreateModalWithUploadZones = ({ initialParentId }: { initialParentI { theme="danger" className="w-full mb-2 justify-center" disabled={!(trashChildren.length > 0)} + testClassId="create-modal-in-trash-button-empty-trash" > { Languages.t('components.side_menu.buttons.empty_trash') } @@ -158,6 +161,7 @@ export default () => { parentId, }); }} + testClassId="sidebar-action-upload-zone" /> @@ -174,6 +179,7 @@ export default () => { size="lg" theme="secondary" className="w-full mb-2 justify-center" + testClassId="sidebar-action-button-open-modal" > {Languages.t('components.side_menu.buttons.create')} diff --git a/tdrive/frontend/src/app/views/client/viewer/drive-preview.tsx b/tdrive/frontend/src/app/views/client/viewer/drive-preview.tsx index a68554f2..077dc22b 100644 --- a/tdrive/frontend/src/app/views/client/viewer/drive-preview.tsx +++ b/tdrive/frontend/src/app/views/client/viewer/drive-preview.tsx @@ -161,6 +161,7 @@ export const DrivePreview: React.FC = ({ items }) => { size="lg" icon={ArrowLeftIcon} onClick={ handleSwitchLeft } + testClassId="drive-preview-button-switch-left" />
diff --git a/tdrive/frontend/src/app/views/client/viewer/images/controls.tsx b/tdrive/frontend/src/app/views/client/viewer/images/controls.tsx index 92475c2b..18e1b970 100644 --- a/tdrive/frontend/src/app/views/client/viewer/images/controls.tsx +++ b/tdrive/frontend/src/app/views/client/viewer/images/controls.tsx @@ -12,6 +12,7 @@ export default () => { size="lg" icon={ZoomOutIcon} onClick={() => getImageControls().zoomOut()} + testClassId="image-control-button-zoom-out" /> diff --git a/tdrive/frontend/src/app/views/join/index.tsx b/tdrive/frontend/src/app/views/join/index.tsx index dc38217f..b1469654 100644 --- a/tdrive/frontend/src/app/views/join/index.tsx +++ b/tdrive/frontend/src/app/views/join/index.tsx @@ -124,6 +124,7 @@ export default (): JSX.Element => { loading={busy} type="primary" onClick={onCreateCompanyBtnClick} + className="testid:button-create-company" > {Languages.t('scenes.join.create_the_company_button')} @@ -163,6 +164,7 @@ export default (): JSX.Element => { loading={busy} type="primary" onClick={onJoinAccountBtnClick} + className="testid:button-login-first" > {Languages.t('scenes.join.login_first_button')} @@ -172,6 +174,7 @@ export default (): JSX.Element => { loading={busy} type="primary" onClick={onJoinAccountBtnClick} + className="testid:button-join-team" > {Languages.t('scenes.join.join_the_team_button')} diff --git a/tdrive/frontend/src/app/views/login/internal/login-view/login-view.jsx b/tdrive/frontend/src/app/views/login/internal/login-view/login-view.jsx index 4162a1c1..6f19ca48 100755 --- a/tdrive/frontend/src/app/views/login/internal/login-view/login-view.jsx +++ b/tdrive/frontend/src/app/views/login/internal/login-view/login-view.jsx @@ -80,6 +80,7 @@ export default class LoginView extends Component { } }} onChange={evt => this.setState({ form_login: evt.target.value })} + testClassId="login-input-username" /> this.setState({ form_password: evt.target.value })} + testClassId="login-input-password" /> {this.state.login.login_error && ( @@ -121,6 +123,7 @@ export default class LoginView extends Component { remember_me: true, }) } + testClassId="login-button-submit" > {this.state.i18n.t('scenes.login.home.login_btn')} diff --git a/tdrive/frontend/src/app/views/login/internal/signin/signin.jsx b/tdrive/frontend/src/app/views/login/internal/signin/signin.jsx index 50d78151..9c3c4197 100755 --- a/tdrive/frontend/src/app/views/login/internal/signin/signin.jsx +++ b/tdrive/frontend/src/app/views/login/internal/signin/signin.jsx @@ -63,12 +63,12 @@ export default class Signin extends Component {
{this.state.login.error_subscribe_username && this.state.username && ( -
+
{this.state.i18n.t('scenes.login.create_account.username_already_exist')}
)} {this.state.username && this.state.errorUsername && ( -
+
{this.state.i18n.t('scenes.login.create_account.fill_in_username', [])}
)} @@ -91,6 +91,7 @@ export default class Signin extends Component { )} value={this.state.firstName} onChange={evt => this.setState({ firstName: evt.target.value })} + testClassId="signin-input-first-name" /> this.setState({ lastName: evt.target.value })} + testClassId="signin-input-last-name" />

{this.state.login.error_subscribe_mailalreadyused && this.state.email && ( -
+
{this.state.i18n.t('scenes.login.create_account.email_used')}
)} {this.state.errorMail && ( -
+
{this.state.i18n.t('scenes.login.create_account.fill_in_email')}
)} @@ -137,6 +139,7 @@ export default class Signin extends Component { placeholder={this.state.i18n.t('scenes.login.create_account.email')} value={this.state.email} onChange={evt => this.setState({ email: evt.target.value })} + testClassId="signin-input-email" /> {this.state.errorPassword && ( @@ -159,6 +162,7 @@ export default class Signin extends Component { placeholder={this.state.i18n.t('scenes.login.create_account.password')} value={this.state.password} onChange={evt => this.setState({ password: evt.target.value })} + testClassId="signin-input-password" />
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} @@ -173,6 +177,7 @@ export default class Signin extends Component { value={this.state.i18n.t('general.continue')} loading={this.state.login.login_loading} loadingTimeout={2000} + testClassId="signin-button-continue" />
@@ -207,6 +212,7 @@ export default class Signin extends Component { value={'Send again'} loading={this.state.login.login_loading} loadingTimeout={2000} + testClassId="signin-button-subscribe-mail" />
);