From 4233482e64b146cb34dfe92a6053dcef0136073d Mon Sep 17 00:00:00 2001 From: rishav-jha-mech Date: Tue, 5 Sep 2023 11:59:25 +0530 Subject: [PATCH] Organization Dashboard achieved 100% CC --- .../OrganizationDashCards/CardItemLoading.tsx | 24 ++ .../OrganizationDashCards/DashboardCard.tsx | 4 +- .../DashboardCardLoading.tsx | 36 ++ .../OrganizationDashboard.test.tsx | 237 +++++++------ .../OrganizationDashboard.tsx | 230 +++++++------ .../OrganizationDashboardMocks.ts | 322 +++++------------- 6 files changed, 394 insertions(+), 459 deletions(-) create mode 100644 src/components/OrganizationDashCards/CardItemLoading.tsx create mode 100644 src/components/OrganizationDashCards/DashboardCardLoading.tsx diff --git a/src/components/OrganizationDashCards/CardItemLoading.tsx b/src/components/OrganizationDashCards/CardItemLoading.tsx new file mode 100644 index 0000000000..923128c2f2 --- /dev/null +++ b/src/components/OrganizationDashCards/CardItemLoading.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import styles from './CardItem.module.css'; + +const cardItemLoading = (): JSX.Element => { + return ( + <> +
+
+
+
+ +   + +
+ + ); +}; + +export default cardItemLoading; diff --git a/src/components/OrganizationDashCards/DashboardCard.tsx b/src/components/OrganizationDashCards/DashboardCard.tsx index 7a659be31d..4ad8fe8849 100644 --- a/src/components/OrganizationDashCards/DashboardCard.tsx +++ b/src/components/OrganizationDashCards/DashboardCard.tsx @@ -6,7 +6,7 @@ import styles from './Dashboardcard.module.css'; const dashBoardCard = (props: { icon: React.ReactNode; title: string; - count: number; + count?: number; }): JSX.Element => { const { icon, count, title } = props; return ( @@ -20,7 +20,7 @@ const dashBoardCard = (props: {
- {count} + {count ?? 0} {title} diff --git a/src/components/OrganizationDashCards/DashboardCardLoading.tsx b/src/components/OrganizationDashCards/DashboardCardLoading.tsx new file mode 100644 index 0000000000..5b596f32b2 --- /dev/null +++ b/src/components/OrganizationDashCards/DashboardCardLoading.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Card, Row } from 'react-bootstrap'; +import Col from 'react-bootstrap/Col'; +import styles from './Dashboardcard.module.css'; + +const dashBoardCardLoading = (): JSX.Element => { + return ( + + + + +
+
+
+ + + + + + + + + ); +}; + +export default dashBoardCardLoading; diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx index 612bbd30de..d171970d3f 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.test.tsx @@ -1,27 +1,27 @@ -import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import type { RenderResult } from '@testing-library/react'; import { act, - render, - screen, fireEvent, - waitFor, + render, + screen } from '@testing-library/react'; -import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { store } from 'state/store'; +import { StaticMockLink } from 'utils/StaticMockLink'; import OrganizationDashboard from './OrganizationDashboard'; import { - MOCKS_WITHOUT_IMAGE, - MOCKS_WITH_IMAGE, + EMPTY_MOCKS, + ERROR_MOCKS, + MOCKS } from './OrganizationDashboardMocks'; -import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; -import { USER_ORGANIZATION_LIST } from 'GraphQl/Queries/Queries'; -import { StaticMockLink } from 'utils/StaticMockLink'; +import dayjs from 'dayjs'; +import { toast } from 'react-toastify'; +import userEvent from '@testing-library/user-event'; async function wait(ms = 100): Promise { await act(() => { @@ -30,125 +30,122 @@ async function wait(ms = 100): Promise { }); }); } -const link2 = new StaticMockLink(MOCKS_WITH_IMAGE, true); -const link3 = new StaticMockLink(MOCKS_WITHOUT_IMAGE, true); -const customRender = (userType: any): RenderResult => { - const mockedUser = { - request: { - query: USER_ORGANIZATION_LIST, - variables: { id: localStorage.getItem('id') }, - }, - result: { - data: { - user: { - userType, - firstName: 'John', - lastName: 'Doe', - image: '', - email: 'John_Does_Palasidoes@gmail.com', - adminFor: { - _id: 1, - name: 'Akatsuki', - image: '', - }, - }, - }, - }, - }; - - const mocks = [mockedUser, ...MOCKS_WITHOUT_IMAGE]; - - const link1 = new StaticMockLink(mocks, true); - - return render( - - - - - - - - - +const link1 = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(EMPTY_MOCKS, true); +const link3 = new StaticMockLink(ERROR_MOCKS, true); + +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +beforeEach(() => { + localStorage.setItem('FirstName', 'John'); + localStorage.setItem('LastName', 'Doe'); + localStorage.setItem('UserType', 'SUPERADMIN'); + localStorage.setItem( + 'UserImage', + 'https://api.dicebear.com/5.x/initials/svg?seed=John%20Doe' ); -}; +}); + +afterEach(() => { + jest.clearAllMocks(); + localStorage.clear(); +}); + describe('Organisation Dashboard Page', () => { - test('should render props and text elements test for the screen', async () => { - window.location.replace('/orglist'); - - const { container } = render( - - - - - - - - - - ); - - expect(container.textContent).not.toBe('Loading data...'); + test('Should render props and text elements test for the screen', async () => { + + await act(async () => { + render( + + + + + + + + + + ) + }); + await wait(); - expect(container.textContent).toMatch('Location'); - expect(container.textContent).toMatch('About'); - expect(container.textContent).toMatch('Statistics'); - expect(window.location).toBeAt('/orglist'); - }); + expect(screen.getByText('Members')).toBeInTheDocument(); + expect(screen.getByText('Admins')).toBeInTheDocument(); + expect(screen.getAllByText('Posts')).toHaveLength(2); + expect(screen.getAllByText('Events')).toHaveLength(2); + expect(screen.getByText('Blocked Users')).toBeInTheDocument(); + expect(screen.getByText('Requests')).toBeInTheDocument(); + expect(screen.getByText('Upcoming events')).toBeInTheDocument(); + expect(screen.getByText('Latest posts')).toBeInTheDocument(); + expect(screen.getByText('Membership requests')).toBeInTheDocument(); + expect(screen.getAllByText('View all')).toHaveLength(3); - test('should display delete button for SUPERADMIN', async () => { - const { getByTestId, queryByTestId } = customRender('SUPERADMIN'); - await waitFor(() => - expect(queryByTestId('deleteClick')).toBeInTheDocument() - ); + // Checking if events are rendered + expect(screen.getByText('Event 1')).toBeInTheDocument(); + expect(screen.getByText(`${dayjs(new Date()).add(1, 'day').format('DD-MM-YYYY')}`)).toBeInTheDocument(); - fireEvent.click(getByTestId('deleteClick')); - fireEvent.click(getByTestId(/deleteOrganizationBtn/i)); - expect(window.location).not.toBeNull(); - }); + // Checking if posts are rendered + expect(screen.getByText('Post 1')).toBeInTheDocument(); - test('should not display delete button for non-SUPERADMIN', async () => { - const { queryByTestId } = customRender('ADMIN'); - await waitFor(() => - expect(queryByTestId('deleteClick')).not.toBeInTheDocument() - ); + // Checking if membership requests are rendered + expect(screen.getByText('Jane Doe')).toBeInTheDocument(); }); - test('Should check if organisation image is present', async () => { - const { container } = render( - - - - - - - - - - ); - - expect(container.textContent).not.toBe('Loading data...'); + test('Testing buttons and checking empty events, posts and membership requests', async () => { + await act(async () => { + render( + + + + + + + + + + ) + }); + await wait(); - const image = screen.getByTestId(/orgDashImgPresent/i); - expect(image).toBeInTheDocument(); + const viewEventsBtn = screen.getByTestId('viewAllEvents'); + const viewPostsBtn = screen.getByTestId('viewAllPosts'); + const viewMSBtn = screen.getByTestId('viewAllMembershipRequests'); + + userEvent.click(viewEventsBtn); + userEvent.click(viewPostsBtn); + fireEvent.click(viewMSBtn); + expect(toast.success).toBeCalledWith('Coming soon!'); + + expect(screen.getByText('No membership requests present')).toBeInTheDocument(); + expect(screen.getByText('No upcoming events')).toBeInTheDocument(); + expect(screen.getByText('No posts present')).toBeInTheDocument(); + }); - test('Should check if organisation image is not present', async () => { - const { container } = render( - - - - - - - - - - ); - - expect(container.textContent).not.toBe('Loading data...'); + + test('Testing buttons and checking empty events, posts and membership requests', async () => { + await act(async () => { + render( + + + + + + + + + + ) + }); + await wait(); - const image = screen.getByTestId(/orgDashImgAbsent/i); - expect(image).toBeInTheDocument(); + expect(window.location).toBeAt('/orglist'); }); + }); diff --git a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx index c51f697565..8a1cbac89e 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboard.tsx +++ b/src/screens/OrganizationDashboard/OrganizationDashboard.tsx @@ -15,7 +15,6 @@ import { ReactComponent as BlockedUsersIcon } from 'assets/svgs/blockedUser.svg' import { ReactComponent as EventsIcon } from 'assets/svgs/events.svg'; import { ReactComponent as PostsIcon } from 'assets/svgs/post.svg'; import { ReactComponent as UsersIcon } from 'assets/svgs/users.svg'; -import Loader from 'components/Loader/Loader'; import DashBoardCard from 'components/OrganizationDashCards/DashboardCard'; import OrganizationScreen from 'components/OrganizationScreen/OrganizationScreen'; import styles from './OrganizationDashboard.module.css'; @@ -28,6 +27,8 @@ import type { } from 'utils/interfaces'; import { toast } from 'react-toastify'; import { useHistory } from 'react-router-dom'; +import CardItemLoading from 'components/OrganizationDashCards/CardItemLoading'; +import DashboardCardLoading from 'components/OrganizationDashCards/DashboardCardLoading'; function organizationDashboard(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'dashboard' }); @@ -40,8 +41,8 @@ function organizationDashboard(): JSX.Element { const { data, - loading, - error, + loading: loadingOrgData, + error: errorOrg, }: { data?: { organizations: InterfaceQueryOrganizationsListObject[]; @@ -58,10 +59,10 @@ function organizationDashboard(): JSX.Element { error: errorPost, }: { data: - | { - postsByOrganization: InterfaceQueryOrganizationPostListItem[]; - } - | undefined; + | { + postsByOrganization: InterfaceQueryOrganizationPostListItem[]; + } + | undefined; loading: boolean; error?: ApolloError; } = useQuery(ORGANIZATION_POST_LIST, { @@ -74,10 +75,10 @@ function organizationDashboard(): JSX.Element { error: errorEvent, }: { data: - | { - eventsByOrganization: InterfaceQueryOrganizationEventListItem[]; - } - | undefined; + | { + eventsByOrganization: InterfaceQueryOrganizationEventListItem[]; + } + | undefined; loading: boolean; error?: ApolloError; } = useQuery(ORGANIZATION_EVENT_LIST, { @@ -99,68 +100,72 @@ function organizationDashboard(): JSX.Element { } }, [eventData?.eventsByOrganization]); - if (loading || loadingPost || loadingEvent) { - return ; - } - - /* istanbul ignore next */ - if (error || errorPost || errorEvent) { + if (errorOrg || errorPost || errorEvent) { window.location.replace('/orglist'); } - - function goTo(path: 'events' | 'post'): void { - history.push(`/org${path}/id=${currentUrl}`); - } - return ( <> - - - } - /> - - - } - /> - - - } - /> - - - } - /> - - - } - /> - - - } - /> - - + {loadingOrgData ? ( + + {[...Array(6)].map((_, index) => { + return ( + + + + ); + })} + + ) : ( + + + } + /> + + + } + /> + + + } + /> + + + } + /> + + + } + /> + + + } + /> + + + )} @@ -169,28 +174,34 @@ function organizationDashboard(): JSX.Element {
- {upcomingEvents.length == 0 ? ( -
-
No upcoming events
-
- ) : ( - upcomingEvents.slice(0, 5).map((event) => { - return ( - - ); + {loadingEvent ? ( + [...Array(4)].map((_, index) => { + return ; }) - )} + ) + : upcomingEvents.length == 0 ? ( +
+
No upcoming events
+
+ ) : ( + upcomingEvents.slice(0, 5).map((event) => { + return ( + + ); + }) + )}
@@ -201,13 +212,18 @@ function organizationDashboard(): JSX.Element { - {postData?.postsByOrganization?.length == 0 ? ( + {loadingPost ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) : postData?.postsByOrganization?.length == 0 ? (
No posts present
@@ -234,31 +250,37 @@ function organizationDashboard(): JSX.Element { - {data?.organizations[0].membershipRequests.length == 0 ? ( -
-
No membership requests present
-
- ) : ( - data?.organizations[0].membershipRequests - .slice(0, 8) - .map((request) => { - return ( - - ); - }) - )} + {loadingOrgData ? ( + [...Array(4)].map((_, index) => { + return ; + }) + ) + : data?.organizations[0].membershipRequests.length == 0 ? ( +
+
No membership requests present
+
+ ) : ( + data?.organizations[0]?.membershipRequests + .slice(0, 8) + .map((request) => { + return ( + + ); + }) + )}
diff --git a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts index 8335e55f91..56b96be695 100644 --- a/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts +++ b/src/screens/OrganizationDashboard/OrganizationDashboardMocks.ts @@ -4,8 +4,9 @@ import { ORGANIZATION_EVENT_LIST, ORGANIZATION_POST_LIST, } from 'GraphQl/Queries/Queries'; +import dayjs from 'dayjs'; -export const MOCKS_WITHOUT_IMAGE = [ +export const MOCKS = [ { request: { query: ORGANIZATIONS_LIST, @@ -14,58 +15,53 @@ export const MOCKS_WITHOUT_IMAGE = [ data: { organizations: [ { - _id: 1, + _id: 123, image: '', name: 'Dummy Organization', description: 'This is a Dummy Organization', + location: 'New Delhi', + isPublic: true, + visibleInSearch: false, creator: { firstName: '', lastName: '', email: '', }, - location: 'New Delhi', - members: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - email: 'johndoe@gmail.com', - }, - admins: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - email: 'johndoe@gmail.com', - }, - membershipRequests: { - _id: '456', - user: { - firstName: 'Sam', - lastName: 'Smith', - email: 'samsmith@gmail.com', + + members: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', }, - }, - blockedUsers: { - _id: '789', - firstName: 'Steve', - lastName: 'Smith', - email: 'stevesmith@gmail.com', - }, - spamCount: [ + ], + admins: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + membershipRequests: [ { - _id: '6954', + _id: '456', user: { - _id: '878', - firstName: 'Joe', - lastName: 'Root', - email: 'joeroot@gmail.com', - }, - isReaded: false, - groupchat: { - _id: '321', - title: 'Dummy', + firstName: 'Jane', + lastName: 'Doe', + email: 'janedoe@gmail.com', }, }, ], + blockedUsers: [ + { + _id: '789', + firstName: 'Steve', + lastName: 'Smith', + email: 'stevesmith@gmail.com', + }, + ], }, ], }, @@ -80,8 +76,8 @@ export const MOCKS_WITHOUT_IMAGE = [ postsByOrganization: [ { _id: 1, - title: 'Akatsuki', - text: 'Capture Jinchuriki', + title: 'Post 1', + text: 'Test Post', imageUrl: '', videoUrl: '', creator: { @@ -95,20 +91,6 @@ export const MOCKS_WITHOUT_IMAGE = [ }, }, }, - { - request: { - query: DELETE_ORGANIZATION_MUTATION, - }, - result: { - data: { - removeOrganization: [ - { - _id: 1, - }, - ], - }, - }, - }, { request: { query: ORGANIZATION_EVENT_LIST, @@ -118,14 +100,28 @@ export const MOCKS_WITHOUT_IMAGE = [ eventsByOrganization: [ { _id: 1, - title: 'Event', + title: 'Event 1', description: 'Event Test', - startDate: '', - endDate: '', + startDate: dayjs(new Date()).add(1, 'day'), + endDate: dayjs(new Date()).add(3, 'day'), location: 'New Delhi', - startTime: '02:00', - endTime: '06:00', - allDay: false, + startTime: '', + endTime: '', + allDay: true, + recurring: false, + isPublic: true, + isRegisterable: true, + }, + { + _id: 2, + title: 'Event 2', + description: 'Event Test', + startDate: dayjs(new Date()), + endDate: dayjs(new Date()).add(1, 'day'), + location: 'Jamaica', + startTime: '', + endTime: '', + allDay: true, recurring: false, isPublic: true, isRegisterable: true, @@ -136,7 +132,7 @@ export const MOCKS_WITHOUT_IMAGE = [ }, ]; -export const MOCKS_NO_TAGS = [ +export const EMPTY_MOCKS = [ { request: { query: ORGANIZATIONS_LIST, @@ -145,56 +141,41 @@ export const MOCKS_NO_TAGS = [ data: { organizations: [ { - _id: 1, + _id: 123, image: '', name: 'Dummy Organization', description: 'This is a Dummy Organization', - creator: { - firstName: '', - lastName: '', - email: '', - }, location: 'New Delhi', - members: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - email: 'johndoe@gmail.com', - }, - admins: { - _id: '123', + isPublic: true, + visibleInSearch: false, + creator: { firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', }, - membershipRequests: { - _id: '456', - user: { - firstName: 'Sam', - lastName: 'Smith', - email: 'samsmith@gmail.com', + members: [ + { + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', }, - }, - blockedUsers: { - _id: '789', - firstName: 'Steve', - lastName: 'Smith', - email: 'stevesmith@gmail.com', - }, - spamCount: [ + ], + admins: [ { - _id: '6954', - user: { - _id: '878', - firstName: 'Joe', - lastName: 'Root', - email: 'joeroot@gmail.com', - }, - isReaded: false, - groupchat: { - _id: '321', - title: 'Dummy', - }, + _id: '123', + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + }, + ], + membershipRequests: [], + blockedUsers: [ + { + _id: '789', + firstName: 'Steve', + lastName: 'Smith', + email: 'stevesmith@gmail.com', }, ], }, @@ -208,21 +189,7 @@ export const MOCKS_NO_TAGS = [ }, result: { data: { - postsByOrganization: [ - { - _id: 1, - title: 'Akatsuki', - text: 'Capture Jinchuriki', - imageUrl: '', - videoUrl: '', - creator: { - _id: '583', - firstName: 'John', - lastName: 'Doe', - email: 'johndoe@gmail.com', - }, - }, - ], + postsByOrganization: [], }, }, }, @@ -232,140 +199,29 @@ export const MOCKS_NO_TAGS = [ }, result: { data: { - eventsByOrganization: [ - { - _id: 1, - title: 'Event', - description: 'Event Test', - startDate: '', - endDate: '', - location: 'New Delhi', - startTime: '02:00', - endTime: '06:00', - allDay: false, - recurring: false, - isPublic: true, - isRegisterable: true, - }, - ], + eventsByOrganization: [], }, }, }, ]; -export const MOCKS_WITH_IMAGE = [ +export const ERROR_MOCKS = [ { request: { query: ORGANIZATIONS_LIST, }, - result: { - data: { - organizations: [ - { - _id: 1, - image: 'https://via.placeholder.com/200x200', - name: 'Dummy Organization', - description: 'This is a Dummy Organization', - creator: { - firstName: '', - lastName: '', - email: '', - }, - location: 'New Delhi', - members: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - email: 'johndoe@gmail.com', - }, - admins: { - _id: '123', - firstName: 'John', - lastName: 'Doe', - email: 'johndoe@gmail.com', - }, - membershipRequests: { - _id: '456', - user: { - firstName: 'Sam', - lastName: 'Smith', - email: 'samsmith@gmail.com', - }, - }, - blockedUsers: { - _id: '789', - firstName: 'Steve', - lastName: 'Smith', - email: 'stevesmith@gmail.com', - }, - spamCount: [ - { - _id: '6954', - user: { - _id: '878', - firstName: 'Joe', - lastName: 'Root', - email: 'joeroot@gmail.com', - }, - isReaded: false, - groupchat: { - _id: '321', - title: 'Dummy', - }, - }, - ], - }, - ], - }, - }, + error: new Error('Mock Graphql ORGANIZATIONS_LIST Error'), }, { request: { query: ORGANIZATION_POST_LIST, }, - result: { - data: { - postsByOrganization: [ - { - _id: 1, - title: 'Akatsuki', - text: 'Capture Jinchuriki', - imageUrl: '', - videoUrl: '', - creator: { - _id: '583', - firstName: 'John', - lastName: 'Doe', - email: 'johndoe@gmail.com', - }, - }, - ], - }, - }, + error: new Error('Mock Graphql ORGANIZATION_POST_LIST Error'), }, { request: { query: ORGANIZATION_EVENT_LIST, }, - result: { - data: { - eventsByOrganization: [ - { - _id: 1, - title: 'Event', - description: 'Event Test', - startDate: '', - endDate: '', - location: 'New Delhi', - startTime: '02:00', - endTime: '06:00', - allDay: false, - recurring: false, - isPublic: true, - isRegisterable: true, - }, - ], - }, - }, + error: new Error('Mock Graphql ORGANIZATION_EVENT_LIST Error'), }, ];