]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18776 Project settings and info link
authorJeremy Davis <jeremy.davis@sonarsource.com>
Thu, 23 Mar 2023 15:10:33 +0000 (16:10 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 27 Mar 2023 20:03:03 +0000 (20:03 +0000)
21 files changed:
server/sonar-web/design-system/src/components/NavBarTabs.tsx
server/sonar-web/design-system/src/components/icons/ChevronDownIcon.tsx
server/sonar-web/design-system/src/components/icons/index.ts
server/sonar-web/design-system/src/helpers/constants.ts
server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx
server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNav-test.tsx
server/sonar-web/src/main/js/app/components/nav/component/__tests__/Menu-test.tsx
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/InfoDrawer.css
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/DrawerLink-test.tsx [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/InfoDrawer-test.tsx [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/InfoDrawerPage-test.tsx [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformation-test.tsx [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformationRenderer-test.tsx [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/DrawerLink-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/InfoDrawer-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/InfoDrawerPage-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformationRenderer-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx
server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/SettingsNav-test.tsx.snap

index 669f2d3642ca740c7b54c1f7f190bf60139260c5..87e8ce3f126a81fe4327b44f24dab70e8362fe89 100644 (file)
 
 import styled from '@emotion/styled';
 import classNames from 'classnames';
+import React from 'react';
 import tw, { theme } from 'twin.macro';
 import { themeBorder, themeColor, themeContrast } from '../helpers/theme';
 import { isDefined } from '../helpers/types';
-import ChevronDownIcon from './icons/ChevronDownIcon';
+import { ChevronDownIcon } from './icons/ChevronDownIcon';
 import NavLink, { NavLinkProps } from './NavLink';
 import Tooltip from './Tooltip';
 
@@ -34,7 +35,7 @@ interface Props extends React.HTMLAttributes<HTMLUListElement> {
 
 export function NavBarTabs({ children, className, ...other }: Props) {
   return (
-    <ul className={classNames('sw-flex sw-items-end sw-gap-6', className)} {...other}>
+    <ul className={`sw-flex sw-items-end sw-gap-6 ${className ?? ''}`} {...other}>
       {children}
     </ul>
   );
@@ -43,17 +44,22 @@ export function NavBarTabs({ children, className, ...other }: Props) {
 interface NavBarTabLinkProps extends Omit<NavLinkProps, 'children'> {
   active?: boolean;
   children?: React.ReactNode;
+  className?: string;
   text: string;
   withChevron?: boolean;
 }
 
 export function NavBarTabLink(props: NavBarTabLinkProps) {
-  const { active, children, text, withChevron = false, ...linkProps } = props;
+  const { active, children, className, text, withChevron = false, ...linkProps } = props;
   return (
     <NavBarTabLinkWrapper>
       <NavLink
         className={({ isActive }) =>
-          classNames('sw-flex sw-items-center', { active: isDefined(active) ? active : isActive })
+          classNames(
+            'sw-flex sw-items-center',
+            { active: isDefined(active) ? active : isActive },
+            className
+          )
         }
         {...linkProps}
       >
@@ -81,27 +87,31 @@ export function DisabledTabLink(props: { label: string; overlay: React.ReactNode
 
 // Styling for <NavLink> due to its special className function, it conflicts when styled with Emotion.
 const NavBarTabLinkWrapper = styled.li`
+  ${tw`sw-body-md`};
   & > a {
     ${tw`sw-pb-3`};
     ${tw`sw-block`};
     ${tw`sw-box-border`};
     ${tw`sw-transition-none`};
-    ${tw`sw-body-md`};
+
     color: ${themeContrast('buttonSecondary')};
     text-decoration: none;
     border-bottom: ${themeBorder('xsActive', 'transparent')};
     padding-bottom: calc(${theme('spacing.3')} + 1px); // 12px spacing + 3px border + 1px = 16px
   }
+
   & > a.active,
   & > a:active,
   & > a:hover,
   & > a:focus {
     border-bottom-color: ${themeColor('tabBorder')};
   }
+
   & > a.active > span[data-text],
   & > a:active > span {
     ${tw`sw-body-md-highlight`};
   }
+
   // This is a hack to have a link take the space of the bold font, so when active other ones are not moving
   & > a > span[data-text]::before {
     ${tw`sw-block`};
index 863c092f78e1c17129e9961101cfe0e73965ce13..b34e88000988df4778402d823577b79469457dfd 100644 (file)
@@ -21,7 +21,7 @@ import { useTheme } from '@emotion/react';
 import { themeColor } from '../../helpers/theme';
 import { CustomIcon, IconProps } from './Icon';
 
-export default function ChevronDownIcon({ fill = 'currentColor', ...iconProps }: IconProps) {
+export function ChevronDownIcon({ fill = 'currentColor', ...iconProps }: IconProps) {
   const theme = useTheme();
   return (
     <CustomIcon {...iconProps}>
index b0992dbdb916fce5fef3739be84695b4cd951e27..303600bd9be952cc4aab839223777d8e5d1f34d5 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 export { default as BranchIcon } from './BranchIcon';
-export { default as ChevronDownIcon } from './ChevronDownIcon';
+export { ChevronDownIcon } from './ChevronDownIcon';
 export { default as ClockIcon } from './ClockIcon';
 export { FlagErrorIcon } from './FlagErrorIcon';
 export { FlagInfoIcon } from './FlagInfoIcon';
index 344d66b7ac5b697948a40e16813928fbf9991c23..c47e78cf7eded97759ed2ab3d3e72b4e22756f8b 100644 (file)
@@ -58,6 +58,7 @@ export const LAYOUT_BANNER_HEIGHT = 44;
 export const LAYOUT_BRANDING_ICON_WIDTH = 198;
 export const LAYOUT_FILTERBAR_HEADER = 56;
 export const LAYOUT_GLOBAL_NAV_HEIGHT = 52;
+export const LAYOUT_PROJECT_NAV_HEIGHT = 110;
 export const LAYOUT_LOGO_MARGIN_RIGHT = 45;
 export const LAYOUT_LOGO_MAX_HEIGHT = 40;
 export const LAYOUT_LOGO_MAX_WIDTH = 150;
index 785922bdb95472cf1b3ca27319fe219401981126..98c59386a469615224ec7bcada4b7b48ca309b20 100644 (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 { TopBar } from 'design-system';
+import { LAYOUT_GLOBAL_NAV_HEIGHT, LAYOUT_PROJECT_NAV_HEIGHT, TopBar } from 'design-system';
 import * as React from 'react';
 import { translate } from '../../../../helpers/l10n';
 import {
@@ -28,7 +28,6 @@ import { BranchLike } from '../../../../types/branch-like';
 import { ComponentQualifier } from '../../../../types/component';
 import { Task, TaskWarning } from '../../../../types/tasks';
 import { Component } from '../../../../types/types';
-import { rawSizes } from '../../../theme';
 import RecentHistory from '../../RecentHistory';
 import ComponentNavProjectBindingErrorNotif from './ComponentNavProjectBindingErrorNotif';
 import Header from './Header';
@@ -52,9 +51,6 @@ export interface ComponentNavProps {
   warnings: TaskWarning[];
 }
 
-const ALERT_HEIGHT = 30;
-const BRANCHLIKE_TOGGLE_ADDED_HEIGHT = 6;
-
 export default function ComponentNav(props: ComponentNavProps) {
   const {
     branchLikes,
@@ -68,7 +64,6 @@ export default function ComponentNav(props: ComponentNavProps) {
     projectBindingErrors,
     warnings,
   } = props;
-  const { contextNavHeightRaw, globalNavHeightRaw } = rawSizes;
 
   const [displayProjectInfo, setDisplayProjectInfo] = React.useState(false);
 
@@ -87,63 +82,58 @@ export default function ComponentNav(props: ComponentNavProps) {
     }
   }, [component, component.key]);
 
-  let contextNavHeight = contextNavHeightRaw;
-
   let prDecoNotifComponent;
   if (projectBindingErrors !== undefined) {
     prDecoNotifComponent = <ComponentNavProjectBindingErrorNotif component={component} />;
-    contextNavHeight += ALERT_HEIGHT;
-  }
-
-  if (branchLikes.length) {
-    contextNavHeight += BRANCHLIKE_TOGGLE_ADDED_HEIGHT;
   }
 
   return (
-    <TopBar id="context-navigation" aria-label={translate('qualifier', component.qualifier)}>
-      <div className="sw-flex sw-justify-between">
-        <Header
-          branchLikes={branchLikes}
-          component={component}
-          currentBranchLike={currentBranchLike}
-          projectBinding={projectBinding}
-        />
-        <HeaderMeta
+    <>
+      <TopBar id="context-navigation" aria-label={translate('qualifier', component.qualifier)}>
+        <div className="sw-flex sw-justify-between">
+          <Header
+            branchLikes={branchLikes}
+            component={component}
+            currentBranchLike={currentBranchLike}
+            projectBinding={projectBinding}
+          />
+          <HeaderMeta
+            branchLike={currentBranchLike}
+            component={component}
+            currentTask={currentTask}
+            currentTaskOnSameBranch={currentTaskOnSameBranch}
+            isInProgress={isInProgress}
+            isPending={isPending}
+            onWarningDismiss={props.onWarningDismiss}
+            warnings={warnings}
+          />
+        </div>
+        <Menu
           branchLike={currentBranchLike}
+          branchLikes={branchLikes}
           component={component}
-          currentTask={currentTask}
-          currentTaskOnSameBranch={currentTaskOnSameBranch}
           isInProgress={isInProgress}
           isPending={isPending}
-          onWarningDismiss={props.onWarningDismiss}
-          warnings={warnings}
-        />
-      </div>
-      <Menu
-        branchLike={currentBranchLike}
-        branchLikes={branchLikes}
-        component={component}
-        isInProgress={isInProgress}
-        isPending={isPending}
-        onToggleProjectInfo={() => {
-          setDisplayProjectInfo(!displayProjectInfo);
-        }}
-        projectInfoDisplayed={displayProjectInfo}
-      />
-      <InfoDrawer
-        displayed={displayProjectInfo}
-        onClose={() => {
-          setDisplayProjectInfo(false);
-        }}
-        top={globalNavHeightRaw + contextNavHeight}
-      >
-        <ProjectInformation
-          branchLike={currentBranchLike}
-          component={component}
-          onComponentChange={props.onComponentChange}
+          onToggleProjectInfo={() => {
+            setDisplayProjectInfo(!displayProjectInfo);
+          }}
+          projectInfoDisplayed={displayProjectInfo}
         />
-      </InfoDrawer>
+        <InfoDrawer
+          displayed={displayProjectInfo}
+          onClose={() => {
+            setDisplayProjectInfo(false);
+          }}
+          top={LAYOUT_GLOBAL_NAV_HEIGHT + LAYOUT_PROJECT_NAV_HEIGHT}
+        >
+          <ProjectInformation
+            branchLike={currentBranchLike}
+            component={component}
+            onComponentChange={props.onComponentChange}
+          />
+        </InfoDrawer>
+      </TopBar>
       {prDecoNotifComponent}
-    </TopBar>
+    </>
   );
 }
index c23e466598920ed4a41ceb132361c9a4bbe0894e..9f2c9475438a0bd2ed798cb49967732ba2d253db 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import classNames from 'classnames';
-import { DisabledTabLink, NavBarTabLink, NavBarTabs, Tooltip } from 'design-system';
+import {
+  DisabledTabLink,
+  Dropdown,
+  ItemNavLink,
+  Link,
+  NavBarTabLink,
+  NavBarTabs,
+  Tooltip,
+} from 'design-system';
 import * as React from 'react';
-import { NavLink } from 'react-router-dom';
-import { ButtonLink } from '../../../../components/controls/buttons';
-import Dropdown from '../../../../components/controls/Dropdown';
-import BulletListIcon from '../../../../components/icons/BulletListIcon';
-import DropdownIcon from '../../../../components/icons/DropdownIcon';
-import SQNavBarTabs from '../../../../components/ui/NavBarTabs';
 import { getBranchLikeQuery, isPullRequest } from '../../../../helpers/branch-like';
 import { hasMessage, translate, translateWithParameters } from '../../../../helpers/l10n';
 import { getPortfolioUrl, getProjectQueryUrl } from '../../../../helpers/urls';
@@ -280,7 +281,7 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
 
-    const isSettingsActive = SETTINGS_URLS.some((url) => window.location.href.indexOf(url) !== -1);
+    const isSettingsActive = SETTINGS_URLS.some((url) => window.location.href.includes(url));
 
     const adminLinks = this.renderAdministrationLinks(query, isProject, isApplication, isPortfolio);
     if (!adminLinks.some((link) => link != null)) {
@@ -290,22 +291,23 @@ export class Menu extends React.PureComponent<Props> {
     return (
       <Dropdown
         data-test="administration"
-        overlay={<ul className="menu">{adminLinks}</ul>}
-        tagName="li"
+        id="component-navigation-admin"
+        size="auto"
+        overlay={adminLinks}
       >
-        {({ onToggleClick, open }) => (
-          <ButtonLink
-            aria-expanded={open}
-            aria-haspopup="menu"
-            className={classNames('dropdown-toggle', { active: isSettingsActive || open })}
-            id="component-navigation-admin"
+        {({ onToggleClick, open, a11yAttrs }) => (
+          <NavBarTabLink
+            active={isSettingsActive || open}
             onClick={onToggleClick}
-          >
-            {hasMessage('layout.settings', component.qualifier)
-              ? translate('layout.settings', component.qualifier)
-              : translate('layout.settings')}
-            <DropdownIcon className="little-spacer-left" />
-          </ButtonLink>
+            text={
+              hasMessage('layout.settings', component.qualifier)
+                ? translate('layout.settings', component.qualifier)
+                : translate('layout.settings')
+            }
+            withChevron={true}
+            to={{}}
+            {...a11yAttrs}
+          />
         )}
       </Dropdown>
     );
@@ -350,17 +352,15 @@ export class Menu extends React.PureComponent<Props> {
 
     return (
       (isProject || isApplication) && (
-        <li>
-          <ButtonLink
-            className="show-project-info-button"
+        <li className="sw-body-md sw-pb-4">
+          <Link
             onClick={this.props.onToggleProjectInfo}
-            innerRef={(node) => {
-              this.projectInfoLink = node;
-            }}
+            preventDefault={true}
+            ref={(node: HTMLAnchorElement | null) => (this.projectInfoLink = node)}
+            to={{}}
           >
-            <BulletListIcon className="little-spacer-right" />
             {label}
-          </ButtonLink>
+          </Link>
         </li>
       )
     );
@@ -371,13 +371,12 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="settings">
-        <NavLink
-          to={{ pathname: '/project/settings', search: new URLSearchParams(query).toString() }}
-        >
-          {translate('project_settings.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="settings"
+        to={{ pathname: '/project/settings', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('project_settings.page')}
+      </ItemNavLink>
     );
   };
 
@@ -391,13 +390,12 @@ export class Menu extends React.PureComponent<Props> {
     }
 
     return (
-      <li key="branches">
-        <NavLink
-          to={{ pathname: '/project/branches', search: new URLSearchParams(query).toString() }}
-        >
-          {translate('project_branch_pull_request.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="branches"
+        to={{ pathname: '/project/branches', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('project_branch_pull_request.page')}
+      </ItemNavLink>
     );
   };
 
@@ -406,13 +404,12 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="baseline">
-        <NavLink
-          to={{ pathname: '/project/baseline', search: new URLSearchParams(query).toString() }}
-        >
-          {translate('project_baseline.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="baseline"
+        to={{ pathname: '/project/baseline', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('project_baseline.page')}
+      </ItemNavLink>
     );
   };
 
@@ -421,16 +418,15 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="import-export">
-        <NavLink
-          to={{
-            pathname: '/project/import_export',
-            search: new URLSearchParams(query).toString(),
-          }}
-        >
-          {translate('project_dump.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="import-export"
+        to={{
+          pathname: '/project/import_export',
+          search: new URLSearchParams(query).toString(),
+        }}
+      >
+        {translate('project_dump.page')}
+      </ItemNavLink>
     );
   };
 
@@ -439,16 +435,15 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="profiles">
-        <NavLink
-          to={{
-            pathname: '/project/quality_profiles',
-            search: new URLSearchParams(query).toString(),
-          }}
-        >
-          {translate('project_quality_profiles.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="profiles"
+        to={{
+          pathname: '/project/quality_profiles',
+          search: new URLSearchParams(query).toString(),
+        }}
+      >
+        {translate('project_quality_profiles.page')}
+      </ItemNavLink>
     );
   };
 
@@ -457,13 +452,12 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="quality_gate">
-        <NavLink
-          to={{ pathname: '/project/quality_gate', search: new URLSearchParams(query).toString() }}
-        >
-          {translate('project_quality_gate.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="quality_gate"
+        to={{ pathname: '/project/quality_gate', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('project_quality_gate.page')}
+      </ItemNavLink>
     );
   };
 
@@ -472,11 +466,12 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="links">
-        <NavLink to={{ pathname: '/project/links', search: new URLSearchParams(query).toString() }}>
-          {translate('project_links.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="links"
+        to={{ pathname: '/project/links', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('project_links.page')}
+      </ItemNavLink>
     );
   };
 
@@ -485,11 +480,12 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="permissions">
-        <NavLink to={{ pathname: '/project_roles', search: new URLSearchParams(query).toString() }}>
-          {translate('permissions.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="permissions"
+        to={{ pathname: '/project_roles', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('permissions.page')}
+      </ItemNavLink>
     );
   };
 
@@ -498,16 +494,15 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="background_tasks">
-        <NavLink
-          to={{
-            pathname: '/project/background_tasks',
-            search: new URLSearchParams(query).toString(),
-          }}
-        >
-          {translate('background_tasks.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="background_tasks"
+        to={{
+          pathname: '/project/background_tasks',
+          search: new URLSearchParams(query).toString(),
+        }}
+      >
+        {translate('background_tasks.page')}
+      </ItemNavLink>
     );
   };
 
@@ -516,11 +511,12 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="update_key">
-        <NavLink to={{ pathname: '/project/key', search: new URLSearchParams(query).toString() }}>
-          {translate('update_key.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="update_key"
+        to={{ pathname: '/project/key', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('update_key.page')}
+      </ItemNavLink>
     );
   };
 
@@ -529,13 +525,12 @@ export class Menu extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <li key="webhooks">
-        <NavLink
-          to={{ pathname: '/project/webhooks', search: new URLSearchParams(query).toString() }}
-        >
-          {translate('webhooks.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="webhooks"
+        to={{ pathname: '/project/webhooks', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('webhooks.page')}
+      </ItemNavLink>
     );
   };
 
@@ -557,13 +552,12 @@ export class Menu extends React.PureComponent<Props> {
     }
 
     return (
-      <li key="project_delete">
-        <NavLink
-          to={{ pathname: '/project/deletion', search: new URLSearchParams(query).toString() }}
-        >
-          {translate('deletion.page')}
-        </NavLink>
-      </li>
+      <ItemNavLink
+        key="project_delete"
+        to={{ pathname: '/project/deletion', search: new URLSearchParams(query).toString() }}
+      >
+        {translate('deletion.page')}
+      </ItemNavLink>
     );
   };
 
@@ -571,9 +565,9 @@ export class Menu extends React.PureComponent<Props> {
     const pathname = isAdmin ? `/project/admin/extension/${key}` : `/project/extension/${key}`;
     const query = { ...baseQuery, qualifier: this.props.component.qualifier };
     return (
-      <li key={key}>
-        <NavLink to={{ pathname, search: new URLSearchParams(query).toString() }}>{name}</NavLink>
-      </li>
+      <ItemNavLink key={key} to={{ pathname, search: new URLSearchParams(query).toString() }}>
+        {name}
+      </ItemNavLink>
     );
   };
 
@@ -586,7 +580,7 @@ export class Menu extends React.PureComponent<Props> {
 
   renderExtensions = () => {
     const query = this.getQuery();
-    const extensions = this.props.component.extensions || [];
+    const extensions = this.props.component.extensions ?? [];
     const withoutSecurityExtension = extensions.filter(
       (extension) =>
         !extension.key.startsWith('securityreport/') && !extension.key.startsWith('governance/')
@@ -599,24 +593,20 @@ export class Menu extends React.PureComponent<Props> {
     return (
       <Dropdown
         data-test="extensions"
-        overlay={
-          <ul className="menu">
-            {withoutSecurityExtension.map((e) => this.renderExtension(e, false, query))}
-          </ul>
-        }
-        tagName="li"
+        id="component-navigation-more"
+        size="auto"
+        overlay={withoutSecurityExtension.map((e) => this.renderExtension(e, false, query))}
       >
-        {({ onToggleClick, open }) => (
-          <ButtonLink
-            aria-expanded={open}
-            aria-haspopup="menu"
-            className={classNames('dropdown-toggle', { active: open })}
-            id="component-navigation-more"
+        {({ onToggleClick, open, a11yAttrs }) => (
+          <NavBarTabLink
+            active={open}
             onClick={onToggleClick}
-          >
-            {translate('more')}
-            <DropdownIcon className="little-spacer-left" />
-          </ButtonLink>
+            preventDefault={true}
+            text={translate('more')}
+            withChevron={true}
+            to={{}}
+            {...a11yAttrs}
+          />
         )}
       </Dropdown>
     );
@@ -624,8 +614,8 @@ export class Menu extends React.PureComponent<Props> {
 
   render() {
     return (
-      <div className="display-flex-center display-flex-space-between">
-        <NavBarTabs className="it__navbar-tabs">
+      <div className="sw-flex sw-justify-between sw-pt-3 it__navbar-tabs">
+        <NavBarTabs>
           {this.renderDashboardLink()}
           {this.renderBreakdownLink()}
           {this.renderIssuesLink()}
@@ -636,10 +626,10 @@ export class Menu extends React.PureComponent<Props> {
           {this.renderActivityLink()}
           {this.renderExtensions()}
         </NavBarTabs>
-        <SQNavBarTabs>
+        <NavBarTabs>
           {this.renderAdministration()}
           {this.renderProjectInformationButton()}
-        </SQNavBarTabs>
+        </NavBarTabs>
       </div>
     );
   }
index 81b2ea7fc3b24ad3ba739651fc1671922f58419b..18c7a3353f229ea36c0b9e9a1d2f8fb0a949627b 100644 (file)
@@ -66,11 +66,11 @@ it('renders correctly when the project binding is incorrect', () => {
 
 it('correctly returns focus to the Project Information link when the drawer is closed', () => {
   renderComponentNav();
-  screen.getByRole('button', { name: 'project.info.title' }).click();
-  expect(screen.getByRole('button', { name: 'project.info.title' })).not.toHaveFocus();
+  screen.getByRole('link', { name: 'project.info.title' }).click();
+  expect(screen.getByRole('link', { name: 'project.info.title' })).not.toHaveFocus();
 
   screen.getByRole('button', { name: 'close' }).click();
-  expect(screen.getByRole('button', { name: 'project.info.title' })).toHaveFocus();
+  expect(screen.getByRole('link', { name: 'project.info.title' })).toHaveFocus();
 });
 
 function renderComponentNav(props: Partial<ComponentNavProps> = {}) {
index ad00e62a704fe335c15b08ffaeb95e967f54a271..599299e7e7bb6a13b2f1efa2403b4926b28c237e 100644 (file)
@@ -18,6 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import { screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
 import * as React from 'react';
 import {
   mockBranch,
@@ -35,7 +36,8 @@ const BASE_COMPONENT = mockComponent({
   name: 'foo',
 });
 
-it('should render correctly', () => {
+it('should render correctly', async () => {
+  const user = userEvent.setup();
   const component = {
     ...BASE_COMPONENT,
     configuration: {
@@ -60,9 +62,9 @@ it('should render correctly', () => {
   // Check the dropdown.
   const button = screen.getByRole('button', { name: 'more' });
   expect(button).toBeInTheDocument();
-  button.click();
-  expect(screen.getByRole('link', { name: 'ComponentFoo' })).toBeInTheDocument();
-  expect(screen.getByRole('link', { name: 'ComponentBar' })).toBeInTheDocument();
+  await user.click(button);
+  expect(screen.getByRole('menuitem', { name: 'ComponentFoo' })).toBeInTheDocument();
+  expect(screen.getByRole('menuitem', { name: 'ComponentBar' })).toBeInTheDocument();
 });
 
 it('should render correctly when on a Portofolio', () => {
@@ -101,13 +103,7 @@ it('should render correctly when on a branch', () => {
   expect(screen.getByRole('link', { name: 'overview.page' })).toBeInTheDocument();
   expect(screen.getByRole('link', { name: 'issues.page' })).toBeInTheDocument();
   expect(screen.getByRole('link', { name: 'layout.measures' })).toBeInTheDocument();
-  expect(screen.getByRole('button', { name: 'project.info.title' })).toBeInTheDocument();
-
-  // If on a branch, regardless is the user is an admin or not, we do not show
-  // the settings link.
-  expect(
-    screen.queryByRole('link', { name: `layout.settings.${ComponentQualifier.Project}` })
-  ).not.toBeInTheDocument();
+  expect(screen.getByRole('link', { name: 'project.info.title' })).toBeInTheDocument();
 });
 
 it('should render correctly when on a pull request', () => {
@@ -140,7 +136,7 @@ it('should disable links if no analysis has been done', () => {
   expect(screen.getByRole('link', { name: 'overview.page' })).toBeInTheDocument();
   expect(screen.queryByRole('link', { name: 'issues.page' })).toHaveClass('disabled-link');
   expect(screen.queryByRole('link', { name: 'layout.measures' })).toHaveClass('disabled-link');
-  expect(screen.getByRole('button', { name: 'project.info.title' })).toBeInTheDocument();
+  expect(screen.getByRole('link', { name: 'project.info.title' })).toBeInTheDocument();
 });
 
 it('should disable links if application has inaccessible projects', () => {
index 224d5625b3f15a49f28d57dca804c9bb1c831a39..1070a3d4c2409b4d526a799074269c9e9767dfe2 100644 (file)
   --drawer-width: 380px;
 }
 
-/* TODO: should we move this? Or handle it differently? */
-.navbar-inner-with-notif .info-drawer {
-  border-top: 1px solid var(--barBorderColor);
-}
-
 .info-drawer-pane {
   background-color: white;
   right: calc(-1 * var(--drawer-width));
   width: var(--drawer-width);
   transition: right 0.3s ease-in-out;
+  border-top: 1px solid var(--barBorderColor);
   border-left: 1px solid var(--barBorderColor);
   box-sizing: border-box;
 }
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/DrawerLink-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/DrawerLink-test.tsx
deleted file mode 100644 (file)
index bbb8536..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { DrawerLink, DrawerLinkProps } from '../DrawerLink';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should call onPageChange when clicked', () => {
-  const onPageChange = jest.fn();
-  const to = 'target';
-  const wrapper = shallowRender({ onPageChange, to });
-
-  wrapper.simulate('click');
-
-  expect(onPageChange).toHaveBeenCalledWith(to);
-});
-
-function shallowRender(props: Partial<DrawerLinkProps<string>> = {}) {
-  return shallow(<DrawerLink label="switch page" onPageChange={jest.fn()} to="id" {...props} />);
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/InfoDrawer-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/InfoDrawer-test.tsx
deleted file mode 100644 (file)
index c19b0e0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { ClearButton } from '../../../../../../components/controls/buttons';
-import InfoDrawer, { InfoDrawerProps } from '../InfoDrawer';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(shallowRender({ displayed: true })).toMatchSnapshot('displayed');
-});
-
-it('should call onClose when button is clicked', () => {
-  const onClose = jest.fn();
-  const wrapper = shallowRender({ onClose, displayed: true });
-  wrapper.find(ClearButton).simulate('click');
-
-  expect(onClose).toHaveBeenCalled();
-});
-
-function shallowRender(props: Partial<InfoDrawerProps> = {}) {
-  return shallow(
-    <InfoDrawer displayed={false} onClose={jest.fn()} top={120} {...props}>
-      <span>content</span>
-    </InfoDrawer>
-  );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/InfoDrawerPage-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/InfoDrawerPage-test.tsx
deleted file mode 100644 (file)
index 7b6e6dc..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import InfoDrawerPage, { InfoDrawerPageProps } from '../InfoDrawerPage';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-  expect(shallowRender({ displayed: true })).toMatchSnapshot();
-});
-
-it('should call onPageChange when clicked', () => {
-  const onPageChange = jest.fn();
-  const wrapper = shallowRender({ onPageChange, displayed: true });
-
-  wrapper.find('.back-button').simulate('click');
-
-  expect(onPageChange).toHaveBeenCalledTimes(1);
-});
-
-function shallowRender(props: Partial<InfoDrawerPageProps> = {}) {
-  return shallow(
-    <InfoDrawerPage displayed={false} onPageChange={jest.fn()} {...props}>
-      <div>content</div>
-    </InfoDrawerPage>
-  );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformation-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformation-test.tsx
deleted file mode 100644 (file)
index c615002..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { mockCurrentUser, mockLoggedInUser, mockMetric } from '../../../../../../helpers/testMocks';
-import { waitAndUpdate } from '../../../../../../helpers/testUtils';
-import { ComponentQualifier, Visibility } from '../../../../../../types/component';
-import ProjectBadges from '../badges/ProjectBadges';
-import { ProjectInformation } from '../ProjectInformation';
-import { ProjectInformationPages } from '../ProjectInformationPages';
-
-jest.mock('../../../../../../api/measures', () => {
-  const { mockMeasure } = jest.requireActual('../../../../../../helpers/testMocks');
-  return {
-    getMeasures: jest.fn().mockResolvedValue([mockMeasure()]),
-  };
-});
-
-it('should render correctly', async () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(shallowRender({ currentUser: mockLoggedInUser() })).toMatchSnapshot('logged in user');
-  expect(
-    shallowRender({ component: mockComponent({ visibility: Visibility.Private }) })
-  ).toMatchSnapshot('private');
-  const wrapper = shallowRender();
-  await waitAndUpdate(wrapper);
-  expect(wrapper).toMatchSnapshot('measures loaded');
-});
-
-it('should handle page change', async () => {
-  const wrapper = shallowRender();
-
-  wrapper.instance().setPage(ProjectInformationPages.badges);
-
-  await waitAndUpdate(wrapper);
-
-  expect(wrapper.state().page).toBe(ProjectInformationPages.badges);
-});
-
-it('should display badge', () => {
-  const wrapper = shallowRender({
-    component: mockComponent({ qualifier: ComponentQualifier.Project }),
-  });
-
-  expect(wrapper.find(ProjectBadges).type).toBeDefined();
-
-  wrapper.setProps({ component: mockComponent({ qualifier: ComponentQualifier.Application }) });
-  expect(wrapper.find(ProjectBadges).type).toBeDefined();
-});
-
-function shallowRender(props: Partial<ProjectInformation['props']> = {}) {
-  return shallow<ProjectInformation>(
-    <ProjectInformation
-      component={mockComponent()}
-      currentUser={mockCurrentUser()}
-      metrics={{
-        coverage: mockMetric(),
-      }}
-      onComponentChange={jest.fn()}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformationRenderer-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformationRenderer-test.tsx
deleted file mode 100644 (file)
index 796f3e6..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { ComponentQualifier, Visibility } from '../../../../../../types/component';
-import {
-  ProjectInformationRenderer,
-  ProjectInformationRendererProps,
-} from '../ProjectInformationRenderer';
-
-jest.mock('react', () => {
-  return {
-    ...jest.requireActual('react'),
-    useEffect: jest.fn().mockImplementation((f) => f()),
-    useRef: jest.fn().mockReturnValue(document.createElement('h2')),
-  };
-});
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(shallowRender({ canConfigureNotifications: false })).toMatchSnapshot('with notifications');
-  expect(shallowRender({ canUseBadges: false })).toMatchSnapshot('no badges');
-  expect(shallowRender({ canConfigureNotifications: false, canUseBadges: false })).toMatchSnapshot(
-    'no badges, no notifications'
-  );
-});
-
-it('should render a private project correctly', () => {
-  expect(
-    shallowRender({ component: mockComponent({ visibility: Visibility.Private }) })
-  ).toMatchSnapshot();
-});
-
-it('should render an app correctly', () => {
-  const component = mockComponent({ qualifier: 'APP' });
-  expect(shallowRender({ component })).toMatchSnapshot('default');
-});
-
-it('should render with description', () => {
-  const component = mockComponent({ description: 'Lorem ipsum' });
-  expect(shallowRender({ component })).toMatchSnapshot();
-});
-
-it('should handle missing quality profiles and quality gates', () => {
-  expect(
-    shallowRender({
-      component: mockComponent({ qualityGate: undefined, qualityProfiles: undefined }),
-    })
-  ).toMatchSnapshot();
-});
-
-it('should render app correctly when regulatoryReport feature is not enabled', () => {
-  expect(
-    shallowRender({
-      hasFeature: jest.fn().mockReturnValue(false),
-    })
-  ).toMatchSnapshot();
-});
-
-it('should set focus on the heading when rendered', () => {
-  const fakeElement = document.createElement('h2');
-  const focus = jest.fn();
-  (React.useRef as jest.Mock).mockReturnValueOnce({ current: { ...fakeElement, focus } });
-
-  shallowRender();
-  expect(focus).toHaveBeenCalled();
-});
-
-function shallowRender(props: Partial<ProjectInformationRendererProps> = {}) {
-  return shallow(
-    <ProjectInformationRenderer
-      hasFeature={jest.fn().mockReturnValue(true)}
-      canConfigureNotifications={true}
-      canUseBadges={true}
-      component={mockComponent({
-        qualifier: ComponentQualifier.Project,
-        visibility: Visibility.Public,
-      })}
-      onComponentChange={jest.fn()}
-      onPageChange={jest.fn()}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/DrawerLink-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/DrawerLink-test.tsx.snap
deleted file mode 100644 (file)
index 56f5596..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<a
-  className="display-flex-space-between bordered-bottom big-padded"
-  onClick={[Function]}
-  role="link"
-  tabIndex={0}
->
-  switch page
-  <ChevronRightIcon />
-</a>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/InfoDrawer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/InfoDrawer-test.tsx.snap
deleted file mode 100644 (file)
index 3628f4e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-<div
-  className="info-drawer info-drawer-pane"
-  style={
-    {
-      "top": 120,
-    }
-  }
-/>
-`;
-
-exports[`should render correctly: displayed 1`] = `
-<div
-  className="info-drawer info-drawer-pane open"
-  style={
-    {
-      "top": 120,
-    }
-  }
->
-  <div
-    className="close-button"
-  >
-    <ClearButton
-      aria-label="close"
-      onClick={[MockFunction]}
-    />
-  </div>
-  <EscKeydownHandler
-    onKeydown={[MockFunction]}
-  >
-    <OutsideClickHandler
-      onClickOutside={[MockFunction]}
-    >
-      <div
-        className="display-flex-column max-height-100"
-      >
-        <span>
-          content
-        </span>
-      </div>
-    </OutsideClickHandler>
-  </EscKeydownHandler>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/InfoDrawerPage-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/InfoDrawerPage-test.tsx.snap
deleted file mode 100644 (file)
index 4525678..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<div
-  className="info-drawer-page info-drawer-pane display-flex-column overflow-hidden"
-/>
-`;
-
-exports[`should render correctly 2`] = `
-<div
-  className="info-drawer-page info-drawer-pane display-flex-column overflow-hidden open"
->
-  <a
-    className="h2 back-button big-padded bordered-bottom"
-    onClick={[Function]}
-    role="link"
-    tabIndex={-1}
-  >
-    <BackIcon
-      className="little-spacer-right"
-    />
-    back
-  </a>
-  <div
-    className="overflow-y-auto big-padded"
-  >
-    <div>
-      content
-    </div>
-  </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap
deleted file mode 100644 (file)
index 42048bd..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-<Fragment>
-  <withAvailableFeaturesContext(Component)
-    canConfigureNotifications={false}
-    canUseBadges={true}
-    component={
-      {
-        "breadcrumbs": [],
-        "key": "my-project",
-        "name": "MyProject",
-        "qualifier": "TRK",
-        "qualityGate": {
-          "isDefault": true,
-          "key": "30",
-          "name": "Sonar way",
-        },
-        "qualityProfiles": [
-          {
-            "deleted": false,
-            "key": "my-qp",
-            "language": "ts",
-            "name": "Sonar way",
-          },
-        ],
-        "tags": [],
-      }
-    }
-    onComponentChange={[MockFunction]}
-    onPageChange={[Function]}
-  />
-  <InfoDrawerPage
-    displayed={false}
-    onPageChange={[Function]}
-  >
-    <ProjectBadges
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-        }
-      }
-    />
-  </InfoDrawerPage>
-</Fragment>
-`;
-
-exports[`should render correctly: logged in user 1`] = `
-<Fragment>
-  <withAvailableFeaturesContext(Component)
-    canConfigureNotifications={true}
-    canUseBadges={true}
-    component={
-      {
-        "breadcrumbs": [],
-        "key": "my-project",
-        "name": "MyProject",
-        "qualifier": "TRK",
-        "qualityGate": {
-          "isDefault": true,
-          "key": "30",
-          "name": "Sonar way",
-        },
-        "qualityProfiles": [
-          {
-            "deleted": false,
-            "key": "my-qp",
-            "language": "ts",
-            "name": "Sonar way",
-          },
-        ],
-        "tags": [],
-      }
-    }
-    onComponentChange={[MockFunction]}
-    onPageChange={[Function]}
-  />
-  <InfoDrawerPage
-    displayed={false}
-    onPageChange={[Function]}
-  >
-    <ProjectBadges
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-        }
-      }
-    />
-  </InfoDrawerPage>
-  <InfoDrawerPage
-    displayed={false}
-    onPageChange={[Function]}
-  >
-    <withNotifications(ProjectNotifications)
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-        }
-      }
-    />
-  </InfoDrawerPage>
-</Fragment>
-`;
-
-exports[`should render correctly: measures loaded 1`] = `
-<Fragment>
-  <withAvailableFeaturesContext(Component)
-    canConfigureNotifications={false}
-    canUseBadges={true}
-    component={
-      {
-        "breadcrumbs": [],
-        "key": "my-project",
-        "name": "MyProject",
-        "qualifier": "TRK",
-        "qualityGate": {
-          "isDefault": true,
-          "key": "30",
-          "name": "Sonar way",
-        },
-        "qualityProfiles": [
-          {
-            "deleted": false,
-            "key": "my-qp",
-            "language": "ts",
-            "name": "Sonar way",
-          },
-        ],
-        "tags": [],
-      }
-    }
-    measures={
-      [
-        {
-          "bestValue": true,
-          "metric": "bugs",
-          "period": {
-            "bestValue": true,
-            "index": 1,
-            "value": "1.0",
-          },
-          "value": "1.0",
-        },
-      ]
-    }
-    onComponentChange={[MockFunction]}
-    onPageChange={[Function]}
-  />
-  <InfoDrawerPage
-    displayed={false}
-    onPageChange={[Function]}
-  >
-    <ProjectBadges
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-        }
-      }
-    />
-  </InfoDrawerPage>
-</Fragment>
-`;
-
-exports[`should render correctly: private 1`] = `
-<Fragment>
-  <withAvailableFeaturesContext(Component)
-    canConfigureNotifications={false}
-    canUseBadges={true}
-    component={
-      {
-        "breadcrumbs": [],
-        "key": "my-project",
-        "name": "MyProject",
-        "qualifier": "TRK",
-        "qualityGate": {
-          "isDefault": true,
-          "key": "30",
-          "name": "Sonar way",
-        },
-        "qualityProfiles": [
-          {
-            "deleted": false,
-            "key": "my-qp",
-            "language": "ts",
-            "name": "Sonar way",
-          },
-        ],
-        "tags": [],
-        "visibility": "private",
-      }
-    }
-    onComponentChange={[MockFunction]}
-    onPageChange={[Function]}
-  />
-  <InfoDrawerPage
-    displayed={false}
-    onPageChange={[Function]}
-  >
-    <ProjectBadges
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-          "visibility": "private",
-        }
-      }
-    />
-  </InfoDrawerPage>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformationRenderer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformationRenderer-test.tsx.snap
deleted file mode 100644 (file)
index 789251f..0000000
+++ /dev/null
@@ -1,1399 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should handle missing quality profiles and quality gates 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": undefined,
-            "qualityProfiles": undefined,
-            "tags": [],
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": undefined,
-            "qualityProfiles": undefined,
-            "tags": [],
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": undefined,
-          "qualityProfiles": undefined,
-          "tags": [],
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="overview.badges.get_badge.TRK"
-          onPageChange={[MockFunction]}
-          to={1}
-        />
-      </li>
-      <li>
-        <Memo(DrawerLink)
-          label="project.info.to_notifications"
-          onPageChange={[MockFunction]}
-          to={2}
-        />
-      </li>
-      <li
-        className="big-padded bordered-bottom"
-      >
-        <ModalButton
-          modal={[Function]}
-        >
-          <Component />
-        </ModalButton>
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render a private project correctly 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-        <PrivacyBadgeContainer
-          qualifier="TRK"
-          visibility="private"
-        />
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "private",
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "private",
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaQualityGate
-        qualityGate={
-          {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          }
-        }
-      />
-      <withLanguagesContext(MetaQualityProfiles)
-        headerClassName="big-spacer-top"
-        profiles={
-          [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ]
-        }
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-          "visibility": "private",
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="overview.badges.get_badge.TRK"
-          onPageChange={[MockFunction]}
-          to={1}
-        />
-      </li>
-      <li>
-        <Memo(DrawerLink)
-          label="project.info.to_notifications"
-          onPageChange={[MockFunction]}
-          to={2}
-        />
-      </li>
-      <li
-        className="big-padded bordered-bottom"
-      >
-        <ModalButton
-          modal={[Function]}
-        >
-          <Component />
-        </ModalButton>
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render an app correctly: default 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      application.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "APP",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "APP",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="APP"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="overview.badges.get_badge.APP"
-          onPageChange={[MockFunction]}
-          to={1}
-        />
-      </li>
-      <li>
-        <Memo(DrawerLink)
-          label="project.info.to_notifications"
-          onPageChange={[MockFunction]}
-          to={2}
-        />
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render app correctly when regulatoryReport feature is not enabled 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-        <PrivacyBadgeContainer
-          qualifier="TRK"
-          visibility="public"
-        />
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaQualityGate
-        qualityGate={
-          {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          }
-        }
-      />
-      <withLanguagesContext(MetaQualityProfiles)
-        headerClassName="big-spacer-top"
-        profiles={
-          [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ]
-        }
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-          "visibility": "public",
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="overview.badges.get_badge.TRK"
-          onPageChange={[MockFunction]}
-          to={1}
-        />
-      </li>
-      <li>
-        <Memo(DrawerLink)
-          label="project.info.to_notifications"
-          onPageChange={[MockFunction]}
-          to={2}
-        />
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render correctly: default 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-        <PrivacyBadgeContainer
-          qualifier="TRK"
-          visibility="public"
-        />
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaQualityGate
-        qualityGate={
-          {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          }
-        }
-      />
-      <withLanguagesContext(MetaQualityProfiles)
-        headerClassName="big-spacer-top"
-        profiles={
-          [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ]
-        }
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-          "visibility": "public",
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="overview.badges.get_badge.TRK"
-          onPageChange={[MockFunction]}
-          to={1}
-        />
-      </li>
-      <li>
-        <Memo(DrawerLink)
-          label="project.info.to_notifications"
-          onPageChange={[MockFunction]}
-          to={2}
-        />
-      </li>
-      <li
-        className="big-padded bordered-bottom"
-      >
-        <ModalButton
-          modal={[Function]}
-        >
-          <Component />
-        </ModalButton>
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render correctly: no badges 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-        <PrivacyBadgeContainer
-          qualifier="TRK"
-          visibility="public"
-        />
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaQualityGate
-        qualityGate={
-          {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          }
-        }
-      />
-      <withLanguagesContext(MetaQualityProfiles)
-        headerClassName="big-spacer-top"
-        profiles={
-          [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ]
-        }
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-          "visibility": "public",
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="project.info.to_notifications"
-          onPageChange={[MockFunction]}
-          to={2}
-        />
-      </li>
-      <li
-        className="big-padded bordered-bottom"
-      >
-        <ModalButton
-          modal={[Function]}
-        >
-          <Component />
-        </ModalButton>
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render correctly: no badges, no notifications 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-        <PrivacyBadgeContainer
-          qualifier="TRK"
-          visibility="public"
-        />
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaQualityGate
-        qualityGate={
-          {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          }
-        }
-      />
-      <withLanguagesContext(MetaQualityProfiles)
-        headerClassName="big-spacer-top"
-        profiles={
-          [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ]
-        }
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-          "visibility": "public",
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li
-        className="big-padded bordered-bottom"
-      >
-        <ModalButton
-          modal={[Function]}
-        >
-          <Component />
-        </ModalButton>
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render correctly: with notifications 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-        <PrivacyBadgeContainer
-          qualifier="TRK"
-          visibility="public"
-        />
-      </div>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-            "visibility": "public",
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaQualityGate
-        qualityGate={
-          {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          }
-        }
-      />
-      <withLanguagesContext(MetaQualityProfiles)
-        headerClassName="big-spacer-top"
-        profiles={
-          [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ]
-        }
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-          "visibility": "public",
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="overview.badges.get_badge.TRK"
-          onPageChange={[MockFunction]}
-          to={1}
-        />
-      </li>
-      <li
-        className="big-padded bordered-bottom"
-      >
-        <ModalButton
-          modal={[Function]}
-        >
-          <Component />
-        </ModalButton>
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
-
-exports[`should render with description 1`] = `
-<Fragment>
-  <div>
-    <h2
-      className="big-padded bordered-bottom"
-      tabIndex={-1}
-    >
-      project.info.title
-    </h2>
-  </div>
-  <div
-    className="overflow-y-auto"
-  >
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <div
-        className="display-flex-center"
-      >
-        <h3
-          className="spacer-right"
-        >
-          project.info.description
-        </h3>
-      </div>
-      <p
-        className="it__project-description"
-      >
-        Lorem ipsum
-      </p>
-      <MetaTags
-        component={
-          {
-            "breadcrumbs": [],
-            "description": "Lorem ipsum",
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-          }
-        }
-        onComponentChange={[MockFunction]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom it__project-loc-value"
-    >
-      <MetaSize
-        component={
-          {
-            "breadcrumbs": [],
-            "description": "Lorem ipsum",
-            "key": "my-project",
-            "name": "MyProject",
-            "qualifier": "TRK",
-            "qualityGate": {
-              "isDefault": true,
-              "key": "30",
-              "name": "Sonar way",
-            },
-            "qualityProfiles": [
-              {
-                "deleted": false,
-                "key": "my-qp",
-                "language": "ts",
-                "name": "Sonar way",
-              },
-            ],
-            "tags": [],
-          }
-        }
-        measures={[]}
-      />
-    </div>
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaQualityGate
-        qualityGate={
-          {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          }
-        }
-      />
-      <withLanguagesContext(MetaQualityProfiles)
-        headerClassName="big-spacer-top"
-        profiles={
-          [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ]
-        }
-      />
-    </div>
-    <MetaLinks
-      component={
-        {
-          "breadcrumbs": [],
-          "description": "Lorem ipsum",
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": [
-            {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": [],
-        }
-      }
-    />
-    <div
-      className="big-padded bordered-bottom"
-    >
-      <MetaKey
-        componentKey="my-project"
-        qualifier="TRK"
-      />
-    </div>
-    <ul>
-      <li>
-        <Memo(DrawerLink)
-          label="overview.badges.get_badge.TRK"
-          onPageChange={[MockFunction]}
-          to={1}
-        />
-      </li>
-      <li>
-        <Memo(DrawerLink)
-          label="project.info.to_notifications"
-          onPageChange={[MockFunction]}
-          to={2}
-        />
-      </li>
-      <li
-        className="big-padded bordered-bottom"
-      >
-        <ModalButton
-          modal={[Function]}
-        >
-          <Component />
-        </ModalButton>
-      </li>
-    </ul>
-  </div>
-</Fragment>
-`;
index 369780bbe5edd4beae480fc9d67c6cffb303b3f4..4222ac6fc3b8b1f89b566ef6963abf5da24dfad7 100644 (file)
@@ -100,7 +100,7 @@ export class SettingsNav extends React.PureComponent<Props> {
     return (
       <Dropdown
         overlay={
-          <ul className="menu">
+          <ul className="menu dropdown-menu">
             <li>
               <NavLink end={true} to="/admin/settings">
                 {translate('settings.page')}
@@ -152,7 +152,7 @@ export class SettingsNav extends React.PureComponent<Props> {
     return (
       <Dropdown
         overlay={
-          <ul className="menu">
+          <ul className="menu dropdown-menu">
             <li>
               <NavLink end={true} to="/admin/projects_management">
                 {translate('management')}
@@ -188,7 +188,7 @@ export class SettingsNav extends React.PureComponent<Props> {
     return (
       <Dropdown
         overlay={
-          <ul className="menu">
+          <ul className="menu dropdown-menu">
             <li>
               <NavLink end={true} to="/admin/users">
                 {translate('users.page')}
index 01c0bb4afc5e92f3291baef17b916ed49cf8f9df..9f662b5310169e60ce14b7f030936265b08c74bd 100644 (file)
@@ -41,7 +41,7 @@ exports[`should render correctly when governance is active 1`] = `
     <Dropdown
       overlay={
         <ul
-          className="menu"
+          className="menu dropdown-menu"
         >
           <li>
             <NavLink
@@ -83,7 +83,7 @@ exports[`should render correctly when governance is active 1`] = `
     <Dropdown
       overlay={
         <ul
-          className="menu"
+          className="menu dropdown-menu"
         >
           <li>
             <NavLink
@@ -126,7 +126,7 @@ exports[`should render correctly when governance is active 1`] = `
     <Dropdown
       overlay={
         <ul
-          className="menu"
+          className="menu dropdown-menu"
         >
           <li>
             <NavLink
@@ -195,7 +195,7 @@ exports[`should work with extensions 1`] = `
     <Dropdown
       overlay={
         <ul
-          className="menu"
+          className="menu dropdown-menu"
         >
           <li>
             <NavLink
@@ -237,7 +237,7 @@ exports[`should work with extensions 1`] = `
     <Dropdown
       overlay={
         <ul
-          className="menu"
+          className="menu dropdown-menu"
         >
           <li>
             <NavLink
@@ -280,7 +280,7 @@ exports[`should work with extensions 1`] = `
     <Dropdown
       overlay={
         <ul
-          className="menu"
+          className="menu dropdown-menu"
         >
           <li>
             <NavLink
@@ -329,7 +329,7 @@ exports[`should work with extensions 2`] = `
   <Dropdown
     overlay={
       <ul
-        className="menu"
+        className="menu dropdown-menu"
       >
         <li>
           <NavLink
@@ -371,7 +371,7 @@ exports[`should work with extensions 2`] = `
   <Dropdown
     overlay={
       <ul
-        className="menu"
+        className="menu dropdown-menu"
       >
         <li>
           <NavLink
@@ -414,7 +414,7 @@ exports[`should work with extensions 2`] = `
   <Dropdown
     overlay={
       <ul
-        className="menu"
+        className="menu dropdown-menu"
       >
         <li>
           <NavLink