Browse Source

SONAR-21692 Fix RTL act warnings from GlobalMessage, Account, ComponentMeasures, ProjectManagement, Login and User apps (#10671)

tags/10.5.0.89998
Ismail Cherri 2 months ago
parent
commit
6148545c1a

+ 14
- 8
server/sonar-web/src/main/js/app/components/__tests__/GlobalMessagesContainer-it.tsx View File

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { screen } from '@testing-library/react';
import { act, screen, waitFor } from '@testing-library/react';
import React from 'react';
import { addGlobalErrorMessage, addGlobalSuccessMessage } from '../../../helpers/globalMessages';
import { renderApp } from '../../../helpers/testReactTestingUtils';
@@ -32,22 +32,28 @@ it('should display messages', async () => {
// we render anything, the GlobalMessageContainer is rendered independently from routing
renderApp('sonarqube', <NullComponent />);

addGlobalErrorMessage('This is an error');
addGlobalSuccessMessage('This was a triumph!');

await waitFor(() => {
addGlobalErrorMessage('This is an error');
addGlobalSuccessMessage('This was a triumph!');
});
expect(await screen.findByRole('alert')).toHaveTextContent('This is an error');
expect(screen.getByRole('status')).toHaveTextContent('This was a triumph!');

// No duplicate message
addGlobalErrorMessage('This is an error');
await waitFor(() => {
addGlobalErrorMessage('This is an error');
});
expect(screen.getByRole('alert')).toHaveTextContent(/^This is an error$/);
addGlobalSuccessMessage('This was a triumph!');
await waitFor(() => {
addGlobalSuccessMessage('This was a triumph!');
});
expect(await screen.findByRole('status')).toHaveTextContent(
/^This was a triumph!This was a triumph!$/,
);

jest.runAllTimers();

act(() => {
jest.runAllTimers();
});
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
expect(screen.queryByRole('status')).not.toBeInTheDocument();


+ 14
- 10
server/sonar-web/src/main/js/apps/account/__tests__/Account-it.tsx View File

@@ -172,11 +172,11 @@ it('should handle a currentUser not logged in', () => {
locationMock.mockRestore();
});

it('should render the top menu', () => {
it('should render the top menu', async () => {
const name = 'Tyler Durden';
renderAccountApp(mockLoggedInUser({ name }));

expect(screen.getByText(name)).toBeInTheDocument();
expect(await screen.findByText(name)).toBeInTheDocument();

const topMenuNavigationItems = [
'my_account.profile',
@@ -190,7 +190,7 @@ it('should render the top menu', () => {
});

describe('profile page', () => {
it('should display all the information', () => {
it('should display all the information', async () => {
const loggedInUser = mockLoggedInUser({
email: 'email@company.com',
groups: ['group1'],
@@ -198,10 +198,10 @@ describe('profile page', () => {
});
renderAccountApp(loggedInUser);

expect(await screen.findByText('group1')).toBeInTheDocument();
expect(screen.getByText('account1')).toBeInTheDocument();
expect(screen.getAllByText(loggedInUser.login)).toHaveLength(2);
expect(screen.getAllByText(loggedInUser.email!)).toHaveLength(2);
expect(screen.getByText('group1')).toBeInTheDocument();
expect(screen.getByText('account1')).toBeInTheDocument();
});

it('should handle missing info', () => {
@@ -392,7 +392,7 @@ describe('security page', () => {
).not.toBeInTheDocument();
});

it("should not suggest creating a Project token if the user doesn't have at least one scannable Projects", () => {
it("should not suggest creating a Project token if the user doesn't have at least one scannable Projects", async () => {
jest.mocked(getScannableProjects).mockResolvedValueOnce({
projects: [],
});
@@ -401,7 +401,9 @@ describe('security page', () => {
securityPagePath,
);

selectEvent.openMenu(screen.getByRole('combobox', { name: 'users.tokens.type' }));
await waitFor(() => {
selectEvent.openMenu(screen.getByRole('combobox', { name: 'users.tokens.type' }));
});
expect(screen.queryByText(`users.tokens.${TokenType.Project}`)).not.toBeInTheDocument();
});

@@ -429,9 +431,11 @@ describe('security page', () => {
securityPagePath,
);

await selectEvent.select(screen.getByRole('combobox', { name: 'users.tokens.type' }), [
`users.tokens.${TokenType.Project}`,
]);
await waitFor(async () => {
await selectEvent.select(screen.getByRole('combobox', { name: 'users.tokens.type' }), [
`users.tokens.${TokenType.Project}`,
]);
});

expect(screen.getByText('Project Name 1')).toBeInTheDocument();
});

+ 2
- 1
server/sonar-web/src/main/js/apps/account/notifications/ProjectModal.tsx View File

@@ -172,7 +172,8 @@ export default class ProjectModal extends React.PureComponent<Props, State> {
});
};

handleSubmit = () => {
handleSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
const { selectedProject } = this.state;

if (selectedProject) {

+ 2
- 2
server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx View File

@@ -310,7 +310,7 @@ describe('navigation', () => {

await user.click(ui.maintainabilityDomainBtn.get());
await user.click(ui.measureBtn('Code Smells 8').get());
await ui.changeViewToList();
await waitFor(() => ui.changeViewToList());

expect(
within(await ui.measuresRow('out.tsx').find()).getByRole('cell', { name: '1' }),
@@ -330,7 +330,7 @@ describe('navigation', () => {

await user.click(ui.maintainabilityDomainBtn.get());
await user.click(ui.measureBtn('Maintainability Rating metric.has_rating_X.E').get());
await ui.changeViewToTreeMap();
await waitFor(() => ui.changeViewToTreeMap());

expect(await ui.treeMapCell(/folderA/).find()).toBeInTheDocument();
expect(ui.treeMapCell(/test1\.js/).get()).toBeInTheDocument();

+ 6
- 6
server/sonar-web/src/main/js/apps/projectDeletion/__tests__/ProjectDeletionApp-it.tsx View File

@@ -52,9 +52,9 @@ it('should be able to delete project', async () => {

expect(byText('deletion.page').get()).toBeInTheDocument();
expect(byText('project_deletion.page.description').get()).toBeInTheDocument();
user.click(byRole('button', { name: 'delete' }).get());
await user.click(byRole('button', { name: 'delete' }).get());
expect(await byRole('dialog', { name: 'qualifier.delete.TRK' }).find()).toBeInTheDocument();
user.click(
await user.click(
byRole('dialog', { name: 'qualifier.delete.TRK' }).byRole('button', { name: 'delete' }).get(),
);

@@ -79,10 +79,10 @@ it('should be able to delete Portfolio', async () => {
expect(byText('deletion.page').get()).toBeInTheDocument();
expect(byText('portfolio_deletion.page.description').get()).toBeInTheDocument();

user.click(byRole('button', { name: 'delete' }).get());
await user.click(byRole('button', { name: 'delete' }).get());

expect(await byRole('dialog', { name: 'qualifier.delete.VW' }).find()).toBeInTheDocument();
user.click(
await user.click(
byRole('dialog', { name: 'qualifier.delete.VW' }).byRole('button', { name: 'delete' }).get(),
);

@@ -107,9 +107,9 @@ it('should be able to delete Application', async () => {
expect(byText('deletion.page').get()).toBeInTheDocument();
expect(byText('application_deletion.page.description').get()).toBeInTheDocument();

user.click(byRole('button', { name: 'delete' }).get());
await user.click(byRole('button', { name: 'delete' }).get());
expect(await byRole('dialog', { name: 'qualifier.delete.APP' }).find()).toBeInTheDocument();
user.click(
await user.click(
byRole('dialog', { name: 'qualifier.delete.APP' }).byRole('button', { name: 'delete' }).get(),
);


+ 19
- 7
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectManagementApp-it.tsx View File

@@ -183,7 +183,9 @@ it('should filter projects', async () => {
const user = userEvent.setup();
renderProjectManagementApp();
await waitFor(() => expect(ui.row.getAll()).toHaveLength(5));
await selectEvent.select(ui.visibilityFilter.get(), 'visibility.public');
await waitFor(() => {
selectEvent.select(ui.visibilityFilter.get(), 'visibility.public');
});
await waitFor(() => expect(ui.row.getAll()).toHaveLength(4));
await user.click(ui.analysisDateFilter.get());
await user.click(await screen.findByRole('gridcell', { name: '5' }));
@@ -191,11 +193,15 @@ it('should filter projects', async () => {
await user.click(ui.provisionedFilter.get());
expect(ui.row.getAll()).toHaveLength(2);
expect(ui.row.getAll()[1]).toHaveTextContent('Project 4');
await selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.VW');
expect(ui.provisionedFilter.query()).not.toBeInTheDocument();
await waitFor(() => {
selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.VW');
});
await waitFor(() => expect(ui.provisionedFilter.query()).not.toBeInTheDocument());
expect(ui.row.getAll()).toHaveLength(2);
await waitFor(() => expect(ui.row.getAll()[1]).toHaveTextContent('Portfolio 1'));
await selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.APP');
await waitFor(() => {
selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.APP');
});
expect(ui.provisionedFilter.query()).not.toBeInTheDocument();
expect(ui.row.getAll()).toHaveLength(2);
await waitFor(() => expect(ui.row.getAll()[1]).toHaveTextContent('Application 1'));
@@ -207,12 +213,16 @@ it('should search by text', async () => {
await waitFor(() => expect(ui.row.getAll()).toHaveLength(5));
await user.type(ui.searchFilter.get(), 'provision');
expect(ui.row.getAll()).toHaveLength(2);
await selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.VW');
await waitFor(() => {
selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.VW');
});
await waitFor(() => expect(ui.row.getAll()).toHaveLength(4));
expect(ui.searchFilter.get()).toHaveValue('');
await user.type(ui.searchFilter.get(), 'Portfolio 2');
expect(ui.row.getAll()).toHaveLength(2);
await selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.APP');
await waitFor(() => {
selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.APP');
});
await waitFor(() => expect(ui.row.getAll()).toHaveLength(4));
expect(ui.searchFilter.get()).toHaveValue('');
await user.type(ui.searchFilter.get(), 'Application 3');
@@ -396,7 +406,9 @@ it('should load more and change the filter without caching old pages', async ()
expect(projectRows[1]).toHaveTextContent('Project 0');
expect(projectRows[60]).toHaveTextContent('Project 59');

await selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.VW');
await waitFor(() => {
selectEvent.select(ui.qualifierFilter.get(), 'qualifiers.VW');
});
await waitFor(() => expect(projectRows[1]).not.toBeInTheDocument());
const portfolioRows = ui.row.getAll();
expect(portfolioRows).toHaveLength(51);

+ 5
- 3
server/sonar-web/src/main/js/apps/sessions/components/__tests__/Login-it.tsx View File

@@ -101,9 +101,11 @@ it('should behave correctly', async () => {
// Incorrect login.
await user.type(loginField, 'janedoe');
await user.type(passwordField, 'invalid');
// Don't use userEvent.click() here. This allows us to more easily see the loading state changes.
submitButton.click();
await waitFor(() => expect(submitButton).toBeDisabled()); // Loading.
await waitFor(() => {
// Don't use userEvent.click() here. This allows us to more easily see the loading state changes.
submitButton.click();
expect(submitButton).toBeDisabled(); // Loading
});
await waitFor(() => {
expect(addGlobalErrorMessage).toHaveBeenCalledWith('login.authentication_failed');
});

+ 10
- 4
server/sonar-web/src/main/js/apps/users/__tests__/UsersApp-it.tsx View File

@@ -722,13 +722,17 @@ it('accessibility', async () => {
// user creation dialog should be accessible
await user.click(await ui.createUserButton.find());
expect(await ui.dialogCreateUser.find()).toBeInTheDocument();
await expect(ui.dialogCreateUser.get()).toHaveNoA11yViolations();
await waitFor(async () => {
await expect(ui.dialogCreateUser.get()).toHaveNoA11yViolations();
});
await user.click(ui.cancelButton.get());

// users group membership dialog should be accessible
user.click(await ui.aliceUpdateGroupButton.find());
await user.click(await ui.aliceUpdateGroupButton.find());
expect(await ui.dialogGroups.find()).toBeInTheDocument();
await expect(await ui.dialogGroups.find()).toHaveNoA11yViolations();
await waitFor(async () => {
await expect(await ui.dialogGroups.find()).toHaveNoA11yViolations();
});
await user.click(ui.doneButton.get());

// user update dialog should be accessible
@@ -748,7 +752,9 @@ it('accessibility', async () => {
);

expect(await ui.dialogTokens.find()).toBeInTheDocument();
await expect(await ui.dialogTokens.find()).toHaveNoA11yViolations();
await waitFor(async () => {
await expect(await ui.dialogTokens.find()).toHaveNoA11yViolations();
});
await user.click(ui.closeButton.get());

// user password dialog should be accessible

Loading…
Cancel
Save