Sfoglia il codice sorgente

[NO JIRA] Splitting issues app IT in multiple file

tags/10.3.0.82913
Revanshu Paliwal 10 mesi fa
parent
commit
608505113e

+ 1
- 0
server/sonar-web/jest.config.js Vedi File

@@ -62,6 +62,7 @@ module.exports = {
outputFilepath: '/tmp/ut-ts-web-monitoring.log',
},
],
['jest-slow-test-reporter', { numTests: 5, warnOnSlowerThan: 10000, color: true }],
],
testTimeout: 60000,
};

+ 1
- 0
server/sonar-web/package.json Vedi File

@@ -100,6 +100,7 @@
"jest-axe": "7.0.1",
"jest-environment-jsdom": "29.5.0",
"jest-junit": "16.0.0",
"jest-slow-test-reporter": "1.0.0",
"jsdom": "21.1.1",
"openapi-types": "12.1.3",
"path-browserify": "1.0.1",

+ 1
- 212
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx Vedi File

@@ -22,7 +22,7 @@ import { act, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { TabKeys } from '../../../components/rules/RuleTabViewer';
import { mockCurrentUser, mockLoggedInUser } from '../../../helpers/testMocks';
import { mockLoggedInUser } from '../../../helpers/testMocks';
import { byRole } from '../../../helpers/testSelector';
import { ComponentQualifier } from '../../../types/component';
import { IssueType } from '../../../types/issues';
@@ -667,214 +667,3 @@ describe('redirects', () => {
expect(screen.getByText('/security_hotspots?assignedToMe=false')).toBeInTheDocument();
});
});

describe('activity', () => {
it('should be able to add or update comment', async () => {
const user = userEvent.setup();
issuesHandler.setIsAdmin(true);
renderIssueApp();
await act(async () => {
await user.click(await screen.findByRole('link', { name: 'Fix that' }));
});

expect(
screen.getByRole('tab', { name: `coding_rules.description_section.title.activity` })
).toBeInTheDocument();

await act(async () => {
await user.click(
screen.getByRole('tab', { name: `coding_rules.description_section.title.activity` })
);
});

// Add comment to the issue
await act(async () => {
await user.click(
screen.getByRole('button', {
name: `issue.activity.add_comment`,
})
);
await user.click(screen.getByRole('textbox'));
await user.keyboard('activity comment');
await user.click(screen.getByText('hotspots.comment.submit'));
});
expect(screen.getByText('activity comment')).toBeInTheDocument();

// Cancel editing the comment
await act(async () => {
await user.click(screen.getByRole('button', { name: 'issue.comment.edit' }));
await user.click(screen.getByRole('textbox'));
await user.keyboard(' new');
await user.click(screen.getByRole('button', { name: 'cancel' }));
});
expect(screen.queryByText('activity comment new')).not.toBeInTheDocument();

// Edit the comment
await act(async () => {
await user.click(screen.getByRole('button', { name: 'issue.comment.edit' }));
await user.click(screen.getByRole('textbox'));
await user.keyboard(' new');
await user.click(screen.getByText('hotspots.comment.submit'));
});
expect(screen.getByText('activity comment new')).toBeInTheDocument();

// Delete the comment
await act(async () => {
await user.click(screen.getByRole('button', { name: 'issue.comment.delete' }));
await user.click(screen.getByRole('button', { name: 'delete' })); // Confirm button
});
expect(screen.queryByText('activity comment new')).not.toBeInTheDocument();
});

it('should be able to show changelog', async () => {
const user = userEvent.setup();
issuesHandler.setIsAdmin(true);
renderIssueApp();

await act(async () => {
await user.click(await screen.findByRole('link', { name: 'Fix that' }));

await user.click(
screen.getByRole('tab', { name: `coding_rules.description_section.title.activity` })
);
});

expect(screen.getByText('issue.activity.review_history.created')).toBeInTheDocument();
expect(
screen.getByText(
'issue.changelog.changed_to.issue.changelog.field.assign.darth.vader (issue.changelog.was.luke.skywalker)'
)
).toBeInTheDocument();
expect(
screen.getByText(
'issue.changelog.changed_to.issue.changelog.field.status.REOPENED (issue.changelog.was.CONFIRMED)'
)
).toBeInTheDocument();
});
});

describe('guide', () => {
it('should display guide', async () => {
const user = userEvent.setup();
renderIssueApp(mockCurrentUser({ isLoggedIn: true }));

expect(await ui.guidePopup.find()).toBeInTheDocument();

expect(await ui.guidePopup.find()).toBeInTheDocument();
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.1.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.1.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.1.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.2.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.2.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.2.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.3.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.3.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.3.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.4.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.4.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.4.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.5.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.5.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.5.5');

expect(ui.guidePopup.byRole('button', { name: 'Next' }).query()).not.toBeInTheDocument();

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

expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide for those who dismissed it', async () => {
renderIssueApp(
mockCurrentUser({ isLoggedIn: true, dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true } })
);

expect((await ui.issueItems.findAll()).length).toBeGreaterThan(0);
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should skip guide', async () => {
const user = userEvent.setup();
renderIssueApp(mockCurrentUser({ isLoggedIn: true }));

expect(await ui.guidePopup.find()).toBeInTheDocument();
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.1.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.1.5');

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

expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide if issues need sync', async () => {
renderProjectIssuesApp(
undefined,
{ needIssueSync: true },
mockCurrentUser({ isLoggedIn: true })
);

expect((await ui.issueItems.findAll()).length).toBeGreaterThan(0);
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide if user is not logged in', async () => {
renderIssueApp(mockCurrentUser({ isLoggedIn: false }));

expect((await ui.issueItems.findAll()).length).toBeGreaterThan(0);
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide if there are no issues', () => {
issuesHandler.setIssueList([]);
renderIssueApp(mockCurrentUser({ isLoggedIn: true }));

expect(ui.loading.query()).not.toBeInTheDocument();
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should show guide on issue page', async () => {
const user = userEvent.setup();
renderProjectIssuesApp(
'project/issues?issues=issue11&open=issue11&id=myproject',
undefined,
mockCurrentUser({ isLoggedIn: true })
);

expect(await ui.guidePopup.find()).toBeInTheDocument();
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.1.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.2.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.3.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.4.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.5.5');

expect(ui.guidePopup.byRole('button', { name: 'Next' }).query()).not.toBeInTheDocument();

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

expect(ui.guidePopup.query()).not.toBeInTheDocument();
});
});

+ 138
- 0
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesAppActivity-it.tsx Vedi File

@@ -0,0 +1,138 @@
/*
* SonarQube
* Copyright (C) 2009-2023 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import { act, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { branchHandler, componentsHandler, issuesHandler, renderIssueApp } from '../test-utils';

jest.mock('../sidebar/Sidebar', () => {
const fakeSidebar = () => {
return <div data-guiding-id="issue-5" />;
};
return {
__esModule: true,
default: fakeSidebar,
Sidebar: fakeSidebar,
};
});

jest.mock('../../../components/common/ScreenPositionHelper', () => ({
__esModule: true,
default: class ScreenPositionHelper extends React.Component<{
children: (args: { top: number }) => React.ReactNode;
}> {
render() {
// eslint-disable-next-line testing-library/no-node-access
return this.props.children({ top: 10 });
}
},
}));

beforeEach(() => {
issuesHandler.reset();
componentsHandler.reset();
branchHandler.reset();
window.scrollTo = jest.fn();
window.HTMLElement.prototype.scrollTo = jest.fn();
});

it('should be able to add or update comment', async () => {
const user = userEvent.setup();
issuesHandler.setIsAdmin(true);
renderIssueApp();
await act(async () => {
await user.click(await screen.findByRole('link', { name: 'Fix that' }));
});

expect(
screen.getByRole('tab', { name: `coding_rules.description_section.title.activity` })
).toBeInTheDocument();

await act(async () => {
await user.click(
screen.getByRole('tab', { name: `coding_rules.description_section.title.activity` })
);
});

// Add comment to the issue
await act(async () => {
await user.click(
screen.getByRole('button', {
name: `issue.activity.add_comment`,
})
);
await user.click(screen.getByRole('textbox'));
await user.keyboard('activity comment');
await user.click(screen.getByText('hotspots.comment.submit'));
});
expect(screen.getByText('activity comment')).toBeInTheDocument();

// Cancel editing the comment
await act(async () => {
await user.click(screen.getByRole('button', { name: 'issue.comment.edit' }));
await user.click(screen.getByRole('textbox'));
await user.keyboard(' new');
await user.click(screen.getByRole('button', { name: 'cancel' }));
});
expect(screen.queryByText('activity comment new')).not.toBeInTheDocument();

// Edit the comment
await act(async () => {
await user.click(screen.getByRole('button', { name: 'issue.comment.edit' }));
await user.click(screen.getByRole('textbox'));
await user.keyboard(' new');
await user.click(screen.getByText('hotspots.comment.submit'));
});
expect(screen.getByText('activity comment new')).toBeInTheDocument();

// Delete the comment
await act(async () => {
await user.click(screen.getByRole('button', { name: 'issue.comment.delete' }));
await user.click(screen.getByRole('button', { name: 'delete' })); // Confirm button
});
expect(screen.queryByText('activity comment new')).not.toBeInTheDocument();
});

it('should be able to show changelog', async () => {
const user = userEvent.setup();
issuesHandler.setIsAdmin(true);
renderIssueApp();

await act(async () => {
await user.click(await screen.findByRole('link', { name: 'Fix that' }));

await user.click(
screen.getByRole('tab', { name: `coding_rules.description_section.title.activity` })
);
});

expect(screen.getByText('issue.activity.review_history.created')).toBeInTheDocument();
expect(
screen.getByText(
'issue.changelog.changed_to.issue.changelog.field.assign.darth.vader (issue.changelog.was.luke.skywalker)'
)
).toBeInTheDocument();
expect(
screen.getByText(
'issue.changelog.changed_to.issue.changelog.field.status.REOPENED (issue.changelog.was.CONFIRMED)'
)
).toBeInTheDocument();
});

+ 183
- 0
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesAppGuide-it.tsx Vedi File

@@ -0,0 +1,183 @@
/*
* SonarQube
* Copyright (C) 2009-2023 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import userEvent from '@testing-library/user-event';
import React from 'react';
import { mockCurrentUser } from '../../../helpers/testMocks';
import { NoticeType } from '../../../types/users';
import {
branchHandler,
componentsHandler,
issuesHandler,
renderIssueApp,
renderProjectIssuesApp,
ui,
} from '../test-utils';

jest.mock('../sidebar/Sidebar', () => {
const fakeSidebar = () => {
return <div data-guiding-id="issue-5" />;
};
return {
__esModule: true,
default: fakeSidebar,
Sidebar: fakeSidebar,
};
});

jest.mock('../../../components/common/ScreenPositionHelper', () => ({
__esModule: true,
default: class ScreenPositionHelper extends React.Component<{
children: (args: { top: number }) => React.ReactNode;
}> {
render() {
// eslint-disable-next-line testing-library/no-node-access
return this.props.children({ top: 10 });
}
},
}));

beforeEach(() => {
issuesHandler.reset();
componentsHandler.reset();
branchHandler.reset();
window.scrollTo = jest.fn();
window.HTMLElement.prototype.scrollTo = jest.fn();
});

it('should display guide', async () => {
const user = userEvent.setup();
renderIssueApp(mockCurrentUser({ isLoggedIn: true }));

expect(await ui.guidePopup.find()).toBeInTheDocument();

expect(await ui.guidePopup.find()).toBeInTheDocument();
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.1.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.1.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.1.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.2.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.2.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.2.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.3.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.3.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.3.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.4.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.4.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.4.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.5.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.5.content');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.5.5');

expect(ui.guidePopup.byRole('button', { name: 'Next' }).query()).not.toBeInTheDocument();

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

expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide for those who dismissed it', async () => {
renderIssueApp(
mockCurrentUser({ isLoggedIn: true, dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true } })
);

expect((await ui.issueItems.findAll()).length).toBeGreaterThan(0);
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should skip guide', async () => {
const user = userEvent.setup();
renderIssueApp(mockCurrentUser({ isLoggedIn: true }));

expect(await ui.guidePopup.find()).toBeInTheDocument();
expect(ui.guidePopup.get()).toHaveTextContent('guiding.issue_list.1.title');
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.1.5');

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

expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide if issues need sync', async () => {
renderProjectIssuesApp(undefined, { needIssueSync: true }, mockCurrentUser({ isLoggedIn: true }));

expect((await ui.issueItems.findAll()).length).toBeGreaterThan(0);
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide if user is not logged in', async () => {
renderIssueApp(mockCurrentUser({ isLoggedIn: false }));

expect((await ui.issueItems.findAll()).length).toBeGreaterThan(0);
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should not show guide if there are no issues', () => {
issuesHandler.setIssueList([]);
renderIssueApp(mockCurrentUser({ isLoggedIn: true }));

expect(ui.loading.query()).not.toBeInTheDocument();
expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

it('should show guide on issue page', async () => {
const user = userEvent.setup();
renderProjectIssuesApp(
'project/issues?issues=issue11&open=issue11&id=myproject',
undefined,
mockCurrentUser({ isLoggedIn: true })
);

expect(await ui.guidePopup.find()).toBeInTheDocument();
expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.1.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.2.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.3.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.4.5');

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

expect(ui.guidePopup.get()).toHaveTextContent('guiding.step_x_of_y.5.5');

expect(ui.guidePopup.byRole('button', { name: 'Next' }).query()).not.toBeInTheDocument();

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

expect(ui.guidePopup.query()).not.toBeInTheDocument();
});

+ 8
- 0
server/sonar-web/yarn.lock Vedi File

@@ -4986,6 +4986,7 @@ __metadata:
jest-axe: 7.0.1
jest-environment-jsdom: 29.5.0
jest-junit: 16.0.0
jest-slow-test-reporter: 1.0.0
jsdom: 21.1.1
lodash: 4.17.21
lunr: 2.3.9
@@ -9632,6 +9633,13 @@ __metadata:
languageName: node
linkType: hard

"jest-slow-test-reporter@npm:1.0.0":
version: 1.0.0
resolution: "jest-slow-test-reporter@npm:1.0.0"
checksum: bfbf15ca823f1a2861c33cbe3e9549638d78fa07dc5197464a1bbeb8a30c2d75e7f6f6976b16117db7decaef62cb94a6d641d2bb5823ad72bb46d2af5d49e217
languageName: node
linkType: hard

"jest-snapshot@npm:^29.5.0":
version: 29.5.0
resolution: "jest-snapshot@npm:29.5.0"

Loading…
Annulla
Salva