From 6703b1d7cbd66b73c92be1d5e26973da6770a8f9 Mon Sep 17 00:00:00 2001 From: Sujit Karki Date: Wed, 24 Sep 2025 10:08:09 +0545 Subject: [PATCH 1/5] add testid identifier to popup trigger and popup content --- frontend/src/components/user/list.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/user/list.js b/frontend/src/components/user/list.js index 6dee901127..1739cd6a5c 100644 --- a/frontend/src/components/user/list.js +++ b/frontend/src/components/user/list.js @@ -339,7 +339,7 @@ export const UsersTable = ({ filters, setFilters, levels }) => { {userDetails.username !== row.original.username && ( + { className="user-popup" > {(close) => ( - +
+ +
)}
)} @@ -490,7 +492,7 @@ export const UserEditMenu = ({ user, token, close, setStatus, levels }) => { }; return ( - <> +

@@ -529,6 +531,6 @@ export const UserEditMenu = ({ user, token, close, setStatus, levels }) => { ); })}

- +
); }; From 48ba01def025c80ebedf9fd325eb6ff82f9ef106 Mon Sep 17 00:00:00 2001 From: Sujit Karki Date: Wed, 24 Sep 2025 10:09:44 +0545 Subject: [PATCH 2/5] Remove unused variable function `getAllByRole` --- frontend/src/components/user/tests/list.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/user/tests/list.test.js b/frontend/src/components/user/tests/list.test.js index 0e5498c211..0ee08fa0c0 100644 --- a/frontend/src/components/user/tests/list.test.js +++ b/frontend/src/components/user/tests/list.test.js @@ -16,7 +16,7 @@ jest.mock('react-hot-toast', () => ({ describe('User list card', () => { it('renders user card', async () => { - const { container, getByText, getAllByRole } = renderWithRouter( + const { container, getByText } = renderWithRouter( Date: Thu, 16 Oct 2025 16:12:30 +0545 Subject: [PATCH 3/5] move redundant code to setup section and make test case async introduce test retries for better handling of intermittent failures --- frontend/src/views/tests/users.test.js | 75 +++++++++++++++++--------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/frontend/src/views/tests/users.test.js b/frontend/src/views/tests/users.test.js index 2c0e21496c..4d988c2228 100644 --- a/frontend/src/views/tests/users.test.js +++ b/frontend/src/views/tests/users.test.js @@ -55,17 +55,32 @@ describe('List Users', () => { }); }); +// Retry failed tests up to 2 times to handle occasional async flakiness +jest.retryTimes(2); describe('Change of role and mapper level', () => { - const setup = () => { + const setup = async () => { const { user, container } = renderWithRouter( - + , ); - return { - user, - container, - }; + + // wait until loading spinner gone + await waitFor(() => + expect(container.getElementsByClassName('show-loading-animation').length).toBe(0), + ); + + // wait for table body + const tbody = await screen.findByTestId('user-list'); + + // ensure rows & triggers are stable + await waitFor(() => { + const triggers = within(tbody).getAllByTestId('action-trigger'); + expect(triggers.length).toBeGreaterThan(0); + expect(screen.getByText(/Ram/i)).toBeInTheDocument(); + }); + + return { tbody, user, container }; }; beforeEach(() => { @@ -73,34 +88,42 @@ describe('Change of role and mapper level', () => { if (popupRoot) popupRoot.innerHTML = ''; }); - it('should call endpoint to update role', async () => { - const { user, container } = setup(); + it('should call endpoint to update level', async () => { + const { tbody, user, container } = await setup(); + + const triggers = await within(tbody).findAllByTestId('action-trigger'); + await user.click(triggers[0]); + + const tooltip = await screen.findByTestId('action-content', {}, { timeout: 1000 }); + + const advancedOption = await within(tooltip).findByText(/advanced/i); + await user.click(advancedOption); + + await waitFor(() => { + expect(screen.queryByTestId('action-content')).not.toBeInTheDocument(); + }); await waitFor(() => expect(container.getElementsByClassName('show-loading-animation').length).toBe(0), ); - await user.click(container.getElementsByClassName('pointer hover-blue-grey')[0]); - const tooltip = await screen.findByRole('tooltip'); - await user.click(within(tooltip).getByText(/advanced/i)); - await waitFor( - () => - expect(tooltip).not.toBeInTheDocument() && - expect(container.getElementsByClassName('show-loading-animation').length).toBe(16), - ); }); - it('should call endpoint to update level', async () => { - const { user, container } = setup(); + it('should call endpoint to update Role', async () => { + const { tbody, user, container } = await setup(); + + const triggers = await within(tbody).findAllByTestId('action-trigger'); + await user.click(triggers[0]); + + const tooltip = await screen.findByTestId('action-content', {}, { timeout: 1000 }); + + const adminOption = await within(tooltip).findByText(/admin/i); + await user.click(adminOption); + + await waitFor(() => { + expect(screen.queryByTestId('action-content')).not.toBeInTheDocument(); + }); await waitFor(() => expect(container.getElementsByClassName('show-loading-animation').length).toBe(0), ); - await user.click(container.getElementsByClassName('pointer hover-blue-grey')[0]); - const tooltip = await screen.findByRole('tooltip'); - await user.click(within(tooltip).getByText(/admin/i)); - await waitFor( - () => - expect(tooltip).not.toBeInTheDocument() && - expect(container.getElementsByClassName('show-loading-animation').length).toBe(16), - ); }); }); From 4c34651963aa4598379bb80a194ecd3bf29c2aaf Mon Sep 17 00:00:00 2001 From: Sujit Karki Date: Thu, 16 Oct 2025 16:15:30 +0545 Subject: [PATCH 4/5] Introduce test retries for better handling of intermittent failures --- frontend/src/views/tests/taskAction.test.js | 5 +++-- frontend/src/views/tests/teams.test.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/views/tests/taskAction.test.js b/frontend/src/views/tests/taskAction.test.js index 5ff81bb9f4..edb3bf186f 100644 --- a/frontend/src/views/tests/taskAction.test.js +++ b/frontend/src/views/tests/taskAction.test.js @@ -31,8 +31,9 @@ describe('Submitting Mapping Status for a Task', () => { return { user, router }; }; + jest.retryTimes(2); it('should stop mapping and direct to tasks selection page', async () => { - act(() => { + await act(() => { store.dispatch({ type: 'SET_LOCALE', locale: 'en-US' }); store.dispatch({ type: 'SET_TOKEN', token: 'validToken' }); store.dispatch({ @@ -62,7 +63,7 @@ describe('Submitting Mapping Status for a Task', () => { , ); - + await waitFor(() => expect(screen.getByRole('heading')).toHaveTextContent( 'We found another mapping task already locked by you', diff --git a/frontend/src/views/tests/teams.test.js b/frontend/src/views/tests/teams.test.js index 9e16cb3d34..5e8f79889c 100644 --- a/frontend/src/views/tests/teams.test.js +++ b/frontend/src/views/tests/teams.test.js @@ -127,6 +127,7 @@ describe('Create Team', () => { }); describe('Edit Team', () => { + jest.retryTimes(2); it('should display default details of the team before editing', async () => { await act(() => { store.dispatch({ From f048c8dc08cc9cb85bc787b6124c8be2ad900488 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 04:36:54 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- frontend/src/views/tests/taskAction.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/tests/taskAction.test.js b/frontend/src/views/tests/taskAction.test.js index edb3bf186f..8dce9aa57e 100644 --- a/frontend/src/views/tests/taskAction.test.js +++ b/frontend/src/views/tests/taskAction.test.js @@ -63,7 +63,7 @@ describe('Submitting Mapping Status for a Task', () => { , ); - + await waitFor(() => expect(screen.getByRole('heading')).toHaveTextContent( 'We found another mapping task already locked by you',