]> source.dussan.org Git - sonarqube.git/commitdiff
Drop unused/sonarcloud feature
authorPhilippe Perrin <philippe.perrin@sonarsource.com>
Tue, 4 Aug 2020 11:35:35 +0000 (13:35 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 11 Aug 2020 20:06:01 +0000 (20:06 +0000)
13 files changed:
server/sonar-web/src/main/js/api/nav.ts
server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx
server/sonar-web/src/main/js/app/components/nav/global/GlobalNavExplore.tsx [deleted file]
server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNav-test.tsx.snap
server/sonar-web/src/main/js/app/utils/startReactApp.tsx
server/sonar-web/src/main/js/apps/explore/Explore.tsx [deleted file]
server/sonar-web/src/main/js/apps/explore/ExploreIssues.tsx [deleted file]
server/sonar-web/src/main/js/apps/explore/ExploreProjects.tsx [deleted file]
server/sonar-web/src/main/js/apps/issues/components/App.tsx
server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx
server/sonar-web/src/main/js/apps/projects/components/AllProjects.tsx
server/sonar-web/src/main/js/apps/projects/components/DefaultPageSelector.tsx
server/sonar-web/src/main/js/apps/projects/components/__tests__/AllProjects-test.tsx

index 94d05fa55d3dd081c87c62f304b0ca183885653c..e5ccf1845cd125dcb2ba007fdecb7938315d67f3 100644 (file)
@@ -21,10 +21,6 @@ import { getJSON } from 'sonar-ui-common/helpers/request';
 import throwGlobalError from '../app/utils/throwGlobalError';
 import { BranchParameters } from '../types/branch-like';
 
-export function getGlobalNavigation(): Promise<T.AppState> {
-  return getJSON('/api/navigation/global');
-}
-
 type NavComponent = T.Omit<T.Component, 'alm' | 'qualifier' | 'leakPeriodDate' | 'path' | 'tags'>;
 
 export function getComponentNavigation(
index 78e44e4536cc9c2a0f81c9155de4b54f9d693f07..3d502b1aca06b3ab14a32457e151e2daecebd8df 100644 (file)
@@ -42,7 +42,6 @@ import EmbedDocsPopupHelper from '../../embed-docs-modal/EmbedDocsPopupHelper';
 import Search from '../../search/Search';
 import './GlobalNav.css';
 import GlobalNavBranding, { SonarCloudNavBranding } from './GlobalNavBranding';
-import GlobalNavExplore from './GlobalNavExplore';
 import GlobalNavMenu from './GlobalNavMenu';
 import GlobalNavUserContainer from './GlobalNavUserContainer';
 
@@ -188,7 +187,6 @@ export class GlobalNav extends React.PureComponent<Props, State> {
               setCurrentUserSetting={this.props.setCurrentUserSetting}
             />
           )}
-          {isSonarCloud() && <GlobalNavExplore location={this.props.location} />}
           <EmbedDocsPopupHelper />
           <Search appState={appState} currentUser={currentUser} />
           {isLoggedIn(currentUser) && (
diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavExplore.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavExplore.tsx
deleted file mode 100644 (file)
index a0ce98c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { Link } from 'react-router';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-
-interface Props {
-  location: { pathname: string };
-}
-
-export default function GlobalNavExplore({ location }: Props) {
-  const active = location.pathname.startsWith('/explore');
-  return (
-    <li>
-      <Link
-        className={active ? 'active' : undefined}
-        to={{ pathname: '/explore/projects', query: { sort: '-analysis_date' } }}>
-        {translate('explore')}
-      </Link>
-    </li>
-  );
-}
index 502966742f52c924ea044b679c4cbd0c753edf87..f5ddebb16d6b2639fb326a18ff3c6bf07486a0dc 100644 (file)
@@ -53,13 +53,6 @@ exports[`should render correctly if there are new features 1`] = `
       onClick={[Function]}
       setCurrentUserSetting={[MockFunction]}
     />
-    <GlobalNavExplore
-      location={
-        Object {
-          "pathname": "",
-        }
-      }
-    />
     <EmbedDocsPopupHelper />
     <withRouter(Search)
       appState={
index 091ca9f14573ca8b4ddc7541c9982c60ee473bc2..44a7a8a386f7b88463d43b635349646eba44ca99 100644 (file)
@@ -38,9 +38,6 @@ import componentMeasuresRoutes from '../../apps/component-measures/routes';
 import customMeasuresRoutes from '../../apps/custom-measures/routes';
 import customMetricsRoutes from '../../apps/custom-metrics/routes';
 import documentationRoutes from '../../apps/documentation/routes';
-import Explore from '../../apps/explore/Explore';
-import ExploreIssues from '../../apps/explore/ExploreIssues';
-import ExploreProjects from '../../apps/explore/ExploreProjects';
 import groupsRoutes from '../../apps/groups/routes';
 import Issues from '../../apps/issues/components/AppContainer';
 import { maintenanceRoutes, setupRoutes } from '../../apps/maintenance/routes';
@@ -292,10 +289,6 @@ export default function startReactApp(
                     <RouteWithChildRoutes path="account" childRoutes={accountRoutes} />
                     <RouteWithChildRoutes path="coding_rules" childRoutes={codingRulesRoutes} />
                     <RouteWithChildRoutes path="documentation" childRoutes={documentationRoutes} />
-                    <Route path="explore" component={Explore}>
-                      <Route path="issues" component={ExploreIssues} />
-                      <Route path="projects" component={ExploreProjects} />
-                    </Route>
                     <Route
                       path="extension/:pluginKey/:extensionKey"
                       component={lazyLoadComponent(() =>
diff --git a/server/sonar-web/src/main/js/apps/explore/Explore.tsx b/server/sonar-web/src/main/js/apps/explore/Explore.tsx
deleted file mode 100644 (file)
index 31411b1..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { Link } from 'react-router';
-import ContextNavBar from 'sonar-ui-common/components/ui/ContextNavBar';
-import NavBarTabs from 'sonar-ui-common/components/ui/NavBarTabs';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { rawSizes } from '../../app/theme';
-
-interface Props {
-  children: JSX.Element;
-}
-
-export default function Explore(props: Props) {
-  return (
-    <div id="explore">
-      <ContextNavBar height={rawSizes.contextNavHeightRaw} id="explore-navigation">
-        <header className="navbar-context-header">
-          <h1>{translate('explore')}</h1>
-        </header>
-
-        <NavBarTabs>
-          <li>
-            <Link activeClassName="active" to="/explore/projects">
-              {translate('projects.page')}
-            </Link>
-          </li>
-          <li>
-            <Link
-              activeClassName="active"
-              to={{ pathname: '/explore/issues', query: { resolved: 'false' } }}>
-              {translate('issues.page')}
-            </Link>
-          </li>
-        </NavBarTabs>
-      </ContextNavBar>
-
-      {props.children}
-    </div>
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/explore/ExploreIssues.tsx b/server/sonar-web/src/main/js/apps/explore/ExploreIssues.tsx
deleted file mode 100644 (file)
index aaa87a2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import AppContainer from '../issues/components/AppContainer';
-
-interface Props {
-  location: { pathname: string; query: T.RawQuery };
-}
-
-export default function ExploreIssues(props: Props) {
-  return (
-    <AppContainer hideAuthorFacet={true} multiOrganizations={true} myIssues={false} {...props} />
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/explore/ExploreProjects.tsx b/server/sonar-web/src/main/js/apps/explore/ExploreProjects.tsx
deleted file mode 100644 (file)
index e571469..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import AllProjectsContainer from '../projects/components/AllProjectsContainer';
-
-interface Props {
-  location: { pathname: string; query: T.RawQuery };
-}
-
-export default function ExploreProjects(props: Props) {
-  return (
-    <AllProjectsContainer
-      isFavorite={false}
-      organization={undefined}
-      storageOptionsSuffix="explore"
-      {...props}
-    />
-  );
-}
index 129267a72f45b91c8837c7b9e7bd821f80e3eec4..a86834fbc1d983535532e4fb69ae72694824976b 100644 (file)
@@ -101,10 +101,7 @@ interface Props {
   currentUser: T.CurrentUser;
   fetchBranchStatus: (branchLike: BranchLike, projectKey: string) => Promise<void>;
   fetchIssues: (query: T.RawQuery, requestOrganizations?: boolean) => Promise<FetchIssuesPromise>;
-  hideAuthorFacet?: boolean;
   location: Location;
-  multiOrganizations?: boolean;
-  myIssues?: boolean;
   onBranchesChange?: () => void;
   organization?: { key: string };
   router: Pick<Router, 'push' | 'replace'>;
@@ -157,7 +154,7 @@ export default class App extends React.PureComponent<Props, State> {
       loadingFacets: {},
       loadingMore: false,
       locationsNavigator: false,
-      myIssues: props.myIssues || areMyIssuesSelected(props.location.query),
+      myIssues: areMyIssuesSelected(props.location.query),
       openFacets: {
         owaspTop10: shouldOpenStandardsChildFacet({}, query, 'owaspTop10'),
         sansTop25: shouldOpenStandardsChildFacet({}, query, 'sansTop25'),
@@ -209,7 +206,7 @@ export default class App extends React.PureComponent<Props, State> {
     }
 
     this.setState({
-      myIssues: nextProps.myIssues || areMyIssuesSelected(nextProps.location.query),
+      myIssues: areMyIssuesSelected(nextProps.location.query),
       openIssue,
       query: parseQuery(nextProps.location.query)
     });
@@ -411,11 +408,7 @@ export default class App extends React.PureComponent<Props, State> {
     }
   };
 
-  fetchIssues = (
-    additional: T.RawQuery,
-    requestFacets = false,
-    requestOrganizations = true
-  ): Promise<FetchIssuesPromise> => {
+  fetchIssues = (additional: T.RawQuery, requestFacets = false): Promise<FetchIssuesPromise> => {
     const { component } = this.props;
     const { myIssues, openFacets, query } = this.state;
 
@@ -451,10 +444,7 @@ export default class App extends React.PureComponent<Props, State> {
       Object.assign(parameters, { assignees: '__me__' });
     }
 
-    return this.props.fetchIssues(
-      parameters,
-      Boolean(requestOrganizations && this.props.multiOrganizations)
-    );
+    return this.props.fetchIssues(parameters, false);
   };
 
   fetchFirstIssues() {
@@ -609,8 +599,7 @@ export default class App extends React.PureComponent<Props, State> {
   };
 
   fetchFacet = (facet: string) => {
-    const requestOrganizations = facet === 'projects';
-    return this.fetchIssues({ ps: 1, facets: mapFacet(facet) }, false, requestOrganizations).then(
+    return this.fetchIssues({ ps: 1, facets: mapFacet(facet) }, false).then(
       ({ facets, ...other }) => {
         if (this.mounted) {
           this.setState(state => ({
@@ -940,8 +929,7 @@ export default class App extends React.PureComponent<Props, State> {
       userOrganizations.find(o => {
         return o.key === organizationKey;
       });
-    const hideAuthorFacet =
-      this.props.hideAuthorFacet || (isSonarCloud() && this.props.myIssues) || !userOrganization;
+    const hideAuthorFacet = !userOrganization;
 
     return (
       <div className="layout-page-filters">
@@ -1103,11 +1091,7 @@ export default class App extends React.PureComponent<Props, State> {
 
             {this.renderBulkChange(openIssue)}
             <PageActions
-              canSetHome={Boolean(
-                !this.props.organization &&
-                  !this.props.component &&
-                  (!isSonarCloud() || this.props.myIssues)
-              )}
+              canSetHome={Boolean(!this.props.organization && !this.props.component)}
               effortTotal={this.state.effortTotal}
               onReload={this.handleReload}
               paging={paging}
index e7fdb63556753682af9da767617aa7c45455a58d..12f8db6b696ab218e1964c54e6f5a0bafbb82b41 100644 (file)
@@ -20,6 +20,7 @@
 import { shallow } from 'enzyme';
 import * as React from 'react';
 import handleRequiredAuthentication from 'sonar-ui-common/helpers/handleRequiredAuthentication';
+import { KeyCodes } from 'sonar-ui-common/helpers/keycodes';
 import { KEYCODE_MAP, keydown, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
 import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
 import {
@@ -83,7 +84,7 @@ it('should render a list of issue', async () => {
 it('should not render for anonymous user', () => {
   shallowRender({
     currentUser: mockCurrentUser({ isLoggedIn: false }),
-    myIssues: true
+    location: mockLocation({ query: { myIssues: true.toString() } })
   });
   expect(handleRequiredAuthentication).toBeCalled();
 });
@@ -129,25 +130,25 @@ it('should correctly bind key events for issue navigation', async () => {
 
   expect(wrapper.state('selected')).toBe(ISSUES[0].key);
 
-  keydown('down');
+  keydown(KeyCodes.DownArrow);
   expect(wrapper.state('selected')).toBe(ISSUES[1].key);
 
-  keydown('up');
-  keydown('up');
+  keydown(KeyCodes.UpArrow);
+  keydown(KeyCodes.UpArrow);
   expect(wrapper.state('selected')).toBe(ISSUES[0].key);
 
-  keydown('down');
-  keydown('down');
-  keydown('down');
-  keydown('down');
-  keydown('down');
-  keydown('down');
+  keydown(KeyCodes.DownArrow);
+  keydown(KeyCodes.DownArrow);
+  keydown(KeyCodes.DownArrow);
+  keydown(KeyCodes.DownArrow);
+  keydown(KeyCodes.DownArrow);
+  keydown(KeyCodes.DownArrow);
   expect(wrapper.state('selected')).toBe(ISSUES[3].key);
 
-  keydown('right');
+  keydown(KeyCodes.RightArrow);
   expect(push).toBeCalledTimes(1);
 
-  keydown('left');
+  keydown(KeyCodes.LeftArrow);
   expect(push).toBeCalledTimes(2);
 });
 
index b8702d7f68aa21b1936011ab512d67646f218a95..745b300033fac6f5ad306bfe63e244c20a71dbe7 100644 (file)
@@ -49,7 +49,6 @@ interface Props {
   organization: T.Organization | undefined;
   qualifiers: ComponentQualifier[];
   router: Pick<Router, 'push' | 'replace'>;
-  storageOptionsSuffix?: string;
 }
 
 interface State {
@@ -61,9 +60,9 @@ interface State {
   total?: number;
 }
 
-const PROJECTS_SORT = 'sonarqube.projects.sort';
-const PROJECTS_VIEW = 'sonarqube.projects.view';
-const PROJECTS_VISUALIZATION = 'sonarqube.projects.visualization';
+export const LS_PROJECTS_SORT = 'sonarqube.projects.sort';
+export const LS_PROJECTS_VIEW = 'sonarqube.projects.view';
+export const LS_PROJECTS_VISUALIZATION = 'sonarqube.projects.visualization';
 
 export class AllProjects extends React.PureComponent<Props, State> {
   mounted = false;
@@ -132,20 +131,19 @@ export class AllProjects extends React.PureComponent<Props, State> {
   getSort = () => this.state.query.sort || 'name';
 
   getStorageOptions = () => {
-    const { storageOptionsSuffix } = this.props;
     const options: {
       sort?: string;
       view?: string;
       visualization?: string;
     } = {};
-    if (get(PROJECTS_SORT, storageOptionsSuffix)) {
-      options.sort = get(PROJECTS_SORT, storageOptionsSuffix) || undefined;
+    if (get(LS_PROJECTS_SORT)) {
+      options.sort = get(LS_PROJECTS_SORT) || undefined;
     }
-    if (get(PROJECTS_VIEW, storageOptionsSuffix)) {
-      options.view = get(PROJECTS_VIEW, storageOptionsSuffix) || undefined;
+    if (get(LS_PROJECTS_VIEW)) {
+      options.view = get(LS_PROJECTS_VIEW) || undefined;
     }
-    if (get(PROJECTS_VISUALIZATION, storageOptionsSuffix)) {
-      options.visualization = get(PROJECTS_VISUALIZATION, storageOptionsSuffix) || undefined;
+    if (get(LS_PROJECTS_VISUALIZATION)) {
+      options.visualization = get(LS_PROJECTS_VISUALIZATION) || undefined;
     }
     return options;
   };
@@ -171,7 +169,6 @@ export class AllProjects extends React.PureComponent<Props, State> {
   };
 
   handlePerspectiveChange = ({ view, visualization }: { view: string; visualization?: string }) => {
-    const { storageOptionsSuffix } = this.props;
     const query: {
       view: string | undefined;
       visualization: string | undefined;
@@ -193,9 +190,9 @@ export class AllProjects extends React.PureComponent<Props, State> {
       this.updateLocationQuery(query);
     }
 
-    save(PROJECTS_SORT, query.sort, storageOptionsSuffix);
-    save(PROJECTS_VIEW, query.view, storageOptionsSuffix);
-    save(PROJECTS_VISUALIZATION, visualization, storageOptionsSuffix);
+    save(LS_PROJECTS_SORT, query.sort);
+    save(LS_PROJECTS_VIEW, query.view);
+    save(LS_PROJECTS_VISUALIZATION, visualization);
   };
 
   handleQueryChange(initialMount: boolean) {
@@ -214,7 +211,7 @@ export class AllProjects extends React.PureComponent<Props, State> {
   handleSortChange = (sort: string, desc: boolean) => {
     const asString = (desc ? '-' : '') + sort;
     this.updateLocationQuery({ sort: asString });
-    save(PROJECTS_SORT, asString, this.props.storageOptionsSuffix);
+    save(LS_PROJECTS_SORT, asString);
   };
 
   stopLoading = () => {
index fc3f6fb794f4f105a222faa305d315ce1c2dc030..45139ff7b6c5d1c5dc5edb669d39947f0fe89c53 100644 (file)
@@ -41,10 +41,6 @@ export class DefaultPageSelector extends React.PureComponent<Props, State> {
   state: State = {};
 
   componentDidMount() {
-    if (isSonarCloud() && !isLoggedIn(this.props.currentUser)) {
-      this.props.router.replace('/explore/projects');
-    }
-
     if (!isSonarCloud()) {
       this.defineIfShouldBeRedirected();
     }
index 438e519eb61388dd769f90a1c5f6685172b40a9d..433f8a5a3c6b3fd549d2855ad576c3dc6edf0afd 100644 (file)
@@ -21,7 +21,12 @@ import { shallow } from 'enzyme';
 import * as React from 'react';
 import { get, save } from 'sonar-ui-common/helpers/storage';
 import { ComponentQualifier } from '../../../../types/component';
-import { AllProjects } from '../AllProjects';
+import {
+  AllProjects,
+  LS_PROJECTS_SORT,
+  LS_PROJECTS_VIEW,
+  LS_PROJECTS_VISUALIZATION
+} from '../AllProjects';
 
 jest.mock('../ProjectsList', () => ({
   // eslint-disable-next-line
@@ -100,12 +105,24 @@ it('fetches projects', () => {
 });
 
 it('redirects to the saved search', () => {
-  (get as jest.Mock).mockImplementation((key: string) =>
-    key === 'sonarqube.projects.view' ? 'leak' : null
-  );
+  const localeStorageMock: T.Dict<string> = {
+    [LS_PROJECTS_VIEW]: 'leak',
+    [LS_PROJECTS_SORT]: 'coverage',
+    [LS_PROJECTS_VISUALIZATION]: 'security'
+  };
+
+  (get as jest.Mock).mockImplementation((key: string) => localeStorageMock[key]);
   const replace = jest.fn();
   shallowRender({}, jest.fn(), replace);
-  expect(replace).lastCalledWith({ pathname: '/projects', query: { view: 'leak' } });
+
+  expect(replace).lastCalledWith({
+    pathname: '/projects',
+    query: {
+      view: localeStorageMock[LS_PROJECTS_VIEW],
+      sort: localeStorageMock[LS_PROJECTS_SORT],
+      visualization: localeStorageMock[LS_PROJECTS_VISUALIZATION]
+    }
+  });
 });
 
 it('changes sort', () => {
@@ -113,7 +130,7 @@ it('changes sort', () => {
   const wrapper = shallowRender({}, push);
   wrapper.find('PageHeader').prop<Function>('onSortChange')('size', false);
   expect(push).lastCalledWith({ pathname: '/projects', query: { sort: 'size' } });
-  expect(save).lastCalledWith('sonarqube.projects.sort', 'size', undefined);
+  expect(save).lastCalledWith(LS_PROJECTS_SORT, 'size');
 });
 
 it('changes perspective to leak', () => {
@@ -124,9 +141,9 @@ it('changes perspective to leak', () => {
     pathname: '/projects',
     query: { view: 'leak', visualization: undefined }
   });
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.sort', undefined, undefined);
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.view', 'leak', undefined);
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.visualization', undefined, undefined);
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_SORT, undefined);
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_VIEW, 'leak');
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_VISUALIZATION, undefined);
 });
 
 it('updates sorting when changing perspective from leak', () => {
@@ -140,9 +157,9 @@ it('updates sorting when changing perspective from leak', () => {
     pathname: '/projects',
     query: { sort: 'coverage', view: undefined, visualization: undefined }
   });
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.sort', 'coverage', undefined);
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.view', undefined, undefined);
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.visualization', undefined, undefined);
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_SORT, 'coverage');
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_VIEW, undefined);
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_VISUALIZATION, undefined);
 });
 
 it('changes perspective to risk visualization', () => {
@@ -156,9 +173,9 @@ it('changes perspective to risk visualization', () => {
     pathname: '/projects',
     query: { view: 'visualizations', visualization: 'risk' }
   });
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.sort', undefined, undefined);
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.view', 'visualizations', undefined);
-  expect(save).toHaveBeenCalledWith('sonarqube.projects.visualization', 'risk', undefined);
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_SORT, undefined);
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_VIEW, 'visualizations');
+  expect(save).toHaveBeenCalledWith(LS_PROJECTS_VISUALIZATION, 'risk');
 });
 
 it('handles favorite projects', () => {