From 6ef003798bfdbbb7d07a9e9dd3b9dba08dd75745 Mon Sep 17 00:00:00 2001 From: Ashish Gupta Date: Wed, 6 Sep 2023 15:54:24 +0530 Subject: [PATCH] chore(ui): fix signup page styling (#13086) * chore(ui): fix signup page styling * fix the file naming convention * optimize signup form --- .../AppContainer/AppContainer.test.tsx | 4 +- .../components/AppContainer/AppContainer.tsx | 4 +- .../TeamsSelectable.interface.ts | 2 +- .../TeamsSelectable/TeamsSelectable.tsx | 2 +- .../ui/src/components/router/AppRouter.tsx | 4 +- .../ui/src/constants/PageHeaders.constant.ts | 2 +- .../BasicSignup.component.tsx | 0 .../ui/src/pages/SignUp/SignUpPage.test.tsx | 227 ++++++++++++++ .../ui/src/pages/SignUp/SignUpPage.tsx | 193 ++++++++++++ ...ount-activation-confirmation.component.tsx | 0 .../basic-signup.style.less | 0 .../{signup => SignUp}/mocks/signup.mock.ts | 13 + .../ui/src/pages/signup/index.test.tsx | 289 ------------------ .../resources/ui/src/pages/signup/index.tsx | 224 -------------- 14 files changed, 443 insertions(+), 521 deletions(-) rename openmetadata-ui/src/main/resources/ui/src/pages/{signup => SignUp}/BasicSignup.component.tsx (100%) create mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.test.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.tsx rename openmetadata-ui/src/main/resources/ui/src/pages/{signup => SignUp}/account-activation-confirmation.component.tsx (100%) rename openmetadata-ui/src/main/resources/ui/src/pages/{signup => SignUp}/basic-signup.style.less (100%) rename openmetadata-ui/src/main/resources/ui/src/pages/{signup => SignUp}/mocks/signup.mock.ts (87%) delete mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/signup/index.test.tsx delete mode 100644 openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.test.tsx index 9b4e97c8251..ae1a07f184f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.test.tsx @@ -64,7 +64,9 @@ jest.mock('components/AppBar/Appbar', () => jest.fn().mockReturnValue(

Appbar

) ); -jest.mock('pages/signup', () => jest.fn().mockReturnValue(

SignUpPage

)); +jest.mock('pages/SignUp/SignUpPage', () => + jest.fn().mockReturnValue(

SignUpPage

) +); jest.mock('components/router/AuthenticatedAppRouter', () => jest.fn().mockReturnValue(

AuthenticatedAppRouter

) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx index e76ae9d13f8..3a2cb8e0b3f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AppContainer/AppContainer.tsx @@ -19,7 +19,7 @@ import LeftSidebar from 'components/MyData/LeftSidebar/LeftSidebar.component'; import AuthenticatedAppRouter from 'components/router/AuthenticatedAppRouter'; import { ROUTES } from 'constants/constants'; import { isEmpty } from 'lodash'; -import SignupPage from 'pages/signup'; +import SignUpPage from 'pages/SignUp/SignUpPage'; import React from 'react'; import { Redirect, Route, Switch } from 'react-router-dom'; import './app-container.less'; @@ -27,7 +27,7 @@ import './app-container.less'; const AppContainer = () => { return ( - + {!isEmpty(AppState.userDetails) && } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.interface.ts index 7585db4f949..4cd70ec21d3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.interface.ts @@ -12,7 +12,7 @@ */ export interface TeamsSelectableProps { showTeamsAlert?: boolean; - onSelectionChange: (teams: string[]) => void; + onSelectionChange?: (teams: string[]) => void; filterJoinable?: boolean; placeholder?: string; selectedTeams?: string[]; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.tsx b/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.tsx index 0c39789688b..9eac0514dd5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/TeamsSelectable/TeamsSelectable.tsx @@ -36,7 +36,7 @@ const TeamsSelectable = ({ const [teams, setTeams] = useState>([]); const onChange = (newValue: string[]) => { - onSelectionChange(newValue); + onSelectionChange && onSelectionChange(newValue); setValue(newValue); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/router/AppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/router/AppRouter.tsx index 840b2d817b9..856aca8c519 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/router/AppRouter.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/router/AppRouter.tsx @@ -14,7 +14,7 @@ import AppContainer from 'components/AppContainer/AppContainer'; import { CustomEventTypes } from 'generated/analytics/webAnalyticEventData'; import { AuthProvider } from 'generated/settings/settings'; -import AccountActivationConfirmation from 'pages/signup/account-activation-confirmation.component'; +import AccountActivationConfirmation from 'pages/SignUp/account-activation-confirmation.component'; import React, { useCallback, useEffect } from 'react'; import { Redirect, Route, Switch, useLocation } from 'react-router-dom'; import { useAnalytics } from 'use-analytics'; @@ -41,7 +41,7 @@ const ResetPassword = withSuspenseFallback( ); const BasicSignupPage = withSuspenseFallback( - React.lazy(() => import('pages/signup/BasicSignup.component')) + React.lazy(() => import('pages/SignUp/BasicSignup.component')) ); const AppRouter = () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/PageHeaders.constant.ts b/openmetadata-ui/src/main/resources/ui/src/constants/PageHeaders.constant.ts index 18d77374775..d7d78d57fdb 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/PageHeaders.constant.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/PageHeaders.constant.ts @@ -121,7 +121,7 @@ export const PAGE_HEADERS = { STORED_PROCEDURE_CUSTOM_ATTRIBUTES: { header: i18n.t('label.stored-procedure'), subHeader: i18n.t('message.define-custom-property-for-entity', { - entity: i18n.t('label.label.stored-procedure'), + entity: i18n.t('label.stored-procedure'), }), }, BOTS: { diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/signup/BasicSignup.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/BasicSignup.component.tsx similarity index 100% rename from openmetadata-ui/src/main/resources/ui/src/pages/signup/BasicSignup.component.tsx rename to openmetadata-ui/src/main/resources/ui/src/pages/SignUp/BasicSignup.component.tsx diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.test.tsx new file mode 100644 index 00000000000..d37b58b4e59 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.test.tsx @@ -0,0 +1,227 @@ +/* + * Copyright 2023 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { act, fireEvent, render, screen } from '@testing-library/react'; +import AppState from 'AppState'; +import React from 'react'; +import { createUser } from 'rest/userAPI'; +import { getImages } from 'utils/CommonUtils'; +import { + mockChangedFormData, + mockCreateUser, + mockFormData, +} from './mocks/signup.mock'; +import SignUp from './SignUpPage'; + +let letExpectedUserName = { + name: 'sample123', + email: 'sample123@sample.com', +}; + +const mockShowErrorToast = jest.fn(); + +jest.mock('react-router-dom', () => ({ + useHistory: jest.fn().mockReturnValue({ + push: jest.fn(), + }), +})); + +jest.mock('components/authentication/auth-provider/AuthProvider', () => ({ + useAuthContext: jest.fn(() => ({ + setIsSigningIn: jest.fn(), + })), +})); + +jest.mock('components/TeamsSelectable/TeamsSelectable', () => + jest.fn().mockImplementation(() =>
TeamSelectable
) +); + +jest.mock('rest/userAPI', () => ({ + createUser: jest + .fn() + .mockImplementation(() => Promise.resolve(mockCreateUser)), +})); + +jest.mock('../../utils/ToastUtils', () => ({ + showErrorToast: jest.fn().mockImplementation(() => mockShowErrorToast), +})); + +jest.mock('../../AppState', () => ({ + ...jest.requireActual('../../AppState'), + newUser: { + name: 'Sample Name', + email: 'sample123@sample.com', + picture: 'Profile Picture', + }, + updateUserDetails: jest.fn(), + updateUserPermissions: jest.fn(), +})); + +jest.mock('../../utils/CommonUtils', () => ({ + getImages: jest + .fn() + .mockResolvedValue( + 'https://lh3.googleusercontent.com/a/ALm5wu0HwEPhAbyRha16cUHrEum-zxTDzj6KZiqYsT5Y=s96-c' + ), + Transi18next: jest.fn().mockReturnValue('text'), +})); + +jest.mock('utils/AuthProvider.util', () => ({ + getNameFromUserData: jest.fn().mockImplementation(() => letExpectedUserName), +})); + +describe('SignUp page', () => { + it('Component should render properly', async () => { + (createUser as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ data: {} }) + ); + render(); + const logo = screen.getByTestId('om-logo'); + const heading = screen.getByTestId('om-heading'); + const form = screen.getByTestId('create-user-form'); + const fullNameLabel = screen.getByTestId('full-name-label'); + const fullNameInput = screen.getByTestId('full-name-input'); + const usernameLabel = screen.getByTestId('username-label'); + const usernameInput = screen.getByTestId('username-input'); + const emailLabel = screen.getByTestId('email-label'); + const emailInput = screen.getByTestId('email-input'); + const selectTeamLabel = screen.getByTestId('select-team-label'); + const createButton = screen.getByTestId('create-button'); + const loadingContent = await screen.queryByTestId('loading-content'); + const submitButton = screen.getByTestId('create-button'); + + expect(logo).toBeInTheDocument(); + expect(heading).toBeInTheDocument(); + expect(form).toBeInTheDocument(); + expect(fullNameLabel).toBeInTheDocument(); + expect(fullNameInput).toBeInTheDocument(); + expect(usernameLabel).toBeInTheDocument(); + expect(usernameInput).toBeInTheDocument(); + expect(emailLabel).toBeInTheDocument(); + expect(emailInput).toBeInTheDocument(); + expect(selectTeamLabel).toBeInTheDocument(); + expect(createButton).toBeInTheDocument(); + expect(loadingContent).toBeNull(); + expect(submitButton).toBeInTheDocument(); + }); + + it('Handlers in forms for change and submit should work properly', async () => { + render(); + const form = screen.getByTestId('create-user-form'); + const fullNameInput = screen.getByTestId( + 'full-name-input' + ) as HTMLInputElement; + const userNameInput = screen.getByTestId( + 'username-input' + ) as HTMLInputElement; + const emailInput = screen.getByTestId('email-input') as HTMLInputElement; + const submitButton = screen.getByTestId('create-button'); + + expect(form).toBeInTheDocument(); + expect(fullNameInput).toHaveValue(mockFormData.name); + expect(userNameInput).toHaveValue(mockFormData.userName); + expect(emailInput).toHaveValue(mockFormData.email); + + await act(async () => { + fireEvent.change(fullNameInput, { + target: { name: 'displayName', value: mockChangedFormData.fullName }, + }); + fireEvent.change(userNameInput, { + target: { name: 'name', value: mockChangedFormData.userName }, + }); + fireEvent.change(emailInput, { + target: { name: 'email', value: mockChangedFormData.email }, + }); + }); + + expect(fullNameInput).toHaveValue(mockChangedFormData.fullName); + expect(userNameInput).toHaveValue(mockChangedFormData.userName); + expect(emailInput).toHaveValue(mockChangedFormData.email); + + fireEvent.click(submitButton); + + await act(async () => { + (createUser as jest.Mock).mockImplementationOnce(() => + Promise.resolve(undefined) + ); + }); + + expect(createUser as jest.Mock).toHaveBeenCalledTimes(1); + }); + + it('Error should be thrown if createUser API fails', async () => { + render(); + const form = screen.getByTestId('create-user-form'); + const fullNameInput = screen.getByTestId('full-name-input'); + const userNameInput = screen.getByTestId('username-input'); + const emailInput = screen.getByTestId('email-input'); + const submitButton = screen.getByTestId('create-button'); + + expect(form).toBeInTheDocument(); + expect(fullNameInput).toHaveValue(mockFormData.name); + expect(userNameInput).toHaveValue(mockFormData.userName); + expect(emailInput).toHaveValue(mockFormData.email); + + await act(async () => { + fireEvent.change(fullNameInput, { + target: { name: 'displayName', value: mockChangedFormData.fullName }, + }); + fireEvent.change(userNameInput, { + target: { name: 'name', value: mockChangedFormData.userName }, + }); + fireEvent.change(emailInput, { + target: { name: 'email', value: mockChangedFormData.email }, + }); + }); + + expect(fullNameInput).toHaveValue(mockChangedFormData.fullName); + expect(userNameInput).toHaveValue(mockChangedFormData.userName); + expect(emailInput).toHaveValue(mockChangedFormData.email); + + fireEvent.click(submitButton); + await act(async () => { + (createUser as jest.Mock).mockImplementationOnce(() => + Promise.reject({ + response: { data: { message: 'error' } }, + }) + ); + }); + + expect(createUser as jest.Mock).toHaveBeenCalledTimes(1); + }); + + it('Handlers in form should work if data is empty', async () => { + (getImages as jest.Mock).mockImplementationOnce(() => Promise.reject('')); + letExpectedUserName = { name: '', email: '' }; + AppState.newUser = { + name: '', + email: '', + picture: '', + }; + render(); + const form = screen.getByTestId('create-user-form'); + const fullNameInput = screen.getByTestId('full-name-input'); + const usernameInput = screen.getByTestId('username-input'); + const emailInput = screen.getByTestId('email-input'); + + expect(form).toBeInTheDocument(); + expect(fullNameInput).toHaveValue(''); + expect(usernameInput).toHaveValue(''); + expect(emailInput).toHaveValue(''); + + const submitButton = screen.getByTestId('create-button'); + fireEvent.click(submitButton); + + expect(createUser as jest.Mock).toHaveBeenCalledTimes(0); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.tsx new file mode 100644 index 00000000000..7d722245e0c --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/SignUpPage.tsx @@ -0,0 +1,193 @@ +/* + * Copyright 2023 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Button, Card, Form, FormProps, Input, Space, Typography } from 'antd'; +import { AxiosError } from 'axios'; +import { useAuthContext } from 'components/authentication/auth-provider/AuthProvider'; +import { UserProfile } from 'components/authentication/auth-provider/AuthProvider.interface'; +import TeamsSelectable from 'components/TeamsSelectable/TeamsSelectable'; +import { CookieStorage } from 'cookie-storage'; +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router-dom'; +import { createUser } from 'rest/userAPI'; +import { getNameFromUserData } from 'utils/AuthProvider.util'; +import appState from '../../AppState'; +import { ReactComponent as OMDLogo } from '../../assets/svg/logo-monogram.svg'; +import { + REDIRECT_PATHNAME, + ROUTES, + VALIDATION_MESSAGES, +} from '../../constants/constants'; +import { getImages, Transi18next } from '../../utils/CommonUtils'; +import { showErrorToast } from '../../utils/ToastUtils'; + +const cookieStorage = new CookieStorage(); + +const SignUp = () => { + const { t } = useTranslation(); + const history = useHistory(); + const { + setIsSigningIn, + jwtPrincipalClaims = [], + authorizerConfig, + } = useAuthContext(); + + const [loading, setLoading] = useState(false); + + const handleCreateNewUser: FormProps['onFinish'] = async (data) => { + setLoading(true); + + try { + const res = await createUser({ + ...data, + profile: { + images: getImages(appState.newUser.picture ?? ''), + }, + }); + + appState.updateUserDetails(res); + cookieStorage.removeItem(REDIRECT_PATHNAME); + setIsSigningIn(false); + history.push(ROUTES.HOME); + } catch (error) { + showErrorToast( + error as AxiosError, + t('server.create-entity-error', { + entity: t('label.user'), + }) + ); + } finally { + setLoading(false); + } + }; + + return ( +
+ + + + + } + values={{ + entity: t('label.open-metadata'), + }} + /> + + + +
+ + + + + + + + + + + + + + + + + + + +
+
+
+ ); +}; + +export default SignUp; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/signup/account-activation-confirmation.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/account-activation-confirmation.component.tsx similarity index 100% rename from openmetadata-ui/src/main/resources/ui/src/pages/signup/account-activation-confirmation.component.tsx rename to openmetadata-ui/src/main/resources/ui/src/pages/SignUp/account-activation-confirmation.component.tsx diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/signup/basic-signup.style.less b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/basic-signup.style.less similarity index 100% rename from openmetadata-ui/src/main/resources/ui/src/pages/signup/basic-signup.style.less rename to openmetadata-ui/src/main/resources/ui/src/pages/SignUp/basic-signup.style.less diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/signup/mocks/signup.mock.ts b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/mocks/signup.mock.ts similarity index 87% rename from openmetadata-ui/src/main/resources/ui/src/pages/signup/mocks/signup.mock.ts rename to openmetadata-ui/src/main/resources/ui/src/pages/SignUp/mocks/signup.mock.ts index 66a770b8584..fa462d7f831 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/signup/mocks/signup.mock.ts +++ b/openmetadata-ui/src/main/resources/ui/src/pages/SignUp/mocks/signup.mock.ts @@ -11,6 +11,19 @@ * limitations under the License. */ +export const mockFormData = { + name: 'Sample Name', + email: 'sample123@sample.com', + picture: 'Profile Picture', + userName: 'sample123', +}; + +export const mockChangedFormData = { + fullName: 'f_name m_name l_name', + userName: 'mockUserName', + email: 'test@gmail.com', +}; + export const mockCreateUser = { data: { id: '911d4be4-6ebf-48a0-9016-43a2cf716428', diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.test.tsx deleted file mode 100644 index 4c03cbbfb08..00000000000 --- a/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.test.tsx +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2022 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { act, fireEvent, render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { createUser } from 'rest/userAPI'; -import SignUp from '.'; -import AppState from '../../AppState'; -import { getImages } from '../../utils/CommonUtils'; -import { mockCreateUser } from './mocks/signup.mock'; - -let letExpectedUserName = { name: 'sample123', email: 'sample123@sample.com' }; - -const mockChangeHandler = jest.fn(); -const mockSubmitHandler = jest.fn(); -const mockShowErrorToast = jest.fn(); - -jest.mock('react-router-dom', () => ({ - useHistory: jest.fn().mockReturnValue({ - push: jest.fn(), - }), -})); - -jest.mock('components/authentication/auth-provider/AuthProvider', () => ({ - useAuthContext: jest.fn(() => ({ - setIsSigningIn: jest.fn(), - })), -})); - -jest.mock('components/TeamsSelectable/TeamsSelectable', () => { - return jest.fn().mockImplementation(() =>
TeamSelectable
); -}); - -jest.mock('rest/userAPI', () => ({ - createUser: jest - .fn() - .mockImplementation(() => Promise.resolve(mockCreateUser)), -})); - -jest.mock('../../utils/ToastUtils', () => ({ - showErrorToast: jest.fn().mockImplementation(() => mockShowErrorToast), -})); - -jest.mock('../../AppState', () => ({ - ...jest.requireActual('../../AppState'), - newUser: { - name: 'Sample Name', - email: 'sample123@sample.com', - picture: 'Profile Picture', - }, - updateUserDetails: jest.fn(), - updateUserPermissions: jest.fn(), -})); - -jest.mock('../../utils/CommonUtils', () => ({ - getImages: jest - .fn() - .mockResolvedValue( - 'https://lh3.googleusercontent.com/a/ALm5wu0HwEPhAbyRha16cUHrEum-zxTDzj6KZiqYsT5Y=s96-c' - ), - Transi18next: jest.fn().mockReturnValue('text'), -})); - -jest.mock('utils/AuthProvider.util', () => ({ - getNameFromUserData: jest.fn().mockImplementation(() => letExpectedUserName), -})); - -describe('SignUp page', () => { - it('Component should render properly', async () => { - (createUser as jest.Mock).mockImplementationOnce(() => - Promise.resolve({ data: {} }) - ); - - const { getByTestId, queryByTestId } = render(); - - const logo = getByTestId('om-logo'); - const heading = getByTestId('om-heading'); - const form = getByTestId('create-user-form'); - const fullNameLabel = getByTestId('full-name-label'); - const fullNameInput = getByTestId('full-name-input'); - const usernameLabel = getByTestId('username-label'); - const usernameInput = getByTestId('username-input'); - const emailLabel = getByTestId('email-label'); - const emailInput = getByTestId('email-input'); - const selectTeamLabel = getByTestId('select-team-label'); - const createButton = getByTestId('create-button'); - const loadingContent = await queryByTestId('loading-content'); - - expect(logo).toBeInTheDocument(); - expect(heading).toBeInTheDocument(); - expect(form).toBeInTheDocument(); - expect(fullNameLabel).toBeInTheDocument(); - expect(fullNameInput).toBeInTheDocument(); - expect(usernameLabel).toBeInTheDocument(); - expect(usernameInput).toBeInTheDocument(); - expect(emailLabel).toBeInTheDocument(); - expect(emailInput).toBeInTheDocument(); - expect(selectTeamLabel).toBeInTheDocument(); - expect(createButton).toBeInTheDocument(); - expect(loadingContent).toBeNull(); - - await act(async () => { - form.onsubmit = mockSubmitHandler; - - fireEvent.submit(form); - - expect(mockSubmitHandler).toHaveBeenCalledTimes(1); - }); - }); - - it('Handlers in forms for change and submit should work properly', async () => { - (createUser as jest.Mock).mockImplementationOnce(() => - Promise.resolve(undefined) - ); - - const { getByTestId } = render(); - - const form = getByTestId('create-user-form'); - const fullNameInput = getByTestId('full-name-input'); - const usernameInput = getByTestId('username-input'); - const emailInput = getByTestId('email-input'); - - expect(form).toBeInTheDocument(); - expect(fullNameInput).toHaveValue('Sample Name'); - expect(usernameInput).toHaveValue('sample123'); - expect(emailInput).toHaveValue('sample123@sample.com'); - - fullNameInput.onchange = mockChangeHandler; - usernameInput.onchange = mockChangeHandler; - emailInput.onchange = mockChangeHandler; - - await act(async () => { - fireEvent.change(fullNameInput, { - target: { name: 'displayName', value: 'Fname Mname Lname' }, - }); - - fireEvent.change(usernameInput, { - target: { name: 'displayName', value: 'mockUserName' }, - }); - fireEvent.change(emailInput, { - target: { name: 'displayName', value: 'sample@sample.com' }, - }); - - expect(mockChangeHandler).toHaveBeenCalledTimes(3); - - form.onsubmit = mockSubmitHandler; - - fireEvent.submit(form); - - expect(mockSubmitHandler).toHaveBeenCalledTimes(1); - }); - }); - - it('Error should be thrown if createUser API fails', async () => { - const { getByTestId } = render(); - - const form = getByTestId('create-user-form'); - const fullNameInput = getByTestId('full-name-input'); - const usernameInput = getByTestId('username-input'); - const emailInput = getByTestId('email-input'); - - expect(form).toBeInTheDocument(); - expect(fullNameInput).toHaveValue('Sample Name'); - expect(usernameInput).toHaveValue('sample123'); - expect(emailInput).toHaveValue('sample123@sample.com'); - - fullNameInput.onchange = mockChangeHandler; - usernameInput.onchange = mockChangeHandler; - emailInput.onchange = mockChangeHandler; - - await act(async () => { - fireEvent.change(fullNameInput, { - target: { name: 'displayName', value: 'Fname Mname Lname' }, - }); - - fireEvent.change(usernameInput, { - target: { name: 'displayName', value: 'mockUserName' }, - }); - fireEvent.change(emailInput, { - target: { name: 'displayName', value: '' }, - }); - }); - - expect(mockChangeHandler).toHaveBeenCalledTimes(3); - - form.onsubmit = mockSubmitHandler; - - await act(async () => { - (createUser as jest.Mock).mockImplementationOnce(() => - Promise.reject({ - response: { data: { message: 'error' } }, - }) - ); - fireEvent.submit(form); - }); - - expect(createUser as jest.Mock).toHaveBeenCalledTimes(1); - }); - - it('Handlers in form should work if data is empty', async () => { - (getImages as jest.Mock).mockImplementationOnce(() => Promise.reject('')); - letExpectedUserName = { name: '', email: '' }; - - AppState.newUser = { - name: '', - email: '', - picture: '', - }; - - const { getByTestId } = render(); - - const form = getByTestId('create-user-form'); - const fullNameInput = getByTestId('full-name-input'); - const usernameInput = getByTestId('username-input'); - const emailInput = getByTestId('email-input'); - - expect(form).toBeInTheDocument(); - expect(fullNameInput).toHaveValue(''); - expect(usernameInput).toHaveValue(''); - expect(emailInput).toHaveValue(''); - - fullNameInput.onchange = mockChangeHandler; - usernameInput.onchange = mockChangeHandler; - emailInput.onchange = mockChangeHandler; - - expect(mockChangeHandler).not.toHaveBeenCalled(); - - form.onsubmit = mockSubmitHandler; - - await act(async () => { - fireEvent.submit(form); - }); - - expect(createUser as jest.Mock).toHaveBeenCalledTimes(0); - }); - - it('Create Button Should Work Properly and call the form handler', async () => { - (createUser as jest.Mock).mockImplementationOnce(() => - Promise.resolve(undefined) - ); - - const { getByTestId } = render(); - - const form = getByTestId('create-user-form'); - const fullNameInput = getByTestId('full-name-input'); - const usernameInput = getByTestId('username-input'); - const emailInput = getByTestId('email-input'); - - expect(form).toBeInTheDocument(); - - fullNameInput.onchange = mockChangeHandler; - usernameInput.onchange = mockChangeHandler; - emailInput.onchange = mockChangeHandler; - - await act(async () => { - fireEvent.change(fullNameInput, { - target: { name: 'displayName', value: 'Fname Mname Lname' }, - }); - - fireEvent.change(usernameInput, { - target: { name: 'displayName', value: 'mockUserName' }, - }); - fireEvent.change(emailInput, { - target: { name: 'displayName', value: 'sample@sample.com' }, - }); - - expect(mockChangeHandler).toHaveBeenCalledTimes(3); - - form.onsubmit = mockSubmitHandler; - - const createButton = getByTestId('create-button'); - - userEvent.click(createButton); - - expect(mockSubmitHandler).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx deleted file mode 100644 index 6e938982c89..00000000000 --- a/openmetadata-ui/src/main/resources/ui/src/pages/signup/index.tsx +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2022 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Button } from 'antd'; -import { AxiosError } from 'axios'; -import { useAuthContext } from 'components/authentication/auth-provider/AuthProvider'; -import { UserProfile } from 'components/authentication/auth-provider/AuthProvider.interface'; -import TeamsSelectable from 'components/TeamsSelectable/TeamsSelectable'; -import { CookieStorage } from 'cookie-storage'; -import React, { useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useHistory } from 'react-router-dom'; -import { createUser } from 'rest/userAPI'; -import { getNameFromUserData } from 'utils/AuthProvider.util'; -import appState from '../../AppState'; -import { ReactComponent as OMDLogo } from '../../assets/svg/logo-monogram.svg'; -import { ELLIPSES, REDIRECT_PATHNAME, ROUTES } from '../../constants/constants'; -import { CreateUser } from '../../generated/api/teams/createUser'; -import { User } from '../../generated/entity/teams/user'; -import { getImages, Transi18next } from '../../utils/CommonUtils'; -import { showErrorToast } from '../../utils/ToastUtils'; - -const cookieStorage = new CookieStorage(); - -const SignUp = () => { - const { t } = useTranslation(); - const history = useHistory(); - const { - setIsSigningIn, - jwtPrincipalClaims = [], - authorizerConfig, - } = useAuthContext(); - - const [selectedTeams, setSelectedTeams] = useState>([]); - const [loading, setLoading] = useState(false); - const [details, setDetails] = useState({ - displayName: appState.newUser.name || '', - ...getNameFromUserData( - appState.newUser as UserProfile, - jwtPrincipalClaims, - authorizerConfig?.principalDomain - ), - }); - - const createNewUser = (details: User | CreateUser) => { - setLoading(true); - createUser(details as CreateUser) - .then((res) => { - if (res) { - appState.updateUserDetails(res); - cookieStorage.removeItem(REDIRECT_PATHNAME); - setIsSigningIn(false); - history.push(ROUTES.HOME); - } else { - setLoading(false); - } - }) - .catch((err: AxiosError) => { - showErrorToast( - err, - t('server.create-entity-error', { - entity: t('label.user'), - }) - ); - }) - .finally(() => { - setLoading(false); - }); - }; - - const onChangeHandler = (e: React.ChangeEvent) => { - e.persist(); - setDetails((prevState) => { - return { - ...prevState, - [e.target.name]: e.target.value, - }; - }); - }; - - const onSubmitHandler = (e: React.FormEvent) => { - e.preventDefault(); - if (details.name && details.displayName) { - createNewUser({ - ...details, - teams: selectedTeams as Array, - profile: { - images: getImages(appState.newUser.picture ?? ''), - }, - }); - } - }; - - return loading ? ( -

- {t('label.creating-account')} - {ELLIPSES} -

- ) : ( - // TODO: replace this with form -
-
-
- -
-
-

- } - values={{ - entity: t('label.open-metadata'), - }} - /> -

-
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
-
-
-
-
- ); -}; - -export default SignUp;