-
-
Notifications
You must be signed in to change notification settings - Fork 814
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 of people.tsx #3308
improve code coverage of people.tsx #3308
Conversation
WalkthroughThe pull request focuses on enhancing the test coverage and functionality of the Changes
Assessment against linked issues
Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Our Pull Request Approval ProcessThanks for contributing! Testing Your CodeRemember, your PRs won't be reviewed until these criteria are met:
Our policies make our code better. ReviewersDo not assign reviewers. Our Queue Monitors will review your PR and assign them.
Reviewing Your CodeYour reviewer(s) will have the following roles:
CONTRIBUTING.mdRead our CONTRIBUTING.md file. Most importantly:
Other
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🔭 Outside diff range comments (1)
src/screens/UserPortal/People/People.tsx (1)
Line range hint
221-228
: Correct the serial number calculation for paginated resultsThe
sno
(serial number) is calculated using(index + 1)
, which resets to 1 on each page. To display a continuous serial number across pages, adjust the calculation to include the currentpage
androwsPerPage
.Apply this diff to correct the calculation:
- sno: (index + 1).toString(), + sno: (page * rowsPerPage + index + 1).toString(),This ensures that serial numbers are unique across all pages.
🧰 Tools
🪛 GitHub Actions: PR Workflow
[warning] Code style issues found. Prettier formatting check failed. Run Prettier with --write to fix.
🧹 Nitpick comments (5)
src/screens/UserPortal/People/People.spec.tsx (4)
37-69
: Consider movingMockData
type to a shared utility fileIf the
MockData
type will be used across multiple test files, consider moving it to a shared utility file or a__mocks__
directory for better reusability and maintainability.
Line range hint
103-108
: Avoid code duplication by centralizing thewait
functionThe
wait
function is defined multiple times in the test file. Consider moving it to a shared utility or helper function to avoid duplication and improve maintainability.Also applies to: 404-410
Line range hint
229-230
: Consolidatewindow.matchMedia
mock to reduce redundancyThe
window.matchMedia
mock is defined multiple times across your tests. Consider creating a shared setup or moving the mock to a global test configuration to reduce redundancy.Also applies to: 576-590, 824-837
563-567
: Avoid mocking React's built-in hooks directlyMocking
React.useState
directly is generally discouraged as it can lead to unpredictable behavior and affect other tests. Consider alternative approaches, such as using component props or context to control state during testing.src/screens/UserPortal/People/People.tsx (1)
139-139
: Fix formatting issues detected by PrettierThere are formatting issues on line 139. Please run Prettier to fix code style issues.
🧰 Tools
🪛 eslint
[error] 139-139: Delete
··
(prettier/prettier)
🪛 GitHub Actions: PR Workflow
[warning] Code style issues found. Prettier formatting check failed. Run Prettier with --write to fix.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/screens/UserPortal/People/People.spec.tsx
(4 hunks)src/screens/UserPortal/People/People.tsx
(3 hunks)
🧰 Additional context used
🪛 eslint
src/screens/UserPortal/People/People.tsx
[error] 116-116: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
[error] 139-139: Delete ··
(prettier/prettier)
🪛 GitHub Actions: PR Workflow
src/screens/UserPortal/People/People.tsx
[warning] Code style issues found. Prettier formatting check failed. Run Prettier with --write to fix.
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Analyse Code With CodeQL (javascript)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/screens/UserPortal/People/People.tsx (1)
115-120
:⚠️ Potential issueReplace
any
type withInterfaceMember
The
admin
parameter in the.map
function should use the existingInterfaceMember
interface instead ofany
to maintain type safety.- const adminsList = data2.organizations[0].admins.map((admin: any) => ({ + const adminsList = data2.organizations[0].admins.map((admin: InterfaceMember) => ({🧰 Tools
🪛 eslint
[error] 116-116: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
🪛 GitHub Check: Performs linting, formatting, type-checking, checking for different source and target branch
[failure] 116-116:
Unexpected any. Specify a different type🪛 GitHub Actions: PR Workflow
[error] 116-116: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)
🧹 Nitpick comments (2)
src/screens/UserPortal/People/People.tsx (2)
124-138
: Consider optimizing member list processingThe member list processing logic could be optimized in two ways:
- Extract the user type determination logic into a separate memoized function
- Consider using
useMemo
formembersList
to prevent unnecessary recalculations+ const determineUserType = useCallback((memberId: string) => + admins?.some((admin) => admin._id === memberId) ? 'Admin' : 'Member', + [admins]); + const membersList = useMemo(() => + data?.organizationsMemberConnection?.edges?.map((memberData: InterfaceMember) => ({ + ...memberData, + userType: determineUserType(memberData._id), + })) ?? [], + [data?.organizationsMemberConnection?.edges, determineUserType]); useEffect(() => { if (data?.organizationsMemberConnection?.edges) { - const membersList = data.organizationsMemberConnection.edges.map( - (memberData: InterfaceMember) => ({ - ...memberData, - userType: admins?.some((admin) => admin._id === memberData._id) - ? 'Admin' - : 'Member', - }), - ); setAllMembers(membersList); setMembers(mode === 0 ? membersList : admins); } }, [data, admins, mode]);
140-142
: Consider consolidating effectsThis effect appears redundant as the same logic exists in the previous effect (lines 124-138). Consider removing this effect to avoid potential race conditions and unnecessary renders.
- useEffect(() => { - setMembers(mode === 0 ? allMembers : admins); - }, [mode, allMembers, admins]);
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/screens/UserPortal/People/People.tsx
(3 hunks)
🧰 Additional context used
🪛 eslint
src/screens/UserPortal/People/People.tsx
[error] 116-116: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
🪛 GitHub Check: Performs linting, formatting, type-checking, checking for different source and target branch
src/screens/UserPortal/People/People.tsx
[failure] 116-116:
Unexpected any. Specify a different type
🪛 GitHub Actions: PR Workflow
src/screens/UserPortal/People/People.tsx
[error] 116-116: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (1)
src/screens/UserPortal/People/People.tsx (1)
221-221
: LGTM! Pagination implementation is robustThe pagination implementation correctly handles the member list with proper null checks and fallbacks.
Also applies to: 245-250
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop-postgres #3308 +/- ##
=====================================================
+ Coverage 8.43% 89.93% +81.49%
=====================================================
Files 310 331 +21
Lines 8069 8572 +503
Branches 1792 1898 +106
=====================================================
+ Hits 681 7709 +7028
+ Misses 7311 602 -6709
- Partials 77 261 +184
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Please make a minor commit. The failing test should be fixed with that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (7)
src/screens/UserPortal/People/People.tsx (2)
127-139
: Consider optimizing member type assignment for better performance.The current implementation performs an O(n*m) operation by calling
admins?.some()
for each member. For better performance with large datasets, consider pre-processing admin IDs into a Set.useEffect(() => { if (data?.organizationsMemberConnection?.edges) { + const adminIds = new Set(admins?.map(admin => admin._id)); const membersList = data.organizationsMemberConnection.edges.map( (memberData: InterfaceMember) => ({ ...memberData, - userType: admins?.some((admin) => admin._id === memberData._id) + userType: adminIds.has(memberData._id) ? 'Admin' : 'Member', }), ); setAllMembers(membersList); setMembers(mode === 0 ? membersList : admins); } }, [data, admins, mode]);
142-143
: Consider combining useEffect hooks.This effect appears redundant with the previous one as both update the
members
state based on similar conditions. Consider removing this effect and letting the previous one handle all member state updates.- useEffect(() => { - setMembers(mode === 0 ? allMembers : admins); - }, [mode, allMembers, admins]);src/screens/UserPortal/People/People.spec.tsx (5)
311-326
: Consider enhancing the loading state test.While the test verifies the presence of the loading state, it could be more thorough by:
- Verifying that the loading state disappears after data is loaded
- Checking that the content is not visible during loading
it('Shows loading state while fetching data', async () => { render( <MockedProvider addTypename={false} link={link}> <BrowserRouter> <Provider store={store}> <I18nextProvider i18n={i18nForTest}> <People /> </I18nextProvider> </Provider> </BrowserRouter> </MockedProvider>, ); expect(screen.getByText('Loading...')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); await wait(); + expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); + expect(screen.getByText('Noble Mittal')).toBeInTheDocument(); });
476-677
: Consider adding error case coverage for mode switching.While the mode switch tests are comprehensive, consider adding tests for:
- Network errors during mode switch
- Invalid response data during transition
Example test case to add:
it('handles network error during mode switch', async () => { const errorMock = { request: { query: ORGANIZATION_ADMINS_LIST, variables: { id: '' }, }, error: new Error('Network error'), }; setupTest([errorMock]); userEvent.click(screen.getByTestId('modeChangeBtn')); await waitFor(() => { userEvent.click(screen.getByTestId('modeBtn1')); }); await waitFor(() => { expect(screen.getByText('Error loading data')).toBeInTheDocument(); }); });
791-884
: Consider additional edge cases for testing.While the current edge cases are well tested, consider adding tests for:
- Maximum page size limits
- Boundary conditions for pagination
- Special characters in search
Example test:
it('handles special characters in search', async () => { const specialCharMock = { request: { query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, variables: { orgId: '', firstName_contains: '%$#@' }, }, result: { data: { organizationsMemberConnection: { edges: [], }, }, }, }; renderComponent([specialCharMock]); userEvent.type(screen.getByTestId('searchInput'), '%$#@'); userEvent.click(screen.getByTestId('searchBtn')); await waitFor(() => { expect(screen.getByText('Nothing to show')).toBeInTheDocument(); }); });
886-996
: Improve test setup reusability.Consider extracting common test setup patterns into reusable helper functions to reduce duplication and improve maintainability.
Example refactor:
const createTestWrapper = (mocks: MockData[] = []) => { return ( <MockedProvider addTypename={false} mocks={mocks}> <BrowserRouter> <Provider store={store}> <I18nextProvider i18n={i18nForTest}> <People /> </I18nextProvider> </Provider> </BrowserRouter> </MockedProvider> ); }; // Usage in tests it('test case', async () => { render(createTestWrapper([mockData])); // test assertions });
1070-1095
: Enhance pagination edge case assertions.While the navigation tests are good, consider adding more specific assertions:
- Verify page numbers
- Check disabled state of navigation buttons
- Validate items per page count
it('handles edge cases in pagination', async () => { renderComponent(); await act(async () => { await new Promise((resolve) => setTimeout(resolve, 0)); }); // Test last page navigation const lastPageButton = screen.getByRole('button', { name: /last page/i }); + expect(lastPageButton).toBeEnabled(); await act(async () => { userEvent.click(lastPageButton); }); // Verify last page content expect(screen.getByText('User14 Test')).toBeInTheDocument(); + expect(lastPageButton).toBeDisabled(); + expect(screen.getAllByRole('row').length).toBe(6); // 5 items + header // Test first page navigation const firstPageButton = screen.getByRole('button', { name: /first page/i }); await act(async () => { userEvent.click(firstPageButton); }); // Verify return to first page expect(screen.getByText('User0 Test')).toBeInTheDocument(); expect(screen.queryByText('User14 Test')).not.toBeInTheDocument(); + expect(firstPageButton).toBeDisabled(); + expect(screen.getAllByRole('row').length).toBe(6); // 5 items + header });
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/screens/UserPortal/People/People.spec.tsx
(4 hunks)src/screens/UserPortal/People/People.tsx
(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Test Application
- GitHub Check: Check Python Code Style
- GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (4)
src/screens/UserPortal/People/People.tsx (2)
115-122
: Well-implemented admin list management!The code properly handles admin data mapping with type safety and null checks. The spread operator usage maintains all admin properties while adding the 'Admin' userType.
222-222
: Robust pagination implementation!The code properly handles member filtering and pagination with appropriate null checks. This implementation ensures reliable rendering of the paginated list.
Also applies to: 246-246
src/screens/UserPortal/People/People.spec.tsx (2)
37-69
: Well-structured type definition and mock data!The
MockData
type is well-defined and the mock data structure is comprehensive, covering both success and error cases.
329-475
: Excellent pagination test coverage!The pagination tests are well-structured with:
- Good use of data generation for test cases
- Clear separation of test setup and assertions
- Coverage of both rows per page changes and pagination logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (3)
src/screens/UserPortal/People/People.spec.tsx (3)
133-161
: Consider adding error scenarios to mock data.The mock data includes empty states but lacks error scenarios. Consider adding mocks for network errors and GraphQL errors to test error handling.
Add error mocks like:
{ request: { query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, variables: { orgId: '', firstName_contains: '' }, }, error: new Error('Network error'), }
1068-1093
: Add error handling test for pagination navigation.The pagination edge cases test should include error handling scenarios when navigation fails.
it('handles pagination errors gracefully', async () => { const errorMock = { request: { query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, variables: { orgId: '', firstName_contains: '' }, }, error: new Error('Failed to fetch page'), }; render( <MockedProvider mocks={[errorMock]} addTypename={false}> <BrowserRouter> <Provider store={store}> <I18nextProvider i18n={i18nForTest}> <People /> </I18nextProvider> </Provider> </BrowserRouter> </MockedProvider>, ); const nextPageButton = screen.getByRole('button', { name: /next page/i }); await act(async () => { userEvent.click(nextPageButton); }); await waitFor(() => { expect(screen.getByText(/error/i)).toBeInTheDocument(); }); });
576-590
: Consolidate duplicate i18next mock implementations.The i18next mock implementation is duplicated. Consider extracting it to a shared helper.
// At the top of the file const mockTranslation = async () => { const actual = await vi.importActual('react-i18next'); return { ...actual, useTranslation: () => ({ t: (key: string) => key === 'nothingToShow' ? 'Nothing to show' : key, i18n: { changeLanguage: () => new Promise(() => {}), }, }), }; }; // Then use it in tests vi.mock('react-i18next', mockTranslation);Also applies to: 633-646
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/screens/UserPortal/People/People.spec.tsx
(4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Test Application
- GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (1)
src/screens/UserPortal/People/People.spec.tsx (1)
37-69
: LGTM! Well-structured type definition for mock data.The
MockData
type is well-defined and covers all necessary fields for both member and admin data structures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/screens/UserPortal/People/People.spec.tsx (2)
36-68
: Consider improving type organization and mock data structure.The
MockData
type definition is well-structured but could be enhanced for better maintainability and reusability.Consider:
- Moving the
MockData
type to a separate types file (e.g.,src/types/test-utils.ts
) for reuse across test files- Using TypeScript utility types to reduce repetition in the nested types
+// src/types/test-utils.ts +import type { DocumentNode } from '@apollo/client'; + +type BaseUser = { + _id: string; + firstName: string; + lastName: string; + image: string | null; + email: string; + createdAt: string; +}; + +type MockData = { + request: { + query: DocumentNode; + variables: Record<string, unknown>; + }; + result?: { + data: { + organizationsMemberConnection?: { + edges: BaseUser[]; + }; + organizations?: { + __typename?: string; + _id: string; + admins: BaseUser[]; + }[]; + }; + }; + error?: Error; +};
556-587
: Simplify mode transition test setup.The mode transition test has complex setup and mocking. Consider breaking it down into smaller, focused test cases.
Split the test into two separate test cases:
it('handles basic mode transition', async () => { setupTest(); await waitFor(() => { expect(screen.getByText('Test User')).toBeInTheDocument(); }); userEvent.click(screen.getByTestId('modeChangeBtn')); await waitFor(() => { userEvent.click(screen.getByTestId('modeBtn1')); }); await waitFor(() => { expect(screen.getByText('Admin User')).toBeInTheDocument(); expect(screen.queryByText('Test User')).not.toBeInTheDocument(); }); }); it('handles mode transition with missing data', async () => { const modeSetter = vi.fn(); vi.spyOn(React, 'useState').mockImplementationOnce(() => [1, modeSetter]); setupTest(); await waitFor(() => { expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); }); });
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/screens/UserPortal/People/People.spec.tsx
(5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Check Python Code Style
- GitHub Check: Test Application
- GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (1)
src/screens/UserPortal/People/People.spec.tsx (1)
324-340
: 🛠️ Refactor suggestionImprove loading state test reliability.
The loading state test could be flaky due to race conditions. Consider using more reliable async testing patterns.
Apply this diff to improve the test reliability:
it('Shows loading state while fetching data', async () => { render( <MockedProvider addTypename={false} link={link}> <BrowserRouter> <Provider store={store}> <I18nextProvider i18n={i18nForTest}> <People /> </I18nextProvider> </Provider> </BrowserRouter> </MockedProvider>, ); - const loadingElement = screen.getByText('Loading...'); - expect(loadingElement).toBeInTheDocument(); - await waitForElementToBeRemoved(loadingElement); + await waitFor(() => { + expect(screen.getByText('Loading...')).toBeInTheDocument(); + }); + + await waitForElementToBeRemoved(() => screen.queryByText('Loading...')); + + // Verify the content is loaded + await waitFor(() => { + expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); + expect(screen.getByText(/Noble Mittal/)).toBeInTheDocument(); + }); });Likely invalid or redundant comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/screens/UserPortal/People/People.spec.tsx (1)
133-161
: Consider extracting empty state mocks to a separate constant.The empty state mock data could be moved to a separate constant for better organization and reusability across tests.
+const EMPTY_STATE_MOCKS = [ + { + request: { + query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, + variables: { orgId: '', firstName_contains: '' }, + }, + result: { + data: { + organizationsMemberConnection: { + edges: [], + }, + }, + }, + }, + { + request: { + query: ORGANIZATION_ADMINS_LIST, + variables: { id: '' }, + }, + result: { + data: { + organizations: [ + { + _id: 'org-1', + admins: [], + }, + ], + }, + }, + }, +];
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/screens/UserPortal/People/People.spec.tsx
(4 hunks)src/screens/UserPortal/People/People.tsx
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/screens/UserPortal/People/People.tsx
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Check Python Code Style
- GitHub Check: Test Application
- GitHub Check: Analyse Code With CodeQL (javascript)
🔇 Additional comments (7)
src/screens/UserPortal/People/People.spec.tsx (7)
37-69
: LGTM! Well-structured type definition for mock data.The
MockData
type is comprehensive and properly typed for GraphQL operations.
311-326
: Add proper loading state assertions.The loading state test needs improvement to ensure reliable testing.
Apply this diff to improve the test:
it('Shows loading state while fetching data', async () => { render( <MockedProvider addTypename={false} link={link}> <BrowserRouter> <Provider store={store}> <I18nextProvider i18n={i18nForTest}> <People /> </I18nextProvider> </Provider> </BrowserRouter> </MockedProvider>, ); - expect(screen.getByText('Loading...')).toBeInTheDocument(); - await wait(); + await waitFor(() => { + expect(screen.getByText('Loading...')).toBeInTheDocument(); + }, { timeout: 1000 }); + await waitForElementToBeRemoved(() => screen.queryByText('Loading...')); });
887-907
: Add assertions to verify expected behavior.The test for non-Enter key press needs proper assertions.
Apply this diff to improve the test:
it('should not trigger search for non-Enter key press', async () => { render( <MockedProvider addTypename={false} mocks={[]}> <BrowserRouter> <Provider store={store}> <I18nextProvider i18n={i18nForTest}> <People /> </I18nextProvider> </Provider> </BrowserRouter> </MockedProvider>, ); const searchInput = screen.getByTestId('searchInput'); + const initialValue = searchInput.value; fireEvent.keyUp(searchInput, { key: 'A', code: 'KeyA' }); - // Wait a bit to ensure no search is triggered - await new Promise((resolve) => setTimeout(resolve, 100)); + await waitFor(() => { + expect(searchInput.value).not.toBe(initialValue); + expect(searchInput.value).toContain('A'); + }); // The loading state should not appear expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); });
910-930
: Avoid direct DOM manipulation in tests.The test for empty input search should not directly manipulate the DOM.
Consider simulating the component state instead:
it('should handle search with empty input value', async () => { render( <MockedProvider addTypename={false} mocks={[]}> <BrowserRouter> <Provider store={store}> <I18nextProvider i18n={i18nForTest}> <People /> </I18nextProvider> </Provider> </BrowserRouter> </MockedProvider>, ); const searchBtn = screen.getByTestId('searchBtn'); const searchInput = screen.getByTestId('searchInput'); - searchInput.remove(); + userEvent.clear(searchInput); userEvent.click(searchBtn); - await new Promise((resolve) => setTimeout(resolve, 100)); + await waitFor(() => { + expect(searchInput.value).toBe(''); + expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); + }); });
789-790
: Implement error handling tests.Error handling tests are still missing from the test suite.
Consider adding tests for:
- Network errors during search
- Invalid response format
- Server errors (500 status)
Example implementation:
it('handles network error during search', async () => { const errorMock: MockData = { request: { query: ORGANIZATIONS_MEMBER_CONNECTION_LIST, variables: { orgId: '', firstName_contains: 'test' }, }, error: new Error('Failed to fetch'), }; renderComponent([errorMock]); userEvent.type(screen.getByTestId('searchInput'), 'test'); userEvent.click(screen.getByTestId('searchBtn')); await waitFor(() => { expect(screen.getByText(/error/i)).toBeInTheDocument(); }); });
807-821
: Ensure consistent mocking of useTranslation.The i18next mock is missing the i18n property.
Apply this diff to improve the mock:
vi.mock('react-i18next', async () => { const actual = await vi.importActual('react-i18next'); return { ...actual, useTranslation: () => ({ t: (key: string) => { const translations: { [key: string]: string } = { nothingToShow: 'Nothing to show', all: 'All', }; return translations[key] || key; }, + i18n: { + changeLanguage: () => new Promise(() => {}), + }, }), }; });
991-1088
: LGTM! Comprehensive pagination edge case tests.The pagination edge case tests are well-structured and cover important scenarios including:
- First/last page navigation
- Page content verification
- State transitions
82e2180
into
PalisadoesFoundation:develop-postgres
What kind of change does this PR introduce?
Test Coverage Improvement
Issue Number:
Fixes #3042
Snapshots/Videos:
If relevant, did you update the documentation?
No documentation updates required for test coverage improvements.
Summary
This PR improves the test coverage for
src/screens/UserPortal/People/People.tsx
to achieve near-complete coverage. Key metrics:Key improvements include:
The branch coverage of 91.66% is a structural limitation due to implicit else conditions in the code that cannot be triggered, as the component's logic is designed to handle specific cases without else paths.
Does this PR introduce a breaking change?
No
Checklist
CodeRabbit AI Review
Test Coverage
Other information
This PR achieves maximum possible test coverage for the People component while acknowledging the structural limitations affecting branch coverage. The branch coverage of 91.66% reflects the component's design where certain conditions don't require explicit else paths.
Have you read the contributing guide?
Yes
Summary by CodeRabbit
New Features
Bug Fixes
Tests