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';
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>
);
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}
>
// 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`};
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}>
* 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';
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;
* 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 {
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';
warnings: TaskWarning[];
}
-const ALERT_HEIGHT = 30;
-const BRANCHLIKE_TOGGLE_ADDED_HEIGHT = 6;
-
export default function ComponentNav(props: ComponentNavProps) {
const {
branchLikes,
projectBindingErrors,
warnings,
} = props;
- const { contextNavHeightRaw, globalNavHeightRaw } = rawSizes;
const [displayProjectInfo, setDisplayProjectInfo] = React.useState(false);
}
}, [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>
+ </>
);
}
* 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';
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)) {
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>
);
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>
)
);
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>
);
};
}
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>
);
};
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>
);
};
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>
);
};
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>
);
};
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>
);
};
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>
);
};
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>
);
};
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>
);
};
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>
);
};
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>
);
};
}
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>
);
};
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>
);
};
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/')
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>
);
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()}
{this.renderActivityLink()}
{this.renderExtensions()}
</NavBarTabs>
- <SQNavBarTabs>
+ <NavBarTabs>
{this.renderAdministration()}
{this.renderProjectInformationButton()}
- </SQNavBarTabs>
+ </NavBarTabs>
</div>
);
}
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> = {}) {
* 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,
name: 'foo',
});
-it('should render correctly', () => {
+it('should render correctly', async () => {
+ const user = userEvent.setup();
const component = {
...BASE_COMPONENT,
configuration: {
// 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', () => {
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', () => {
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', () => {
--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;
}
+++ /dev/null
-/*
- * 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} />);
-}
+++ /dev/null
-/*
- * 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>
- );
-}
+++ /dev/null
-/*
- * 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>
- );
-}
+++ /dev/null
-/*
- * 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}
- />
- );
-}
+++ /dev/null
-/*
- * 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}
- />
- );
-}
+++ /dev/null
-// 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>
-`;
+++ /dev/null
-// 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>
-`;
+++ /dev/null
-// 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>
-`;
+++ /dev/null
-// 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>
-`;
+++ /dev/null
-// 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>
-`;
return (
<Dropdown
overlay={
- <ul className="menu">
+ <ul className="menu dropdown-menu">
<li>
<NavLink end={true} to="/admin/settings">
{translate('settings.page')}
return (
<Dropdown
overlay={
- <ul className="menu">
+ <ul className="menu dropdown-menu">
<li>
<NavLink end={true} to="/admin/projects_management">
{translate('management')}
return (
<Dropdown
overlay={
- <ul className="menu">
+ <ul className="menu dropdown-menu">
<li>
<NavLink end={true} to="/admin/users">
{translate('users.page')}
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink
<Dropdown
overlay={
<ul
- className="menu"
+ className="menu dropdown-menu"
>
<li>
<NavLink