diff --git a/src/style/app.module.css b/src/style/app.module.css
index 982cec9672..d21c2bb845 100644
--- a/src/style/app.module.css
+++ b/src/style/app.module.css
@@ -539,6 +539,116 @@ hr {
color: var(--bs-primary) !important;
}
+.pageNotFound {
+ position: relative;
+ bottom: 20px;
+}
+
+.pageNotFound h3 {
+ font-family: 'Roboto', sans-serif;
+ font-weight: normal;
+ letter-spacing: 1px;
+}
+
+.pageNotFound .brand span {
+ margin-top: 50px;
+ font-size: 40px;
+}
+.pageNotFound .brand h3 {
+ font-weight: 300;
+ margin: 10px 0 0 0;
+}
+.pageNotFound h1.head {
+ font-size: 250px;
+ font-weight: 900;
+ color: #31bb6b;
+ letter-spacing: 25px;
+ margin: 10px 0 0 0;
+}
+.pageNotFound h1.head span {
+ position: relative;
+ display: inline-block;
+}
+.pageNotFound h1.head span:before,
+.pageNotFound h1.head span:after {
+ position: absolute;
+ top: 50%;
+ width: 50%;
+ height: 1px;
+ background: #fff;
+ content: '';
+}
+.pageNotFound h1.head span:before {
+ left: -55%;
+}
+.pageNotFound h1.head span:after {
+ right: -55%;
+}
+
+@media (max-width: 1024px) {
+ .pageNotFound h1.head {
+ font-size: 200px;
+ letter-spacing: 25px;
+ }
+}
+
+@media (max-width: 768px) {
+ .pageNotFound h1.head {
+ font-size: 150px;
+ letter-spacing: 25px;
+ }
+}
+
+@media (max-width: 640px) {
+ .pageNotFound h1.head {
+ font-size: 150px;
+ letter-spacing: 0;
+ }
+}
+
+@media (max-width: 480px) {
+ .pageNotFound .brand h3 {
+ font-size: 20px;
+ }
+ .pageNotFound h1.head {
+ font-size: 130px;
+ letter-spacing: 0;
+ }
+ .pageNotFound h1.head span:before,
+ .pageNotFound h1.head span:after {
+ width: 40%;
+ }
+ .pageNotFound h1.head span:before {
+ left: -45%;
+ }
+ .pageNotFound h1.head span:after {
+ right: -45%;
+ }
+ .pageNotFound p {
+ font-size: 18px;
+ }
+}
+
+@media (max-width: 320px) {
+ .pageNotFound .brand h3 {
+ font-size: 16px;
+ }
+ .pageNotFound h1.head {
+ font-size: 100px;
+ letter-spacing: 0;
+ }
+ .pageNotFound h1.head span:before,
+ .pageNotFound h1.head span:after {
+ width: 25%;
+ }
+ .pageNotFound h1.head span:before {
+ left: -30%;
+ }
+ .pageNotFound h1.head span:after {
+ right: -30%;
+ }
+}
+
@media (max-width: 520px) {
.btnsContainer {
margin-bottom: 0;
From 13aad7cf5a30e62cc75a57d22acdc7ca98850d7b Mon Sep 17 00:00:00 2001
From: Bandhan Majumder <133476557+bandhan-majumder@users.noreply.github.com>
Date: Sun, 22 Dec 2024 19:28:59 +0530
Subject: [PATCH 32/57] refactor: jest to vitest of itemUpdateStatusModal :
fixes #2557 (#2714)
---
...est.tsx => ItemUpdateStatusModal.spec.tsx} | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
rename src/screens/OrganizationActionItems/{ItemUpdateStatusModal.test.tsx => ItemUpdateStatusModal.spec.tsx} (96%)
diff --git a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.test.tsx b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.spec.tsx
similarity index 96%
rename from src/screens/OrganizationActionItems/ItemUpdateStatusModal.test.tsx
rename to src/screens/OrganizationActionItems/ItemUpdateStatusModal.spec.tsx
index aa28b14d40..4d9e16d11e 100644
--- a/src/screens/OrganizationActionItems/ItemUpdateStatusModal.test.tsx
+++ b/src/screens/OrganizationActionItems/ItemUpdateStatusModal.spec.tsx
@@ -16,11 +16,12 @@ import { toast } from 'react-toastify';
import ItemUpdateStatusModal, {
type InterfaceItemUpdateStatusModalProps,
} from './ItemUpdateStatusModal';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -35,8 +36,8 @@ const t = JSON.parse(
const itemProps: InterfaceItemUpdateStatusModalProps[] = [
{
isOpen: true,
- hide: jest.fn(),
- actionItemsRefetch: jest.fn(),
+ hide: vi.fn(),
+ actionItemsRefetch: vi.fn(),
actionItem: {
_id: 'actionItemId1',
assignee: null,
@@ -75,8 +76,8 @@ const itemProps: InterfaceItemUpdateStatusModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
- actionItemsRefetch: jest.fn(),
+ hide: vi.fn(),
+ actionItemsRefetch: vi.fn(),
actionItem: {
_id: 'actionItemId1',
assignee: null,
@@ -148,8 +149,8 @@ const itemProps: InterfaceItemUpdateStatusModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
- actionItemsRefetch: jest.fn(),
+ hide: vi.fn(),
+ actionItemsRefetch: vi.fn(),
actionItem: {
_id: 'actionItemId1',
assignee: {
From ca0b0f679703324bee740a7007fda3b2a197db32 Mon Sep 17 00:00:00 2001
From: Bandhan Majumder <133476557+bandhan-majumder@users.noreply.github.com>
Date: Sun, 22 Dec 2024 19:58:26 +0530
Subject: [PATCH 33/57] refactor: jest to vitest : fixes #2557 (#2713)
---
...odal.test.tsx => ItemDeleteModal.spec.tsx} | 23 +++++++++++++------
1 file changed, 16 insertions(+), 7 deletions(-)
rename src/screens/OrganizationActionItems/{ItemDeleteModal.test.tsx => ItemDeleteModal.spec.tsx} (91%)
diff --git a/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx b/src/screens/OrganizationActionItems/ItemDeleteModal.spec.tsx
similarity index 91%
rename from src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx
rename to src/screens/OrganizationActionItems/ItemDeleteModal.spec.tsx
index fffeebfd7f..5bdb1ffde1 100644
--- a/src/screens/OrganizationActionItems/ItemDeleteModal.test.tsx
+++ b/src/screens/OrganizationActionItems/ItemDeleteModal.spec.tsx
@@ -3,7 +3,13 @@ import type { ApolloLink } from '@apollo/client';
import { MockedProvider } from '@apollo/react-testing';
import { LocalizationProvider } from '@mui/x-date-pickers';
import type { RenderResult } from '@testing-library/react';
-import { fireEvent, render, screen, waitFor } from '@testing-library/react';
+import {
+ fireEvent,
+ render,
+ screen,
+ waitFor,
+ act,
+} from '@testing-library/react';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
@@ -16,11 +22,12 @@ import { toast } from 'react-toastify';
import ItemDeleteModal, {
type InterfaceItemDeleteModalProps,
} from './ItemDeleteModal';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -34,8 +41,8 @@ const t = JSON.parse(
const itemProps: InterfaceItemDeleteModalProps = {
isOpen: true,
- hide: jest.fn(),
- actionItemsRefetch: jest.fn(),
+ hide: vi.fn(),
+ actionItemsRefetch: vi.fn(),
actionItem: {
_id: 'actionItemId1',
assignee: null,
@@ -102,7 +109,9 @@ describe('Testing ItemDeleteModal', () => {
renderItemDeleteModal(link1, itemProps);
expect(screen.getByTestId('deleteyesbtn')).toBeInTheDocument();
- fireEvent.click(screen.getByTestId('deleteyesbtn'));
+ await act(() => {
+ fireEvent.click(screen.getByTestId('deleteyesbtn'));
+ });
await waitFor(() => {
expect(itemProps.actionItemsRefetch).toHaveBeenCalled();
From ed0a01cc93e30858b2ecc8450e9ab64a2d898734 Mon Sep 17 00:00:00 2001
From: Bandhan Majumder <133476557+bandhan-majumder@users.noreply.github.com>
Date: Sun, 22 Dec 2024 19:59:16 +0530
Subject: [PATCH 34/57] Refactor: jest to vitest of itemModal : fixes #2557
(#2715)
---
...{ItemModal.test.tsx => ItemModal.spec.tsx} | 33 ++++++++++---------
1 file changed, 17 insertions(+), 16 deletions(-)
rename src/screens/OrganizationActionItems/{ItemModal.test.tsx => ItemModal.spec.tsx} (98%)
diff --git a/src/screens/OrganizationActionItems/ItemModal.test.tsx b/src/screens/OrganizationActionItems/ItemModal.spec.tsx
similarity index 98%
rename from src/screens/OrganizationActionItems/ItemModal.test.tsx
rename to src/screens/OrganizationActionItems/ItemModal.spec.tsx
index a58496e6df..1fe3d6fca5 100644
--- a/src/screens/OrganizationActionItems/ItemModal.test.tsx
+++ b/src/screens/OrganizationActionItems/ItemModal.spec.tsx
@@ -21,12 +21,13 @@ import { StaticMockLink } from 'utils/StaticMockLink';
import { toast } from 'react-toastify';
import type { InterfaceItemModalProps } from './ItemModal';
import ItemModal from './ItemModal';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
- warning: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
+ warning: vi.fn(),
},
}));
@@ -45,28 +46,28 @@ const t = {
const itemProps: InterfaceItemModalProps[] = [
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
orgId: 'orgId',
eventId: undefined,
- actionItemsRefetch: jest.fn(),
+ actionItemsRefetch: vi.fn(),
editMode: false,
actionItem: null,
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
orgId: 'orgId',
eventId: 'eventId',
- actionItemsRefetch: jest.fn(),
+ actionItemsRefetch: vi.fn(),
editMode: false,
actionItem: null,
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
orgId: 'orgId',
eventId: undefined,
- actionItemsRefetch: jest.fn(),
+ actionItemsRefetch: vi.fn(),
editMode: true,
actionItem: {
_id: 'actionItemId1',
@@ -106,10 +107,10 @@ const itemProps: InterfaceItemModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
orgId: 'orgId',
eventId: undefined,
- actionItemsRefetch: jest.fn(),
+ actionItemsRefetch: vi.fn(),
editMode: true,
actionItem: {
_id: 'actionItemId2',
@@ -149,10 +150,10 @@ const itemProps: InterfaceItemModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
orgId: 'orgId',
eventId: 'eventId',
- actionItemsRefetch: jest.fn(),
+ actionItemsRefetch: vi.fn(),
editMode: true,
actionItem: {
_id: 'actionItemId2',
@@ -202,10 +203,10 @@ const itemProps: InterfaceItemModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
orgId: 'orgId',
eventId: 'eventId',
- actionItemsRefetch: jest.fn(),
+ actionItemsRefetch: vi.fn(),
editMode: true,
actionItem: {
_id: 'actionItemId2',
From e2a86ae4773ade0d0cb835167bb5f905a1a2d6b6 Mon Sep 17 00:00:00 2001
From: Bandhan Majumder <133476557+bandhan-majumder@users.noreply.github.com>
Date: Sun, 22 Dec 2024 19:59:59 +0530
Subject: [PATCH 35/57] refactor: jest to vitest of itemViewModal : fixes #2557
(#2716)
* refactor: jest to vitest of itemViewModal : fixes #2557
* Update ItemViewModal.spec.tsx
---
...iewModal.test.tsx => ItemViewModal.spec.tsx} | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
rename src/screens/OrganizationActionItems/{ItemViewModal.test.tsx => ItemViewModal.spec.tsx} (97%)
diff --git a/src/screens/OrganizationActionItems/ItemViewModal.test.tsx b/src/screens/OrganizationActionItems/ItemViewModal.spec.tsx
similarity index 97%
rename from src/screens/OrganizationActionItems/ItemViewModal.test.tsx
rename to src/screens/OrganizationActionItems/ItemViewModal.spec.tsx
index 297cfab6a8..b6423e356d 100644
--- a/src/screens/OrganizationActionItems/ItemViewModal.test.tsx
+++ b/src/screens/OrganizationActionItems/ItemViewModal.spec.tsx
@@ -18,11 +18,12 @@ import type {
InterfaceUserInfo,
InterfaceVolunteerGroupInfo,
} from 'utils/interfaces';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -86,7 +87,7 @@ const actionItemCategory = {
const itemProps: InterfaceViewModalProps[] = [
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
item: {
_id: 'actionItemId1',
assignee: createAssignee(assigneeWithoutImage),
@@ -108,7 +109,7 @@ const itemProps: InterfaceViewModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
item: {
_id: 'actionItemId2',
assignee: createAssignee(assigneeWithImage),
@@ -130,7 +131,7 @@ const itemProps: InterfaceViewModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
item: {
_id: 'actionItemId2',
assignee: null,
@@ -152,7 +153,7 @@ const itemProps: InterfaceViewModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
item: {
_id: 'actionItemId2',
assignee: null,
@@ -174,7 +175,7 @@ const itemProps: InterfaceViewModalProps[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
item: {
_id: 'actionItemId2',
assignee: null,
From 84c167cf4b9f8b846f1bab04e65f9e2db62eb63c Mon Sep 17 00:00:00 2001
From: Shiva <148421597+shivasankaran18@users.noreply.github.com>
Date: Sun, 22 Dec 2024 20:05:12 +0530
Subject: [PATCH 36/57] Refactor : Vitest to EventVolunteers/VolunteerGroups
Screen (#2696)
* refactor:vitest to EventVolunteers/VolunteerGroups screen
* add:ts-doc
* fix:codereabbit sugg
---------
Co-authored-by: Peter Harrison <16875803+palisadoes@users.noreply.github.com>
---
...tsx => VolunteerGroupDeleteModal.spec.tsx} | 17 +++++++---
....test.tsx => VolunteerGroupModal.spec.tsx} | 25 +++++++++-----
...t.tsx => VolunteerGroupViewModal.spec.tsx} | 5 +--
...oups.test.tsx => VolunteerGroups.spec.tsx} | 34 +++++++++++++++----
4 files changed, 59 insertions(+), 22 deletions(-)
rename src/screens/EventVolunteers/VolunteerGroups/{VolunteerGroupDeleteModal.test.tsx => VolunteerGroupDeleteModal.spec.tsx} (92%)
rename src/screens/EventVolunteers/VolunteerGroups/{VolunteerGroupModal.test.tsx => VolunteerGroupModal.spec.tsx} (96%)
rename src/screens/EventVolunteers/VolunteerGroups/{VolunteerGroupViewModal.test.tsx => VolunteerGroupViewModal.spec.tsx} (98%)
rename src/screens/EventVolunteers/VolunteerGroups/{VolunteerGroups.test.tsx => VolunteerGroups.spec.tsx} (89%)
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.spec.tsx
similarity index 92%
rename from src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.test.tsx
rename to src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.spec.tsx
index 05c2dab5ff..8e726028db 100644
--- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.test.tsx
+++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.spec.tsx
@@ -16,11 +16,18 @@ import { toast } from 'react-toastify';
import type { InterfaceDeleteVolunteerGroupModal } from './VolunteerGroupDeleteModal';
import VolunteerGroupDeleteModal from './VolunteerGroupDeleteModal';
import userEvent from '@testing-library/user-event';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+/**
+ * Mock implementation of the `react-toastify` module.
+ * Mocks the `toast` object with `success` and `error` methods to allow testing
+ * without triggering actual toast notifications.
+ */
+
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -39,8 +46,8 @@ const t = {
const itemProps: InterfaceDeleteVolunteerGroupModal[] = [
{
isOpen: true,
- hide: jest.fn(),
- refetchGroups: jest.fn(),
+ hide: vi.fn(),
+ refetchGroups: vi.fn(),
group: {
_id: 'groupId',
name: 'Group 1',
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.spec.tsx
similarity index 96%
rename from src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.test.tsx
rename to src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.spec.tsx
index 2fc0b2e348..79b1d94545 100644
--- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.test.tsx
+++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.spec.tsx
@@ -22,11 +22,18 @@ import { toast } from 'react-toastify';
import type { InterfaceVolunteerGroupModal } from './VolunteerGroupModal';
import GroupModal from './VolunteerGroupModal';
import userEvent from '@testing-library/user-event';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+/**
+ * Mock implementation of the `react-toastify` module.
+ * Mocks the `toast` object with `success` and `error` methods to allow testing
+ * without triggering actual toast notifications.
+ */
+
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -45,19 +52,19 @@ const t = {
const itemProps: InterfaceVolunteerGroupModal[] = [
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
eventId: 'eventId',
orgId: 'orgId',
- refetchGroups: jest.fn(),
+ refetchGroups: vi.fn(),
mode: 'create',
group: null,
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
eventId: 'eventId',
orgId: 'orgId',
- refetchGroups: jest.fn(),
+ refetchGroups: vi.fn(),
mode: 'edit',
group: {
_id: 'groupId',
@@ -96,10 +103,10 @@ const itemProps: InterfaceVolunteerGroupModal[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
eventId: 'eventId',
orgId: 'orgId',
- refetchGroups: jest.fn(),
+ refetchGroups: vi.fn(),
mode: 'edit',
group: {
_id: 'groupId',
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.spec.tsx
similarity index 98%
rename from src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.test.tsx
rename to src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.spec.tsx
index 94c34923a2..b029909809 100644
--- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.test.tsx
+++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.spec.tsx
@@ -11,6 +11,7 @@ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import i18n from 'utils/i18nForTest';
import type { InterfaceVolunteerGroupViewModal } from './VolunteerGroupViewModal';
import VolunteerGroupViewModal from './VolunteerGroupViewModal';
+import { vi } from 'vitest';
const t = {
...JSON.parse(
@@ -25,7 +26,7 @@ const t = {
const itemProps: InterfaceVolunteerGroupViewModal[] = [
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
group: {
_id: 'groupId',
name: 'Group 1',
@@ -63,7 +64,7 @@ const itemProps: InterfaceVolunteerGroupViewModal[] = [
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
group: {
_id: 'groupId',
name: 'Group 1',
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.spec.tsx
similarity index 89%
rename from src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx
rename to src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.spec.tsx
index 0dcba34a3a..2ce6e6a9dd 100644
--- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.test.tsx
+++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroups.spec.tsx
@@ -7,13 +7,14 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
-import { MemoryRouter, Route, Routes } from 'react-router-dom';
+import { MemoryRouter, Route, Routes, useParams } from 'react-router-dom';
import { store } from 'state/store';
import { StaticMockLink } from 'utils/StaticMockLink';
import i18n from 'utils/i18nForTest';
import VolunteerGroups from './VolunteerGroups';
import type { ApolloLink } from '@apollo/client';
import { MOCKS, MOCKS_EMPTY, MOCKS_ERROR } from './VolunteerGroups.mocks';
+import { vi } from 'vitest';
const link1 = new StaticMockLink(MOCKS);
const link2 = new StaticMockLink(MOCKS_ERROR);
@@ -61,19 +62,30 @@ const renderVolunteerGroups = (link: ApolloLink): RenderResult => {
);
};
+/** Mock useParams to provide consistent test data */
+
describe('Testing VolunteerGroups Screen', () => {
beforeAll(() => {
- jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({ orgId: 'orgId', eventId: 'eventId' }),
- }));
+ vi.mock('react-router-dom', async () => {
+ const actualDom = await vi.importActual('react-router-dom');
+ return {
+ ...actualDom,
+ useParams: vi.fn(),
+ };
+ });
});
afterAll(() => {
- jest.clearAllMocks();
+ vi.clearAllMocks();
});
+ const mockRouteParams = (orgId = 'orgId', eventId = 'eventId'): void => {
+ vi.mocked(useParams).mockReturnValue({ orgId, eventId });
+ };
+
it('should redirect to fallback URL if URL params are undefined', async () => {
+ /** Mocking the useParams hook to return undefined parameters */
+ mockRouteParams('', '');
render(
@@ -98,12 +110,14 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('should render Groups screen', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const searchInput = await screen.findByTestId('searchBy');
expect(searchInput).toBeInTheDocument();
});
it('Check Sorting Functionality', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const searchInput = await screen.findByTestId('searchBy');
expect(searchInput).toBeInTheDocument();
@@ -133,6 +147,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('Search by Groups', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const searchInput = await screen.findByTestId('searchBy');
expect(searchInput).toBeInTheDocument();
@@ -153,6 +168,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('Search by Leader', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const searchInput = await screen.findByTestId('searchBy');
expect(searchInput).toBeInTheDocument();
@@ -174,6 +190,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('should render screen with No Groups', async () => {
+ mockRouteParams();
renderVolunteerGroups(link3);
await waitFor(() => {
@@ -183,6 +200,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('Error while fetching groups data', async () => {
+ mockRouteParams();
renderVolunteerGroups(link2);
await waitFor(() => {
@@ -191,6 +209,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('Open and close ViewModal', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const viewGroupBtn = await screen.findAllByTestId('viewGroupBtn');
@@ -201,6 +220,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('Open and Close Delete Modal', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const deleteGroupBtn = await screen.findAllByTestId('deleteGroupBtn');
@@ -211,6 +231,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('Open and close GroupModal (Edit)', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const editGroupBtn = await screen.findAllByTestId('editGroupBtn');
@@ -221,6 +242,7 @@ describe('Testing VolunteerGroups Screen', () => {
});
it('Open and close GroupModal (Create)', async () => {
+ mockRouteParams();
renderVolunteerGroups(link1);
const createGroupBtn = await screen.findByTestId('createGroupBtn');
From 3d6b6bc778b51f182cb56abba6179fe850d0d38f Mon Sep 17 00:00:00 2001
From: Gurram Karthik <167804249+gurramkarthiknetha@users.noreply.github.com>
Date: Sun, 22 Dec 2024 20:10:49 +0530
Subject: [PATCH 37/57] fixed #2505 :Refactor CSS Structure for
EventVolunteers: Improved Maintainability and UI Consistency (#2675)
* fixed-2505
* changed acc to bot
* changed acc to coderabbin
* removed due to conflicts
* final change
* resloved conflict
* changed some file to improve the codecov
* improved time
* deleted file
* changed some path
* changed acc to code rabbin
* updated
* changed acc to code rabbin
* fixed-time
* decreased the time
---
.../OrganizationScreen.test.tsx | 1 +
.../EventVolunteers.module.css | 266 ------------------
.../EventVolunteers/Requests/Requests.tsx | 22 +-
.../EventVolunteers/VolunteerContainer.tsx | 2 +-
.../VolunteerGroupDeleteModal.tsx | 2 +-
.../VolunteerGroups/VolunteerGroupModal.tsx | 2 +-
.../VolunteerGroupViewModal.tsx | 10 +-
.../VolunteerGroups/VolunteerGroups.tsx | 26 +-
.../Volunteers/VolunteerCreateModal.tsx | 2 +-
.../Volunteers/VolunteerDeleteModal.tsx | 2 +-
.../Volunteers/VolunteerViewModal.tsx | 6 +-
.../EventVolunteers/Volunteers/Volunteers.tsx | 26 +-
.../Volunteer/Groups/GroupModal.tsx | 2 +-
.../UserPortal/Volunteer/Groups/Groups.tsx | 2 +-
src/setupTests.ts | 2 +-
src/style/app.module.css | 182 ++++++++++++
16 files changed, 236 insertions(+), 319 deletions(-)
delete mode 100644 src/screens/EventVolunteers/EventVolunteers.module.css
diff --git a/src/components/OrganizationScreen/OrganizationScreen.test.tsx b/src/components/OrganizationScreen/OrganizationScreen.test.tsx
index 9bb95bbd4a..d1c4c81c27 100644
--- a/src/components/OrganizationScreen/OrganizationScreen.test.tsx
+++ b/src/components/OrganizationScreen/OrganizationScreen.test.tsx
@@ -85,6 +85,7 @@ describe('Testing OrganizationScreen', () => {
const openButton = screen.getByTestId('openMenu');
fireEvent.click(openButton);
+ // Check for expand class after opening
expect(screen.getByTestId('mainpageright')).toHaveClass(styles.contract);
});
diff --git a/src/screens/EventVolunteers/EventVolunteers.module.css b/src/screens/EventVolunteers/EventVolunteers.module.css
deleted file mode 100644
index 84b19f0a9f..0000000000
--- a/src/screens/EventVolunteers/EventVolunteers.module.css
+++ /dev/null
@@ -1,266 +0,0 @@
-/* Toggle Btn */
-.toggleGroup {
- width: 50%;
- min-width: 20rem;
- margin: 0.5rem 0rem;
-}
-
-.toggleBtn {
- padding: 0rem;
- height: 2rem;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
-.toggleBtn:hover {
- color: #31bb6b !important;
-}
-
-input[type='radio']:checked + label {
- background-color: #31bb6a50 !important;
-}
-
-input[type='radio']:checked + label:hover {
- color: black !important;
-}
-
-.actionItemsContainer {
- height: 90vh;
-}
-
-.actionItemModal {
- max-width: 80vw;
- margin-top: 2vh;
- margin-left: 13vw;
-}
-
-.datediv {
- display: flex;
- flex-direction: row;
-}
-
-.datebox {
- width: 90%;
- border-radius: 7px;
- outline: none;
- box-shadow: none;
- padding-top: 2px;
- padding-bottom: 2px;
- padding-right: 5px;
- padding-left: 5px;
- margin-right: 5px;
- margin-left: 5px;
-}
-
-.dropdownToggle {
- margin-bottom: 0;
- display: flex;
-}
-
-.dropdownModalToggle {
- width: 50%;
-}
-
-.errorIcon {
- transform: scale(1.5);
- color: var(--bs-danger);
- margin-bottom: 1rem;
-}
-
-.greenregbtn {
- margin: 1rem 0 0;
- margin-top: 15px;
- border: 1px solid var(--bs-gray-300);
- box-shadow: 0 2px 2px var(--bs-gray-300);
- padding: 10px 10px;
- border-radius: 5px;
- background-color: var(--bs-primary);
- width: 100%;
- font-size: 16px;
- color: var(--bs-white);
- outline: none;
- font-weight: 600;
- cursor: pointer;
- transition:
- transform 0.2s,
- box-shadow 0.2s;
- width: 100%;
-}
-
-hr {
- border: none;
- height: 1px;
- background-color: var(--bs-gray-500);
- margin: 1rem;
-}
-
-.iconContainer {
- display: flex;
- justify-content: flex-end;
-}
-.icon {
- margin: 1px;
-}
-
-.message {
- margin-top: 25%;
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
-}
-
-.preview {
- display: flex;
- flex-direction: row;
- font-weight: 900;
- font-size: 16px;
- color: rgb(80, 80, 80);
-}
-
-.removeFilterIcon {
- cursor: pointer;
-}
-
-.searchForm {
- display: inline;
-}
-
-.view {
- margin-left: 2%;
- font-weight: 600;
- font-size: 16px;
- color: var(--bs-gray-600);
-}
-
-/* header (search, filter, dropdown) */
-.btnsContainer {
- display: flex;
- margin: 0.5rem 0 1.5rem 0;
-}
-
-.btnsContainer .input {
- flex: 1;
- min-width: 18rem;
- position: relative;
-}
-
-.btnsContainer input {
- outline: 1px solid var(--bs-gray-400);
-}
-
-.btnsContainer .input button {
- width: 52px;
-}
-
-.noOutline input {
- outline: none;
-}
-
-.noOutline input:disabled {
- -webkit-text-fill-color: black !important;
-}
-
-.noOutline textarea:disabled {
- -webkit-text-fill-color: black !important;
-}
-
-.inputField {
- margin-top: 10px;
- margin-bottom: 10px;
- background-color: white;
- box-shadow: 0 1px 1px #31bb6b;
-}
-
-.inputField > button {
- padding-top: 10px;
- padding-bottom: 10px;
-}
-
-.dropdown {
- background-color: white;
- border: 1px solid #31bb6b;
- position: relative;
- display: inline-block;
- color: #31bb6b;
-}
-
-/* Action Items Data Grid */
-.rowBackground {
- background-color: var(--bs-white);
- max-height: 120px;
-}
-
-.tableHeader {
- background-color: var(--bs-primary);
- color: var(--bs-white);
- font-size: 1rem;
-}
-
-.chipIcon {
- height: 0.9rem !important;
-}
-
-.chip {
- height: 1.5rem !important;
-}
-
-.active {
- background-color: #31bb6a50 !important;
-}
-
-.pending {
- background-color: #ffd76950 !important;
- color: #bb952bd0 !important;
- border-color: #bb952bd0 !important;
-}
-
-/* Modals */
-.itemModal {
- max-width: 80vw;
- margin-top: 2vh;
- margin-left: 13vw;
-}
-
-.titlemodal {
- color: #707070;
- font-weight: 600;
- font-size: 32px;
- width: 65%;
- margin-bottom: 0px;
-}
-
-.modalCloseBtn {
- width: 40px;
- height: 40px;
- padding: 1rem;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
-.imageContainer {
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 0.5rem;
-}
-
-.TableImage {
- object-fit: cover;
- width: 25px !important;
- height: 25px !important;
- border-radius: 100% !important;
-}
-
-.avatarContainer {
- width: 28px;
- height: 26px;
-}
-
-/* Modal Table (Groups & Assignments) */
-.modalTable {
- max-height: 220px;
- overflow-y: auto;
-}
diff --git a/src/screens/EventVolunteers/Requests/Requests.tsx b/src/screens/EventVolunteers/Requests/Requests.tsx
index 41abcad763..b19be3d2a0 100644
--- a/src/screens/EventVolunteers/Requests/Requests.tsx
+++ b/src/screens/EventVolunteers/Requests/Requests.tsx
@@ -13,7 +13,7 @@ import {
type GridColDef,
} from '@mui/x-data-grid';
import Avatar from 'components/Avatar/Avatar';
-import styles from '../EventVolunteers.module.css';
+import styles from '../../../style/app.module.css';
import { USER_VOLUNTEER_MEMBERSHIP } from 'GraphQl/Queries/EventVolunteerQueries';
import type { InterfaceVolunteerMembership } from 'utils/interfaces';
import dayjs from 'dayjs';
@@ -154,7 +154,7 @@ function requests(): JSX.Element {
align: 'center',
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
return params.row.id;
},
@@ -167,7 +167,7 @@ function requests(): JSX.Element {
minWidth: 100,
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
const { firstName, lastName, image } = params.row.volunteer.user;
return (
@@ -180,14 +180,14 @@ function requests(): JSX.Element {
src={image}
alt="volunteer"
data-testid={`volunteer_image`}
- className={styles.TableImage}
+ className={styles.TableImages}
/>
) : (
@@ -205,7 +205,7 @@ function requests(): JSX.Element {
minWidth: 150,
align: 'center',
headerAlign: 'center',
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
sortable: false,
renderCell: (params: GridCellParams) => {
return dayjs(params.row.createdAt).format('DD/MM/YYYY');
@@ -219,7 +219,7 @@ function requests(): JSX.Element {
minWidth: 100,
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
return (
<>
@@ -251,7 +251,7 @@ function requests(): JSX.Element {
return (
{/* Header with search, filter and Create Button */}
-
+
{
setSearchValue(e.target.value);
@@ -282,7 +282,7 @@ function requests(): JSX.Element {
@@ -316,7 +316,7 @@ function requests(): JSX.Element {
hideFooter={true}
getRowId={(row) => row._id}
sx={dataGridStyle}
- getRowClassName={() => `${styles.rowBackground}`}
+ getRowClassName={() => `${styles.rowBackgrounds}`}
autoHeight
rowHeight={65}
rows={requests.map((request, index) => ({
diff --git a/src/screens/EventVolunteers/VolunteerContainer.tsx b/src/screens/EventVolunteers/VolunteerContainer.tsx
index 1a425a706e..e026c6f7c8 100644
--- a/src/screens/EventVolunteers/VolunteerContainer.tsx
+++ b/src/screens/EventVolunteers/VolunteerContainer.tsx
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Navigate, useParams } from 'react-router-dom';
-import styles from './EventVolunteers.module.css';
+import styles from '../../style/app.module.css';
import { HiUserGroup, HiUser } from 'react-icons/hi2';
import Volunteers from './Volunteers/Volunteers';
import VolunteerGroups from './VolunteerGroups/VolunteerGroups';
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx
index 33132bfd33..89c788e220 100644
--- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx
+++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupDeleteModal.tsx
@@ -1,5 +1,5 @@
import { Button, Modal } from 'react-bootstrap';
-import styles from '../EventVolunteers.module.css';
+import styles from '../../../style/app.module.css';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation } from '@apollo/client';
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx
index 5bfb1eff2b..e36ecaa0bd 100644
--- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx
+++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupModal.tsx
@@ -5,7 +5,7 @@ import type {
InterfaceUserInfo,
InterfaceVolunteerGroupInfo,
} from 'utils/interfaces';
-import styles from '../EventVolunteers.module.css';
+import styles from '../../../style/app.module.css';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQuery } from '@apollo/client';
diff --git a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx
index 70994bd4e5..5fb090649f 100644
--- a/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx
+++ b/src/screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal.tsx
@@ -1,6 +1,6 @@
import { Button, Form, Modal } from 'react-bootstrap';
import type { InterfaceVolunteerGroupInfo } from 'utils/interfaces';
-import styles from '../EventVolunteers.module.css';
+import styles from '../../../style/app.module.css';
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
@@ -123,14 +123,14 @@ const VolunteerGroupViewModal: React.FC = ({
src={leader.image}
alt="Volunteer"
data-testid="leader_image"
- className={styles.TableImage}
+ className={styles.TableImages}
/>
) : (
= ({
src={creator.image}
alt="Volunteer"
data-testid="creator_image"
- className={styles.TableImage}
+ className={styles.TableImages}
/>
) : (
{
return (
{
const { _id, firstName, lastName, image } = params.row.leader;
return (
@@ -194,14 +194,14 @@ function volunteerGroups(): JSX.Element {
src={image}
alt="Assignee"
data-testid={`image${_id + 1}`}
- className={styles.TableImage}
+ className={styles.TableImages}
/>
) : (
@@ -219,7 +219,7 @@ function volunteerGroups(): JSX.Element {
align: 'center',
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
return (
@@ -235,7 +235,7 @@ function volunteerGroups(): JSX.Element {
align: 'center',
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
return (
@@ -252,7 +252,7 @@ function volunteerGroups(): JSX.Element {
minWidth: 100,
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
return (
<>
@@ -293,7 +293,7 @@ function volunteerGroups(): JSX.Element {
return (
{/* Header with search, filter and Create Button */}
-
+
{
setSearchValue(e.target.value);
@@ -325,7 +325,7 @@ function volunteerGroups(): JSX.Element {
@@ -350,7 +350,7 @@ function volunteerGroups(): JSX.Element {
@@ -400,7 +400,7 @@ function volunteerGroups(): JSX.Element {
),
}}
sx={dataGridStyle}
- getRowClassName={() => `${styles.rowBackground}`}
+ getRowClassName={() => `${styles.rowBackgrounds}`}
autoHeight
rowHeight={65}
rows={groups.map((group, index) => ({
diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx
index 6b4a1e3f0c..dee45376db 100644
--- a/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx
+++ b/src/screens/EventVolunteers/Volunteers/VolunteerCreateModal.tsx
@@ -1,7 +1,7 @@
import type { ChangeEvent } from 'react';
import { Button, Form, Modal } from 'react-bootstrap';
import type { InterfaceUserInfo } from 'utils/interfaces';
-import styles from '../EventVolunteers.module.css';
+import styles from '../../../style/app.module.css';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQuery } from '@apollo/client';
diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx
index 8f253fdf50..5c841a2f11 100644
--- a/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx
+++ b/src/screens/EventVolunteers/Volunteers/VolunteerDeleteModal.tsx
@@ -1,5 +1,5 @@
import { Button, Modal } from 'react-bootstrap';
-import styles from '../EventVolunteers.module.css';
+import styles from '../../../style/app.module.css';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation } from '@apollo/client';
diff --git a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx
index 0904d34b9c..830bacf8cc 100644
--- a/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx
+++ b/src/screens/EventVolunteers/Volunteers/VolunteerViewModal.tsx
@@ -1,6 +1,6 @@
import { Button, Form, Modal } from 'react-bootstrap';
import type { InterfaceEventVolunteerInfo } from 'utils/interfaces';
-import styles from '../EventVolunteers.module.css';
+import styles from '../../../style/app.module.css';
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
@@ -83,14 +83,14 @@ const VolunteerViewModal: React.FC = ({
src={user.image}
alt="Volunteer"
data-testid="volunteer_image"
- className={styles.TableImage}
+ className={styles.TableImages}
/>
) : (
{
const { _id, firstName, lastName, image } = params.row.user;
return (
@@ -192,7 +192,7 @@ function volunteers(): JSX.Element {
src={image}
alt="volunteer"
data-testid="volunteer_image"
- className={styles.TableImage}
+ className={styles.TableImages}
/>
) : (
@@ -200,7 +200,7 @@ function volunteers(): JSX.Element {
key={_id + '1'}
dataTestId="volunteer_avatar"
containerStyle={styles.imageContainer}
- avatarStyle={styles.TableImage}
+ avatarStyle={styles.TableImages}
name={firstName + ' ' + lastName}
alt={firstName + ' ' + lastName}
/>
@@ -219,7 +219,7 @@ function volunteers(): JSX.Element {
minWidth: 100,
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
return (
{
return (
{
return (
@@ -278,7 +278,7 @@ function volunteers(): JSX.Element {
minWidth: 100,
headerAlign: 'center',
sortable: false,
- headerClassName: `${styles.tableHeader}`,
+ headerClassName: `${styles.tableHeaders}`,
renderCell: (params: GridCellParams) => {
return (
<>
@@ -310,7 +310,7 @@ function volunteers(): JSX.Element {
return (
{/* Header with search, filter and Create Button */}
-
+
{
setSearchValue(e.target.value);
@@ -341,7 +341,7 @@ function volunteers(): JSX.Element {
@@ -365,7 +365,7 @@ function volunteers(): JSX.Element {
@@ -421,7 +421,7 @@ function volunteers(): JSX.Element {
),
}}
sx={dataGridStyle}
- getRowClassName={() => `${styles.rowBackground}`}
+ getRowClassName={() => `${styles.rowBackgrounds}`}
autoHeight
rowHeight={65}
rows={volunteers.map((volunteer, index) => ({
diff --git a/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx
index 4ae162cd70..27f461b462 100644
--- a/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx
+++ b/src/screens/UserPortal/Volunteer/Groups/GroupModal.tsx
@@ -5,7 +5,7 @@ import type {
InterfaceVolunteerGroupInfo,
InterfaceVolunteerMembership,
} from 'utils/interfaces';
-import styles from 'screens/EventVolunteers/EventVolunteers.module.css';
+import styles from 'style/app.module.css';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQuery } from '@apollo/client';
diff --git a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx
index 3941f461d5..160dc0b23a 100644
--- a/src/screens/UserPortal/Volunteer/Groups/Groups.tsx
+++ b/src/screens/UserPortal/Volunteer/Groups/Groups.tsx
@@ -16,7 +16,7 @@ import {
} from '@mui/x-data-grid';
import { debounce, Stack } from '@mui/material';
import Avatar from 'components/Avatar/Avatar';
-import styles from 'screens/EventVolunteers/EventVolunteers.module.css';
+import styles from '../../../../style/app.module.css';
import { EVENT_VOLUNTEER_GROUP_LIST } from 'GraphQl/Queries/EventVolunteerQueries';
import VolunteerGroupViewModal from 'screens/EventVolunteers/VolunteerGroups/VolunteerGroupViewModal';
import useLocalStorage from 'utils/useLocalstorage';
diff --git a/src/setupTests.ts b/src/setupTests.ts
index eac7093309..f0b48b39d0 100644
--- a/src/setupTests.ts
+++ b/src/setupTests.ts
@@ -32,4 +32,4 @@ jestPreviewConfigure({
autoPreview: true,
});
-jest.setTimeout(15000);
+jest.setTimeout(17000);
diff --git a/src/style/app.module.css b/src/style/app.module.css
index d21c2bb845..365b00556b 100644
--- a/src/style/app.module.css
+++ b/src/style/app.module.css
@@ -868,3 +868,185 @@ hr {
max-height: calc(100vh - 18rem);
overflow: auto;
}
+
+#individualRadio,
+#requestsRadio,
+#groupsRadio,
+.toggleBtn:hover {
+ color: var(--brand-primary) !important;
+}
+
+input[type='radio']:checked + label {
+ background-color: var(--brand-primary-light) !important;
+}
+
+.dropdownToggle {
+ margin-bottom: 0;
+ display: flex;
+}
+
+.dropdownModalToggle {
+ width: 50%;
+}
+
+.greenregbtn {
+ margin-top: 1rem;
+ border: 1px solid var(--bs-gray-300);
+ box-shadow: 0 2px 2px var(--bs-gray-300);
+ padding: 10px 10px;
+ border-radius: 5px;
+ background-color: var(--bs-primary);
+ width: 100%;
+ font-size: 16px;
+ color: var(--bs-white);
+ outline: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition:
+ transform 0.2s,
+ box-shadow 0.2s;
+}
+
+.removeFilterIcon {
+ cursor: pointer;
+}
+
+.searchForm {
+ display: inline;
+}
+
+.view {
+ margin-left: 2%;
+ font-weight: 600;
+ font-size: 16px;
+ color: var(--bs-gray-600);
+}
+
+/* header (search, filter, dropdown) */
+.btncon .btnsContainer {
+ display: flex;
+ margin: 0.5rem 0 1.5rem 0;
+}
+
+.btncon .btnsContainer .input {
+ flex: 1;
+ min-width: 18rem;
+ position: relative;
+}
+
+.btncon .btnsContainer input {
+ outline: 1px solid var(--bs-gray-400);
+}
+
+.btncon .btnsContainer .input button {
+ width: 52px;
+}
+
+.noOutline input:disabled {
+ -webkit-text-fill-color: black !important;
+}
+
+.noOutline textarea:disabled {
+ color: var(--bs-black) !important;
+ opacity: 1;
+}
+
+.inputField {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ background-color: white;
+ box-shadow: 0 1px 1px var(--brand-primary);
+}
+
+.inputField > button {
+ padding-top: 10px;
+ padding-bottom: 10px;
+}
+
+.dropdowns {
+ background-color: white;
+ border: 1px solid #31bb6b;
+ position: relative;
+ display: inline-block;
+ color: #31bb6b;
+}
+
+/* Action Items Data Grid */
+.rowBackgrounds {
+ background-color: var(--bs-white);
+ max-height: 120px;
+}
+
+.tableHeaders {
+ background-color: var(--bs-primary);
+ color: var(--bs-white);
+ font-size: 1rem;
+}
+
+.chipIcon {
+ height: 0.9rem !important;
+}
+
+.chip {
+ height: 1.5rem !important;
+}
+
+.active {
+ background-color: var(--status-active-bg);
+}
+
+.pending {
+ background-color: var(--status-pending-bg);
+ color: var(--status-pending-text);
+ border-color: var(--status-pending-border);
+}
+
+/* Modals */
+.itemModal {
+ max-width: 80vw;
+ margin-top: 2vh;
+ margin-left: 13vw;
+}
+
+.titlemodal {
+ color: #707070;
+ font-weight: 600;
+ font-size: 32px;
+ width: 65%;
+ margin-bottom: 0px;
+}
+
+.modalCloseBtn {
+ width: 40px;
+ height: 40px;
+ padding: 1rem;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.imageContainer {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 0.5rem;
+}
+
+.TableImages {
+ object-fit: cover;
+ width: var(--image-width, 100%);
+ height: var(--image-height, auto);
+ border-radius: 0;
+ margin-right: var(--image-spacing, 8px);
+}
+
+.avatarContainer {
+ width: 28px;
+ height: 26px;
+}
+
+/* Modal Table (Groups & Assignments) */
+.modalTable {
+ max-height: 220px;
+ overflow-y: auto;
+}
From 139e9854a3b37079fa09d8e6a4cec53cc6883e4c Mon Sep 17 00:00:00 2001
From: Abhishek Raj <113784630+abbi4code@users.noreply.github.com>
Date: Sun, 22 Dec 2024 20:15:55 +0530
Subject: [PATCH 38/57] chore: migrated checkinwrapper tests jest to vitest
(#2709)
---
...InWrapper.test.tsx => CheckInWrapper.spec.tsx} | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
rename src/components/CheckIn/{CheckInWrapper.test.tsx => CheckInWrapper.spec.tsx} (76%)
diff --git a/src/components/CheckIn/CheckInWrapper.test.tsx b/src/components/CheckIn/CheckInWrapper.spec.tsx
similarity index 76%
rename from src/components/CheckIn/CheckInWrapper.test.tsx
rename to src/components/CheckIn/CheckInWrapper.spec.tsx
index 81f53d0043..06b2695f88 100644
--- a/src/components/CheckIn/CheckInWrapper.test.tsx
+++ b/src/components/CheckIn/CheckInWrapper.spec.tsx
@@ -13,6 +13,19 @@ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { checkInQueryMock } from './mocks';
import { StaticMockLink } from 'utils/StaticMockLink';
+/**
+ * This file contains unit tests for the CheckInWrapper component.
+ *
+ * The tests cover:
+ * - Rendering and behavior of the modal component.
+ * - Functionality of the button to open and close the modal.
+ * - Integration with mocked GraphQL queries for testing Apollo Client.
+ *
+ * Purpose:
+ * These tests ensure that the CheckInWrapper component behaves as expected
+ * when opening and closing modals, and correctly integrates with its dependencies.
+ */
+
const link = new StaticMockLink(checkInQueryMock, true);
describe('Testing CheckIn Wrapper', () => {
@@ -20,7 +33,7 @@ describe('Testing CheckIn Wrapper', () => {
eventId: 'event123',
};
- test('The button to open and close the modal should work properly', async () => {
+ it('The button to open and close the modal should work properly', async () => {
render(
From 685a12c3566e4d32f02da96a7e8a65bdaee2bed9 Mon Sep 17 00:00:00 2001
From: Mayank Jha <132004139+MayankJha014@users.noreply.github.com>
Date: Mon, 23 Dec 2024 03:46:05 +0530
Subject: [PATCH 39/57] manage tag css to app.module (#2722)
* manage tag css to app.module
* coderaddit ai chnages
---
src/screens/ManageTag/ManageTag.module.css | 127 ---------------------
src/style/app.module.css | 40 ++++---
2 files changed, 23 insertions(+), 144 deletions(-)
delete mode 100644 src/screens/ManageTag/ManageTag.module.css
diff --git a/src/screens/ManageTag/ManageTag.module.css b/src/screens/ManageTag/ManageTag.module.css
deleted file mode 100644
index deecd4a9b7..0000000000
--- a/src/screens/ManageTag/ManageTag.module.css
+++ /dev/null
@@ -1,127 +0,0 @@
-.btnsContainer {
- display: flex;
- margin: 2rem 0;
-}
-
-.btnsContainer .btnsBlock {
- display: flex;
- width: max-content;
-}
-
-.btnsContainer .btnsBlock button {
- margin-left: 1rem;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
-.btnsContainer .input {
- flex: 1;
- position: relative;
- max-width: 60%;
- justify-content: space-between;
-}
-
-.btnsContainer input {
- outline: 1px solid var(--bs-gray-400);
-}
-
-.btnsContainer .input button {
- width: 52px;
-}
-
-@media (max-width: 1020px) {
- .btnsContainer {
- flex-direction: column;
- margin: 1.5rem 0;
- }
-
- .btnsContainer .btnsBlock {
- margin: 1.5rem 0 0 0;
- justify-content: space-between;
- }
-
- .btnsContainer .btnsBlock button {
- margin: 0;
- }
-
- .btnsContainer .btnsBlock div button {
- margin-right: 1.5rem;
- }
-}
-
-/* For mobile devices */
-
-@media (max-width: 520px) {
- .btnsContainer {
- margin-bottom: 0;
- }
-
- .btnsContainer .btnsBlock {
- display: block;
- margin-top: 1rem;
- margin-right: 0;
- }
-
- .btnsContainer .btnsBlock div {
- flex: 1;
- }
-
- .btnsContainer .btnsBlock div[title='Sort organizations'] {
- margin-right: 0.5rem;
- }
-
- .btnsContainer .btnsBlock button {
- margin-bottom: 1rem;
- margin-right: 0;
- width: 100%;
- }
-}
-
-.errorContainer {
- min-height: 100vh;
-}
-
-.errorMessage {
- margin-top: 25%;
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
-}
-
-.errorIcon {
- transform: scale(1.5);
- color: var(--bs-danger);
- margin-bottom: 1rem;
-}
-
-.tableHeader {
- background-color: var(--bs-primary);
- color: var(--bs-white);
- font-size: 1rem;
-}
-
-.rowBackground {
- background-color: var(--bs-white);
- max-height: 120px;
-}
-
-.tagsBreadCrumbs {
- color: var(--bs-gray);
- cursor: pointer;
-}
-
-.tagsBreadCrumbs:hover {
- color: var(--bs-blue);
- font-weight: 600;
- text-decoration: underline;
-}
-
-.manageTagScrollableDiv {
- scrollbar-width: thin;
- scrollbar-color: var(--bs-gray-400) var(--bs-white);
-
- max-height: calc(100vh - 18rem);
- overflow: auto;
-}
diff --git a/src/style/app.module.css b/src/style/app.module.css
index 365b00556b..56dc7e8854 100644
--- a/src/style/app.module.css
+++ b/src/style/app.module.css
@@ -218,6 +218,7 @@
.btnsContainer .btnsBlock {
display: flex;
+ width: max-content;
}
.btnsContainer .btnsBlock button {
@@ -230,6 +231,12 @@
.btnsContainer .input {
flex: 1;
position: relative;
+ max-width: 60%;
+ justify-content: space-between;
+}
+
+.btnsContainer input {
+ outline: 1px solid var(--bs-gray-400);
}
.btnsContainer .input button {
@@ -363,6 +370,8 @@
.rowBackground {
background-color: var(--row-background);
+ max-height: 120px;
+ overflow-y: auto;
}
.tableHeader {
@@ -430,6 +439,20 @@
cursor: pointer;
}
+.manageTagScrollableDiv {
+ scrollbar-width: thin;
+ scrollbar-color: var(--bs-gray-400) var(--bs-white);
+
+ max-height: calc(100vh - 18rem);
+ overflow: auto;
+}
+
+.tagsBreadCrumbs:hover {
+ color: var(--bs-blue);
+ font-weight: 600;
+ text-decoration: underline;
+}
+
.orgUserTagsScrollableDiv {
scrollbar-width: auto;
scrollbar-color: var(--bs-gray-400) var(--bs-white);
@@ -727,11 +750,6 @@ hr {
}
}
-.btnsContainer .btnsBlock {
- display: flex;
- width: max-content;
-}
-
.btnsContainer .btnsBlock button {
margin-left: 1rem;
display: flex;
@@ -739,13 +757,6 @@ hr {
align-items: center;
}
-.btnsContainer .input {
- flex: 1;
- position: relative;
- max-width: 60%;
- justify-content: space-between;
-}
-
.btnsContainer input {
outline: 1px solid var(--bs-gray-400);
}
@@ -815,11 +826,6 @@ hr {
color: var(--bs-white);
font-size: 1rem;
}
-.rowBackground {
- background-color: var(--bs-white);
- max-height: 120px;
- overflow-y: auto;
-}
.subTagsLink {
color: var(--bs-blue);
From e31ccf655d122726fef4d87a29f9dcf85d966763 Mon Sep 17 00:00:00 2001
From: Syed Ali Ul Hasan
Date: Mon, 23 Dec 2024 03:55:50 +0530
Subject: [PATCH 40/57] refactored src/screens/UserPortal/Volunteer/Invitations
from jest to vitest (#2723)
---
...itations.test.tsx => Invitations.spec.tsx} | 25 +++++++++++--------
1 file changed, 14 insertions(+), 11 deletions(-)
rename src/screens/UserPortal/Volunteer/Invitations/{Invitations.test.tsx => Invitations.spec.tsx} (96%)
diff --git a/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx b/src/screens/UserPortal/Volunteer/Invitations/Invitations.spec.tsx
similarity index 96%
rename from src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx
rename to src/screens/UserPortal/Volunteer/Invitations/Invitations.spec.tsx
index 2c0cafc6a9..867f95c1aa 100644
--- a/src/screens/UserPortal/Volunteer/Invitations/Invitations.test.tsx
+++ b/src/screens/UserPortal/Volunteer/Invitations/Invitations.spec.tsx
@@ -21,14 +21,24 @@ import {
} from './Invitations.mocks';
import { toast } from 'react-toastify';
import useLocalStorage from 'utils/useLocalstorage';
+import { vi, expect } from 'vitest';
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
+vi.mock('react-router-dom', async () => {
+ const actual = await vi.importActual('react-router-dom');
+ return {
+ ...actual,
+ useParams: () => ({ orgId: 'orgId' }),
+ useNavigate: vi.fn(),
+ };
+});
+
const { setItem } = useLocalStorage();
const link1 = new StaticMockLink(MOCKS);
@@ -79,19 +89,12 @@ const renderInvitations = (link: ApolloLink): RenderResult => {
};
describe('Testing Invvitations Screen', () => {
- beforeAll(() => {
- jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({ orgId: 'orgId' }),
- }));
- });
-
beforeEach(() => {
setItem('userId', 'userId');
});
afterAll(() => {
- jest.clearAllMocks();
+ vi.clearAllMocks();
});
it('should redirect to fallback URL if URL params are undefined', async () => {
From cda28369f4a71e8a7175b9bd4c7916251e647792 Mon Sep 17 00:00:00 2001
From: khushi santosh patil
<143253539+khushipatil1523@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:02:55 +0530
Subject: [PATCH 41/57] convert from jest to vitest #2486 (#2705)
* convert from jest to vitest
* changes done
* changes done
* changes done
---
...ments.test.tsx => Advertisements.spec.tsx} | 41 +++++++++++--------
1 file changed, 24 insertions(+), 17 deletions(-)
rename src/components/Advertisements/{Advertisements.test.tsx => Advertisements.spec.tsx} (96%)
diff --git a/src/components/Advertisements/Advertisements.test.tsx b/src/components/Advertisements/Advertisements.spec.tsx
similarity index 96%
rename from src/components/Advertisements/Advertisements.test.tsx
rename to src/components/Advertisements/Advertisements.spec.tsx
index 88bbb1255c..1e2d92b392 100644
--- a/src/components/Advertisements/Advertisements.test.tsx
+++ b/src/components/Advertisements/Advertisements.spec.tsx
@@ -1,4 +1,6 @@
import React, { act } from 'react';
+import { describe, test, expect, vi } from 'vitest';
+
import {
ApolloClient,
ApolloLink,
@@ -7,25 +9,28 @@ import {
InMemoryCache,
} from '@apollo/client';
import { MockedProvider } from '@apollo/client/testing';
+
import { fireEvent, render, screen } from '@testing-library/react';
-import 'jest-location-mock';
import type { DocumentNode, NormalizedCacheObject } from '@apollo/client';
import userEvent from '@testing-library/user-event';
import { BACKEND_URL } from 'Constant/constant';
-import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations';
+
+import { ADD_ADVERTISEMENT_MUTATION } from '../../GraphQl/Mutations/mutations';
import {
ORGANIZATIONS_LIST,
ORGANIZATION_ADVERTISEMENT_LIST,
PLUGIN_GET,
-} from 'GraphQl/Queries/Queries';
+} from '../../GraphQl/Queries/Queries';
+
import { I18nextProvider } from 'react-i18next';
+
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
-import { store } from 'state/store';
-import i18nForTest from 'utils/i18nForTest';
-import useLocalStorage from 'utils/useLocalstorage';
+import { store } from '../../state/store';
+import i18nForTest from '../../utils/i18nForTest';
+import useLocalStorage from '../../utils/useLocalstorage';
import Advertisement from './Advertisements';
const { getItem } = useLocalStorage();
@@ -50,18 +55,22 @@ const client: ApolloClient = new ApolloClient({
link: ApolloLink.from([httpLink]),
});
-jest.mock('components/AddOn/support/services/Plugin.helper', () => ({
+vi.mock('components/AddOn/support/services/Plugin.helper', () => ({
__esModule: true,
- default: jest.fn().mockImplementation(() => ({
- fetchInstalled: jest.fn().mockResolvedValue([]),
- fetchStore: jest.fn().mockResolvedValue([]),
+ default: vi.fn().mockImplementation(() => ({
+ fetchInstalled: vi.fn().mockResolvedValue([]),
+ fetchStore: vi.fn().mockResolvedValue([]),
})),
}));
let mockID: string | undefined = '1';
-jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({ orgId: mockID }),
-}));
+
+vi.mock('react-router-dom', async () => {
+ const actual = await vi.importActual('react-router-dom');
+ return {
+ ...actual,
+ useParams: () => ({ orgId: mockID }),
+ };
+});
const today = new Date();
const tomorrow = today;
@@ -466,18 +475,16 @@ describe('Testing Advertisement Component', () => {
/\b(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d{1,2})\s+(\d{4})\b/,
);
let dateObject = new Date();
-
if (dateMatch) {
const monthName = dateMatch[1];
const day = parseInt(dateMatch[2], 10);
const year = parseInt(dateMatch[3], 10);
-
const monthIndex =
'JanFebMarAprMayJunJulAugSepOctNovDec'.indexOf(monthName) / 3;
dateObject = new Date(year, monthIndex, day);
}
-
+ console.log(dateObject);
expect(dateObject.getTime()).toBeLessThan(new Date().getTime());
});
From 986bef80972fef714745a932d77f890cf3d1dbf7 Mon Sep 17 00:00:00 2001
From: Peter Harrison <16875803+palisadoes@users.noreply.github.com>
Date: Sun, 22 Dec 2024 14:33:24 -0800
Subject: [PATCH 42/57] Revert "convert from jest to vitest #2486 (#2705)"
(#2731)
This reverts commit cda28369f4a71e8a7175b9bd4c7916251e647792.
---
...ments.spec.tsx => Advertisements.test.tsx} | 41 ++++++++-----------
1 file changed, 17 insertions(+), 24 deletions(-)
rename src/components/Advertisements/{Advertisements.spec.tsx => Advertisements.test.tsx} (96%)
diff --git a/src/components/Advertisements/Advertisements.spec.tsx b/src/components/Advertisements/Advertisements.test.tsx
similarity index 96%
rename from src/components/Advertisements/Advertisements.spec.tsx
rename to src/components/Advertisements/Advertisements.test.tsx
index 1e2d92b392..88bbb1255c 100644
--- a/src/components/Advertisements/Advertisements.spec.tsx
+++ b/src/components/Advertisements/Advertisements.test.tsx
@@ -1,6 +1,4 @@
import React, { act } from 'react';
-import { describe, test, expect, vi } from 'vitest';
-
import {
ApolloClient,
ApolloLink,
@@ -9,28 +7,25 @@ import {
InMemoryCache,
} from '@apollo/client';
import { MockedProvider } from '@apollo/client/testing';
-
import { fireEvent, render, screen } from '@testing-library/react';
+import 'jest-location-mock';
import type { DocumentNode, NormalizedCacheObject } from '@apollo/client';
import userEvent from '@testing-library/user-event';
import { BACKEND_URL } from 'Constant/constant';
-
-import { ADD_ADVERTISEMENT_MUTATION } from '../../GraphQl/Mutations/mutations';
+import { ADD_ADVERTISEMENT_MUTATION } from 'GraphQl/Mutations/mutations';
import {
ORGANIZATIONS_LIST,
ORGANIZATION_ADVERTISEMENT_LIST,
PLUGIN_GET,
-} from '../../GraphQl/Queries/Queries';
-
+} from 'GraphQl/Queries/Queries';
import { I18nextProvider } from 'react-i18next';
-
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
-import { store } from '../../state/store';
-import i18nForTest from '../../utils/i18nForTest';
-import useLocalStorage from '../../utils/useLocalstorage';
+import { store } from 'state/store';
+import i18nForTest from 'utils/i18nForTest';
+import useLocalStorage from 'utils/useLocalstorage';
import Advertisement from './Advertisements';
const { getItem } = useLocalStorage();
@@ -55,22 +50,18 @@ const client: ApolloClient = new ApolloClient({
link: ApolloLink.from([httpLink]),
});
-vi.mock('components/AddOn/support/services/Plugin.helper', () => ({
+jest.mock('components/AddOn/support/services/Plugin.helper', () => ({
__esModule: true,
- default: vi.fn().mockImplementation(() => ({
- fetchInstalled: vi.fn().mockResolvedValue([]),
- fetchStore: vi.fn().mockResolvedValue([]),
+ default: jest.fn().mockImplementation(() => ({
+ fetchInstalled: jest.fn().mockResolvedValue([]),
+ fetchStore: jest.fn().mockResolvedValue([]),
})),
}));
let mockID: string | undefined = '1';
-
-vi.mock('react-router-dom', async () => {
- const actual = await vi.importActual('react-router-dom');
- return {
- ...actual,
- useParams: () => ({ orgId: mockID }),
- };
-});
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useParams: () => ({ orgId: mockID }),
+}));
const today = new Date();
const tomorrow = today;
@@ -475,16 +466,18 @@ describe('Testing Advertisement Component', () => {
/\b(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d{1,2})\s+(\d{4})\b/,
);
let dateObject = new Date();
+
if (dateMatch) {
const monthName = dateMatch[1];
const day = parseInt(dateMatch[2], 10);
const year = parseInt(dateMatch[3], 10);
+
const monthIndex =
'JanFebMarAprMayJunJulAugSepOctNovDec'.indexOf(monthName) / 3;
dateObject = new Date(year, monthIndex, day);
}
- console.log(dateObject);
+
expect(dateObject.getTime()).toBeLessThan(new Date().getTime());
});
From 3c6f6dae1f1aa00dc64a99331a167669b8a52375 Mon Sep 17 00:00:00 2001
From: IITI-tushar <165766280+IITI-tushar@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:05:16 +0530
Subject: [PATCH 43/57] Add AdvertisementEntry.spec.tsx for Vitest migration
(#2680)
* Add AdvertisementEntry.spec.tsx for Vitest migration
* Update AdvertisementEntry.spec.tsx removes eslint-disable
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
* Update AdvertisementEntry.spec.tsx
---
.../AdvertisementEntry.spec.tsx | 649 ++++++++++++++++++
1 file changed, 649 insertions(+)
create mode 100644 src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.spec.tsx
diff --git a/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.spec.tsx b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.spec.tsx
new file mode 100644
index 0000000000..4d27df6e22
--- /dev/null
+++ b/src/components/Advertisements/core/AdvertisementEntry/AdvertisementEntry.spec.tsx
@@ -0,0 +1,649 @@
+import React from 'react';
+import { render, fireEvent, waitFor, screen } from '@testing-library/react';
+import {
+ ApolloClient,
+ ApolloProvider,
+ InMemoryCache,
+ ApolloLink,
+ HttpLink,
+} from '@apollo/client';
+import type { NormalizedCacheObject } from '@apollo/client';
+import { BrowserRouter } from 'react-router-dom';
+import AdvertisementEntry from './AdvertisementEntry';
+import AdvertisementRegister from '../AdvertisementRegister/AdvertisementRegister';
+import { Provider } from 'react-redux';
+import { store } from 'state/store';
+import { BACKEND_URL } from 'Constant/constant';
+import i18nForTest from 'utils/i18nForTest';
+import { I18nextProvider } from 'react-i18next';
+import dayjs from 'dayjs';
+import useLocalStorage from 'utils/useLocalstorage';
+import { MockedProvider } from '@apollo/client/testing';
+import { ORGANIZATION_ADVERTISEMENT_LIST } from 'GraphQl/Queries/OrganizationQueries';
+import { DELETE_ADVERTISEMENT_BY_ID } from 'GraphQl/Mutations/mutations';
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import '@testing-library/jest-dom';
+
+const { getItem } = useLocalStorage();
+
+const httpLink = new HttpLink({
+ uri: BACKEND_URL,
+ headers: {
+ authorization: 'Bearer ' + getItem('token') || '',
+ },
+});
+const translations = JSON.parse(
+ JSON.stringify(
+ i18nForTest.getDataByLanguage('en')?.translation?.advertisement ?? null,
+ ),
+);
+
+const client: ApolloClient = new ApolloClient({
+ cache: new InMemoryCache(),
+ link: ApolloLink.from([httpLink]),
+});
+
+const mockUseMutation = vi.fn();
+vi.mock('@apollo/client', async () => {
+ const actual = await vi.importActual('@apollo/client');
+ return {
+ ...actual,
+ useMutation: () => mockUseMutation(),
+ };
+});
+
+vi.mock('react-router-dom', async () => {
+ const actual = await vi.importActual('react-router-dom');
+ return {
+ ...actual,
+ useParams: () => ({ orgId: '1' }),
+ };
+});
+
+describe('Testing Advertisement Entry Component', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('Testing rendering and deleting of advertisement', async () => {
+ const deleteAdByIdMock = vi.fn();
+ mockUseMutation.mockReturnValue([deleteAdByIdMock]);
+ const { getByTestId, getAllByText } = render(
+
+
+
+
+
+
+
+
+ ,
+ );
+
+ //Testing rendering
+ expect(getByTestId('AdEntry')).toBeInTheDocument();
+ expect(getAllByText('POPUP')[0]).toBeInTheDocument();
+ expect(getAllByText('Advert1')[0]).toBeInTheDocument();
+ expect(screen.getByTestId('media')).toBeInTheDocument();
+
+ //Testing successful deletion
+ fireEvent.click(getByTestId('moreiconbtn'));
+ fireEvent.click(getByTestId('deletebtn'));
+
+ await waitFor(() => {
+ expect(screen.getByTestId('delete_title')).toBeInTheDocument();
+ expect(screen.getByTestId('delete_body')).toBeInTheDocument();
+ });
+
+ fireEvent.click(getByTestId('delete_yes'));
+
+ await waitFor(() => {
+ expect(deleteAdByIdMock).toHaveBeenCalledWith({
+ variables: {
+ id: '1',
+ },
+ });
+ const deletedMessage = screen.queryByText('Advertisement Deleted');
+ expect(deletedMessage).toBeNull();
+ });
+
+ //Testing unsuccessful deletion
+ deleteAdByIdMock.mockRejectedValueOnce(new Error('Deletion Failed'));
+
+ fireEvent.click(getByTestId('moreiconbtn'));
+
+ fireEvent.click(getByTestId('delete_yes'));
+
+ await waitFor(() => {
+ expect(deleteAdByIdMock).toHaveBeenCalledWith({
+ variables: {
+ id: '1',
+ },
+ });
+ const deletionFailedText = screen.queryByText((content, element) => {
+ return (
+ element?.textContent === 'Deletion Failed' &&
+ element.tagName.toLowerCase() === 'div'
+ );
+ });
+ expect(deletionFailedText).toBeNull();
+ });
+ });
+
+ it('should use default props when none are provided', () => {
+ render(
+ ,
+ : void {
+ throw new Error('Function not implemented.');
+ }}
+ />,
+ );
+
+ //Check if component renders with default ''(empty string)
+ const elements = screen.getAllByText(''); // This will return an array of matching elements
+ elements.forEach((element) => expect(element).toBeInTheDocument());
+
+ // Check that the component renders with default `mediaUrl` (empty string)
+ const mediaElement = screen.getByTestId('media');
+ expect(mediaElement).toHaveAttribute('src', '');
+
+ // Check that the component renders with default `endDate`
+ const defaultEndDate = new Date().toDateString();
+ expect(screen.getByText(`Ends on ${defaultEndDate}`)).toBeInTheDocument();
+
+ // Check that the component renders with default `startDate`
+ const defaultStartDate = new Date().toDateString();
+ expect(screen.getByText(`Ends on ${defaultStartDate}`)).toBeInTheDocument(); //fix text "Ends on"?
+ });
+
+ it('should correctly override default props when values are provided', () => {
+ const mockName = 'Test Ad';
+ const mockType = 'Banner';
+ const mockMediaUrl = 'https://example.com/media.png';
+ const mockEndDate = new Date(2025, 11, 31);
+ const mockStartDate = new Date(2024, 0, 1);
+ const mockOrganizationId = 'org123';
+
+ const { getByText } = render(
+ ,
+ : void {
+ throw new Error('Function not implemented.');
+ }}
+ />,
+ );
+
+ // Check that the component renders with provided values
+ expect(getByText(mockName)).toBeInTheDocument();
+ expect(getByText(mockType)).toBeInTheDocument();
+ expect(screen.getByTestId('media')).toHaveAttribute('src', mockMediaUrl);
+ expect(
+ getByText(`Ends on ${mockEndDate.toDateString()}`),
+ ).toBeInTheDocument();
+ });
+
+ it('should open and close the dropdown when options button is clicked', () => {
+ const { getByTestId, queryByText, getAllByText } = render(
+
+
+
+
+
+
+
+
+ ,
+ );
+
+ // Test initial rendering
+ expect(getByTestId('AdEntry')).toBeInTheDocument();
+ expect(getAllByText('POPUP')[0]).toBeInTheDocument();
+ expect(getAllByText('Advert1')[0]).toBeInTheDocument();
+
+ // Test dropdown functionality
+ const optionsButton = getByTestId('moreiconbtn');
+
+ // Initially, the dropdown should not be visible
+ expect(queryByText('Edit')).toBeNull();
+
+ // Click to open the dropdown
+ fireEvent.click(optionsButton);
+
+ // After clicking the button, the dropdown should be visible
+ expect(queryByText('Edit')).toBeInTheDocument();
+
+ // Click again to close the dropdown
+ fireEvent.click(optionsButton);
+
+ // After the second click, the dropdown should be hidden again
+ expect(queryByText('Edit')).toBeNull();
+ });
+
+ it('Updates the advertisement and shows success toast on successful update', async () => {
+ const updateAdByIdMock = vi.fn().mockResolvedValue({
+ data: {
+ updateAdvertisement: {
+ advertisement: {
+ _id: '1',
+ name: 'Updated Advertisement',
+ mediaUrl: '',
+ startDate: dayjs(new Date()).add(1, 'day').format('YYYY-MM-DD'),
+ endDate: dayjs(new Date()).add(2, 'days').format('YYYY-MM-DD'),
+ type: 'BANNER',
+ },
+ },
+ },
+ });
+
+ mockUseMutation.mockReturnValue([updateAdByIdMock]);
+
+ render(
+
+
+
+
+
+
+
+
+ ,
+ );
+
+ const optionsButton = screen.getByTestId('moreiconbtn');
+ fireEvent.click(optionsButton);
+ fireEvent.click(screen.getByTestId('editBtn'));
+
+ fireEvent.change(screen.getByLabelText('Enter name of Advertisement'), {
+ target: { value: 'Updated Advertisement' },
+ });
+
+ expect(screen.getByLabelText('Enter name of Advertisement')).toHaveValue(
+ 'Updated Advertisement',
+ );
+
+ fireEvent.change(screen.getByLabelText(translations.Rtype), {
+ target: { value: 'BANNER' },
+ });
+ expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER');
+
+ fireEvent.change(screen.getByLabelText(translations.RstartDate), {
+ target: { value: dayjs().add(1, 'day').format('YYYY-MM-DD') },
+ });
+
+ fireEvent.change(screen.getByLabelText(translations.RendDate), {
+ target: { value: dayjs().add(2, 'days').format('YYYY-MM-DD') },
+ });
+
+ fireEvent.click(screen.getByTestId('addonupdate'));
+
+ expect(updateAdByIdMock).toHaveBeenCalledWith({
+ variables: {
+ id: '1',
+ name: 'Updated Advertisement',
+ type: 'BANNER',
+ startDate: dayjs().add(1, 'day').format('YYYY-MM-DD'),
+ endDate: dayjs().add(2, 'days').format('YYYY-MM-DD'),
+ },
+ });
+ });
+
+ it('Simulating if the mutation doesnt have data variable while updating', async () => {
+ const updateAdByIdMock = vi.fn().mockResolvedValue({
+ updateAdvertisement: {
+ _id: '1',
+ name: 'Updated Advertisement',
+ type: 'BANNER',
+ },
+ });
+
+ mockUseMutation.mockReturnValue([updateAdByIdMock]);
+
+ render(
+
+
+
+
+
+
+
+
+ ,
+ );
+
+ const optionsButton = screen.getByTestId('moreiconbtn');
+ fireEvent.click(optionsButton);
+ fireEvent.click(screen.getByTestId('editBtn'));
+
+ fireEvent.change(screen.getByLabelText('Enter name of Advertisement'), {
+ target: { value: 'Updated Advertisement' },
+ });
+
+ expect(screen.getByLabelText('Enter name of Advertisement')).toHaveValue(
+ 'Updated Advertisement',
+ );
+
+ fireEvent.change(screen.getByLabelText(translations.Rtype), {
+ target: { value: 'BANNER' },
+ });
+ expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER');
+
+ fireEvent.click(screen.getByTestId('addonupdate'));
+
+ expect(updateAdByIdMock).toHaveBeenCalledWith({
+ variables: {
+ id: '1',
+ name: 'Updated Advertisement',
+ type: 'BANNER',
+ },
+ });
+ });
+
+ it('Simulating if the mutation does not have data variable while registering', async () => {
+ vi.stubGlobal('location', {
+ reload: vi.fn(),
+ href: 'https://example.com/page/id=1',
+ });
+
+ const createAdByIdMock = vi.fn().mockResolvedValue({
+ data1: {
+ createAdvertisement: {
+ _id: '1',
+ },
+ },
+ });
+
+ mockUseMutation.mockReturnValue([createAdByIdMock]);
+
+ render(
+
+
+
+
+ {
+
+ }
+
+
+
+ ,
+ );
+
+ fireEvent.click(screen.getByTestId('createAdvertisement'));
+
+ fireEvent.change(screen.getByLabelText('Enter name of Advertisement'), {
+ target: { value: 'Updated Advertisement' },
+ });
+
+ expect(screen.getByLabelText('Enter name of Advertisement')).toHaveValue(
+ 'Updated Advertisement',
+ );
+
+ fireEvent.change(screen.getByLabelText(translations.Rtype), {
+ target: { value: 'BANNER' },
+ });
+ expect(screen.getByLabelText(translations.Rtype)).toHaveValue('BANNER');
+
+ fireEvent.change(screen.getByLabelText(translations.RstartDate), {
+ target: { value: '2023-01-01' },
+ });
+ expect(screen.getByLabelText(translations.RstartDate)).toHaveValue(
+ '2023-01-01',
+ );
+
+ fireEvent.change(screen.getByLabelText(translations.RendDate), {
+ target: { value: '2023-02-01' },
+ });
+ expect(screen.getByLabelText(translations.RendDate)).toHaveValue(
+ '2023-02-01',
+ );
+
+ fireEvent.click(screen.getByTestId('addonregister'));
+
+ expect(createAdByIdMock).toHaveBeenCalledWith({
+ variables: {
+ organizationId: '1',
+ name: 'Updated Advertisement',
+ file: '',
+ type: 'BANNER',
+ startDate: dayjs(new Date('2023-01-01')).format('YYYY-MM-DD'),
+ endDate: dayjs(new Date('2023-02-01')).format('YYYY-MM-DD'),
+ },
+ });
+ });
+
+ it('delete advertisement', async () => {
+ const deleteAdByIdMock = vi.fn();
+ const mocks = [
+ {
+ request: {
+ query: ORGANIZATION_ADVERTISEMENT_LIST,
+ variables: {
+ id: '1',
+ first: 2,
+ after: null,
+ last: null,
+ before: null,
+ },
+ },
+ result: {
+ data: {
+ organizations: [
+ {
+ _id: '1',
+ advertisements: {
+ edges: [
+ {
+ node: {
+ _id: '1',
+ name: 'Advertisement1',
+ startDate: '2022-01-01',
+ endDate: '2023-01-01',
+ mediaUrl: 'http://example1.com',
+ },
+ cursor: 'cursor1',
+ },
+ {
+ node: {
+ _id: '2',
+ name: 'Advertisement2',
+ startDate: '2024-02-01',
+ endDate: '2025-02-01',
+ mediaUrl: 'http://example2.com',
+ },
+ cursor: 'cursor2',
+ },
+ {
+ node: {
+ _id: '3',
+ name: 'Advertisement1',
+ startDate: '2022-01-01',
+ endDate: '2023-01-01',
+ mediaUrl: 'http://example1.com',
+ },
+ cursor: 'cursor3',
+ },
+ {
+ node: {
+ _id: '4',
+ name: 'Advertisement2',
+ startDate: '2024-02-01',
+ endDate: '2025-02-01',
+ mediaUrl: 'http://example2.com',
+ },
+ cursor: 'cursor4',
+ },
+ {
+ node: {
+ _id: '5',
+ name: 'Advertisement1',
+ startDate: '2022-01-01',
+ endDate: '2023-01-01',
+ mediaUrl: 'http://example1.com',
+ },
+ cursor: 'cursor5',
+ },
+ {
+ node: {
+ _id: '6',
+ name: 'Advertisement2',
+ startDate: '2024-02-01',
+ endDate: '2025-02-01',
+ mediaUrl: 'http://example2.com',
+ },
+ cursor: 'cursor6',
+ },
+ ],
+ pageInfo: {
+ startCursor: 'cursor1',
+ endCursor: 'cursor6',
+ hasNextPage: true,
+ hasPreviousPage: false,
+ },
+ totalCount: 8,
+ },
+ },
+ ],
+ },
+ },
+ },
+ {
+ request: {
+ query: DELETE_ADVERTISEMENT_BY_ID,
+ variables: {
+ id: '1',
+ },
+ },
+ result: {
+ data: {
+ advertisements: {
+ _id: null,
+ },
+ },
+ },
+ },
+ ];
+ mockUseMutation.mockReturnValue([deleteAdByIdMock]);
+ const { getByTestId, getAllByText } = render(
+
+
+
+
+
+
+
+
+
+
+ ,
+ );
+
+ //Testing rendering
+ expect(getByTestId('AdEntry')).toBeInTheDocument();
+ expect(getAllByText('POPUP')[0]).toBeInTheDocument();
+ expect(getAllByText('Advert1')[0]).toBeInTheDocument();
+ expect(screen.getByTestId('media')).toBeInTheDocument();
+
+ //Testing successful deletion
+ fireEvent.click(getByTestId('moreiconbtn'));
+ fireEvent.click(getByTestId('deletebtn'));
+
+ await waitFor(() => {
+ expect(screen.getByTestId('delete_title')).toBeInTheDocument();
+ expect(screen.getByTestId('delete_body')).toBeInTheDocument();
+ });
+
+ fireEvent.click(getByTestId('delete_yes'));
+
+ await waitFor(() => {
+ expect(deleteAdByIdMock).toHaveBeenCalledWith({
+ variables: {
+ id: '1',
+ },
+ });
+ const deletedMessage = screen.queryByText('Advertisement Deleted');
+ expect(deletedMessage).toBeNull();
+ });
+
+ //Testing unsuccessful deletion
+ deleteAdByIdMock.mockRejectedValueOnce(new Error('Deletion Failed'));
+
+ fireEvent.click(getByTestId('moreiconbtn'));
+
+ fireEvent.click(getByTestId('delete_yes'));
+
+ await waitFor(() => {
+ expect(deleteAdByIdMock).toHaveBeenCalledWith({
+ variables: {
+ id: '1',
+ },
+ });
+ const deletionFailedText = screen.queryByText((content, element) => {
+ return (
+ element?.textContent === 'Deletion Failed' &&
+ element.tagName.toLowerCase() === 'div'
+ );
+ });
+ expect(deletionFailedText).toBeNull();
+ });
+ });
+});
From 8633bc67eb4cfbcdeb9dc0b608683fcf17f715a6 Mon Sep 17 00:00:00 2001
From: IITI-tushar <165766280+IITI-tushar@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:06:27 +0530
Subject: [PATCH 44/57] update and rename Settings.test.tsx to
Settings.spec.tsx fixes #2579 (#2718)
* Update and rename Settings.test.tsx to Settings.spec.tsx
* Update Settings.spec.tsx- removed-deprecated-methods-suggested-by-coderabbit
---
.../{Settings.test.tsx => Settings.spec.tsx} | 38 +++++++++----------
1 file changed, 17 insertions(+), 21 deletions(-)
rename src/screens/UserPortal/Settings/{Settings.test.tsx => Settings.spec.tsx} (92%)
diff --git a/src/screens/UserPortal/Settings/Settings.test.tsx b/src/screens/UserPortal/Settings/Settings.spec.tsx
similarity index 92%
rename from src/screens/UserPortal/Settings/Settings.test.tsx
rename to src/screens/UserPortal/Settings/Settings.spec.tsx
index fd9e1ed350..39d853862f 100644
--- a/src/screens/UserPortal/Settings/Settings.test.tsx
+++ b/src/screens/UserPortal/Settings/Settings.spec.tsx
@@ -1,5 +1,6 @@
-import React, { act } from 'react';
-import { fireEvent, render, screen } from '@testing-library/react';
+import React from 'react';
+import { describe, expect, beforeAll, vi } from 'vitest';
+import { render, screen, fireEvent, act } from '@testing-library/react';
import { MockedProvider } from '@apollo/react-testing';
import { I18nextProvider } from 'react-i18next';
import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations';
@@ -119,31 +120,27 @@ const resizeWindow = (width: number): void => {
async function wait(ms = 100): Promise {
await act(async () => {
- return new Promise((resolve) => {
- setTimeout(resolve, ms);
- });
+ vi.advanceTimersByTime(ms);
});
}
describe('Testing Settings Screen [User Portal]', () => {
- // Mock implementation of matchMedia
beforeAll(() => {
+ vi.useFakeTimers();
Object.defineProperty(window, 'matchMedia', {
writable: true,
- value: jest.fn().mockImplementation((query) => ({
+ value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
- addListener: jest.fn(), // Deprecated
- removeListener: jest.fn(), // Deprecated
- addEventListener: jest.fn(),
- removeEventListener: jest.fn(),
- dispatchEvent: jest.fn(),
+ addEventListener: vi.fn(),
+ removeEventListener: vi.fn(),
+ dispatchEvent: vi.fn(),
})),
});
});
- test('Screen should be rendered properly', async () => {
+ it('Screen should be rendered properly', async () => {
await act(async () => {
render(
@@ -163,7 +160,7 @@ describe('Testing Settings Screen [User Portal]', () => {
expect(screen.queryAllByText('Settings')).not.toBe([]);
});
- test('input works properly', async () => {
+ it('input works properly', async () => {
await act(async () => {
render(
@@ -220,7 +217,7 @@ describe('Testing Settings Screen [User Portal]', () => {
expect(screen.getByTestId('profile-picture')).toBeInTheDocument();
});
- test('resetChangesBtn works properly', async () => {
+ it('resetChangesBtn works properly', async () => {
await act(async () => {
render(
@@ -253,7 +250,7 @@ describe('Testing Settings Screen [User Portal]', () => {
expect(screen.getByLabelText('Birth Date')).toHaveValue('2024-03-01');
});
- test('resetChangesBtn works properly when the details are empty', async () => {
+ it('resetChangesBtn works properly when the details are empty', async () => {
await act(async () => {
render(
@@ -286,7 +283,7 @@ describe('Testing Settings Screen [User Portal]', () => {
expect(screen.getByLabelText('Birth Date')).toHaveValue('');
});
- test('sidebar', async () => {
+ it('sidebar', async () => {
await act(async () => {
render(
@@ -311,7 +308,7 @@ describe('Testing Settings Screen [User Portal]', () => {
act(() => openMenuBtn.click());
});
- test('Testing sidebar when the screen size is less than or equal to 820px', async () => {
+ it('Testing sidebar when the screen size is less than or equal to 820px', async () => {
resizeWindow(800);
await act(async () => {
render(
@@ -328,7 +325,6 @@ describe('Testing Settings Screen [User Portal]', () => {
});
await wait();
-
screen.debug();
const openMenuBtn = screen.queryByTestId('openMenu');
@@ -348,7 +344,7 @@ describe('Testing Settings Screen [User Portal]', () => {
}
});
- test('renders events attended card correctly', async () => {
+ it('renders events attended card correctly', async () => {
render(
@@ -368,7 +364,7 @@ describe('Testing Settings Screen [User Portal]', () => {
expect(screen.getByText('No Events Attended')).toBeInTheDocument();
});
- test('renders events attended card correctly with events', async () => {
+ it('renders events attended card correctly with events', async () => {
const mockEventsAttended = [
{ _id: '1', title: 'Event 1' },
{ _id: '2', title: 'Event 2' },
From 8a21cbbcb27a954820266a02bcd5e83a194ec5b0 Mon Sep 17 00:00:00 2001
From: Nikhil Raj <125121367+hustlernik@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:08:04 +0530
Subject: [PATCH 45/57] fix:smooth infinite scroll for users list (#2726)
---
src/screens/Users/Users.tsx | 112 ++++++++++++++++++------------------
1 file changed, 56 insertions(+), 56 deletions(-)
diff --git a/src/screens/Users/Users.tsx b/src/screens/Users/Users.tsx
index 3ea165d7b0..b046679a00 100644
--- a/src/screens/Users/Users.tsx
+++ b/src/screens/Users/Users.tsx
@@ -70,6 +70,7 @@ const Users = (): JSX.Element => {
const { getItem } = useLocalStorage();
const perPageResult = 12;
+ const tableLoaderRowLength = 4;
const [isLoading, setIsLoading] = useState(true);
const [hasMore, setHasMore] = useState(true);
const [isLoadingMore, setIsLoadingMore] = useState(false);
@@ -432,67 +433,66 @@ const Users = (): JSX.Element => {
) : (
- {isLoading ? (
-
- ) : (
-
- }
- hasMore={hasMore}
- className={styles.listBox}
- data-testid="users-list"
- endMessage={
-
-
{tCommon('endOfResults')}
-
- }
- >
-
-
-
- {headerTitles.map((title: string, index: number) => {
+ {isLoading && (
+
+ )}
+
+ }
+ hasMore={hasMore}
+ className={styles.listBox}
+ data-testid="users-list"
+ endMessage={
+
+
{tCommon('endOfResults')}
+
+ }
+ >
+
+
+
+ {headerTitles.map((title: string, index: number) => {
+ return (
+
+ {title}
+ |
+ );
+ })}
+
+
+
+ {usersData &&
+ displayedUsers.map(
+ (user: InterfaceQueryUserListItem, index: number) => {
return (
-
- {title}
- |
+
);
- })}
-
-
-
- {usersData &&
- displayedUsers.map(
- (user: InterfaceQueryUserListItem, index: number) => {
- return (
-
- );
- },
- )}
-
-
-
- )}
+ },
+ )}
+
+
+
)}
>
);
};
-
export default Users;
From a295db30220035bbd00ef60c7977ae63c325436c Mon Sep 17 00:00:00 2001
From: Rafiul Hasan <67283985+rafidoth@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:40:07 +0600
Subject: [PATCH 46/57] Fixes #2670 : Refactored src/screen/PageNotFound
component test from jest to vitest (#2708)
* Refactored Refactor: src/screens/PageNotFound from Jest to Vitest
* Refactored :src/screens/PageNotFound from Jest to Vitest
* Refactored :src/screens/PageNotFound from Jest to Vitest
* Refactored :src/screens/PageNotFound from Jest to Vitest
---
...otFound.test.tsx => PageNotFound.spec.tsx} | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
rename src/screens/PageNotFound/{PageNotFound.test.tsx => PageNotFound.spec.tsx} (68%)
diff --git a/src/screens/PageNotFound/PageNotFound.test.tsx b/src/screens/PageNotFound/PageNotFound.spec.tsx
similarity index 68%
rename from src/screens/PageNotFound/PageNotFound.test.tsx
rename to src/screens/PageNotFound/PageNotFound.spec.tsx
index 501d9f7ef3..4557eb5af4 100644
--- a/src/screens/PageNotFound/PageNotFound.test.tsx
+++ b/src/screens/PageNotFound/PageNotFound.spec.tsx
@@ -8,11 +8,11 @@ import { store } from 'state/store';
import PageNotFound from './PageNotFound';
import i18nForTest from 'utils/i18nForTest';
import useLocalStorage from 'utils/useLocalstorage';
-
+import { it, expect, describe } from 'vitest';
const { setItem } = useLocalStorage();
describe('Testing Page not found component', () => {
- test('Component should be rendered properly for User', () => {
+ it('should render component properly for User', () => {
//setItem('AdminFor', undefined);
render(
@@ -24,15 +24,15 @@ describe('Testing Page not found component', () => {
,
);
- expect(screen.getByText(/Talawa User/i)).toBeTruthy();
- expect(screen.getByText(/404/i)).toBeTruthy();
+ expect(screen.getByText(/Talawa User/i)).toBeInTheDocument();
+ expect(screen.getByText(/404/i)).toBeInTheDocument();
expect(
screen.getByText(/Oops! The Page you requested was not found!/i),
- ).toBeTruthy();
- expect(screen.getByText(/Back to Home/i)).toBeTruthy();
+ ).toBeInTheDocument();
+ expect(screen.getByText(/Back to Home/i)).toBeInTheDocument();
});
- test('Component should be rendered properly for ADMIN or SUPERADMIN', () => {
+ it('should render properly for ADMIN or SUPERADMIN', () => {
setItem('AdminFor', [
{
_id: '6537904485008f171cf29924',
@@ -49,11 +49,11 @@ describe('Testing Page not found component', () => {
,
);
- expect(screen.getByText(/Talawa Admin Portal/i)).toBeTruthy();
- expect(screen.getByText(/404/i)).toBeTruthy();
+ expect(screen.getByText(/Talawa Admin Portal/i)).toBeInTheDocument();
+ expect(screen.getByText(/404/i)).toBeInTheDocument();
expect(
screen.getByText(/Oops! The Page you requested was not found!/i),
- ).toBeTruthy();
- expect(screen.getByText(/Back to Home/i)).toBeTruthy();
+ ).toBeInTheDocument();
+ expect(screen.getByText(/Back to Home/i)).toBeInTheDocument();
});
});
From d5a790d262477fd1a79cc0acfbcccfad20bea969 Mon Sep 17 00:00:00 2001
From: Vedant Gupta <115912707+im-vedant@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:12:07 +0530
Subject: [PATCH 47/57] Refactor: src/screens/OrganizationVenues from Jest to
Vitest (#2665)
* Refactored some code
* Migrate src/screens/OrganizationVenues from jest to vitest
* Revert "Refactored some code"
This reverts commit 02eb9d4fa59009ba81d93d5b137ba2d0f95eae23.
* replaced vi.mock with vi.doMock
* Add comments
* Suppressed Css error
* Fix customTableCell issue
* add data-testid attributes for toggle state for improved testability
* feat: updated jest config and package-lock.json to include identity-obj-proxy to mock Css modules
* Fix linting errors
* refactor : src\components\MemberDetail\customTableCell.test.tsx and src\components\OrganizationScreen\OrganizationScreen.test.tsx from jest to vitest
* Removed data-expanded attribute from mainpageright div
* Add test cases in src/components/MemberDetail/CustomTableCell
---------
Co-authored-by: im-vedant <194vedantgutpa@gmail.com>
Co-authored-by: Peter Harrison <16875803+palisadoes@users.noreply.github.com>
---
.../MemberDetail/customTableCell.spec.tsx | 160 ++++++++++++++++
.../MemberDetail/customTableCell.test.tsx | 171 ------------------
...n.test.tsx => OrganizationScreen.spec.tsx} | 7 +-
...s.test.tsx => OrganizationVenues.spec.tsx} | 38 ++--
4 files changed, 187 insertions(+), 189 deletions(-)
create mode 100644 src/components/MemberDetail/customTableCell.spec.tsx
delete mode 100644 src/components/MemberDetail/customTableCell.test.tsx
rename src/components/OrganizationScreen/{OrganizationScreen.test.tsx => OrganizationScreen.spec.tsx} (95%)
rename src/screens/OrganizationVenues/{OrganizationVenues.test.tsx => OrganizationVenues.spec.tsx} (92%)
diff --git a/src/components/MemberDetail/customTableCell.spec.tsx b/src/components/MemberDetail/customTableCell.spec.tsx
new file mode 100644
index 0000000000..81a088d5bb
--- /dev/null
+++ b/src/components/MemberDetail/customTableCell.spec.tsx
@@ -0,0 +1,160 @@
+import React from 'react';
+import { render, screen, waitFor } from '@testing-library/react';
+import { MockedProvider } from '@apollo/client/testing';
+import { BrowserRouter } from 'react-router-dom';
+import { CustomTableCell } from './customTableCell';
+import { EVENT_DETAILS } from 'GraphQl/Queries/Queries';
+import { vi } from 'vitest';
+vi.mock('react-toastify', () => ({
+ toast: {
+ success: vi.fn(),
+ error: vi.fn(),
+ },
+}));
+
+const mocks = [
+ {
+ request: {
+ query: EVENT_DETAILS,
+ variables: { id: 'event123' },
+ },
+ result: {
+ data: {
+ event: {
+ _id: 'event123',
+ title: 'Test Event',
+ description: 'This is a test event description',
+ startDate: '2023-05-01',
+ endDate: '2023-05-02',
+ startTime: '09:00:00',
+ endTime: '17:00:00',
+ allDay: false,
+ location: 'Test Location',
+ recurring: true,
+ baseRecurringEvent: {
+ _id: 'recurringEvent123',
+ },
+ organization: {
+ _id: 'org456',
+ members: [
+ { _id: 'member1', firstName: 'John', lastName: 'Doe' },
+ { _id: 'member2', firstName: 'Jane', lastName: 'Smith' },
+ ],
+ },
+ attendees: [{ _id: 'user1' }, { _id: 'user2' }],
+ },
+ },
+ },
+ },
+];
+
+describe('CustomTableCell', () => {
+ it('renders event details correctly', async () => {
+ render(
+
+
+
+
+ ,
+ );
+
+ await waitFor(() => screen.getByTestId('custom-row'));
+
+ expect(screen.getByText('Test Event')).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ new Date('2023-05-01').toLocaleDateString(undefined, {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ timeZone: 'UTC',
+ }),
+ ),
+ ).toBeInTheDocument();
+ expect(screen.getByText('Yes')).toBeInTheDocument();
+ expect(screen.getByText('2')).toBeInTheDocument();
+
+ const link = screen.getByRole('link', { name: 'Test Event' });
+ expect(link).toHaveAttribute('href', '/event/org456/event123');
+ });
+
+ it('displays loading state', () => {
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByRole('progressbar')).toBeInTheDocument();
+ });
+
+ it('displays error state', async () => {
+ const errorMock = [
+ {
+ request: {
+ query: EVENT_DETAILS,
+ variables: { id: 'event123' },
+ },
+ error: new Error('An error occurred'),
+ },
+ ];
+
+ render(
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(
+ screen.getByText(
+ 'Unable to load event details. Please try again later.',
+ ),
+ ).toBeInTheDocument();
+ });
+ });
+
+ it('displays no event found message', async () => {
+ const noEventMock = [
+ {
+ request: {
+ query: EVENT_DETAILS,
+ variables: { id: 'event123' },
+ },
+ result: {
+ data: {
+ event: null,
+ },
+ },
+ },
+ ];
+
+ render(
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(
+ screen.getByText('Event not found or has been deleted'),
+ ).toBeInTheDocument();
+ });
+ });
+});
diff --git a/src/components/MemberDetail/customTableCell.test.tsx b/src/components/MemberDetail/customTableCell.test.tsx
deleted file mode 100644
index bc296a74f3..0000000000
--- a/src/components/MemberDetail/customTableCell.test.tsx
+++ /dev/null
@@ -1,171 +0,0 @@
-import React from 'react';
-import { render, screen, waitFor } from '@testing-library/react';
-import { MockedProvider } from '@apollo/client/testing';
-import { BrowserRouter } from 'react-router-dom';
-import { CustomTableCell } from './customTableCell';
-import { EVENT_DETAILS } from 'GraphQl/Queries/Queries';
-
-jest.mock('react-toastify', () => ({
- toast: {
- success: jest.fn(),
- error: jest.fn(),
- },
-}));
-
-const mocks = [
- {
- request: {
- query: EVENT_DETAILS,
- variables: { id: 'event123' },
- },
- result: {
- data: {
- event: {
- _id: 'event123',
- title: 'Test Event',
- description: 'This is a test event description',
- startDate: '2023-05-01',
- endDate: '2023-05-02',
- startTime: '09:00:00',
- endTime: '17:00:00',
- allDay: false,
- location: 'Test Location',
- recurring: true,
- baseRecurringEvent: {
- _id: 'recurringEvent123',
- },
- organization: {
- _id: 'org456',
- members: [
- { _id: 'member1', firstName: 'John', lastName: 'Doe' },
- { _id: 'member2', firstName: 'Jane', lastName: 'Smith' },
- ],
- },
- attendees: [{ _id: 'user1' }, { _id: 'user2' }],
- },
- },
- },
- },
-];
-
-describe('CustomTableCell', () => {
- it('renders event details correctly', async () => {
- render(
-
-
-
-
- ,
- );
-
- await waitFor(() => screen.getByTestId('custom-row'));
-
- expect(screen.getByText('Test Event')).toBeInTheDocument();
- expect(screen.getByText('May 1, 2023')).toBeInTheDocument();
- expect(screen.getByText('Yes')).toBeInTheDocument();
- expect(screen.getByText('2')).toBeInTheDocument();
-
- const link = screen.getByRole('link', { name: 'Test Event' });
- expect(link).toHaveAttribute('href', '/event/org456/event123');
- });
-
- it('displays loading state', () => {
- render(
-
-
- ,
- );
-
- expect(screen.getByRole('progressbar')).toBeInTheDocument();
- });
-
- // it('displays error state', async () => {
- // const errorMock = [
- // {
- // request: {
- // query: EVENT_DETAILS,
- // variables: { id: 'event123' },
- // },
- // error: new Error('An error occurred'),
- // },
- // ];
-
- // render(
- //
- //
- // ,
- // );
-
- // await waitFor(
- // () => {
- // expect(
- // screen.getByText('Error loading event details'),
- // ).toBeInTheDocument();
- // },
- // { timeout: 2000 },
- // );
-
- // // Check if the error message from toast has been called
- // expect(toast.error).toHaveBeenCalledWith('An error occurred');
- // });
-
- // it('displays no event found message', async () => {
- // const noEventMock = [
- // {
- // request: {
- // query: EVENT_DETAILS,
- // variables: { id: 'event123' },
- // },
- // result: {
- // data: {
- // event: {
- // _id: null,
- // title: null,
- // startDate: null,
- // description: null,
- // endDate: null,
- // startTime: null,
- // endTime: null,
- // allDay: false,
- // location: null,
- // recurring: null,
- // organization: {
- // _id: null,
- // members: [],
- // },
- // baseRecurringEvent: {
- // _id: 'recurringEvent123',
- // },
- // attendees: [],
- // },
- // },
- // },
- // },
- // ];
-
- // render(
- //
- //
- // ,
- // );
-
- // await waitFor(() => screen.getByText('No event found'));
- // expect(screen.getByText('No event found')).toBeInTheDocument();
- // });
-});
diff --git a/src/components/OrganizationScreen/OrganizationScreen.test.tsx b/src/components/OrganizationScreen/OrganizationScreen.spec.tsx
similarity index 95%
rename from src/components/OrganizationScreen/OrganizationScreen.test.tsx
rename to src/components/OrganizationScreen/OrganizationScreen.spec.tsx
index d1c4c81c27..e6a75c46d8 100644
--- a/src/components/OrganizationScreen/OrganizationScreen.test.tsx
+++ b/src/components/OrganizationScreen/OrganizationScreen.spec.tsx
@@ -2,7 +2,6 @@ import React from 'react';
import { MockedProvider } from '@apollo/react-testing';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { I18nextProvider } from 'react-i18next';
-import 'jest-location-mock';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import { store } from 'state/store';
@@ -11,10 +10,10 @@ import OrganizationScreen from './OrganizationScreen';
import { ORGANIZATION_EVENT_LIST } from 'GraphQl/Queries/Queries';
import { StaticMockLink } from 'utils/StaticMockLink';
import styles from './OrganizationScreen.module.css';
-
+import { vi } from 'vitest';
const mockID: string | undefined = '123';
-jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
+vi.mock('react-router-dom', async () => ({
+ ...(await vi.importActual('react-router-dom')),
useParams: () => ({ orgId: mockID }),
useMatch: () => ({ params: { eventId: 'event123', orgId: '123' } }),
}));
diff --git a/src/screens/OrganizationVenues/OrganizationVenues.test.tsx b/src/screens/OrganizationVenues/OrganizationVenues.spec.tsx
similarity index 92%
rename from src/screens/OrganizationVenues/OrganizationVenues.test.tsx
rename to src/screens/OrganizationVenues/OrganizationVenues.spec.tsx
index 5b8b9933a1..e306c56cfc 100644
--- a/src/screens/OrganizationVenues/OrganizationVenues.test.tsx
+++ b/src/screens/OrganizationVenues/OrganizationVenues.spec.tsx
@@ -1,3 +1,15 @@
+/**
+ * Tests for the OrganizationVenues component.
+ * These tests include:
+ * - Ensuring the component renders correctly with default props.
+ * - Handling the absence of `orgId` by redirecting to the homepage.
+ * - Fetching and displaying venues via Apollo GraphQL queries.
+ * - Allowing users to search venues by name or description.
+ * - Sorting venues by capacity in ascending or descending order.
+ * - Verifying that long venue names or descriptions are handled gracefully.
+ * - Testing loading states and edge cases for Apollo queries.
+ * - Mocking GraphQL mutations for venue-related actions and validating their behavior.
+ */
import React from 'react';
import { MockedProvider } from '@apollo/react-testing';
import type { RenderResult } from '@testing-library/react';
@@ -10,7 +22,6 @@ import {
} from '@testing-library/react';
import { Provider } from 'react-redux';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
-import 'jest-location-mock';
import { I18nextProvider } from 'react-i18next';
import OrganizationVenues from './OrganizationVenues';
import { store } from 'state/store';
@@ -19,7 +30,7 @@ import { StaticMockLink } from 'utils/StaticMockLink';
import { VENUE_LIST } from 'GraphQl/Queries/OrganizationQueries';
import type { ApolloLink } from '@apollo/client';
import { DELETE_VENUE_MUTATION } from 'GraphQl/Mutations/VenueMutations';
-
+import { vi } from 'vitest';
const MOCKS = [
{
request: {
@@ -239,11 +250,11 @@ async function wait(ms = 100): Promise
{
});
}
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- warning: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ warning: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -272,14 +283,14 @@ const renderOrganizationVenue = (link: ApolloLink): RenderResult => {
describe('OrganizationVenue with missing orgId', () => {
beforeAll(() => {
- jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
+ vi.doMock('react-router-dom', async () => ({
+ ...(await vi.importActual('react-router-dom')),
useParams: () => ({ orgId: undefined }),
}));
});
afterAll(() => {
- jest.clearAllMocks();
+ vi.clearAllMocks();
});
test('Redirect to /orglist when orgId is falsy/undefined', async () => {
render(
@@ -299,7 +310,6 @@ describe('OrganizationVenue with missing orgId', () => {
,
);
-
await waitFor(() => {
const paramsError = screen.getByTestId('paramsError');
expect(paramsError).toBeInTheDocument();
@@ -308,17 +318,17 @@ describe('OrganizationVenue with missing orgId', () => {
});
describe('Organisation Venues', () => {
- global.alert = jest.fn();
+ global.alert = vi.fn();
beforeAll(() => {
- jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
+ vi.doMock('react-router-dom', async () => ({
+ ...(await vi.importActual('react-router-dom')),
useParams: () => ({ orgId: 'orgId' }),
}));
});
afterAll(() => {
- jest.clearAllMocks();
+ vi.clearAllMocks();
});
test('searches the venue list correctly by Name', async () => {
From 9108753fc80fb7014fda74caa9419a5e33d0179e Mon Sep 17 00:00:00 2001
From: Aaditya Agarwal
Date: Mon, 23 Dec 2024 04:14:58 +0530
Subject: [PATCH 48/57] Upgrade inquirer version to 11.0.2 (#2720)
* upgraded inqurier version
* updated custom port tests
* chaged isnan with number.isnan
* added tests for invalid port
* added reserved ports functionality
* improved type safety, maintainability and organisation
* added clear all mocks
---
package-lock.json | 1015 +++++++----------
package.json | 2 +-
.../askForCustomPort/askForCustomPort.test.ts | 112 +-
.../askForCustomPort/askForCustomPort.ts | 65 +-
.../askForTalawaApiUrl.test.ts | 14 +-
.../askForTalawaApiUrl/askForTalawaApiUrl.ts | 2 +-
6 files changed, 577 insertions(+), 633 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 24478f4f69..07a65a79c6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,7 +41,7 @@
"i18next": "^23.15.1",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.6.1",
- "inquirer": "^8.0.0",
+ "inquirer": "^11.0.2",
"js-cookie": "^3.0.1",
"lcov-result-merger": "^5.0.1",
"markdown-toc": "^1.2.0",
@@ -99,7 +99,6 @@
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.5.0",
"@vitest/coverage-istanbul": "^2.1.5",
- "@vitest/eslint-plugin": "^1.1.14",
"babel-jest": "^29.7.0",
"cross-env": "^7.0.3",
"eslint": "^8.49.0",
@@ -109,7 +108,6 @@
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-tsdoc": "^0.3.0",
- "eslint-plugin-vitest": "^0.5.4",
"husky": "^9.1.6",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.4.5",
@@ -3159,6 +3157,239 @@
"dev": true,
"license": "BSD-3-Clause"
},
+ "node_modules/@inquirer/checkbox": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-3.0.1.tgz",
+ "integrity": "sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/figures": "^1.0.6",
+ "@inquirer/type": "^2.0.0",
+ "ansi-escapes": "^4.3.2",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/confirm": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-4.0.1.tgz",
+ "integrity": "sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/type": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/core": {
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.2.1.tgz",
+ "integrity": "sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/figures": "^1.0.6",
+ "@inquirer/type": "^2.0.0",
+ "@types/mute-stream": "^0.0.4",
+ "@types/node": "^22.5.5",
+ "@types/wrap-ansi": "^3.0.0",
+ "ansi-escapes": "^4.3.2",
+ "cli-width": "^4.1.0",
+ "mute-stream": "^1.0.0",
+ "signal-exit": "^4.1.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^6.2.0",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/editor": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-3.0.1.tgz",
+ "integrity": "sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/type": "^2.0.0",
+ "external-editor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/expand": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-3.0.1.tgz",
+ "integrity": "sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/type": "^2.0.0",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/figures": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.9.tgz",
+ "integrity": "sha512-BXvGj0ehzrngHTPTDqUoDT3NXL8U0RxUk2zJm2A66RhCEIWdtU1v6GuUqNAgArW4PQ9CinqIWyHdQgdwOj06zQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/input": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-3.0.1.tgz",
+ "integrity": "sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/type": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/number": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-2.0.1.tgz",
+ "integrity": "sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/type": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/password": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-3.0.1.tgz",
+ "integrity": "sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/type": "^2.0.0",
+ "ansi-escapes": "^4.3.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/prompts": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-6.0.1.tgz",
+ "integrity": "sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/checkbox": "^3.0.1",
+ "@inquirer/confirm": "^4.0.1",
+ "@inquirer/editor": "^3.0.1",
+ "@inquirer/expand": "^3.0.1",
+ "@inquirer/input": "^3.0.1",
+ "@inquirer/number": "^2.0.1",
+ "@inquirer/password": "^3.0.1",
+ "@inquirer/rawlist": "^3.0.1",
+ "@inquirer/search": "^2.0.1",
+ "@inquirer/select": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/rawlist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-3.0.1.tgz",
+ "integrity": "sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/type": "^2.0.0",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/search": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-2.0.1.tgz",
+ "integrity": "sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/figures": "^1.0.6",
+ "@inquirer/type": "^2.0.0",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/select": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-3.0.1.tgz",
+ "integrity": "sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/figures": "^1.0.6",
+ "@inquirer/type": "^2.0.0",
+ "ansi-escapes": "^4.3.2",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-2.0.0.tgz",
+ "integrity": "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==",
+ "license": "MIT",
+ "dependencies": {
+ "mute-stream": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -5706,11 +5937,19 @@
"@types/unist": "*"
}
},
+ "node_modules/@types/mute-stream": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz",
+ "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/node": {
"version": "22.9.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
"integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==",
- "devOptional": true,
"dependencies": {
"undici-types": "~6.19.8"
}
@@ -5908,6 +6147,12 @@
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q=="
},
+ "node_modules/@types/wrap-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz",
+ "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==",
+ "license": "MIT"
+ },
"node_modules/@types/yargs": {
"version": "16.0.5",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz",
@@ -6379,36 +6624,15 @@
"node": ">=18"
}
},
- "node_modules/@vitest/eslint-plugin": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.14.tgz",
- "integrity": "sha512-ej0cT5rUt7uvwxuu7Qxkm7fI+eaOq8vD34qGpuRoXCdvOybOlE5GDqtgvVCYbxLANkcRJfm5VDU1TnJmQRHi9g==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@typescript-eslint/utils": ">= 8.0",
- "eslint": ">= 8.57.0",
- "typescript": ">= 5.0.0",
- "vitest": "*"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- },
- "vitest": {
- "optional": true
- }
- }
- },
"node_modules/@vitest/expect": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.8.tgz",
- "integrity": "sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.5.tgz",
+ "integrity": "sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "2.1.8",
- "@vitest/utils": "2.1.8",
+ "@vitest/spy": "2.1.5",
+ "@vitest/utils": "2.1.5",
"chai": "^5.1.2",
"tinyrainbow": "^1.2.0"
},
@@ -6417,13 +6641,13 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.8.tgz",
- "integrity": "sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.5.tgz",
+ "integrity": "sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "2.1.8",
+ "@vitest/spy": "2.1.5",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.12"
},
@@ -6457,13 +6681,13 @@
}
},
"node_modules/@vitest/runner": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.8.tgz",
- "integrity": "sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.5.tgz",
+ "integrity": "sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "2.1.8",
+ "@vitest/utils": "2.1.5",
"pathe": "^1.1.2"
},
"funding": {
@@ -6471,13 +6695,13 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.8.tgz",
- "integrity": "sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.5.tgz",
+ "integrity": "sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.1.8",
+ "@vitest/pretty-format": "2.1.5",
"magic-string": "^0.30.12",
"pathe": "^1.1.2"
},
@@ -6485,10 +6709,23 @@
"url": "https://opencollective.com/vitest"
}
},
+ "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.5.tgz",
+ "integrity": "sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
"node_modules/@vitest/spy": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.8.tgz",
- "integrity": "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.5.tgz",
+ "integrity": "sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6499,13 +6736,13 @@
}
},
"node_modules/@vitest/utils": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz",
- "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.5.tgz",
+ "integrity": "sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.1.8",
+ "@vitest/pretty-format": "2.1.5",
"loupe": "^3.1.2",
"tinyrainbow": "^1.2.0"
},
@@ -6513,6 +6750,19 @@
"url": "https://opencollective.com/vitest"
}
},
+ "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.5.tgz",
+ "integrity": "sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
"node_modules/@wry/caches": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz",
@@ -6780,16 +7030,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/array.prototype.findlast": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
@@ -7364,39 +7604,6 @@
"node": ">=8"
}
},
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/bl/node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
"node_modules/bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
@@ -7914,7 +8121,8 @@
"node_modules/chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
- "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "license": "MIT"
},
"node_modules/chart.js": {
"version": "4.4.6",
@@ -8030,17 +8238,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/cli-spinners": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
- "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/cli-truncate": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
@@ -8108,11 +8305,12 @@
}
},
"node_modules/cli-width": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
- "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
+ "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "license": "ISC",
"engines": {
- "node": ">= 10"
+ "node": ">= 12"
}
},
"node_modules/cliui": {
@@ -8859,25 +9057,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/defaults": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
- "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
- "dependencies": {
- "clone": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/defaults/node_modules/clone": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
- "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
- "engines": {
- "node": ">=0.8"
- }
- },
"node_modules/defer-to-connect": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
@@ -9029,19 +9208,6 @@
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz",
"integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg=="
},
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -9851,221 +10017,68 @@
"string.prototype.matchall": "^4.0.11",
"string.prototype.repeat": "^1.0.0"
},
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/resolve": {
- "version": "2.0.0-next.5",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
- "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/eslint-plugin-tsdoc": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.3.0.tgz",
- "integrity": "sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==",
- "dev": true,
- "dependencies": {
- "@microsoft/tsdoc": "0.15.0",
- "@microsoft/tsdoc-config": "0.17.0"
- }
- },
- "node_modules/eslint-plugin-vitest": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.5.4.tgz",
- "integrity": "sha512-um+odCkccAHU53WdKAw39MY61+1x990uXjSPguUCq3VcEHdqJrOb8OTMrbYlY6f9jAKx7x98kLVlIe3RJeJqoQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/utils": "^7.7.1"
- },
- "engines": {
- "node": "^18.0.0 || >= 20.0.0"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "vitest": "*"
- },
- "peerDependenciesMeta": {
- "@typescript-eslint/eslint-plugin": {
- "optional": true
- },
- "vitest": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/scope-manager": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz",
- "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "7.18.0",
- "@typescript-eslint/visitor-keys": "7.18.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/types": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
- "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/typescript-estree": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz",
- "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "@typescript-eslint/types": "7.18.0",
- "@typescript-eslint/visitor-keys": "7.18.0",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/utils": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz",
- "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "7.18.0",
- "@typescript-eslint/types": "7.18.0",
- "@typescript-eslint/typescript-estree": "7.18.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
+ "engines": {
+ "node": ">=4"
+ },
"peerDependencies": {
- "eslint": "^8.56.0"
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
- "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/visitor-keys": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz",
- "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==",
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "7.18.0",
- "eslint-visitor-keys": "^3.4.3"
+ "esutils": "^2.0.2"
},
"engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "node": ">=0.10.0"
}
},
- "node_modules/eslint-plugin-vitest/node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "node_modules/eslint-plugin-react/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
+ "engines": {
+ "node": ">=4.0"
}
},
- "node_modules/eslint-plugin-vitest/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
"dev": true,
- "license": "ISC",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
},
- "engines": {
- "node": ">=16 || 14 >=14.17"
+ "bin": {
+ "resolve": "bin/resolve"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-tsdoc": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.3.0.tgz",
+ "integrity": "sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==",
+ "dev": true,
+ "dependencies": {
+ "@microsoft/tsdoc": "0.15.0",
+ "@microsoft/tsdoc-config": "0.17.0"
}
},
"node_modules/eslint-visitor-keys": {
@@ -10508,6 +10521,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
"integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "license": "MIT",
"dependencies": {
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
@@ -10521,6 +10535,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -10606,28 +10621,6 @@
"bser": "2.1.1"
}
},
- "node_modules/figures": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
- "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
- "dependencies": {
- "escape-string-regexp": "^1.0.5"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/figures/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -11062,27 +11055,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/globrex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
@@ -11242,6 +11214,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
"engines": {
"node": ">=8"
}
@@ -11744,79 +11717,22 @@
"dev": true
},
"node_modules/inquirer": {
- "version": "8.2.6",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz",
- "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==",
- "dependencies": {
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.1.1",
- "cli-cursor": "^3.1.0",
- "cli-width": "^3.0.0",
- "external-editor": "^3.0.3",
- "figures": "^3.0.0",
- "lodash": "^4.17.21",
- "mute-stream": "0.0.8",
- "ora": "^5.4.1",
- "run-async": "^2.4.0",
- "rxjs": "^7.5.5",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0",
- "through": "^2.3.6",
- "wrap-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/inquirer/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/inquirer/node_modules/cli-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
- "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
- "dependencies": {
- "restore-cursor": "^3.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/inquirer/node_modules/restore-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
- "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/inquirer/node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-11.1.0.tgz",
+ "integrity": "sha512-CmLAZT65GG/v30c+D2Fk8+ceP6pxD6RL+hIUOWAltCmeyEqWYwqu9v76q03OvjyZ3AB0C1Ala2stn1z/rMqGEw==",
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
+ "@inquirer/core": "^9.2.1",
+ "@inquirer/prompts": "^6.0.1",
+ "@inquirer/type": "^2.0.0",
+ "@types/mute-stream": "^0.0.4",
+ "ansi-escapes": "^4.3.2",
+ "mute-stream": "^1.0.0",
+ "run-async": "^3.0.0",
+ "rxjs": "^7.8.1"
},
"engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
"node_modules/internal-slot": {
@@ -12122,14 +12038,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-interactive": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
- "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -12344,17 +12252,6 @@
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
"dev": true
},
- "node_modules/is-unicode-supported": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
- "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-weakmap": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
@@ -14688,7 +14585,8 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
},
"node_modules/lodash._reinterpolate": {
"version": "3.0.0",
@@ -14735,36 +14633,6 @@
"lodash._reinterpolate": "^3.0.0"
}
},
- "node_modules/log-symbols": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
- "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
- "dependencies": {
- "chalk": "^4.1.0",
- "is-unicode-supported": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
"node_modules/log-update": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
@@ -15277,6 +15145,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
"engines": {
"node": ">=6"
}
@@ -15377,9 +15246,13 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/mute-stream": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
- "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
},
"node_modules/nanoid": {
"version": "3.3.7",
@@ -15793,6 +15666,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
"dependencies": {
"mimic-fn": "^2.1.0"
},
@@ -15870,66 +15744,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/ora": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
- "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
- "dependencies": {
- "bl": "^4.1.0",
- "chalk": "^4.1.0",
- "cli-cursor": "^3.1.0",
- "cli-spinners": "^2.5.0",
- "is-interactive": "^1.0.0",
- "is-unicode-supported": "^0.1.0",
- "log-symbols": "^4.1.0",
- "strip-ansi": "^6.0.0",
- "wcwidth": "^1.0.1"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/ora/node_modules/cli-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
- "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
- "dependencies": {
- "restore-cursor": "^3.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ora/node_modules/restore-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
- "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/os-browserify": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
@@ -15939,6 +15753,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -17642,9 +17457,10 @@
]
},
"node_modules/run-async": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
- "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
+ "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
+ "license": "MIT",
"engines": {
"node": ">=0.12.0"
}
@@ -17980,7 +17796,8 @@
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
@@ -18438,6 +18255,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -18586,11 +18404,6 @@
"node": ">=8"
}
},
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
- },
"node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
@@ -18697,6 +18510,7 @@
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "license": "MIT",
"dependencies": {
"os-tmpdir": "~1.0.2"
},
@@ -19537,8 +19351,7 @@
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
- "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
- "devOptional": true
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.1",
@@ -19958,9 +19771,9 @@
}
},
"node_modules/vite-node": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.8.tgz",
- "integrity": "sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.5.tgz",
+ "integrity": "sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -20292,19 +20105,19 @@
}
},
"node_modules/vitest": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.8.tgz",
- "integrity": "sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==",
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.5.tgz",
+ "integrity": "sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "2.1.8",
- "@vitest/mocker": "2.1.8",
- "@vitest/pretty-format": "^2.1.8",
- "@vitest/runner": "2.1.8",
- "@vitest/snapshot": "2.1.8",
- "@vitest/spy": "2.1.8",
- "@vitest/utils": "2.1.8",
+ "@vitest/expect": "2.1.5",
+ "@vitest/mocker": "2.1.5",
+ "@vitest/pretty-format": "^2.1.5",
+ "@vitest/runner": "2.1.5",
+ "@vitest/snapshot": "2.1.5",
+ "@vitest/spy": "2.1.5",
+ "@vitest/utils": "2.1.5",
"chai": "^5.1.2",
"debug": "^4.3.7",
"expect-type": "^1.1.0",
@@ -20316,7 +20129,7 @@
"tinypool": "^1.0.1",
"tinyrainbow": "^1.2.0",
"vite": "^5.0.0",
- "vite-node": "2.1.8",
+ "vite-node": "2.1.5",
"why-is-node-running": "^2.3.0"
},
"bin": {
@@ -20331,8 +20144,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "2.1.8",
- "@vitest/ui": "2.1.8",
+ "@vitest/browser": "2.1.5",
+ "@vitest/ui": "2.1.5",
"happy-dom": "*",
"jsdom": "*"
},
@@ -20409,14 +20222,6 @@
"loose-envify": "^1.0.0"
}
},
- "node_modules/wcwidth": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
- "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
- "dependencies": {
- "defaults": "^1.0.3"
- }
- },
"node_modules/web-vitals": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
@@ -20758,6 +20563,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/yoctocolors-cjs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz",
+ "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/zen-observable": {
"version": "0.8.15",
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
diff --git a/package.json b/package.json
index aee85b5772..a922f88205 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
"i18next": "^23.15.1",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.6.1",
- "inquirer": "^8.0.0",
+ "inquirer": "^11.0.2",
"js-cookie": "^3.0.1",
"lcov-result-merger": "^5.0.1",
"markdown-toc": "^1.2.0",
diff --git a/src/setup/askForCustomPort/askForCustomPort.test.ts b/src/setup/askForCustomPort/askForCustomPort.test.ts
index 0df6259ba1..c46f7b3f91 100644
--- a/src/setup/askForCustomPort/askForCustomPort.test.ts
+++ b/src/setup/askForCustomPort/askForCustomPort.test.ts
@@ -1,24 +1,110 @@
import inquirer from 'inquirer';
-import { askForCustomPort } from './askForCustomPort';
+import { askForCustomPort, validatePort } from './askForCustomPort';
jest.mock('inquirer');
describe('askForCustomPort', () => {
- test('should return default port if user provides no input', async () => {
- jest
- .spyOn(inquirer, 'prompt')
- .mockResolvedValueOnce({ customPort: '4321' });
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ describe('basic port validation', () => {
+ test('should return default port if user provides no input', async () => {
+ jest
+ .spyOn(inquirer, 'prompt')
+ .mockResolvedValueOnce({ customPort: '4321' });
+
+ const result = await askForCustomPort();
+ expect(result).toBe(4321);
+ });
+
+ test('should return user-provided port', async () => {
+ jest
+ .spyOn(inquirer, 'prompt')
+ .mockResolvedValueOnce({ customPort: '8080' });
+
+ const result = await askForCustomPort();
+ expect(result).toBe(8080);
+ });
+
+ test('should return validation error if port not between 1 and 65535', () => {
+ expect(validatePort('abcd')).toBe(
+ 'Please enter a valid port number between 1 and 65535.',
+ );
+ expect(validatePort('-1')).toBe(
+ 'Please enter a valid port number between 1 and 65535.',
+ );
+ expect(validatePort('70000')).toBe(
+ 'Please enter a valid port number between 1 and 65535.',
+ );
+ });
+ });
- const result = await askForCustomPort();
- expect(result).toBe('4321');
+ describe('retry mechanism', () => {
+ test('should handle invalid port input and prompt again', async () => {
+ jest
+ .spyOn(inquirer, 'prompt')
+ .mockResolvedValueOnce({ customPort: 'abcd' })
+ .mockResolvedValueOnce({ customPort: '8080' });
+
+ const result = await askForCustomPort();
+ expect(result).toBe(8080);
+ });
+
+ test('should return default port after maximum retry attempts', async () => {
+ jest
+ .spyOn(inquirer, 'prompt')
+ .mockResolvedValueOnce({ customPort: 'invalid-port-attempt1' })
+ .mockResolvedValueOnce({ customPort: 'invalid-port-attempt2' })
+ .mockResolvedValueOnce({ customPort: 'invalid-port-attempt3' })
+ .mockResolvedValueOnce({ customPort: 'invalid-port-attempt4' })
+ .mockResolvedValueOnce({ customPort: 'invalid-port-attempt5' })
+ .mockResolvedValueOnce({ customPort: 'invalid-port-attempt6' });
+
+ const result = await askForCustomPort();
+ expect(result).toBe(4321);
+ });
});
- test('should return user-provided port', async () => {
- jest
- .spyOn(inquirer, 'prompt')
- .mockResolvedValueOnce({ customPort: '8080' });
+ describe('reserved ports', () => {
+ test('should return user-provided port after confirming reserved port', async () => {
+ jest
+ .spyOn(inquirer, 'prompt')
+ .mockResolvedValueOnce({ customPort: '80' })
+ .mockResolvedValueOnce({ confirmPort: true });
+
+ const result = await askForCustomPort();
+ expect(result).toBe(80);
+ });
+
+ test('should re-prompt user for port if reserved port confirmation is denied', async () => {
+ jest
+ .spyOn(inquirer, 'prompt')
+ .mockResolvedValueOnce({ customPort: '80' })
+ .mockResolvedValueOnce({ confirmPort: false })
+ .mockResolvedValueOnce({ customPort: '8080' });
+
+ const result = await askForCustomPort();
+ expect(result).toBe(8080);
+ });
+
+ test('should return default port if reserved port confirmation is denied after maximum retry attempts', async () => {
+ jest
+ .spyOn(inquirer, 'prompt')
+ .mockResolvedValueOnce({ customPort: '80' })
+ .mockResolvedValueOnce({ confirmPort: false })
+ .mockResolvedValueOnce({ customPort: '80' })
+ .mockResolvedValueOnce({ confirmPort: false })
+ .mockResolvedValueOnce({ customPort: '80' })
+ .mockResolvedValueOnce({ confirmPort: false })
+ .mockResolvedValueOnce({ customPort: '80' })
+ .mockResolvedValueOnce({ confirmPort: false })
+ .mockResolvedValueOnce({ customPort: '80' })
+ .mockResolvedValueOnce({ confirmPort: false })
+ .mockResolvedValueOnce({ customPort: '80' });
- const result = await askForCustomPort();
- expect(result).toBe('8080');
+ const result = await askForCustomPort();
+ expect(result).toBe(4321);
+ });
});
});
diff --git a/src/setup/askForCustomPort/askForCustomPort.ts b/src/setup/askForCustomPort/askForCustomPort.ts
index 8a923f678f..dd0fd51854 100644
--- a/src/setup/askForCustomPort/askForCustomPort.ts
+++ b/src/setup/askForCustomPort/askForCustomPort.ts
@@ -1,14 +1,63 @@
import inquirer from 'inquirer';
-export async function askForCustomPort(): Promise {
- const { customPort } = await inquirer.prompt([
+const DEFAULT_PORT = 4321;
+const MAX_RETRY_ATTEMPTS = 5;
+
+export function validatePort(input: string): string | boolean {
+ const port = Number(input);
+ if (
+ Number.isNaN(port) ||
+ !Number.isInteger(port) ||
+ port <= 0 ||
+ port > 65535
+ ) {
+ return 'Please enter a valid port number between 1 and 65535.';
+ }
+ return true;
+}
+
+export async function reservedPortWarning(port: number): Promise {
+ const { confirmPort } = await inquirer.prompt<{ confirmPort: boolean }>([
{
- type: 'input',
- name: 'customPort',
- message:
- 'Enter custom port for development server (leave blank for default 4321):',
- default: 4321,
+ type: 'confirm',
+ name: 'confirmPort',
+ message: `Port ${port} is a reserved port. Are you sure you want to use it?`,
+ default: false,
},
]);
- return customPort;
+
+ return confirmPort;
+}
+
+export async function askForCustomPort(): Promise {
+ let remainingAttempts = MAX_RETRY_ATTEMPTS;
+
+ while (remainingAttempts--) {
+ const { customPort } = await inquirer.prompt<{ customPort: string }>([
+ {
+ type: 'input',
+ name: 'customPort',
+ message: `Enter custom port for development server (leave blank for default ${DEFAULT_PORT}):`,
+ default: DEFAULT_PORT.toString(),
+ validate: validatePort,
+ },
+ ]);
+
+ if (customPort && validatePort(customPort) === true) {
+ if (Number(customPort) >= 1024) {
+ return Number(customPort);
+ }
+
+ if (
+ Number(customPort) < 1024 &&
+ (await reservedPortWarning(Number(customPort)))
+ ) {
+ return Number(customPort);
+ }
+ }
+ }
+ console.log(
+ `\nMaximum attempts reached. Using default port ${DEFAULT_PORT}.`,
+ );
+ return DEFAULT_PORT;
}
diff --git a/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts
index b1490222b4..3a11a0d799 100644
--- a/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts
+++ b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.test.ts
@@ -30,17 +30,9 @@ describe('askForTalawaApiUrl', () => {
});
test('should return the default endpoint when the user does not enter anything', async () => {
- const mockPrompt = jest
- .spyOn(inquirer, 'prompt')
- .mockImplementation(async (questions: any) => {
- const answers: Record = {};
- questions.forEach(
- (question: { name: string | number; default: any }) => {
- answers[question.name] = question.default;
- },
- );
- return answers;
- });
+ const mockPrompt = jest.spyOn(inquirer, 'prompt').mockResolvedValueOnce({
+ endpoint: 'http://localhost:4000/graphql/',
+ });
const result = await askForTalawaApiUrl();
diff --git a/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts
index 97daa1ac89..713ed7dc68 100644
--- a/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts
+++ b/src/setup/askForTalawaApiUrl/askForTalawaApiUrl.ts
@@ -1,7 +1,7 @@
import inquirer from 'inquirer';
export async function askForTalawaApiUrl(): Promise {
- const { endpoint } = await inquirer.prompt([
+ const { endpoint } = await inquirer.prompt<{ endpoint: string }>([
{
type: 'input',
name: 'endpoint',
From 705dcbc98755fe231f9b9cf636701c2c1b132625 Mon Sep 17 00:00:00 2001
From: Akshat Gupta <88035400+Akshat76845@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:16:07 +0530
Subject: [PATCH 49/57] Refactor : src/screens/OrgContribution component from
Jest to Vitest (#2729)
* Converted from Jest to Vitest
* Converted the code from Jest to Vitest
* Converted from Jest to Vitest
---------
Co-authored-by: Akshat
---
...tion.test.tsx => OrgContribution.spec.tsx} | 20 +++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
rename src/screens/OrgContribution/{OrgContribution.test.tsx => OrgContribution.spec.tsx} (80%)
diff --git a/src/screens/OrgContribution/OrgContribution.test.tsx b/src/screens/OrgContribution/OrgContribution.spec.tsx
similarity index 80%
rename from src/screens/OrgContribution/OrgContribution.test.tsx
rename to src/screens/OrgContribution/OrgContribution.spec.tsx
index f9f63c6807..f12057a626 100644
--- a/src/screens/OrgContribution/OrgContribution.test.tsx
+++ b/src/screens/OrgContribution/OrgContribution.spec.tsx
@@ -1,9 +1,9 @@
-import React, { act } from 'react';
+import React from 'react';
import { MockedProvider } from '@apollo/react-testing';
import { render } from '@testing-library/react';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
-import 'jest-location-mock';
+import { vi, describe, test, expect } from 'vitest';
import { I18nextProvider } from 'react-i18next';
import OrgContribution from './OrgContribution';
@@ -12,15 +12,20 @@ import i18nForTest from 'utils/i18nForTest';
import { StaticMockLink } from 'utils/StaticMockLink';
const link = new StaticMockLink([], true);
async function wait(ms = 100): Promise {
- await act(() => {
- return new Promise((resolve) => {
- setTimeout(resolve, ms);
- });
+ await new Promise((resolve) => {
+ setTimeout(resolve, ms);
});
}
describe('Organisation Contribution Page', () => {
test('should render props and text elements test for the screen', async () => {
+ Object.defineProperty(window, 'location', {
+ value: {
+ assign: vi.fn(),
+ },
+ writable: true,
+ });
+
window.location.assign('/orglist');
const { container } = render(
@@ -37,11 +42,10 @@ describe('Organisation Contribution Page', () => {
expect(container.textContent).not.toBe('Loading data...');
await wait();
-
expect(container.textContent).toMatch('Filter by Name');
expect(container.textContent).toMatch('Filter by Trans. ID');
expect(container.textContent).toMatch('Recent Stats');
expect(container.textContent).toMatch('Contribution');
- expect(window.location).toBeAt('/orglist');
+ expect(window.location.assign).toHaveBeenCalledWith('/orglist');
});
});
From 92ce58dfd00128a722943f4e38f739eaaa1eb1f1 Mon Sep 17 00:00:00 2001
From: Gurram Karthik <167804249+gurramkarthiknetha@users.noreply.github.com>
Date: Mon, 23 Dec 2024 04:21:39 +0530
Subject: [PATCH 50/57] fixed:#1887 Event and Holiday Calendar View (#2676)
* fixed-1887
* changed acc to bot
* final change
* gitpush final change
* 1 conflict resloved
* 1 conflict reslove
* 2nd conflict resloved
* changed css acc to gautam-divyanshu
* decreased time
* changed in event calendar
---------
Co-authored-by: Peter Harrison <16875803+palisadoes@users.noreply.github.com>
---
.../EventCalendar/EventCalendar.module.css | 177 ++++++++++++-
.../EventCalendar/EventCalendar.tsx | 240 +++++++-----------
src/screens/UserPortal/Posts/Posts.test.tsx | 5 +-
src/setupTests.ts | 2 +-
4 files changed, 265 insertions(+), 159 deletions(-)
diff --git a/src/components/EventCalendar/EventCalendar.module.css b/src/components/EventCalendar/EventCalendar.module.css
index 921af48bae..607d750f85 100644
--- a/src/components/EventCalendar/EventCalendar.module.css
+++ b/src/components/EventCalendar/EventCalendar.module.css
@@ -271,14 +271,6 @@
.expand_event_list {
display: block;
}
-
-.list_container {
- padding: 5px;
- width: fit-content;
- display: flex;
- flex-direction: row;
-}
-
.event_list_hour {
display: flex;
flex-direction: row;
@@ -316,7 +308,8 @@
flex-grow: 1;
}
-@media only screen and (max-width: 700px) {
+@media only screen and (max-width: var(--mobile-breakpoint)) {
+ /** @breakpoint --mobile-breakpoint: 768px */
.event_list {
display: none;
}
@@ -331,7 +324,7 @@
}
}
-@media only screen and (max-width: 500px) {
+@media only screen and (max-width: var(--small-mobile-breakpoint)) {
.btn__more {
font-size: 12px;
}
@@ -344,7 +337,22 @@
gap: 10px;
margin-top: 35px;
}
+.base_card {
+ flex: 1;
+ padding: 20px;
+ border-radius: 10px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
+}
+
+.holidays_card {
+ composes: base_card;
+ background-color: var(--holiday-card-bg);
+}
+.events_card {
+ composes: base_card;
+ background-color: #ffffff;
+}
.card__holidays {
background-color: rgba(246, 242, 229, 1);
display: flex;
@@ -415,9 +423,150 @@
border-radius: 10px;
}
-.userEvents__color {
- height: 15px;
- width: 40px;
- background: rgba(146, 200, 141, 0.5);
+.baseIndicator {
+ border-radius: 5px;
+ width: 20px;
+ height: 12px;
+ display: inline-block;
+}
+
+.holidayText {
+ font-size: 14px;
+ color: #555555;
+}
+.eventsLegend {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.list_container {
+ padding: 5px;
+ width: fit-content;
+ display: flex;
+ align-items: center;
+ gap: var(--indicator-spacing);
+}
+
+.holidayIndicator {
+ composes: baseIndicator;
+ background-color: rgba(0, 0, 0, 0.15);
+}
+
+:root {
+ /* Color scheme for holiday-related elements */
+ --color-user-event: rgba(139, 195, 74, 1);
+ /* Holiday colors */
+ --color-holiday-indicator: rgba(0, 0, 0, 0.15);
+ --color-holiday-date: rgba(255, 152, 0, 1);
+ /* Breakpoints for responsive design */
+ --mobile-breakpoint: 700px;
+ --small-mobile-breakpoint: 480px;
+ --text-color-primary: rgba(51, 51, 51, 1);
+ --text-color-secondary: rgba(85, 85, 85, 1);
+ /* Card styles */
+ --card-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ --holiday-card-bg: #f6f2e5;
+ --holiday-date-color: #d35400;
+ --indicator-spacing: 8px;
+ /* Interactive states */
+ --hover-bg-color: rgba(0, 0, 0, 0.05);
+}
+.organizationIndicator {
+ composes: baseIndicator;
+ background-color: rgba(82, 172, 255, 0.5);
+}
+
+.legendText {
+ font-size: 14px;
+ color: #555555;
+}
+@media only screen and (max-width: var(--mobile-breakpoint)) {
+ .list_container,
+ .eventsLegend {
+ gap: 4px;
+ }
+
+ .holidayIndicator,
+ .organizationIndicator {
+ width: 16px;
+ height: 10px;
+ }
+
+ .holidayText,
+ .legendText {
+ font-size: 12px;
+ }
+}
+.card_title {
+ font-size: 16px;
+ font-weight: 600;
+ color: var(--text-color-primary);
+ margin-bottom: 15px;
+}
+
+.card_list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.card_list_item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 10px;
+ font-size: 14px;
+ color: var(--text-color-secondary);
+}
+
+.holiday_date {
+ font-weight: 500;
+ margin-right: 10px;
+ color: var(--holiday-date-color);
+}
+
+.calendar_infocards {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: flex-start;
+ gap: 20px;
+ padding: 20px;
+ background-color: var(--grey-bg-color);
+}
+.holidays_card,
+.events_card {
+ flex: 1;
+ padding: 20px;
border-radius: 10px;
+ box-shadow: var(--card-shadow);
+}
+
+.holidays_card {
+ background-color: var(--holiday-card-bg);
+}
+
+.events_card {
+ background-color: white;
+}
+
+.legend {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.userEvents__color {
+ composes: baseIndicator;
+ display: inline-block;
+ background-color: rgba(139, 195, 74, 1);
+}
+
+.card_list_item:hover {
+ background-color: var(--hover-bg-color);
+ transition: background-color 0.2s ease;
+}
+.card_list_item:focus-visible {
+ background-color: var(--hover-bg-color);
+ transition: background-color 0.2s ease;
}
diff --git a/src/components/EventCalendar/EventCalendar.tsx b/src/components/EventCalendar/EventCalendar.tsx
index 575bda391e..ebcf8be942 100644
--- a/src/components/EventCalendar/EventCalendar.tsx
+++ b/src/components/EventCalendar/EventCalendar.tsx
@@ -1,16 +1,14 @@
import EventListCard from 'components/EventListCard/EventListCard';
import dayjs from 'dayjs';
+import React, { useState, useEffect, useMemo } from 'react';
import Button from 'react-bootstrap/Button';
-import React, { useState, useEffect } from 'react';
import styles from './EventCalendar.module.css';
import { ChevronLeft, ChevronRight } from '@mui/icons-material';
-import CurrentHourIndicator from 'components/CurrentHourIndicator/CurrentHourIndicator';
import { ViewType } from 'screens/OrganizationEvents/OrganizationEvents';
import HolidayCard from '../HolidayCards/HolidayCard';
-import { holidays, hours, months, weekdays } from './constants';
+import { holidays, months, weekdays } from './constants';
import type { InterfaceRecurrenceRule } from 'utils/recurrenceUtils';
import YearlyEventCalender from './YearlyEventCalender';
-
interface InterfaceEventListCardProps {
userRole?: string;
key?: string;
@@ -75,7 +73,6 @@ const Calendar: React.FC = ({
);
const [expanded, setExpanded] = useState(-1);
const [windowWidth, setWindowWidth] = useState(window.screen.width);
-
useEffect(() => {
function handleResize(): void {
setWindowWidth(window.screen.width);
@@ -138,9 +135,21 @@ const Calendar: React.FC = ({
}
};
- /**
- * Moves the calendar view to the next month.
- */
+ const filteredHolidays = useMemo(() => {
+ return Array.isArray(holidays)
+ ? holidays.filter((holiday) => {
+ if (!holiday.date) {
+ if (process.env.NODE_ENV !== 'test') {
+ console.warn(`Holiday "${holiday.name}" has no date specified.`);
+ }
+ return false;
+ }
+ const holidayMonth = dayjs(holiday.date, 'MM-DD', true).month();
+ return holidayMonth === currentMonth;
+ })
+ : [];
+ }, [holidays, currentMonth]);
+
const handleNextMonth = (): void => {
if (currentMonth === 11) {
setCurrentMonth(0);
@@ -149,10 +158,6 @@ const Calendar: React.FC = ({
setCurrentMonth(currentMonth + 1);
}
};
-
- /**
- * Moves the calendar view to the previous date.
- */
const handlePrevDate = (): void => {
if (currentDate > 1) {
setCurrentDate(currentDate - 1);
@@ -193,9 +198,6 @@ const Calendar: React.FC = ({
}
};
- /**
- * Moves the calendar view to today's date.
- */
const handleTodayButton = (): void => {
setCurrentYear(today.getFullYear());
setCurrentMonth(today.getMonth());
@@ -264,6 +266,17 @@ const Calendar: React.FC = ({
);
}) || [];
+ const shouldShowViewMore = useMemo(() => {
+ return (
+ allDayEventsList.length > 2 ||
+ (windowWidth <= 700 && allDayEventsList.length > 0)
+ );
+ }, [allDayEventsList.length, windowWidth]);
+
+ const handleExpandClick: () => void = () => {
+ toggleExpand(-100);
+ };
+
return (
<>
@@ -284,7 +297,6 @@ const Calendar: React.FC
= ({
? styles.expand_list_container
: styles.list_container
}
- style={{ width: 'fit-content' }}
>
= ({
: styles.event_list_hour
}
>
- {expanded === -100
- ? allDayEventsList
- : allDayEventsList?.slice(0, 1)}
+ {Array.isArray(allDayEventsList) &&
+ allDayEventsList.length > 0 ? (
+ expanded === -100 ? (
+ allDayEventsList
+ ) : (
+ allDayEventsList.slice(0, 1)
+ )
+ ) : (
+
+ No events available
+
+ )}
- {(allDayEventsList?.length > 2 ||
- (windowWidth <= 700 && allDayEventsList?.length > 0)) && (
+ {Array.isArray(allDayEventsList) && (
)}
- {hours.map((hour, index) => {
- const timeEventsList: JSX.Element[] =
- events
- ?.filter((datas) => {
- const currDate = new Date(
- currentYear,
- currentMonth,
- currentDate,
- );
-
- if (
- parseInt(datas.startTime?.slice(0, 2) as string).toString() ==
- (index % 24).toString() &&
- datas.startDate == dayjs(currDate).format('YYYY-MM-DD')
- ) {
- return datas;
- }
- })
- .map((datas: InterfaceEventListCardProps) => {
- const attendees: { _id: string }[] = [];
- datas.attendees?.forEach((attendee: { _id: string }) => {
- const r = {
- _id: attendee._id,
- };
-
- attendees.push(r);
- });
-
- return (
-
- );
- }) || [];
- return (
-
-
-
{`${hour}`}
+
+
+
Holidays
+
+ {filteredHolidays.map((holiday, index) => (
+ -
+
+ {months[parseInt(holiday.date.slice(0, 2), 10) - 1]}{' '}
+ {holiday.date.slice(3)}
+
+ {holiday.name}
+
+ ))}
+
+
+
+
+
Events
+
+
+
+ Holidays
-
-
0
- ? styles.event_list_parent_current
- : styles.event_list_parent
- }
- >
- {index % 24 == new Date().getHours() &&
- new Date().getDate() == currentDate && (
-
- )}
-
-
- {}
- {expanded === index
- ? timeEventsList
- : timeEventsList?.slice(0, 1)}
-
- {(timeEventsList?.length > 1 ||
- (windowWidth <= 700 && timeEventsList?.length > 0)) && (
-
- )}
-
+
+
+
+ Events Created by Organization
+
+
+
+
+
+ Events Created by User
+
- );
- })}
+
+
>
);
};
@@ -448,10 +407,10 @@ const Calendar: React.FC
= ({
return days.map((date, index) => {
const className = [
date.getDay() === 0 || date.getDay() === 6 ? styles.day_weekends : '',
- date.toLocaleDateString() === today.toLocaleDateString() //Styling for today day cell
+ date.toLocaleDateString() === today.toLocaleDateString()
? styles.day__today
: '',
- date.getMonth() !== currentMonth ? styles.day__outside : '', //Styling for days outside the current month
+ date.getMonth() !== currentMonth ? styles.day__outside : '',
selectedDate?.getTime() === date.getTime() ? styles.day__selected : '',
styles.day,
].join(' ');
@@ -504,13 +463,12 @@ const Calendar: React.FC = ({
);
}) || [];
- const holidayList: JSX.Element[] = holidays
- .filter((holiday) => {
- if (holiday.date == dayjs(date).format('MM-DD')) return holiday;
- })
+ const holidayList: JSX.Element[] = filteredHolidays
+ .filter((holiday) => holiday.date === dayjs(date).format('MM-DD'))
.map((holiday) => {
return ;
});
+
return (
= ({
)}
{viewType == ViewType.MONTH ? (
-
+ <>
{weekdays.map((weekday, index) => (
@@ -611,18 +569,14 @@ const Calendar: React.FC = ({
))}
{renderDays()}
-
+ >
+ ) : viewType == ViewType.YEAR ? (
+
) : (
- //
-
- {viewType == ViewType.YEAR ? (
-
- ) : (
-
{renderHours()}
- )}
-
+
{renderHours()}
)}
+
{viewType == ViewType.YEAR ? (
diff --git a/src/screens/UserPortal/Posts/Posts.test.tsx b/src/screens/UserPortal/Posts/Posts.test.tsx
index aa5f03fdcf..433e36f94a 100644
--- a/src/screens/UserPortal/Posts/Posts.test.tsx
+++ b/src/screens/UserPortal/Posts/Posts.test.tsx
@@ -1,7 +1,7 @@
import React, { act } from 'react';
import { MockedProvider } from '@apollo/react-testing';
import type { RenderResult } from '@testing-library/react';
-import { render, screen, waitFor, within } from '@testing-library/react';
+import { render, screen, within } from '@testing-library/react';
import { I18nextProvider } from 'react-i18next';
import userEvent from '@testing-library/user-event';
import {
@@ -395,5 +395,8 @@ describe('HomeScreen with invalid orgId', () => {
);
const homeEl = await screen.findByTestId('homeEl');
expect(homeEl).toBeInTheDocument();
+
+ const postCardContainers = screen.queryAllByTestId('postCardContainer');
+ expect(postCardContainers).toHaveLength(0);
});
});
diff --git a/src/setupTests.ts b/src/setupTests.ts
index f0b48b39d0..d204b3ddc9 100644
--- a/src/setupTests.ts
+++ b/src/setupTests.ts
@@ -32,4 +32,4 @@ jestPreviewConfigure({
autoPreview: true,
});
-jest.setTimeout(17000);
+jest.setTimeout(18000);
From fd0fe5caf89ab653976e2f9be5f3ea4d0d2b0987 Mon Sep 17 00:00:00 2001
From: prathmesh703 <146568950+prathmesh703@users.noreply.github.com>
Date: Mon, 23 Dec 2024 07:56:57 +0530
Subject: [PATCH 51/57] Refactor: src/screens/OrganizationFunds from Jest to
Vitest (#2685)
---
...{FundModal.test.tsx => FundModal.spec.tsx} | 47 ++++++++++++++++---
src/screens/OrganizationFunds/FundModal.tsx | 8 ++--
...ds.test.tsx => OrganizationFunds.spec.tsx} | 41 +++++++++++-----
3 files changed, 72 insertions(+), 24 deletions(-)
rename src/screens/OrganizationFunds/{FundModal.test.tsx => FundModal.spec.tsx} (85%)
rename src/screens/OrganizationFunds/{OrganizationFunds.test.tsx => OrganizationFunds.spec.tsx} (85%)
diff --git a/src/screens/OrganizationFunds/FundModal.test.tsx b/src/screens/OrganizationFunds/FundModal.spec.tsx
similarity index 85%
rename from src/screens/OrganizationFunds/FundModal.test.tsx
rename to src/screens/OrganizationFunds/FundModal.spec.tsx
index c74b0434c3..7296f31661 100644
--- a/src/screens/OrganizationFunds/FundModal.test.tsx
+++ b/src/screens/OrganizationFunds/FundModal.spec.tsx
@@ -21,11 +21,12 @@ import { toast } from 'react-toastify';
import { MOCKS, MOCKS_ERROR } from './OrganizationFundsMocks';
import type { InterfaceFundModal } from './FundModal';
import FundModal from './FundModal';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -38,7 +39,7 @@ const translations = JSON.parse(
const fundProps: InterfaceFundModal[] = [
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
fund: {
_id: 'fundId',
name: 'Fund 1',
@@ -54,13 +55,13 @@ const fundProps: InterfaceFundModal[] = [
lastName: 'Doe',
},
},
- refetchFunds: jest.fn(),
+ refetchFunds: vi.fn(),
orgId: 'orgId',
mode: 'create',
},
{
isOpen: true,
- hide: jest.fn(),
+ hide: vi.fn(),
fund: {
_id: 'fundId',
name: 'Fund 1',
@@ -76,7 +77,7 @@ const fundProps: InterfaceFundModal[] = [
lastName: 'Doe',
},
},
- refetchFunds: jest.fn(),
+ refetchFunds: vi.fn(),
orgId: 'orgId',
mode: 'edit',
},
@@ -104,6 +105,7 @@ const renderFundModal = (
describe('PledgeModal', () => {
afterEach(() => {
cleanup();
+ vi.clearAllMocks();
});
it('should populate form fields with correct values in edit mode', async () => {
@@ -184,6 +186,37 @@ describe('PledgeModal', () => {
});
});
+ it('should not update the fund when no fields are changed', async () => {
+ renderFundModal(link1, fundProps[1]);
+
+ // Simulate no change to the fields
+ const fundNameInput = screen.getByLabelText(translations.fundName);
+ fireEvent.change(fundNameInput, { target: { value: 'Fund 1' } });
+
+ const fundIdInput = screen.getByLabelText(translations.fundId);
+ fireEvent.change(fundIdInput, { target: { value: '1111' } });
+
+ const taxDeductibleSwitch = screen.getByTestId('setTaxDeductibleSwitch');
+ fireEvent.click(taxDeductibleSwitch);
+ fireEvent.click(taxDeductibleSwitch);
+
+ const defaultSwitch = screen.getByTestId('setDefaultSwitch');
+ fireEvent.click(defaultSwitch);
+ fireEvent.click(defaultSwitch);
+
+ const archivedSwitch = screen.getByTestId('archivedSwitch');
+ fireEvent.click(archivedSwitch);
+ fireEvent.click(archivedSwitch);
+
+ fireEvent.click(screen.getByTestId('createFundFormSubmitBtn'));
+
+ await waitFor(() => {
+ expect(toast.success).not.toHaveBeenCalled();
+ expect(fundProps[1].refetchFunds).not.toHaveBeenCalled();
+ expect(fundProps[1].hide).not.toHaveBeenCalled();
+ });
+ });
+
it('should update fund', async () => {
renderFundModal(link1, fundProps[1]);
diff --git a/src/screens/OrganizationFunds/FundModal.tsx b/src/screens/OrganizationFunds/FundModal.tsx
index de4329e55c..b33270b30f 100644
--- a/src/screens/OrganizationFunds/FundModal.tsx
+++ b/src/screens/OrganizationFunds/FundModal.tsx
@@ -139,7 +139,9 @@ const FundModal: React.FC
= ({
if (isDefault != fund?.isDefault) {
updatedFields.isDefault = isDefault;
}
-
+ if (Object.keys(updatedFields).length === 0) {
+ return;
+ }
await updateFund({
variables: {
id: fund?._id,
@@ -157,9 +159,7 @@ const FundModal: React.FC = ({
hide();
toast.success(t('fundUpdated') as string);
} catch (error: unknown) {
- if (error instanceof Error) {
- toast.error(error.message);
- }
+ toast.error((error as Error).message);
}
};
diff --git a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx b/src/screens/OrganizationFunds/OrganizationFunds.spec.tsx
similarity index 85%
rename from src/screens/OrganizationFunds/OrganizationFunds.test.tsx
rename to src/screens/OrganizationFunds/OrganizationFunds.spec.tsx
index c6983e1d6d..b259b7da65 100644
--- a/src/screens/OrganizationFunds/OrganizationFunds.test.tsx
+++ b/src/screens/OrganizationFunds/OrganizationFunds.spec.tsx
@@ -11,7 +11,7 @@ import {
import userEvent from '@testing-library/user-event';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
-import { MemoryRouter, Route, Routes } from 'react-router-dom';
+import { MemoryRouter, Route, Routes, useParams } from 'react-router-dom';
import { store } from 'state/store';
import { StaticMockLink } from 'utils/StaticMockLink';
import i18nForTest from 'utils/i18nForTest';
@@ -20,11 +20,12 @@ import { MOCKS, MOCKS_ERROR, NO_FUNDS } from './OrganizationFundsMocks';
import type { ApolloLink } from '@apollo/client';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import { vi } from 'vitest';
-jest.mock('react-toastify', () => ({
+vi.mock('react-toastify', () => ({
toast: {
- success: jest.fn(),
- error: jest.fn(),
+ success: vi.fn(),
+ error: vi.fn(),
},
}));
@@ -67,21 +68,22 @@ const renderOrganizationFunds = (link: ApolloLink): RenderResult => {
describe('OrganizationFunds Screen =>', () => {
beforeEach(() => {
- jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({ orgId: 'orgId' }),
- }));
- });
-
- afterEach(() => {
- jest.clearAllMocks();
+ vi.mock('react-router-dom', async () => {
+ const actual = await vi.importActual('react-router-dom');
+ return {
+ ...actual,
+ useParams: vi.fn(),
+ };
+ });
});
afterEach(() => {
+ vi.clearAllMocks();
cleanup();
});
it('should render the Campaign Pledge screen', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
await waitFor(() => {
expect(screen.getByTestId('searchByName')).toBeInTheDocument();
@@ -89,29 +91,34 @@ describe('OrganizationFunds Screen =>', () => {
});
it('should redirect to fallback URL if URL params are undefined', async () => {
+ vi.mocked(useParams).mockReturnValue({});
render(
- } />
}
/>
+
} />
,
);
+ await waitFor(() => {
+ expect(window.location.pathname).toBe('/');
+ });
await waitFor(() => {
expect(screen.getByTestId('paramsError')).toBeInTheDocument();
});
});
it('open and close Create Fund modal', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
const createFundBtn = await screen.findByTestId('createFundBtn');
@@ -128,6 +135,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('open and close update fund modal', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
await waitFor(() => {
@@ -150,6 +158,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('Search the Funds list by name', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
const searchField = await screen.findByTestId('searchByName');
fireEvent.change(searchField, {
@@ -163,6 +172,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('should render the Fund screen with error', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link2);
await waitFor(() => {
expect(screen.getByTestId('errorMsg')).toBeInTheDocument();
@@ -170,6 +180,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('renders the empty fund component', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link3);
await waitFor(() =>
expect(screen.getByText(translations.noFundsFound)).toBeInTheDocument(),
@@ -177,6 +188,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('Sort the Pledges list by Latest created Date', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
const sortBtn = await screen.findByTestId('filter');
@@ -198,6 +210,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('Sort the Pledges list by Earliest created Date', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
const sortBtn = await screen.findByTestId('filter');
@@ -219,6 +232,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('Click on Fund Name', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
const fundName = await screen.findAllByTestId('fundName');
@@ -231,6 +245,7 @@ describe('OrganizationFunds Screen =>', () => {
});
it('Click on View Campaign', async () => {
+ vi.mocked(useParams).mockReturnValue({ orgId: 'orgId' });
renderOrganizationFunds(link1);
const viewBtn = await screen.findAllByTestId('viewBtn');
From ea264ce6a2c8dc3e2f997c9f3a041018fab57955 Mon Sep 17 00:00:00 2001
From: Shiva <148421597+shivasankaran18@users.noreply.github.com>
Date: Mon, 23 Dec 2024 22:38:31 +0530
Subject: [PATCH 52/57] Refactor : Vitest to SidePanel Component (#2735)
* refactor:vitest to Sidepanel
* ts-doc comments
---
.../SidePanel/{SidePanel.test.tsx => SidePanel.spec.tsx} | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
rename src/components/AddOn/support/components/SidePanel/{SidePanel.test.tsx => SidePanel.spec.tsx} (82%)
diff --git a/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx b/src/components/AddOn/support/components/SidePanel/SidePanel.spec.tsx
similarity index 82%
rename from src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx
rename to src/components/AddOn/support/components/SidePanel/SidePanel.spec.tsx
index d929278d0e..4a5f4e5692 100644
--- a/src/components/AddOn/support/components/SidePanel/SidePanel.test.tsx
+++ b/src/components/AddOn/support/components/SidePanel/SidePanel.spec.tsx
@@ -11,11 +11,16 @@ const client: ApolloClient
= new ApolloClient({
});
describe('Testing Contribution Stats', () => {
+ /**
+ * Props to be passed to the `SidePanel` component during the test.
+ */
const props = {
collapse: true,
children: '234',
};
-
+ /**
+ * Verifies that the `SidePanel` component renders correctly with given props.
+ */
test('should render props and text elements test for the SidePanel component', () => {
render(
From 23a5f6300ab5e6403ab8347b52347d8c917b2ea9 Mon Sep 17 00:00:00 2001
From: Shiva <148421597+shivasankaran18@users.noreply.github.com>
Date: Mon, 23 Dec 2024 22:42:45 +0530
Subject: [PATCH 53/57] refactor:vitest to checkInModal (#2734)
---
.../{CheckInModal.test.tsx => CheckInModal.spec.tsx} | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
rename src/components/CheckIn/{CheckInModal.test.tsx => CheckInModal.spec.tsx} (89%)
diff --git a/src/components/CheckIn/CheckInModal.test.tsx b/src/components/CheckIn/CheckInModal.spec.tsx
similarity index 89%
rename from src/components/CheckIn/CheckInModal.test.tsx
rename to src/components/CheckIn/CheckInModal.spec.tsx
index 1660c7c4bb..4f5a05328e 100644
--- a/src/components/CheckIn/CheckInModal.test.tsx
+++ b/src/components/CheckIn/CheckInModal.spec.tsx
@@ -12,6 +12,7 @@ import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { checkInQueryMock } from './mocks';
import { StaticMockLink } from 'utils/StaticMockLink';
+import { vi } from 'vitest';
const link = new StaticMockLink(checkInQueryMock, true);
@@ -19,9 +20,14 @@ describe('Testing Check In Attendees Modal', () => {
const props = {
show: true,
eventId: 'event123',
- handleClose: jest.fn(),
+ handleClose: vi.fn(),
};
+ /**
+ * Test case for rendering the CheckInModal component and verifying functionality.
+ * It checks that the modal renders fetched users and verifies the filtering mechanism.
+ */
+
test('The modal should be rendered, and all the fetched users should be shown properly and user filtering should work', async () => {
const { queryByText, queryByLabelText } = render(
From 86d59c211a7d914120f54051f2e9e9708b1a46dc Mon Sep 17 00:00:00 2001
From: MANDEEP N H <146331633+mandeepnh5@users.noreply.github.com>
Date: Mon, 23 Dec 2024 22:54:52 +0530
Subject: [PATCH 54/57] Refactoring CSS files: merged FundCompaignPledge styles
into global app.module.css (#2706)
* Update fundcomapignpledge
* deleted fundcompaignpledge local css file
* Fix linting issues
* fixed type check
* Update src/style/app.module.css
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* fixed some coderabbit issue
* Fixed testing issue
* Update src/style/app.module.css
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Fix coderabbit suggestion
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
.../FundCampaignPledge.module.css | 273 ------------------
.../FundCampaignPledge/FundCampaignPledge.tsx | 28 +-
.../FundCampaignPledge/PledgeDeleteModal.tsx | 2 +-
.../FundCampaignPledge/PledgeModal.tsx | 12 +-
src/style/app.module.css | 223 ++++++++++++++
5 files changed, 244 insertions(+), 294 deletions(-)
delete mode 100644 src/screens/FundCampaignPledge/FundCampaignPledge.module.css
diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.module.css b/src/screens/FundCampaignPledge/FundCampaignPledge.module.css
deleted file mode 100644
index cdf4476267..0000000000
--- a/src/screens/FundCampaignPledge/FundCampaignPledge.module.css
+++ /dev/null
@@ -1,273 +0,0 @@
-.pledgeContainer {
- margin: 0.6rem 0;
-}
-
-.container {
- min-height: 100vh;
-}
-
-.pledgeModal {
- max-width: 80vw;
- margin-top: 2vh;
- margin-left: 13vw;
-}
-
-.titlemodal {
- color: #707070;
- font-weight: 600;
- font-size: 32px;
- width: 65%;
- margin-bottom: 0px;
-}
-
-.modalCloseBtn {
- width: 40px;
- height: 40px;
- padding: 1rem;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
-.greenregbtn {
- margin: 1rem 0 0;
- margin-top: 15px;
- border: 1px solid #e8e5e5;
- box-shadow: 0 2px 2px #e8e5e5;
- padding: 10px 10px;
- border-radius: 5px;
- background-color: #31bb6b;
- width: 100%;
- font-size: 16px;
- color: white;
- outline: none;
- font-weight: 600;
- cursor: pointer;
- transition:
- transform 0.2s,
- box-shadow 0.2s;
- width: 100%;
-}
-.message {
- margin-top: 25%;
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
-}
-
-.errorIcon {
- transform: scale(1.5);
- color: var(--bs-danger);
- margin-bottom: 1rem;
-}
-
-.btnsContainer {
- display: flex;
- gap: 0.8rem;
- margin: 2.2rem 0 0.8rem 0;
-}
-
-.btnsContainer .input {
- flex: 1;
- min-width: 18rem;
- position: relative;
-}
-
-.btnsContainer input {
- outline: 1px solid var(--bs-gray-400);
-}
-
-.btnsContainer .input button {
- width: 52px;
-}
-
-.inputField {
- background-color: white;
- box-shadow: 0 1px 1px #31bb6b;
-}
-
-.dropdown {
- background-color: white;
- border: 1px solid #31bb6b;
- position: relative;
- display: inline-block;
- color: #31bb6b;
-}
-
-.tableHeader {
- background-color: var(--bs-primary);
- color: var(--bs-white);
- font-size: 1rem;
-}
-
-.rowBackground {
- background-color: var(--bs-white);
- max-height: 120px;
-}
-
-.TableImage {
- object-fit: cover;
- width: 25px !important;
- height: 25px !important;
- border-radius: 100% !important;
-}
-
-.avatarContainer {
- width: 28px;
- height: 26px;
-}
-
-.imageContainer {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.pledgerContainer {
- display: flex;
- align-items: center;
- justify-content: center;
- margin: 0.1rem 0.25rem;
- gap: 0.25rem;
- padding: 0.25rem 0.45rem;
- border-radius: 0.35rem;
- background-color: #31bb6b33;
- height: 2.2rem;
- margin-top: 0.75rem;
-}
-
-.noOutline input {
- outline: none;
-}
-
-.overviewContainer {
- display: flex;
- gap: 7rem;
- width: 100%;
- justify-content: space-between;
- margin: 1.5rem 0 0 0;
- padding: 1.25rem 2rem;
- background-color: rgba(255, 255, 255, 0.591);
-
- box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
- border-radius: 0.5rem;
-}
-
-.titleContainer {
- display: flex;
- flex-direction: column;
- gap: 0.6rem;
-}
-
-.titleContainer h3 {
- font-size: 1.75rem;
- font-weight: 750;
- color: #5e5e5e;
- margin-top: 0.2rem;
-}
-
-.titleContainer span {
- font-size: 0.9rem;
- margin-left: 0.5rem;
- font-weight: lighter;
- color: #707070;
-}
-
-.raisedAmount {
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 1.25rem;
- font-weight: 750;
- color: #5e5e5e;
-}
-
-.progressContainer {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- flex-grow: 1;
-}
-
-.progress {
- margin-top: 0.2rem;
- display: flex;
- flex-direction: column;
- gap: 0.3rem;
-}
-
-.endpoints {
- display: flex;
- position: relative;
- font-size: 0.85rem;
-}
-
-.start {
- position: absolute;
- top: 0px;
-}
-
-.end {
- position: absolute;
- top: 0px;
- right: 0px;
-}
-
-.moreContainer {
- display: flex;
- align-items: center;
-}
-
-.moreContainer:hover {
- text-decoration: underline;
- cursor: pointer;
-}
-
-.popup {
- z-index: 50;
- border-radius: 0.5rem;
- font-family: sans-serif;
- font-weight: 500;
- font-size: 0.875rem;
- margin-top: 0.5rem;
- padding: 0.75rem;
- border: 1px solid #e2e8f0;
- background-color: white;
- color: #1e293b;
- box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 0.15);
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.popupExtra {
- max-height: 15rem;
- overflow-y: auto;
-}
-
-.toggleGroup {
- width: 50%;
- min-width: 27.75rem;
- margin: 0.5rem 0rem;
-}
-
-.toggleBtn {
- padding: 0rem;
- height: 30px;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
-.toggleBtn:hover {
- color: #31bb6b !important;
-}
-
-input[type='radio']:checked + label {
- background-color: #31bb6a50 !important;
-}
-
-input[type='radio']:checked + label:hover {
- color: black !important;
-}
diff --git a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx
index d14ee9de06..8942265eea 100644
--- a/src/screens/FundCampaignPledge/FundCampaignPledge.tsx
+++ b/src/screens/FundCampaignPledge/FundCampaignPledge.tsx
@@ -9,7 +9,7 @@ import { Button, Dropdown, Form } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
import { Navigate, useParams } from 'react-router-dom';
import { currencySymbols } from 'utils/currency';
-import styles from './FundCampaignPledge.module.css';
+import styles from '../../style/app.module.css';
import PledgeDeleteModal from './PledgeDeleteModal';
import PledgeModal from './PledgeModal';
import { Breadcrumbs, Link, Stack, Typography } from '@mui/material';
@@ -233,14 +233,14 @@ const fundCampaignPledge = (): JSX.Element => {
src={user.image}
alt="pledge"
data-testid={`image${index + 1}`}
- className={styles.TableImage}
+ className={styles.TableImagePledge}
/>
) : (
-
-
+
+
setSearchTerm(e.target.value)}
data-testid="searchPledger"
@@ -557,7 +557,7 @@ const fundCampaignPledge = (): JSX.Element => {
),
}}
sx={dataGridStyle}
- getRowClassName={() => `${styles.rowBackground}`}
+ getRowClassName={() => `${styles.rowBackgroundPledge}`}
autoHeight
rowHeight={65}
rows={pledges.map((pledge) => ({
@@ -607,14 +607,14 @@ const fundCampaignPledge = (): JSX.Element => {
src={user.image}
alt="pledger"
data-testid={`extraImage${index + 1}`}
- className={styles.TableImage}
+ className={styles.TableImagePledge}
/>
) : (
= ({
= ({
format="DD/MM/YYYY"
label={tCommon('startDate')}
value={dayjs(pledgeStartDate)}
- className={styles.noOutline}
+ className={styles.noOutlinePledge}
onChange={(date: Dayjs | null): void => {
if (date) {
setFormState({
@@ -280,7 +280,7 @@ const PledgeModal: React.FC = ({
{
if (date) {
@@ -327,7 +327,7 @@ const PledgeModal: React.FC = ({
{
if (parseInt(e.target.value) > 0) {
@@ -343,7 +343,7 @@ const PledgeModal: React.FC = ({
{/* Button to submit the pledge form */}