diff --git a/packages/core/admin/admin/src/components/LocalesProvider/__mocks__/useLocalesProvider.js b/packages/core/admin/admin/src/components/LocalesProvider/__mocks__/useLocalesProvider.js new file mode 100644 index 0000000000..d828c887fe --- /dev/null +++ b/packages/core/admin/admin/src/components/LocalesProvider/__mocks__/useLocalesProvider.js @@ -0,0 +1,7 @@ +export default function useLocalesProvider() { + return { + changeLocale() {}, + localeNames: { en: 'English' }, + messages: ['test'], + }; +} diff --git a/packages/core/admin/admin/src/hooks/useConfigurations/__mocks__/index.js b/packages/core/admin/admin/src/hooks/useConfigurations/__mocks__/index.js new file mode 100644 index 0000000000..cf76a036fb --- /dev/null +++ b/packages/core/admin/admin/src/hooks/useConfigurations/__mocks__/index.js @@ -0,0 +1,7 @@ +export default function () { + return { + logos: { + auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' }, + }, + }; +} diff --git a/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js b/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js index 0d91e95198..7bf8f569fb 100644 --- a/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js +++ b/packages/core/admin/admin/src/pages/AuthPage/components/Register/index.js @@ -1,7 +1,6 @@ import React, { useState, useEffect } from 'react'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; -import get from 'lodash/get'; import omit from 'lodash/omit'; import { useHistory } from 'react-router-dom'; import PropTypes from 'prop-types'; @@ -14,6 +13,7 @@ import { useTracking, getYupInnerErrors, Link, + useAPIErrorHandler, } from '@strapi/helper-plugin'; import { Box, @@ -27,17 +27,10 @@ import { Typography, } from '@strapi/design-system'; import { EyeStriked, Eye } from '@strapi/icons'; -import UnauthenticatedLayout, { - Column, - LayoutContent, -} from '../../../../layouts/UnauthenticatedLayout'; +import UnauthenticatedLayout, { LayoutContent } from '../../../../layouts/UnauthenticatedLayout'; import Logo from '../../../../components/UnauthenticatedLogo'; import FieldActionWrapper from '../FieldActionWrapper'; -const CenteredBox = styled(Box)` - text-align: center; -`; - const A = styled.a` color: ${({ theme }) => theme.colors.primary600}; `; @@ -58,6 +51,8 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => const { trackUsage } = useTracking(); const { formatMessage } = useIntl(); const query = useQuery(); + const { formatAPIError } = useAPIErrorHandler(); + const registrationToken = query.get('registrationToken'); useEffect(() => { @@ -73,17 +68,17 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => if (data) { setUserInfo(data); } - } catch (err) { - const errorMessage = get(err, ['response', 'data', 'message'], 'An error occurred'); + } catch (error) { + const message = formatAPIError(error); toggleNotification({ type: 'warning', - message: errorMessage, + message, }); // Redirect to the oops page in case of an invalid token // @alexandrebodin @JAB I am not sure it is the wanted behavior - push(`/auth/oops?info=${encodeURIComponent(errorMessage)}`); + push(`/auth/oops?info=${encodeURIComponent(message)}`); } }; @@ -92,6 +87,20 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => // eslint-disable-next-line react-hooks/exhaustive-deps }, [registrationToken]); + function normalizeData(data) { + return Object.entries(data).reduce((acc, [key, value]) => { + let normalizedvalue = value; + + if (!['password', 'confirmPassword'].includes(key) && typeof value === 'string') { + normalizedvalue = normalizedvalue.trim(); + } + + acc[key] = normalizedvalue; + + return acc; + }, {}); + } + return ( @@ -107,8 +116,10 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => news: false, }} onSubmit={async (data, formik) => { + const normalizedData = normalizeData(data); + try { - await schema.validate(data, { abortEarly: false }); + await schema.validate(normalizedData, { abortEarly: false }); if (submitCount > 0 && authType === 'register-admin') { trackUsage('didSubmitWithErrorsFirstAdmin', { count: submitCount.toString() }); @@ -117,11 +128,11 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => if (registrationToken) { // We need to pass the registration token in the url param to the api in order to submit another admin user onSubmit( - { userInfo: omit(data, ['registrationToken']), registrationToken }, + { userInfo: omit(normalizedData, ['registrationToken']), registrationToken }, formik ); } else { - onSubmit(data, formik); + onSubmit(normalizedData, formik); } } catch (err) { const errors = getYupInnerErrors(err); @@ -138,27 +149,26 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => return (
- + - - - {formatMessage({ - id: 'Auth.form.welcome.title', - defaultMessage: 'Welcome to Strapi!', - })} - - - - - {formatMessage({ - id: 'Auth.form.register.subtitle', - defaultMessage: - 'Credentials are only used to authenticate in Strapi. All saved data will be stored in your database.', - })} - - - - + + + {formatMessage({ + id: 'Auth.form.welcome.title', + defaultMessage: 'Welcome to Strapi!', + })} + + + + {formatMessage({ + id: 'Auth.form.register.subtitle', + defaultMessage: + 'Credentials are only used to authenticate in Strapi. All saved data will be stored in your database.', + })} + + + + value={values.password} error={errors.password ? formatMessage(errors.password) : undefined} endAction={ - // eslint-disable-next-line react/jsx-wrap-multilines { e.preventDefault(); @@ -245,7 +254,6 @@ const Register = ({ authType, fieldsToDisable, noSignin, onSubmit, schema }) => errors.confirmPassword ? formatMessage(errors.confirmPassword) : undefined } endAction={ - // eslint-disable-next-line react/jsx-wrap-multilines { e.preventDefault(); diff --git a/packages/core/admin/admin/src/pages/AuthPage/components/Register/tests/index.test.js b/packages/core/admin/admin/src/pages/AuthPage/components/Register/tests/index.test.js index 5ab577896f..d90ce81f1e 100644 --- a/packages/core/admin/admin/src/pages/AuthPage/components/Register/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/AuthPage/components/Register/tests/index.test.js @@ -1,1154 +1,213 @@ import React from 'react'; -import { render } from '@testing-library/react'; +import { act, render, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { ThemeProvider, lightTheme } from '@strapi/design-system'; import { Router } from 'react-router-dom'; -import { TrackingProvider } from '@strapi/helper-plugin'; +import { TrackingProvider, useQuery, useNotification } from '@strapi/helper-plugin'; import { createMemoryHistory } from 'history'; import * as yup from 'yup'; import { IntlProvider } from 'react-intl'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; + import Register from '..'; -jest.mock('../../../../../components/LocalesProvider/useLocalesProvider', () => () => ({ - changeLocale() {}, - localeNames: { en: 'English' }, - messages: ['test'], -})); -jest.mock('../../../../../hooks/useConfigurations', () => () => ({ - logos: { - auth: { custom: 'customAuthLogo.png', default: 'defaultAuthLogo.png' }, - }, -})); +jest.mock('../../../../../hooks/useConfigurations'); +jest.mock('../../../../../components/LocalesProvider/useLocalesProvider'); + jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), - useNotification: () => jest.fn({}), + useQuery: jest.fn().mockReturnValue({ + get: jest.fn(), + }), + useNotification: jest.fn().mockReturnValue(jest.fn()), })); -describe('ADMIN | PAGES | AUTH | Register', () => { - it('should render and match the snapshot', () => { - const history = createMemoryHistory(); - const { container } = render( - - - - - {}} - schema={yup.object()} - /> - - - - +const server = setupServer( + rest.get('*/registration-info', async (req, res, ctx) => { + const token = req.url.searchParams.get('registrationToken'); + + console.log('waat', token); + + if (token === 'error') { + return res(ctx.status(401), ctx.json({})); + } + + return res( + ctx.json({ + data: { + firstname: 'Token firstname', + lastname: 'Token lastname', + email: 'test+register-token@strapi.io', + }, + }) ); - - expect(container.firstChild).toMatchInlineSnapshot(` - .c1 { - padding-top: 24px; - padding-right: 40px; - } - - .c2 { - background: #4945ff; - padding: 8px; - padding-right: 16px; - padding-left: 16px; - border-radius: 4px; - border-color: #4945ff; - border: 1px solid #4945ff; - cursor: pointer; - } - - .c10 { - padding-top: 8px; - padding-bottom: 64px; - } - - .c11 { - background: #ffffff; - padding-top: 48px; - padding-right: 56px; - padding-bottom: 48px; - padding-left: 56px; - border-radius: 4px; - box-shadow: 0px 1px 4px rgba(33,33,52,0.1); - } - - .c16 { - padding-top: 24px; - padding-bottom: 4px; - } - - .c18 { - padding-bottom: 32px; - } - - .c34 { - padding-right: 12px; - padding-left: 8px; - } - - .c35 { - background: transparent; - border-style: none; - } - - .c44 { - padding-left: 8px; - } - - .c46 { - background: #4945ff; - padding: 8px; - padding-right: 16px; - padding-left: 16px; - border-radius: 4px; - border-color: #4945ff; - border: 1px solid #4945ff; - width: 100%; - cursor: pointer; - } - - .c0 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - } - - .c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - gap: 8px; - } - - .c8 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - } - - .c21 { - -webkit-align-items: stretch; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - gap: 24px; - } - - .c24 { - -webkit-align-items: stretch; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - gap: 4px; - } - - .c29 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - } - - .c36 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: unset; - -webkit-justify-content: unset; - -ms-flex-pack: unset; - justify-content: unset; - } - - .c47 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-inline-box; - display: -webkit-inline-flex; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - gap: 8px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - } - - .c7 { - font-size: 0.75rem; - line-height: 1.33; - font-weight: 600; - color: #ffffff; - } - - .c17 { - font-weight: 600; - font-size: 2rem; - line-height: 1.25; - color: #32324d; - } - - .c20 { - font-size: 1rem; - line-height: 1.5; - color: #666687; - } - - .c25 { - font-size: 0.75rem; - line-height: 1.33; - font-weight: 600; - color: #32324d; - } - - .c27 { - font-size: 0.875rem; - line-height: 1.43; - color: #d02b20; - } - - .c40 { - font-size: 0.75rem; - line-height: 1.33; - color: #666687; - } - - .c41 { - font-size: 0.875rem; - line-height: 1.43; - color: #32324d; - } - - .c49 { - font-size: 0.875rem; - line-height: 1.43; - font-weight: 600; - color: #ffffff; - } - - .c4 { - position: relative; - outline: none; - } - - .c4 svg { - height: 12px; - width: 12px; - } - - .c4 svg > g, - .c4 svg path { - fill: #ffffff; - } - - .c4[aria-disabled='true'] { - pointer-events: none; - } - - .c4:after { - -webkit-transition-property: all; - transition-property: all; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - border-radius: 8px; - content: ''; - position: absolute; - top: -4px; - bottom: -4px; - left: -4px; - right: -4px; - border: 2px solid transparent; - } - - .c4:focus-visible { - outline: none; - } - - .c4:focus-visible:after { - border-radius: 8px; - content: ''; - position: absolute; - top: -5px; - bottom: -5px; - left: -5px; - right: -5px; - border: 2px solid #4945ff; - } - - .c43 { - height: 18px; - min-width: 18px; - margin: 0; - border-radius: 4px; - border: 1px solid #c0c0cf; - -webkit-appearance: none; - background-color: #ffffff; - cursor: pointer; - } - - .c43:checked { - background-color: #4945ff; - border: 1px solid #4945ff; - } - - .c43:checked:after { - content: ''; - display: block; - position: relative; - background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGgKICAgIGQ9Ik04LjU1MzIzIDAuMzk2OTczQzguNjMxMzUgMC4zMTYzNTUgOC43NjA1MSAwLjMxNTgxMSA4LjgzOTMxIDAuMzk1NzY4TDkuODYyNTYgMS40MzQwN0M5LjkzODkzIDEuNTExNTcgOS45MzkzNSAxLjYzNTkgOS44NjM0OSAxLjcxMzlMNC4wNjQwMSA3LjY3NzI0QzMuOTg1OSA3Ljc1NzU1IDMuODU3MDcgNy43NTgwNSAzLjc3ODM0IDcuNjc4MzRMMC4xMzg2NiAzLjk5MzMzQzAuMDYxNzc5OCAzLjkxNTQ5IDAuMDYxNzEwMiAzLjc5MDMyIDAuMTM4NTA0IDMuNzEyNEwxLjE2MjEzIDIuNjczNzJDMS4yNDAzOCAyLjU5NDMyIDEuMzY4NDMgMi41OTQyMiAxLjQ0NjggMi42NzM0OEwzLjkyMTc0IDUuMTc2NDdMOC41NTMyMyAwLjM5Njk3M1oiCiAgICBmaWxsPSJ3aGl0ZSIKICAvPgo8L3N2Zz4=) no-repeat no-repeat center center; - width: 10px; - height: 10px; - left: 50%; - top: 50%; - -webkit-transform: translateX(-50%) translateY(-50%); - -ms-transform: translateX(-50%) translateY(-50%); - transform: translateX(-50%) translateY(-50%); - } - - .c43:checked:disabled:after { - background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGgKICAgIGQ9Ik04LjU1MzIzIDAuMzk2OTczQzguNjMxMzUgMC4zMTYzNTUgOC43NjA1MSAwLjMxNTgxMSA4LjgzOTMxIDAuMzk1NzY4TDkuODYyNTYgMS40MzQwN0M5LjkzODkzIDEuNTExNTcgOS45MzkzNSAxLjYzNTkgOS44NjM0OSAxLjcxMzlMNC4wNjQwMSA3LjY3NzI0QzMuOTg1OSA3Ljc1NzU1IDMuODU3MDcgNy43NTgwNSAzLjc3ODM0IDcuNjc4MzRMMC4xMzg2NiAzLjk5MzMzQzAuMDYxNzc5OCAzLjkxNTQ5IDAuMDYxNzEwMiAzLjc5MDMyIDAuMTM4NTA0IDMuNzEyNEwxLjE2MjEzIDIuNjczNzJDMS4yNDAzOCAyLjU5NDMyIDEuMzY4NDMgMi41OTQyMiAxLjQ0NjggMi42NzM0OEwzLjkyMTc0IDUuMTc2NDdMOC41NTMyMyAwLjM5Njk3M1oiCiAgICBmaWxsPSIjOEU4RUE5IgogIC8+Cjwvc3ZnPg==) no-repeat no-repeat center center; - } - - .c43:disabled { - background-color: #dcdce4; - border: 1px solid #c0c0cf; - } - - .c43:indeterminate { - background-color: #4945ff; - border: 1px solid #4945ff; - } - - .c43:indeterminate:after { - content: ''; - display: block; - position: relative; - color: white; - height: 2px; - width: 10px; - background-color: #ffffff; - left: 50%; - top: 50%; - -webkit-transform: translateX(-50%) translateY(-50%); - -ms-transform: translateX(-50%) translateY(-50%); - transform: translateX(-50%) translateY(-50%); - } - - .c43:indeterminate:disabled { - background-color: #dcdce4; - border: 1px solid #c0c0cf; - } - - .c43:indeterminate:disabled:after { - background-color: #8e8ea9; - } - - .c39 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - } - - .c5 { - height: 2rem; - border: 1px solid transparent; - background: transparent; - } - - .c5[aria-disabled='true'] { - border: 1px solid #dcdce4; - background: #eaeaef; - } - - .c5[aria-disabled='true'] .c6 { - color: #666687; - } - - .c5[aria-disabled='true'] svg > g,.c5[aria-disabled='true'] svg path { - fill: #666687; - } - - .c5[aria-disabled='true']:active { - border: 1px solid #dcdce4; - background: #eaeaef; - } - - .c5[aria-disabled='true']:active .c6 { - color: #666687; - } - - .c5[aria-disabled='true']:active svg > g,.c5[aria-disabled='true']:active svg path { - fill: #666687; - } - - .c5:hover { - background-color: #f6f6f9; - } - - .c5:active { - border: 1px solid undefined; - background: undefined; - } - - .c5 .c6 { - color: #32324d; - } - - .c5 svg > g, - .c5 svg path { - fill: #8e8ea9; - } - - .c48 { - height: 2.5rem; - } - - .c48[aria-disabled='true'] { - border: 1px solid #dcdce4; - background: #eaeaef; - } - - .c48[aria-disabled='true'] .c6 { - color: #666687; - } - - .c48[aria-disabled='true'] svg > g,.c48[aria-disabled='true'] svg path { - fill: #666687; - } - - .c48[aria-disabled='true']:active { - border: 1px solid #dcdce4; - background: #eaeaef; - } - - .c48[aria-disabled='true']:active .c6 { - color: #666687; - } - - .c48[aria-disabled='true']:active svg > g,.c48[aria-disabled='true']:active svg path { - fill: #666687; - } - - .c48:hover { - border: 1px solid #7b79ff; - background: #7b79ff; - } - - .c48:active { - border: 1px solid #4945ff; - background: #4945ff; - } - - .c48 svg > g, - .c48 svg path { - fill: #ffffff; - } - - .c26 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - } - - .c28 { - line-height: 0; - } - - .c31 { - border: none; - border-radius: 4px; - padding-bottom: 0.65625rem; - padding-left: 16px; - padding-right: 16px; - padding-top: 0.65625rem; - color: #32324d; - font-weight: 400; - font-size: 0.875rem; - display: block; - width: 100%; - background: inherit; - } - - .c31::-webkit-input-placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c31::-moz-placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c31:-ms-input-placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c31::placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c31[aria-disabled='true'] { - color: inherit; - } - - .c31:focus { - outline: none; - box-shadow: none; - } - - .c32 { - border: none; - border-radius: 4px; - padding-bottom: 0.65625rem; - padding-left: 16px; - padding-right: 0; - padding-top: 0.65625rem; - color: #32324d; - font-weight: 400; - font-size: 0.875rem; - display: block; - width: 100%; - background: inherit; - } - - .c32::-webkit-input-placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c32::-moz-placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c32:-ms-input-placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c32::placeholder { - color: #8e8ea9; - opacity: 1; - } - - .c32[aria-disabled='true'] { - color: inherit; - } - - .c32:focus { - outline: none; - box-shadow: none; - } - - .c30 { - border: 1px solid #dcdce4; - border-radius: 4px; - background: #ffffff; - outline: none; - box-shadow: 0; - -webkit-transition-property: border-color,box-shadow,fill; - transition-property: border-color,box-shadow,fill; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - } - - .c30:focus-within { - border: 1px solid #4945ff; - box-shadow: #4945ff 0px 0px 0px 2px; - } - - .c37 { - font-size: 1.6rem; - padding: 0; - } - - .c42 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: flex-start; - -webkit-box-align: flex-start; - -ms-flex-align: flex-start; - align-items: flex-start; - } - - .c42 * { - cursor: pointer; - } - - .c9 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - } - - .c9 svg { - height: 4px; - width: 6px; - } - - .c22 { - display: grid; - grid-template-columns: repeat(12,1fr); - gap: 16px; - } - - .c23 { - grid-column: span 6; - max-width: 100%; - } - - .c13:focus-visible { - outline: none; - } - - .c12 { - margin: 0 auto; - width: 552px; - } - - .c14 { - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - } - - .c15 { - height: 4.5rem; - } - - .c38 svg { - height: 1rem; - width: 1rem; - } - - .c38 svg path { - fill: #666687; - } - - .c19 { - text-align: center; - } - - .c45 { - color: #4945ff; - } - - .c33::-ms-reveal { - display: none; - } - - @media (max-width:68.75rem) { - .c23 { - grid-column: span; - } - } - - @media (max-width:34.375rem) { - .c23 { - grid-column: span; - } - } - -
-
-
-
- -
-
-
-
-
- -
-
- -
-

- Welcome to Strapi! -

-
-
- - Credentials are only used to authenticate in Strapi. All saved data will be stored in your database. - -
-
-
-
-
-
-
-
-
- -
- -
-
-
-
-
-
-
-
-
-
-
- -
- -
-
-
-
-
-
-
-
-
-
- -
- -
-
-
-
-
-
-
- -
- -
- -
-
-

- Must be at least 8 characters, 1 uppercase, 1 lowercase & 1 number -

-
-
-
-
-
-
- -
- -
- -
-
-
-
-
-
-
- -
-
- -
-
- -
-
-
- `); + }) +); + +const ComponentFixture = (props) => { + const history = createMemoryHistory(); + + return ( + + + + + {}} + schema={yup.object()} + {...props} + /> + + + + + ); +}; + +const setup = (props) => { + const user = userEvent.setup(); + + return { + ...render(), + user, + }; +}; + +describe('ADMIN | PAGES | AUTH | Register', () => { + beforeAll(() => { + server.listen(); + }); + + afterAll(() => { + server.close(); + }); + + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('Render form elements', () => { + const { getByText, getByRole, getByLabelText } = setup(); + + const labels = ['Firstname', 'Lastname', 'Email', 'Password', 'Confirm Password']; + + labels.forEach((label) => { + expect(getByText(label)).toBeInTheDocument(); + expect(getByLabelText(new RegExp(`^${label}`, 'i'))).toBeInTheDocument(); + }); + + expect( + getByText( + /keep me updated about new features & upcoming improvements \(by doing this you accept the and the \)\./i + ) + ).toBeInTheDocument(); + expect(getByRole('checkbox', { name: /news/i })).toBeInTheDocument(); + expect(getByRole('button', { name: /let's start/i })).toBeInTheDocument(); + }); + + it('Serialize the form and normalize input values', async () => { + const spy = jest.fn(); + const { getByRole, getByLabelText, user } = setup({ onSubmit: spy }); + + await user.type(getByLabelText(/Firstname/i), ' First name '); + await user.type(getByLabelText(/Lastname/i), ' Last name '); + await user.type(getByLabelText(/Email/i), ' test@strapi.io '); + await user.type(getByLabelText(/^Password/i), ' secret '); + await user.type(getByLabelText(/Confirm Password/i), ' secret '); + + await act(async () => { + await user.click(getByRole('button', { name: /let's start/i })); + }); + + expect(spy).toHaveBeenCalledWith( + { + firstname: 'First name', + lastname: 'Last name', + email: 'test@strapi.io', + news: false, + registrationToken: undefined, + confirmPassword: ' secret ', + password: ' secret ', + }, + expect.any(Object) + ); + }); + + it('Disable fields', () => { + const { getByLabelText } = setup({ + fieldsToDisable: ['email', 'firstname'], + }); + + expect(getByLabelText(/Firstname/i)).not.toHaveAttribute('disabled'); + expect(getByLabelText(/Email/i)).toHaveAttribute('disabled'); + }); + + it('Set defaults if the registration token is set and omits it when submitting', async () => { + const spy = jest.fn(); + const query = useQuery(); + query.get.mockReturnValue('my-token'); + + const { getByLabelText, getByRole, user } = setup({ onSubmit: spy }); + + await waitFor(() => expect(getByLabelText(/Firstname/i)).toHaveValue('Token firstname')); + + expect(getByLabelText(/Lastname/i)).toHaveValue('Token lastname'); + expect(getByLabelText(/Email/i)).toHaveValue('test+register-token@strapi.io'); + + await act(async () => { + await user.click(getByRole('button', { name: /let's start/i })); + }); + + expect(spy).toHaveBeenCalledWith( + { + registrationToken: 'my-token', + userInfo: expect.not.objectContaining({ + registrationToken: expect.any(String), + }), + }, + expect.any(Object) + ); + }); + + it('Shows an error notification if the token does not exist', async () => { + const query = useQuery(); + const toggleNotification = useNotification(); + + query.get.mockReturnValue('error'); + + setup(); + + await waitFor(() => expect(toggleNotification).toHaveBeenCalled()); + + expect(toggleNotification).toHaveBeenCalledWith({ + type: 'warning', + message: expect.any(String), + }); + }); + + it('Violates the yup schema and displays error messages', async () => { + const { getByText, getByRole, user } = setup({ + schema: yup.object().shape({ + firstname: yup.string().trim().required(), + lastname: yup.string(), + password: yup.string().required(), + email: yup.string().required(), + confirmPassword: yup.string().required(), + }), + }); + + await act(async () => { + await user.click(getByRole('button', { name: /let's start/i })); + }); + + expect(getByText(/firstname is a required field/i)).toBeInTheDocument(); + expect(getByText(/email is a required field/i)).toBeInTheDocument(); + expect(getByText(/^password is a required field/i)).toBeInTheDocument(); + expect(getByText(/confirmpassword is a required field/i)).toBeInTheDocument(); }); });