aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>2022-08-04 14:12:18 +0200
committersonartech <sonartech@sonarsource.com>2022-08-09 20:03:19 +0000
commitab5fe3cabc421afc11d1bcb1deae4439ba150a43 (patch)
treee9722de08c87f8696b00978282fc6fb709229943 /server/sonar-web
parent71c6caf8e97af7015c265b2fe237fbc0df196694 (diff)
downloadsonarqube-ab5fe3cabc421afc11d1bcb1deae4439ba150a43.tar.gz
sonarqube-ab5fe3cabc421afc11d1bcb1deae4439ba150a43.zip
SONAR-16536 Navigating to secondary location from any tab
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx43
-rw-r--r--server/sonar-web/src/main/js/apps/issues/__tests__/actions-test.ts22
-rw-r--r--server/sonar-web/src/main/js/apps/issues/actions.ts18
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx14
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx10
-rw-r--r--server/sonar-web/src/main/js/components/rules/TabViewer.tsx7
7 files changed, 75 insertions, 41 deletions
diff --git a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
index 7236a4c7272..d0e9abd2661 100644
--- a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
+++ b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
@@ -122,6 +122,7 @@ export default class IssuesServiceMock {
locations: [
{
component: 'project:file.foo',
+ msg: 'location 1',
textRange: {
startLine: 1,
endLine: 1,
@@ -135,6 +136,7 @@ export default class IssuesServiceMock {
locations: [
{
component: 'project:file.bar',
+ msg: 'location 2',
textRange: {
startLine: 20,
endLine: 20,
diff --git a/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx b/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx
index 9e4d644cd42..533446d99cd 100644
--- a/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx
@@ -402,6 +402,49 @@ it('should open the actions popup using keyboard shortcut', async () => {
expect(screen.getByRole('searchbox', { name: 'search_verb' })).toBeInTheDocument();
});
+it('should show code tabs when any secondary location is selected', async () => {
+ const user = userEvent.setup();
+ renderIssueApp();
+
+ await user.click(await screen.findByRole('region', { name: 'Fix this' }));
+ expect(screen.getByText('location 1')).toBeInTheDocument();
+ expect(screen.getByText('location 2')).toBeInTheDocument();
+
+ // Select the "why is this an issue" tab
+ await user.click(
+ screen.getByRole('button', { name: 'coding_rules.description_section.title.root_cause' })
+ );
+ expect(
+ screen.queryByRole('row', {
+ name: '2 source_viewer.tooltip.covered import java.util. ArrayList ;'
+ })
+ ).not.toBeInTheDocument();
+
+ await user.click(screen.getByRole('link', { name: '1 location 1' }));
+ expect(
+ screen.getByRole('row', {
+ name: '2 source_viewer.tooltip.covered import java.util. ArrayList ;'
+ })
+ ).toBeInTheDocument();
+
+ // selecting the same selected hotspot location should also navigate back to code page
+ await user.click(
+ screen.getByRole('button', { name: 'coding_rules.description_section.title.root_cause' })
+ );
+ expect(
+ screen.queryByRole('row', {
+ name: '2 source_viewer.tooltip.covered import java.util. ArrayList ;'
+ })
+ ).not.toBeInTheDocument();
+
+ await user.click(screen.getByRole('link', { name: '1 location 1' }));
+ expect(
+ screen.getByRole('row', {
+ name: '2 source_viewer.tooltip.covered import java.util. ArrayList ;'
+ })
+ ).toBeInTheDocument();
+});
+
describe('redirects', () => {
it('should work for hotspots', () => {
renderProjectIssuesApp(`project/issues?types=${IssueType.SecurityHotspot}`);
diff --git a/server/sonar-web/src/main/js/apps/issues/__tests__/actions-test.ts b/server/sonar-web/src/main/js/apps/issues/__tests__/actions-test.ts
index 4a4e212c399..9fd0d4f26fc 100644
--- a/server/sonar-web/src/main/js/apps/issues/__tests__/actions-test.ts
+++ b/server/sonar-web/src/main/js/apps/issues/__tests__/actions-test.ts
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { mockIssue } from '../../../helpers/testMocks';
-import { enableLocationsNavigator, selectFlow, selectLocation } from '../actions';
+import { enableLocationsNavigator, selectFlow } from '../actions';
import { State } from '../components/IssuesApp';
describe('selectFlow', () => {
@@ -97,23 +97,3 @@ describe('enableLocationsNavigator', () => {
expect(enableLocationsNavigator({} as State)).toBeNull();
});
});
-
-describe('selectLocation', () => {
- it('should select location and enable locations navigator', () => {
- expect(selectLocation(5)({ openIssue: mockIssue() })).toEqual({
- locationsNavigator: true,
- selectedLocationIndex: 5
- });
- });
-
- it('should deselect location when clicked again', () => {
- expect(selectLocation(5)({ openIssue: mockIssue(), selectedLocationIndex: 5 })).toEqual({
- locationsNavigator: false,
- selectedLocationIndex: undefined
- });
- });
-
- it('should ignore if no open issue', () => {
- expect(selectLocation(5)({ openIssue: undefined })).toBeNull();
- });
-});
diff --git a/server/sonar-web/src/main/js/apps/issues/actions.ts b/server/sonar-web/src/main/js/apps/issues/actions.ts
index 18ce6916045..94a84475d07 100644
--- a/server/sonar-web/src/main/js/apps/issues/actions.ts
+++ b/server/sonar-web/src/main/js/apps/issues/actions.ts
@@ -40,24 +40,6 @@ export function disableLocationsNavigator() {
return { locationsNavigator: false };
}
-export function selectLocation(nextIndex: number) {
- return (state: Pick<State, 'selectedLocationIndex' | 'openIssue'>) => {
- const { selectedLocationIndex: index, openIssue } = state;
- if (openIssue) {
- if (index === nextIndex) {
- // disable locations when selecting (clicking) the same location
- return {
- locationsNavigator: false,
- selectedLocationIndex: undefined
- };
- } else {
- return { locationsNavigator: true, selectedLocationIndex: nextIndex };
- }
- }
- return null;
- };
-}
-
export function selectNextLocation(
state: Pick<State, 'selectedFlowIndex' | 'selectedLocationIndex' | 'openIssue'>
) {
diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
index 2ec1d67ee9a..b3c2305d7ad 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
@@ -797,7 +797,19 @@ export class App extends React.PureComponent<Props, State> {
};
selectLocation = (index: number) => {
- this.setState(actions.selectLocation(index));
+ const { selectedLocationIndex } = this.state;
+ if (index === selectedLocationIndex) {
+ this.setState({ selectedLocationIndex: undefined }, () => {
+ this.setState({ selectedLocationIndex: index });
+ });
+ } else {
+ this.setState(({ openIssue }) => {
+ if (openIssue) {
+ return { locationsNavigator: true, selectedLocationIndex: index };
+ }
+ return null;
+ });
+ }
};
selectNextLocation = () => {
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
index de2f6ebc605..498b2df1e9a 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineCode.tsx
@@ -41,6 +41,16 @@ export default class LineCode extends React.PureComponent<React.PropsWithChildre
activeMarkerNode?: HTMLElement | null;
symbols?: NodeListOf<HTMLElement>;
+ componentDidMount() {
+ if (this.activeMarkerNode) {
+ this.activeMarkerNode.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ inline: 'center'
+ });
+ }
+ }
+
componentDidUpdate(prevProps: Props) {
if (
this.props.highlightedLocationMessage &&
diff --git a/server/sonar-web/src/main/js/components/rules/TabViewer.tsx b/server/sonar-web/src/main/js/components/rules/TabViewer.tsx
index 92c90d1e4e4..c54cea37523 100644
--- a/server/sonar-web/src/main/js/components/rules/TabViewer.tsx
+++ b/server/sonar-web/src/main/js/components/rules/TabViewer.tsx
@@ -94,7 +94,12 @@ export class TabViewer extends React.PureComponent<TabViewerProps, State> {
prevProps.codeTabContent !== codeTabContent ||
prevProps.currentUser !== currentUser
) {
- this.setState(pState => this.computeState(pState, prevProps.ruleDetails !== ruleDetails));
+ this.setState(pState =>
+ this.computeState(
+ pState,
+ prevProps.ruleDetails !== ruleDetails || prevProps.codeTabContent !== codeTabContent
+ )
+ );
}
if (selectedTab?.key === TabKeys.MoreInfo) {