Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Code Coverage in src/components/OrgPeopleListCard/OrgPeopleListCard.tsx #3112

Merged
merged 2 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 152 additions & 31 deletions src/components/OrgPeopleListCard/OrgPeopleListCard.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,99 @@
import React, { act } from 'react';
import { render, screen } from '@testing-library/react';
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import { MockedProvider } from '@apollo/react-testing';
import userEvent from '@testing-library/user-event';
import { I18nextProvider } from 'react-i18next';

import { BrowserRouter } from 'react-router-dom';
import OrgPeopleListCard from './OrgPeopleListCard';
import { REMOVE_MEMBER_MUTATION } from 'GraphQl/Mutations/mutations';
import i18nForTest from 'utils/i18nForTest';
import { BrowserRouter } from 'react-router-dom';
import { StaticMockLink } from 'utils/StaticMockLink';
import { describe, test, expect, vi } from 'vitest';
import { describe, test, expect, vi, beforeEach } from 'vitest';
import { toast } from 'react-toastify';

// Mock react-toastify
vi.mock('react-toastify', () => ({
toast: {
success: vi.fn(),
error: vi.fn(),
},
}));

// Mock react-router-dom
vi.mock('react-router-dom', async () => {
const actual = await vi.importActual('react-router-dom');
return {
...actual,
useParams: () => ({ orgId: '456' }),
Navigate: ({ to }: { to: string }) => {
window.location.pathname = to;
return null;
},
};
});

const MOCKS = [
{
request: {
query: REMOVE_MEMBER_MUTATION,
variable: { userid: '123', orgid: '456' },
variables: {
userid: '1',
orgid: '456',
},
},
result: {
data: {
organizations: [
{
_id: '1',
},
],
removeMember: {
_id: '1',
},
},
},
delay: 0,
},
];

const ERROR_MOCKS = [
{
request: {
query: REMOVE_MEMBER_MUTATION,
variables: {
userid: '1',
orgid: '456',
},
},
error: new Error('Failed to remove member'),
},
];
const link = new StaticMockLink(MOCKS, true);
async function wait(ms = 100): Promise<void> {
await act(() => {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
});
}

describe('Testing Organization People List Card', () => {
const props = {
toggleRemoveModal: () => true,
toggleRemoveModal: vi.fn(),
id: '1',
};
global.alert = vi.fn();

test('should render props and text elements test for the page component', async () => {
global.confirm = (): boolean => true;
beforeEach(() => {
vi.clearAllMocks();
// Mock window.location
Object.defineProperty(window, 'location', {
value: {
pathname: '',
reload: vi.fn(),
},
writable: true,
});
});

test('should render modal and handle successful member removal', async () => {
const link = new StaticMockLink(MOCKS, true);

render(
<MockedProvider addTypename={false} link={link}>
<MockedProvider
addTypename={false}
link={link}
defaultOptions={{
mutate: { errorPolicy: 'all' },
}}
>
<BrowserRouter>
<I18nextProvider i18n={i18nForTest}>
<OrgPeopleListCard {...props} />
Expand All @@ -56,26 +102,101 @@ describe('Testing Organization People List Card', () => {
</MockedProvider>,
);

await wait();
// Check if modal is rendered
expect(screen.getByText(/Remove Member/i)).toBeInTheDocument();
expect(
screen.getByText(/Do you want to remove this member?/i),
).toBeInTheDocument();

// Check buttons
expect(screen.getByRole('button', { name: /yes/i })).toBeInTheDocument();
expect(screen.getByRole('button', { name: /no/i })).toBeInTheDocument();

// Click remove button
const removeButton = screen.getByTestId('removeMemberBtn');
await userEvent.click(removeButton);

// Wait for mutation to complete
await new Promise((resolve) => setTimeout(resolve, 0));

// Wait for mutation and toast
await waitFor(
() => {
expect(toast.success).toHaveBeenCalled();
},
{ timeout: 3000 },
);

userEvent.click(screen.getByTestId(/removeMemberBtn/i));
// Check if page reload is triggered after delay
await waitFor(
() => {
expect(window.location.reload).toHaveBeenCalled();
},
{ timeout: 3000 },
);
});

test('Should not render modal when id is undefined', async () => {
global.confirm = (): boolean => false;
test('should handle failed member removal', async () => {
const link = new StaticMockLink(ERROR_MOCKS, true);

render(
<MockedProvider addTypename={false} link={link}>
<BrowserRouter>
<I18nextProvider i18n={i18nForTest}>
<OrgPeopleListCard id={undefined} toggleRemoveModal={() => true} />
<OrgPeopleListCard {...props} />
</I18nextProvider>
</BrowserRouter>
</MockedProvider>,
);

// Click remove button
const removeButton = screen.getByTestId('removeMemberBtn');
await userEvent.click(removeButton);

// Check error handling
await waitFor(
() => {
expect(toast.error).toHaveBeenCalled();
},
{ timeout: 3000 },
);
});

test('should handle modal close', async () => {
render(
<MockedProvider addTypename={false}>
<BrowserRouter>
<I18nextProvider i18n={i18nForTest}>
<OrgPeopleListCard {...props} />
</I18nextProvider>
</BrowserRouter>
</MockedProvider>,
);

await wait();
// Close via No button
const noButton = screen.getByRole('button', { name: /no/i });
await userEvent.click(noButton);
expect(props.toggleRemoveModal).toHaveBeenCalled();

expect(window.location.pathname).toEqual('/orglist');
// Close via close button
const closeButton = screen.getByRole('button', { name: '' }); // Close icon button
await userEvent.click(closeButton);
expect(props.toggleRemoveModal).toHaveBeenCalled();
});

test('should redirect when id is undefined', async () => {
render(
<MockedProvider addTypename={false}>
<BrowserRouter>
<I18nextProvider i18n={i18nForTest}>
<OrgPeopleListCard id={undefined} toggleRemoveModal={vi.fn()} />
</I18nextProvider>
</BrowserRouter>
</MockedProvider>,
);

await waitFor(() => {
expect(window.location.pathname).toBe('/orglist');
});
});
});
2 changes: 0 additions & 2 deletions src/components/OrgPeopleListCard/OrgPeopleListCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,13 @@ function orgPeopleListCard(
},
});
// If the mutation is successful, show a success message and reload the page
/* istanbul ignore next */
if (data) {
toast.success(t('memberRemoved') as string);
setTimeout(() => {
window.location.reload();
}, 2000);
}
} catch (error: unknown) {
/* istanbul ignore next */
errorHandler(t, error);
}
};
Expand Down
Loading