From 5587c9df08b259fc9f6ff494c242fd9bd23f3baa Mon Sep 17 00:00:00 2001 From: Akansha Sakhre Date: Wed, 5 Mar 2025 12:35:19 +0530 Subject: [PATCH] added test cases and apis --- .../GoogleIntegration/GoogleIntegration.tsx | 6 +- .../Certificates/Certificate.test.tsx | 89 +++++++++++ src/containers/Certificates/Certificate.tsx | 33 +++-- .../CertificatesList/CertificateList.tsx | 72 +++++---- src/graphql/mutations/Certificate.ts | 45 ++++++ src/graphql/queries/Certificate.ts | 37 +++++ src/mocks/Certificate.ts | 140 ++++++++++++++++++ .../AuthenticatedRoute/AuthenticatedRoute.tsx | 3 +- 8 files changed, 379 insertions(+), 46 deletions(-) create mode 100644 src/containers/Certificates/Certificate.test.tsx create mode 100644 src/graphql/mutations/Certificate.ts create mode 100644 src/graphql/queries/Certificate.ts create mode 100644 src/mocks/Certificate.ts diff --git a/src/components/UI/GoogleIntegration/GoogleIntegration.tsx b/src/components/UI/GoogleIntegration/GoogleIntegration.tsx index 4bea0bda3..53d55b794 100644 --- a/src/components/UI/GoogleIntegration/GoogleIntegration.tsx +++ b/src/components/UI/GoogleIntegration/GoogleIntegration.tsx @@ -19,7 +19,6 @@ interface GoogleIntegrationProps { listItemName: string; listItem: string; redirectionLink: string; - title: string; } const permissionOptions = [ @@ -38,7 +37,6 @@ const permissionOptions = [ ]; const GoogleIntegration = ({ - type, states, icon, formFields, @@ -53,7 +51,6 @@ const GoogleIntegration = ({ listItemName, listItem, redirectionLink, - title, }: GoogleIntegrationProps) => { const { t } = useTranslation(); @@ -70,7 +67,6 @@ const GoogleIntegration = ({ ); }; diff --git a/src/containers/Certificates/Certificate.test.tsx b/src/containers/Certificates/Certificate.test.tsx new file mode 100644 index 000000000..6fd01a861 --- /dev/null +++ b/src/containers/Certificates/Certificate.test.tsx @@ -0,0 +1,89 @@ +import { MockedProvider } from '@apollo/client/testing'; +import { CERTIFICATE_LIST_MOCKS, CERTIFICATE_MOCKS } from 'mocks/Certificate'; +import { MemoryRouter, Route, Routes } from 'react-router'; +import CertificateList from './CertificatesList/CertificateList'; +import Certificate from './Certificate'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import * as Notification from 'common/notification'; + +const wrapper = ( + + + + } /> + } /> + } /> + + + +); + +const notificationSpy = vi.spyOn(Notification, 'setNotification'); + +describe('Certificate', () => { + test('should render Certificate list', async () => { + render(wrapper); + + await waitFor(() => { + expect(screen.getByText('Certificates')).toBeInTheDocument(); + }); + }); + + test('should edit a certificate', async () => { + render(wrapper); + + await waitFor(() => { + expect(screen.getByText('Certificates')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getAllByTestId('EditIcon')[0]); + + await waitFor(() => { + expect(screen.getByText('Edit Certificate')).toBeInTheDocument(); + }); + + fireEvent.change(screen.getAllByRole('textbox')[0], { target: { value: 'new label' } }); + fireEvent.click(screen.getByText('Save')); + + await waitFor(() => { + expect(notificationSpy).toBeCalledWith('Certificate edited successfully!'); + }); + }); + + test('should create a certificate', async () => { + render(wrapper); + + await waitFor(() => { + expect(screen.getByText('Certificates')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getByTestId('newItemButton')); + + await waitFor(() => { + expect(screen.getByText('Add a new Certificate')).toBeInTheDocument(); + }); + + const inputs = screen.getAllByRole('textbox'); + + fireEvent.change(inputs[0], { target: { value: 'label' } }); + fireEvent.change(inputs[1], { target: { value: 'description' } }); + + // testing url validation + fireEvent.change(inputs[2], { target: { value: 'url' } }); + fireEvent.click(screen.getByText('Save')); + await waitFor(() => { + expect(screen.getByText('Invalid URL')).toBeInTheDocument(); + }); + fireEvent.change(inputs[2], { + target: { + value: 'https://docs.google.com/presentation/d/1fBrDFDCD2iwnaKg8sxKd45lRbqLuBFvsZbSH1sjm7aI/edit#slide=id.p', + }, + }); + + fireEvent.click(screen.getByText('Save')); + + await waitFor(() => { + expect(notificationSpy).toBeCalledWith('Certificate created successfully!'); + }); + }); +}); diff --git a/src/containers/Certificates/Certificate.tsx b/src/containers/Certificates/Certificate.tsx index 41ce17ab8..c2f744e28 100644 --- a/src/containers/Certificates/Certificate.tsx +++ b/src/containers/Certificates/Certificate.tsx @@ -1,21 +1,21 @@ import { Input } from 'components/UI/Form/Input/Input'; import GoogleIntegration from 'components/UI/GoogleIntegration/GoogleIntegration'; -import { CREATE_SHEET, DELETE_SHEET, UPDATE_SHEET } from 'graphql/mutations/Sheet'; -import { GET_SHEET } from 'graphql/queries/Sheet'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import * as Yup from 'yup'; import CertificateIcon from 'assets/images/Certificate.svg?react'; +import { GET_CERTIFICATE } from 'graphql/queries/Certificate'; +import { CREATE_CERTIFICATE, DELETE_CERTIFICATE, UPDATE_CERTIFICATE } from 'graphql/mutations/Certificate'; const regex = /^https:\/\/docs\.google\.com\/presentation\/d\/[a-zA-Z0-9_-]+(?:\/.*)?$/; const dialogMessage = "You won't be able to use this certificate again."; const icon = ; const queries = { - getItemQuery: GET_SHEET, - createItemQuery: CREATE_SHEET, - updateItemQuery: UPDATE_SHEET, - deleteItemQuery: DELETE_SHEET, + getItemQuery: GET_CERTIFICATE, + createItemQuery: CREATE_CERTIFICATE, + updateItemQuery: UPDATE_CERTIFICATE, + deleteItemQuery: DELETE_CERTIFICATE, }; const Certificate = () => { @@ -61,13 +61,24 @@ const Certificate = () => { }, ]; - const setStates = () => {}; - const setPayload = () => {}; + const setStates = ({ label: labelvalue, description: descriptionValue, url: urlValue }: any) => { + setLabel(labelvalue); + setDescription(descriptionValue); + setUrl(urlValue); + }; + const setPayload = ({ label: labelvalue, description: descriptionValue, url: urlValue }: any) => { + const payload = { + label: labelvalue, + description: descriptionValue, + url: urlValue, + }; + + return payload; + }; return ( { setStates={setStates} dialogMessage={dialogMessage} listItemName="Certificate" - listItem="certificate" - redirectionLink="custom-certificates" + listItem="certificateTemplate" + redirectionLink="certificates" icon={icon} {...queries} /> diff --git a/src/containers/Certificates/CertificatesList/CertificateList.tsx b/src/containers/Certificates/CertificatesList/CertificateList.tsx index 47d0a2bcc..f213a5069 100644 --- a/src/containers/Certificates/CertificatesList/CertificateList.tsx +++ b/src/containers/Certificates/CertificatesList/CertificateList.tsx @@ -1,34 +1,33 @@ -import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import CertificateIcon from 'assets/images/Certificate.svg?react'; -import { GET_SHEET_COUNT, GET_SHEETS } from 'graphql/queries/Sheet'; -import { DELETE_SHEET, SYNC_SHEET } from 'graphql/mutations/Sheet'; import { List } from 'containers/List/List'; import styles from './CertificateList.module.css'; import { certificatesInfo } from 'common/HelpData'; +import { COUNT_CERTIFICATES, LIST_CERTIFICATES } from 'graphql/queries/Certificate'; +import { DELETE_CERTIFICATE } from 'graphql/mutations/Certificate'; +import { copyToClipboardMethod } from 'common/utils'; +import { setNotification } from 'common/notification'; +import CopyAllOutlined from 'assets/images/icons/Flow/Copy.svg?react'; const queries = { - countQuery: GET_SHEET_COUNT, - filterItemsQuery: GET_SHEETS, - deleteItemQuery: DELETE_SHEET, + countQuery: COUNT_CERTIFICATES, + filterItemsQuery: LIST_CERTIFICATES, + deleteItemQuery: DELETE_CERTIFICATE, }; const getLabel = (label: string) =>

{label}

; -const getDescription = (label?: string) =>

Description of the Certificate

; +const getDescription = (description: string) => ( +

{description.length < 100 ? description : `${description.slice(0, 100)}...`}

+); const columnStyles = [styles.Label, styles.Description, styles.Actions]; const certificateIcon = ; -export const SheetIntegrationList = () => { +export const CertificateList = () => { const { t } = useTranslation(); - const [warnings, setWarnings] = useState({}); - const [showdialog, setShowDialog] = useState(false); - - let dialog; - const getColumns: any = ({ label, description }: any) => ({ label: getLabel(label), description: getDescription(description), @@ -44,23 +43,38 @@ export const SheetIntegrationList = () => { columnStyles, }; + const copyUuid = (_id: string, item: any) => { + if (item.id) { + copyToClipboardMethod(item.id); + } else { + setNotification('Sorry! UUID not found', 'warning'); + } + }; + + const additionalAction = () => [ + { + label: t('Copy UUID'), + icon: , + parameter: 'id', + dialog: copyUuid, + }, + ]; + return ( - <> - {dialog} - - + ); }; -export default SheetIntegrationList; +export default CertificateList; diff --git a/src/graphql/mutations/Certificate.ts b/src/graphql/mutations/Certificate.ts new file mode 100644 index 000000000..709b66beb --- /dev/null +++ b/src/graphql/mutations/Certificate.ts @@ -0,0 +1,45 @@ +import { gql } from '@apollo/client'; + +export const CREATE_CERTIFICATE = gql` + mutation CreateCertificateTemplate($input: CertificateTemplateInput!) { + createCertificateTemplate(input: $input) { + certificateTemplate { + label + id + } + errors { + key + message + } + } + } +`; + +export const UPDATE_CERTIFICATE = gql` + mutation UpdateCertificateTemplate($id: ID!, $input: CertificateTemplateInput!) { + updateCertificateTemplate(id: $id, input: $input) { + certificateTemplate { + id + label + } + errors { + message + key + } + } + } +`; + +export const DELETE_CERTIFICATE = gql` + mutation DeleteCertificateTemplate($id: ID!) { + deleteCertificateTemplate(id: $id) { + certificateTemplate { + label + } + errors { + key + message + } + } + } +`; diff --git a/src/graphql/queries/Certificate.ts b/src/graphql/queries/Certificate.ts new file mode 100644 index 000000000..6b1292f3b --- /dev/null +++ b/src/graphql/queries/Certificate.ts @@ -0,0 +1,37 @@ +import { gql } from '@apollo/client'; + +export const LIST_CERTIFICATES = gql` + query CertificateTemplates($filter: CertificateTemplateFilter, $opts: Opts) { + certificateTemplates(filter: $filter, opts: $opts) { + id + description + label + type + url + } + } +`; + +export const COUNT_CERTIFICATES = gql` + query RootQueryType($filter: CertificateTemplateFilter) { + countCertificateTemplates(filter: $filter) + } +`; + +export const GET_CERTIFICATE = gql` + query CertificateTemplate($id: ID!) { + certificateTemplate(id: $id) { + certificateTemplate { + id + label + type + url + description + } + errors { + message + key + } + } + } +`; diff --git a/src/mocks/Certificate.ts b/src/mocks/Certificate.ts new file mode 100644 index 000000000..1ef69e9b6 --- /dev/null +++ b/src/mocks/Certificate.ts @@ -0,0 +1,140 @@ +import { CREATE_CERTIFICATE, UPDATE_CERTIFICATE } from 'graphql/mutations/Certificate'; +import { COUNT_CERTIFICATES, GET_CERTIFICATE, LIST_CERTIFICATES } from 'graphql/queries/Certificate'; + +const listCertificates = { + request: { + query: LIST_CERTIFICATES, + variables: { filter: {}, opts: { limit: 50, offset: 0, order: 'ASC', orderWith: 'label' } }, + }, + result: { + data: { + certificateTemplates: [ + { + __typename: 'CertificateTemplate', + description: 'description1', + id: '1', + label: 'label 1', + type: 'SLIDES', + url: 'https://docs.google.com/presentation/d/1fBrDFDCD2iwnaKg8sxKd45lRbqLuBFvsZbSH1sjm7aI/edit#slide=id.p', + }, + { + __typename: 'CertificateTemplate', + description: 'description1', + id: '2', + label: 'label 2', + type: 'SLIDES', + url: 'https://docs.google.com/presentation/d/1fBrDFDCD2iwnaKg8sxKd45lRbqLuBFvsZbSH1sjm7aI/edit#slide=id.p', + }, + ], + }, + }, +}; + +const countCertificates = { + request: { + query: COUNT_CERTIFICATES, + variables: { filter: {} }, + }, + result: { + data: { + countCertificateTemplates: 1, + }, + }, +}; + +const getCertificate = { + request: { + query: GET_CERTIFICATE, + variables: { + id: '1', + }, + }, + result: { + data: { + certificateTemplate: { + __typename: 'CertificateTemplateResult', + certificateTemplate: { + __typename: 'CertificateTemplate', + description: 'despcription 2', + id: '1', + label: 'label 1', + type: 'SLIDES', + url: 'https://docs.google.com/presentation/d/1fBrDFDCD2iwnaKg8sxKd45lRbqLuBFvsZbSH1sjm7aI/edit#slide=id.p', + }, + errors: null, + }, + }, + }, +}; + +const createCertificate = { + request: { + query: CREATE_CERTIFICATE, + variables: { + input: { + label: 'label', + description: 'description', + url: 'https://docs.google.com/presentation/d/1fBrDFDCD2iwnaKg8sxKd45lRbqLuBFvsZbSH1sjm7aI/edit#slide=id.p', + }, + }, + }, + result: { + data: { + createCertificateTemplate: { + __typename: 'CertificateTemplateResult', + certificateTemplate: { + __typename: 'CertificateTemplate', + id: '4', + label: 'title', + }, + errors: null, + }, + }, + }, +}; + +const updateCertificate = { + request: { + query: UPDATE_CERTIFICATE, + variables: { + id: '1', + input: { + label: 'new label', + description: 'despcription 2', + url: 'https://docs.google.com/presentation/d/1fBrDFDCD2iwnaKg8sxKd45lRbqLuBFvsZbSH1sjm7aI/edit#slide=id.p', + }, + }, + }, + result: { + data: { + updateCertificateTemplate: { + __typename: 'CertificateTemplateResult', + certificateTemplate: { + __typename: 'CertificateTemplate', + id: '1', + label: 'new label', + }, + errors: null, + }, + }, + }, +}; + +const deleteCertificate = { + request: { + query: LIST_CERTIFICATES, + variables: {}, + }, + result: { + data: {}, + }, +}; + +export const CERTIFICATE_LIST_MOCKS = [ + listCertificates, + listCertificates, + countCertificates, + countCertificates, + getCertificate, +]; +export const CERTIFICATE_MOCKS = [createCertificate, updateCertificate, deleteCertificate]; diff --git a/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx b/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx index 0f0f59511..67b36a0f9 100644 --- a/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx +++ b/src/routes/AuthenticatedRoute/AuthenticatedRoute.tsx @@ -155,7 +155,8 @@ const routeAdmin = ( } /> } /> - } /> + } /> + } /> } />