-
-
Notifications
You must be signed in to change notification settings - Fork 803
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve Code Coverage in src/components/UserPortal/CommentCard/Commen…
…tCard.tsx (#3093) * Improve Code Coverage in src/components/UserPortal/CommentCard/CommentCard.tsx * Improve Code Coverage in src/components/UserPortal/CommentCard/CommentCard.tsx
- Loading branch information
1 parent
4713884
commit f190f74
Showing
2 changed files
with
348 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import userEvent from '@testing-library/user-event'; | |
import { LIKE_COMMENT, UNLIKE_COMMENT } from 'GraphQl/Mutations/mutations'; | ||
import useLocalStorage from 'utils/useLocalstorage'; | ||
import { vi } from 'vitest'; | ||
import { toast } from 'react-toastify'; | ||
|
||
/** | ||
* Unit tests for the CommentCard component. | ||
|
@@ -26,6 +27,12 @@ import { vi } from 'vitest'; | |
*/ | ||
const { getItem, setItem } = useLocalStorage(); | ||
|
||
vi.mock('react-toastify', () => ({ | ||
toast: { | ||
error: vi.fn(), | ||
}, | ||
})); | ||
|
||
async function wait(ms = 100): Promise<void> { | ||
await act(() => { | ||
return new Promise((resolve) => { | ||
|
@@ -67,11 +74,30 @@ const MOCKS = [ | |
}, | ||
]; | ||
|
||
const defaultProps = { | ||
id: '1', | ||
creator: { | ||
id: '1', | ||
firstName: 'test', | ||
lastName: 'user', | ||
email: '[email protected]', | ||
}, | ||
likeCount: 1, | ||
likedBy: [{ id: '1' }], | ||
text: 'testComment', | ||
handleLikeComment: vi.fn(), | ||
handleDislikeComment: vi.fn(), | ||
}; | ||
|
||
const handleLikeComment = vi.fn(); | ||
const handleDislikeComment = vi.fn(); | ||
const link = new StaticMockLink(MOCKS, true); | ||
|
||
describe('Testing CommentCard Component [User Portal]', () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await act(async () => { | ||
await i18nForTest.changeLanguage('en'); | ||
|
@@ -249,4 +275,323 @@ describe('Testing CommentCard Component [User Portal]', () => { | |
setItem('userId', beforeUserId); | ||
} | ||
}); | ||
|
||
it('should handle like mutation error correctly', async () => { | ||
const errorMock = { | ||
request: { | ||
query: LIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
error: new Error('Failed to like comment'), | ||
}; | ||
|
||
const link = new StaticMockLink([errorMock], true); | ||
setItem('userId', '2'); // Set user as not having liked the comment | ||
|
||
render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await wait(); | ||
|
||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
await wait(); | ||
|
||
expect(toast.error).toHaveBeenCalled(); | ||
expect(defaultProps.handleLikeComment).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should handle unlike mutation error correctly', async () => { | ||
const errorMock = { | ||
request: { | ||
query: UNLIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
error: new Error('Failed to unlike comment'), | ||
}; | ||
|
||
const link = new StaticMockLink([errorMock], true); | ||
setItem('userId', '1'); // Set user as having liked the comment | ||
|
||
render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await wait(); | ||
|
||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
await wait(); | ||
|
||
expect(toast.error).toHaveBeenCalled(); | ||
expect(defaultProps.handleDislikeComment).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should successfully like a comment and update UI', async () => { | ||
const successMock = { | ||
request: { | ||
query: LIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
result: { | ||
data: { | ||
likeComment: { | ||
_id: '1', | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
const link = new StaticMockLink([successMock], true); | ||
setItem('userId', '2'); // Set user as not having liked the comment | ||
|
||
const { container } = render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await wait(); | ||
|
||
const initialLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
await wait(); | ||
|
||
const updatedLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
expect(updatedLikes).not.toBe(initialLikes); | ||
expect(defaultProps.handleLikeComment).toHaveBeenCalledWith('1'); | ||
}); | ||
|
||
it('should successfully unlike a comment and update UI', async () => { | ||
const successMock = { | ||
request: { | ||
query: UNLIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
result: { | ||
data: { | ||
unlikeComment: { | ||
_id: '1', | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
const link = new StaticMockLink([successMock], true); | ||
setItem('userId', '1'); // Set user as having liked the comment | ||
|
||
const { container } = render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await wait(); | ||
|
||
const initialLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
await wait(); | ||
|
||
const updatedLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
expect(updatedLikes).not.toBe(initialLikes); | ||
expect(defaultProps.handleDislikeComment).toHaveBeenCalledWith('1'); | ||
}); | ||
|
||
it('should show loading state while mutation is in progress', async () => { | ||
const slowMock = { | ||
request: { | ||
query: LIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
result: { | ||
data: { | ||
likeComment: { | ||
_id: '1', | ||
}, | ||
}, | ||
}, | ||
delay: 100, | ||
}; | ||
|
||
const link = new StaticMockLink([slowMock], true); | ||
setItem('userId', '2'); // Set user as not having liked the comment | ||
|
||
render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await wait(); | ||
|
||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
|
||
// HourglassBottomIcon should be visible during loading | ||
expect( | ||
document.querySelector('[data-testid="HourglassBottomIcon"]'), | ||
).toBeInTheDocument(); | ||
|
||
await wait(150); | ||
|
||
// After loading, ThumbUpIcon should be visible | ||
expect( | ||
document.querySelector('[data-testid="ThumbUpIcon"]'), | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
it('should not update state if mutation returns no data', async () => { | ||
const noDataMock = { | ||
request: { | ||
query: LIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
result: { | ||
data: null, | ||
}, | ||
}; | ||
|
||
const link = new StaticMockLink([noDataMock], true); | ||
setItem('userId', '2'); // Set user as not having liked the comment | ||
|
||
const { container } = render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
await wait(); | ||
|
||
const initialLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
await wait(); | ||
|
||
const updatedLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
expect(updatedLikes).toBe(initialLikes); | ||
expect(defaultProps.handleLikeComment).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should handle successful mutation with empty data for unlike', async () => { | ||
const emptyDataMock = { | ||
request: { | ||
query: UNLIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
result: { | ||
data: { | ||
unlikeComment: null, | ||
}, | ||
}, | ||
}; | ||
|
||
const link = new StaticMockLink([emptyDataMock], true); | ||
setItem('userId', '1'); // Set user as having liked the comment | ||
|
||
const { container } = render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
const initialLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
|
||
await wait(); | ||
|
||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
await wait(); | ||
|
||
// Verify that the likes count hasn't changed | ||
const updatedLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
expect(updatedLikes).toBe(initialLikes); | ||
|
||
// Verify that the callback wasn't called | ||
expect(defaultProps.handleDislikeComment).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should handle successful mutation with empty data for like', async () => { | ||
const emptyDataMock = { | ||
request: { | ||
query: LIKE_COMMENT, | ||
variables: { commentId: '1' }, | ||
}, | ||
result: { | ||
data: { | ||
likeComment: null, | ||
}, | ||
}, | ||
}; | ||
|
||
const link = new StaticMockLink([emptyDataMock], true); | ||
setItem('userId', '2'); // Set user as not having liked the comment | ||
|
||
const { container } = render( | ||
<MockedProvider addTypename={false} link={link}> | ||
<BrowserRouter> | ||
<Provider store={store}> | ||
<I18nextProvider i18n={i18nForTest}> | ||
<CommentCard {...defaultProps} /> | ||
</I18nextProvider> | ||
</Provider> | ||
</BrowserRouter> | ||
</MockedProvider>, | ||
); | ||
|
||
const initialLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
|
||
await wait(); | ||
|
||
userEvent.click(screen.getByTestId('likeCommentBtn')); | ||
await wait(); | ||
|
||
// Verify that the likes count hasn't changed | ||
const updatedLikes = container.textContent?.match(/\d+ Likes/)?.[0]; | ||
expect(updatedLikes).toBe(initialLikes); | ||
|
||
// Verify that the callback wasn't called | ||
expect(defaultProps.handleLikeComment).not.toHaveBeenCalled(); | ||
}); | ||
}); |
Oops, something went wrong.