From 1c6fdb65d750a68fbf34863c532004c1f82ca6c2 Mon Sep 17 00:00:00 2001 From: skbhagat0502 Date: Wed, 15 Nov 2023 00:03:49 +0530 Subject: [PATCH 1/4] Fix user profile buttons layout and added form validation --- src/components/LeftDrawer/LeftDrawer.tsx | 5 +-- .../LeftDrawerEvent/LeftDrawerEvent.tsx | 4 +- .../LeftDrawerOrg/LeftDrawerOrg.tsx | 5 +-- src/components/UserUpdate/UserUpdate.tsx | 32 ++++++++++++--- .../MemberDetail/MemberDetail.module.css | 19 ++++++--- src/screens/MemberDetail/MemberDetail.tsx | 40 ++++++++++--------- 6 files changed, 67 insertions(+), 38 deletions(-) diff --git a/src/components/LeftDrawer/LeftDrawer.tsx b/src/components/LeftDrawer/LeftDrawer.tsx index 57eacce0a7..d0b6220021 100644 --- a/src/components/LeftDrawer/LeftDrawer.tsx +++ b/src/components/LeftDrawer/LeftDrawer.tsx @@ -2,7 +2,6 @@ import React from 'react'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import { useHistory } from 'react-router-dom'; -import { toast } from 'react-toastify'; import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; import { ReactComponent as OrganizationsIcon } from 'assets/svgs/organizations.svg'; @@ -28,7 +27,7 @@ const leftDrawer = ({ const firstName = localStorage.getItem('FirstName'); const lastName = localStorage.getItem('LastName'); const userImage = localStorage.getItem('UserImage'); - + const userId = localStorage.getItem('id'); const history = useHistory(); const logout = (): void => { @@ -135,7 +134,7 @@ const leftDrawer = ({ className={styles.profileContainer} data-testid="profileBtn" onClick={(): void => { - toast.success('Profile page coming soon!'); + history.push(`/member/id=${userId}`); }} >
diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx b/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx index 2e3ac65cde..5feb818a89 100644 --- a/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx +++ b/src/components/LeftDrawerEvent/LeftDrawerEvent.tsx @@ -1,7 +1,6 @@ import React from 'react'; import Button from 'react-bootstrap/Button'; import { useHistory } from 'react-router-dom'; -import { toast } from 'react-toastify'; import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; import { ReactComponent as LogoutIcon } from 'assets/svgs/logout.svg'; import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; @@ -35,6 +34,7 @@ const leftDrawerEvent = ({ const firstName = localStorage.getItem('FirstName'); const lastName = localStorage.getItem('LastName'); const userImage = localStorage.getItem('UserImage'); + const userId = localStorage.getItem('id'); const history = useHistory(); const logout = (): void => { @@ -138,7 +138,7 @@ const leftDrawerEvent = ({ className={styles.profileContainer} data-testid="profileBtn" onClick={(): void => { - toast.success('Profile page coming soon!'); + history.push(`/member/id=${userId}`); }} >
diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx index 13c40da74d..73c5e4364d 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.tsx @@ -7,7 +7,6 @@ import React, { useEffect, useState } from 'react'; import Button from 'react-bootstrap/Button'; import { useTranslation } from 'react-i18next'; import { useHistory } from 'react-router-dom'; -import { toast } from 'react-toastify'; import type { TargetsType } from 'state/reducers/routesReducer'; import type { InterfaceQueryOrganizationsListObject } from 'utils/interfaces'; import { ReactComponent as AngleRightIcon } from 'assets/svgs/angleRight.svg'; @@ -49,7 +48,7 @@ const leftDrawerOrg = ({ const firstName = localStorage.getItem('FirstName'); const lastName = localStorage.getItem('LastName'); const userImage = localStorage.getItem('UserImage'); - + const userId = localStorage.getItem('id'); const history = useHistory(); // Set organization data @@ -184,7 +183,7 @@ const leftDrawerOrg = ({ className={styles.profileContainer} data-testid="profileBtn" onClick={(): void => { - toast.success('Profile page coming soon!'); + history.push(`/member/id=${userId}`); }} >
diff --git a/src/components/UserUpdate/UserUpdate.tsx b/src/components/UserUpdate/UserUpdate.tsx index 95e43874c9..e445db77aa 100644 --- a/src/components/UserUpdate/UserUpdate.tsx +++ b/src/components/UserUpdate/UserUpdate.tsx @@ -6,6 +6,7 @@ import Button from 'react-bootstrap/Button'; import styles from './UserUpdate.module.css'; import convertToBase64 from 'utils/convertToBase64'; import { USER_DETAILS } from 'GraphQl/Queries/Queries'; +import { useLocation } from 'react-router-dom'; import { languages } from 'utils/languages'; import { toast } from 'react-toastify'; @@ -21,7 +22,8 @@ interface InterfaceUserUpdateProps { const UserUpdate: React.FC = ({ id, }): JSX.Element => { - const currentUrl = localStorage.getItem('id'); + const location = useLocation(); + const currentUrl = location.state?.id || localStorage.getItem('id') || id; const { t } = useTranslation('translation', { keyPrefix: 'userUpdate', }); @@ -41,7 +43,7 @@ const UserUpdate: React.FC = ({ loading: loading, error: error, } = useQuery(USER_DETAILS, { - variables: { id: localStorage.getItem('id') ?? id }, // For testing we are sending the id as a prop + variables: { id: currentUrl }, // For testing we are sending the id as a prop }); React.useEffect(() => { if (data) { @@ -65,13 +67,31 @@ const UserUpdate: React.FC = ({ const loginLink = async (): Promise => { try { + const firstName = formState.firstName; + const lastName = formState.lastName; + const email = formState.email; + const file = formState.file; + let toSubmit = true; + if (firstName.trim().length == 0 || !firstName) { + toast.warning('First Name cannot be blank!'); + toSubmit = false; + } + if (lastName.trim().length == 0 || !lastName) { + toast.warning('Last Name cannot be blank!'); + toSubmit = false; + } + if (email.trim().length == 0 || !email) { + toast.warning('Email cannot be blank!'); + toSubmit = false; + } + if (!toSubmit) return; const { data } = await updateUser({ variables: { //Currently on these fields are supported by the api - firstName: formState.firstName, - lastName: formState.lastName, - email: formState.email, - file: formState.file, + firstName, + lastName, + email, + file, }, }); /* istanbul ignore next */ diff --git a/src/screens/MemberDetail/MemberDetail.module.css b/src/screens/MemberDetail/MemberDetail.module.css index 53f1ff9ccb..3d2ec749e3 100644 --- a/src/screens/MemberDetail/MemberDetail.module.css +++ b/src/screens/MemberDetail/MemberDetail.module.css @@ -112,6 +112,16 @@ justify-content: space-between; } +.flexclm { + display: flex; + flex-direction: column; +} + +.btngroup { + display: flex; + gap: 2rem; + margin-bottom: 2rem; +} @media screen and (max-width: 1200px) { .justifysp { padding-left: 55px; @@ -336,13 +346,12 @@ border-color: #31bb6b; background-color: #31bb6b; color: white; - padding-right: 10px; - padding-left: 10px; - justify-content: flex-end; - float: right; - text-align: right; box-shadow: none; height: 2.5rem; + width: max-content; + display: flex; + justify-content: center; + align-items: center; } .userImage { diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx index 914996ce35..53f889e6f7 100644 --- a/src/screens/MemberDetail/MemberDetail.tsx +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -28,7 +28,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { const [state, setState] = useState(1); const location = useLocation(); - const currentUrl = window.location.href.split('=')[1]; + const currentUrl = location.state?.id || localStorage.getItem('id') || id; document.title = t('title'); const [adda] = useMutation(ADD_ADMIN_MUTATION); @@ -37,7 +37,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { loading: loading, error: error, } = useQuery(USER_DETAILS, { - variables: { id: location.state?.id ?? id }, // For testing we are sending the id as a prop + variables: { id: currentUrl }, // For testing we are sending the id as a prop }); if (loading) { @@ -94,23 +94,25 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => { {state == 1 ? (
- +

{t('title')}

- - +
+ + +
@@ -283,7 +285,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => {
) : ( - + )} From f58c669059580895193677cfd2ef1b9f95bfe80d Mon Sep 17 00:00:00 2001 From: skbhagat0502 Date: Wed, 15 Nov 2023 02:20:57 +0530 Subject: [PATCH 2/4] Fix falling tests and warnings --- src/components/LeftDrawer/LeftDrawer.test.tsx | 3 -- .../LeftDrawerEvent/LeftDrawerEvent.test.tsx | 2 -- .../LeftDrawerOrg/LeftDrawerOrg.test.tsx | 2 -- src/components/UserUpdate/UserUpdate.test.tsx | 28 +++++++++++++++++-- .../MemberDetail/MemberDetail.test.tsx | 2 +- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/components/LeftDrawer/LeftDrawer.test.tsx b/src/components/LeftDrawer/LeftDrawer.test.tsx index 2a64d72f95..bd7652dab4 100644 --- a/src/components/LeftDrawer/LeftDrawer.test.tsx +++ b/src/components/LeftDrawer/LeftDrawer.test.tsx @@ -5,7 +5,6 @@ import 'jest-localstorage-mock'; import { I18nextProvider } from 'react-i18next'; import { BrowserRouter } from 'react-router-dom'; -import { toast } from 'react-toastify'; import i18nForTest from 'utils/i18nForTest'; import type { InterfaceLeftDrawerProps } from './LeftDrawer'; import LeftDrawer from './LeftDrawer'; @@ -89,7 +88,6 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { // Coming soon userEvent.click(screen.getByTestId(/profileBtn/i)); - expect(toast.success).toHaveBeenCalledWith('Profile page coming soon!'); // Send to roles screen userEvent.click(rolesBtn); @@ -234,7 +232,6 @@ describe('Testing Left Drawer component for ADMIN', () => { // Coming soon userEvent.click(screen.getByTestId(/profileBtn/i)); - expect(toast.success).toHaveBeenCalledWith('Profile page coming soon!'); // Send to roles screen userEvent.click(orgsBtn); diff --git a/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx b/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx index 0fabcd2c55..889ba7fea6 100644 --- a/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx +++ b/src/components/LeftDrawerEvent/LeftDrawerEvent.test.tsx @@ -4,7 +4,6 @@ import userEvent from '@testing-library/user-event'; import 'jest-localstorage-mock'; import { I18nextProvider } from 'react-i18next'; import { BrowserRouter } from 'react-router-dom'; -import { toast } from 'react-toastify'; import i18nForTest from 'utils/i18nForTest'; import LeftDrawerEvent, { type InterfaceLeftDrawerProps, @@ -138,7 +137,6 @@ describe('Testing Left Drawer component for the Event Dashboard', () => { expect(props.setShowAddEventProjectModal).toHaveBeenCalled(); fireEvent.click(queryByTestId(/profileBtn/i) as HTMLElement); - expect(toast.success).toHaveBeenCalledWith('Profile page coming soon!'); }); test('Testing Drawer when hideDrawer is null', () => { diff --git a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx index ff10c1b28b..4d4d0db4b5 100644 --- a/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx +++ b/src/components/LeftDrawerOrg/LeftDrawerOrg.test.tsx @@ -5,7 +5,6 @@ import 'jest-localstorage-mock'; import { I18nextProvider } from 'react-i18next'; import { BrowserRouter } from 'react-router-dom'; -import { toast } from 'react-toastify'; import i18nForTest from 'utils/i18nForTest'; import type { InterfaceLeftDrawerProps } from './LeftDrawerOrg'; import LeftDrawerOrg from './LeftDrawerOrg'; @@ -267,7 +266,6 @@ describe('Testing Left Drawer component for SUPERADMIN', () => { await wait(); expect(screen.getByTestId(/orgBtn/i)).toBeInTheDocument(); userEvent.click(screen.getByTestId(/profileBtn/i)); - expect(toast.success).toHaveBeenCalledWith('Profile page coming soon!'); }); test('Testing Menu Buttons', async () => { diff --git a/src/components/UserUpdate/UserUpdate.test.tsx b/src/components/UserUpdate/UserUpdate.test.tsx index 7b627367a9..aca8a579a2 100644 --- a/src/components/UserUpdate/UserUpdate.test.tsx +++ b/src/components/UserUpdate/UserUpdate.test.tsx @@ -3,12 +3,13 @@ import { act, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import userEvent from '@testing-library/user-event'; import { I18nextProvider } from 'react-i18next'; - +import { BrowserRouter as Router } from 'react-router-dom'; import UserUpdate from './UserUpdate'; import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; import i18nForTest from 'utils/i18nForTest'; import { USER_DETAILS } from 'GraphQl/Queries/Queries'; import { StaticMockLink } from 'utils/StaticMockLink'; +import { toast } from 'react-toastify'; const MOCKS = [ { @@ -95,7 +96,9 @@ describe('Testing User Update', () => { render( - + + + ); @@ -131,4 +134,25 @@ describe('Testing User Update', () => { expect(screen.getByPlaceholderText(/Email/i)).toBeInTheDocument(); expect(screen.getByText(/Display Image/i)).toBeInTheDocument(); }); + test('should display warnings for blank form submission', async () => { + jest.spyOn(toast, 'warning'); + + render( + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByText(/Save Changes/i)); + + expect(toast.warning).toHaveBeenCalledWith('First Name cannot be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Last Name cannot be blank!'); + expect(toast.warning).toHaveBeenCalledWith('Email cannot be blank!'); + }); }); diff --git a/src/screens/MemberDetail/MemberDetail.test.tsx b/src/screens/MemberDetail/MemberDetail.test.tsx index 94fd20700e..6a52ba41c5 100644 --- a/src/screens/MemberDetail/MemberDetail.test.tsx +++ b/src/screens/MemberDetail/MemberDetail.test.tsx @@ -270,6 +270,6 @@ describe('MemberDetail', () => { expect(container.textContent).not.toBe('Loading data...'); - waitFor(() => userEvent.click(screen.getByText(/edit/i))); + waitFor(() => userEvent.click(screen.getByText(/Edit Profile/i))); }); }); From c116e9a76d81c44fa093e9bf2fec2c0b371056e5 Mon Sep 17 00:00:00 2001 From: skbhagat0502 Date: Wed, 15 Nov 2023 06:24:53 +0530 Subject: [PATCH 3/4] Add test for missed lines --- src/screens/MemberDetail/MemberDetail.test.tsx | 4 ++-- src/screens/MemberDetail/MemberDetail.tsx | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/screens/MemberDetail/MemberDetail.test.tsx b/src/screens/MemberDetail/MemberDetail.test.tsx index 6a52ba41c5..6cd61296f6 100644 --- a/src/screens/MemberDetail/MemberDetail.test.tsx +++ b/src/screens/MemberDetail/MemberDetail.test.tsx @@ -172,6 +172,8 @@ describe('MemberDetail', () => { expect(screen.getAllByText(/Role/i)).toHaveLength(2); expect(screen.getAllByText(/Created/i)).toHaveLength(4); expect(screen.getAllByText(/Joined/i)).toHaveLength(2); + expect(screen.getByTestId('stateBtn')).toBeInTheDocument(); + userEvent.click(screen.getByTestId('stateBtn')); }); test('prettyDate function should work properly', () => { // If the date is provided @@ -250,12 +252,10 @@ describe('MemberDetail', () => { ) ); }); - test('should call setState with 2 when button is clicked', async () => { const props = { id: 'rishav-jha-mech', }; - const { container } = render( diff --git a/src/screens/MemberDetail/MemberDetail.tsx b/src/screens/MemberDetail/MemberDetail.tsx index 53f889e6f7..b243dfae98 100644 --- a/src/screens/MemberDetail/MemberDetail.tsx +++ b/src/screens/MemberDetail/MemberDetail.tsx @@ -106,6 +106,7 @@ const MemberDetail: React.FC = ({ id }): JSX.Element => {