aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js
diff options
context:
space:
mode:
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>2023-03-21 17:13:04 +0100
committersonartech <sonartech@sonarsource.com>2023-03-27 20:03:03 +0000
commitb211e45ffe83cbf8eaa98c3539b2ee3a952162e2 (patch)
tree700099740e34c64a82bc4ed02041d7f2c5e51406 /server/sonar-web/src/main/js
parent54686faf91547cd918e84c8e081a722ce974c89d (diff)
downloadsonarqube-b211e45ffe83cbf8eaa98c3539b2ee3a952162e2.tar.gz
sonarqube-b211e45ffe83cbf8eaa98c3539b2ee3a952162e2.zip
SONAR-18776 Migrating breadcrumb and branch selector to MIUI
Diffstat (limited to 'server/sonar-web/src/main/js')
-rw-r--r--server/sonar-web/src/main/js/app/components/global-search/GlobalSearchResult.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/Breadcrumb.tsx93
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/Header.tsx18
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/Breadcrumb-test.tsx73
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/Header-test.tsx186
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Header-test.tsx.snap153
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchHelpTooltip.tsx130
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.css78
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.tsx98
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/CurrentBranchLike.tsx138
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/Menu.tsx72
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx47
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItemList.tsx44
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/PRLink.tsx83
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/QualityGateStatus.tsx63
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/BranchLikeNavigation-test.tsx73
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/CurrentBranchLike-test.tsx129
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/Menu-test.tsx116
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItem-test.tsx56
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItemList-test.tsx52
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/BranchLikeNavigation-test.tsx.snap195
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap307
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/Menu-test.tsx.snap323
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap146
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItemList-test.tsx.snap417
-rw-r--r--server/sonar-web/src/main/js/components/common/DocumentationTooltip.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/icons/BranchLikeIcon.tsx14
-rw-r--r--server/sonar-web/src/main/js/components/icons/__tests__/__snapshots__/BranchLikeIcon-test.tsx.snap4
-rw-r--r--server/sonar-web/src/main/js/helpers/mocks/branch-like.ts18
29 files changed, 657 insertions, 2477 deletions
diff --git a/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchResult.tsx b/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchResult.tsx
index 982f207add5..fc86449221d 100644
--- a/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchResult.tsx
+++ b/server/sonar-web/src/main/js/app/components/global-search/GlobalSearchResult.tsx
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import classNames from 'classnames';
-import { ClockIcon, ItemLink, SearchText, TextMuted } from 'design-system';
+import { ClockIcon, ItemLink, TextBold, TextMuted } from 'design-system';
import * as React from 'react';
import FavoriteIcon from '../../../components/icons/FavoriteIcon';
import { translate } from '../../../helpers/l10n';
@@ -54,7 +54,7 @@ export default class GlobalSearchResult extends React.PureComponent<Props> {
to={to}
>
<div className="sw-flex sw-justify-between sw-items-center sw-w-full">
- <SearchText match={component.match} name={component.name} />
+ <TextBold match={component.match} name={component.name} />
<div className="sw-ml-2">
{component.isFavorite && <FavoriteIcon favorite={true} size={16} />}
{!component.isFavorite && component.isRecentlyBrowsed && (
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/Breadcrumb.tsx b/server/sonar-web/src/main/js/app/components/nav/component/Breadcrumb.tsx
index 50c85a8c046..2dd18a0151a 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/Breadcrumb.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/Breadcrumb.tsx
@@ -17,87 +17,48 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { last } from 'lodash';
+import { HoverLink, TextMuted } from 'design-system';
import * as React from 'react';
-import Link from '../../../../components/common/Link';
-import QualifierIcon from '../../../../components/icons/QualifierIcon';
-import { isMainBranch } from '../../../../helpers/branch-like';
+import Favorite from '../../../../components/controls/Favorite';
import { getComponentOverviewUrl } from '../../../../helpers/urls';
-import { BranchLike } from '../../../../types/branch-like';
import { Component } from '../../../../types/types';
-import { colors } from '../../../theme';
+import { CurrentUser, isLoggedIn } from '../../../../types/users';
export interface BreadcrumbProps {
component: Component;
- currentBranchLike: BranchLike | undefined;
+ currentUser: CurrentUser;
}
export function Breadcrumb(props: BreadcrumbProps) {
- const {
- component: { breadcrumbs },
- currentBranchLike,
- } = props;
- const lastBreadcrumbElement = last(breadcrumbs);
- const isNotMainBranch = currentBranchLike && !isMainBranch(currentBranchLike);
+ const { component, currentUser } = props;
return (
- <div className="big flex-shrink display-flex-center">
- {breadcrumbs.map((breadcrumbElement, i) => {
- const isFirst = i === 0;
- const isNotLast = i < breadcrumbs.length - 1;
+ <div className="sw-text-sm sw-flex sw-justify-center">
+ {component.breadcrumbs.map((breadcrumbElement, i) => {
+ const isNotLast = i < component.breadcrumbs.length - 1;
const isLast = !isNotLast;
- const showQualifierIcon = isFirst && lastBreadcrumbElement;
-
- const name =
- isNotMainBranch || isNotLast ? (
- <>
- {showQualifierIcon && !isNotMainBranch && (
- <QualifierIcon
- className="spacer-right"
- qualifier={lastBreadcrumbElement.qualifier}
- fill={colors.neutral800}
- />
- )}
- <Link
- className="link-no-underline"
- to={getComponentOverviewUrl(breadcrumbElement.key, breadcrumbElement.qualifier)}
- >
- {showQualifierIcon && isNotMainBranch && (
- <QualifierIcon
- className="spacer-right"
- qualifier={lastBreadcrumbElement.qualifier}
- fill={colors.primary}
- />
- )}
- {breadcrumbElement.name}
- </Link>
- </>
- ) : (
- <>
- {showQualifierIcon && (
- <QualifierIcon
- className="spacer-right"
- qualifier={lastBreadcrumbElement.qualifier}
- fill={colors.neutral800}
- />
- )}
- {breadcrumbElement.name}
- </>
- );
return (
- <span className="flex-shrink display-flex-center" key={breadcrumbElement.key}>
- {isLast ? (
- <h1 className="text-ellipsis" title={breadcrumbElement.name}>
- {name}
- </h1>
- ) : (
- <span className="text-ellipsis" title={breadcrumbElement.name}>
- {name}
- </span>
+ <div key={breadcrumbElement.key} className="sw-flex">
+ {isLast && isLoggedIn(currentUser) && (
+ <Favorite
+ className="sw-mr-2"
+ component={component.key}
+ favorite={Boolean(component.isFavorite)}
+ qualifier={component.qualifier}
+ />
)}
- {isNotLast && <span className="slash-separator" />}
- </span>
+ <HoverLink
+ blurAfterClick={true}
+ className="js-project-link sw-flex"
+ key={breadcrumbElement.name}
+ title={breadcrumbElement.name}
+ to={getComponentOverviewUrl(breadcrumbElement.key, breadcrumbElement.qualifier)}
+ >
+ <TextMuted text={breadcrumbElement.name} />
+ </HoverLink>
+ {isNotLast && <span className="slash-separator sw-mx-2.5" />}
+ </div>
);
})}
</div>
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/Header.tsx b/server/sonar-web/src/main/js/app/components/nav/component/Header.tsx
index 145ae9377dd..08f786d3a91 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/Header.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/Header.tsx
@@ -18,14 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import Favorite from '../../../../components/controls/Favorite';
import { ProjectAlmBindingResponse } from '../../../../types/alm-settings';
import { BranchLike } from '../../../../types/branch-like';
import { Component } from '../../../../types/types';
-import { CurrentUser, isLoggedIn } from '../../../../types/users';
+import { CurrentUser } from '../../../../types/users';
import withCurrentUserContext from '../../current-user/withCurrentUserContext';
import BranchLikeNavigation from './branch-like/BranchLikeNavigation';
-import CurrentBranchLikeMergeInformation from './branch-like/CurrentBranchLikeMergeInformation';
import { Breadcrumb } from './Breadcrumb';
export interface HeaderProps {
@@ -40,25 +38,17 @@ export function Header(props: HeaderProps) {
const { branchLikes, component, currentBranchLike, currentUser, projectBinding } = props;
return (
- <div className="display-flex-center flex-shrink">
- <Breadcrumb component={component} currentBranchLike={currentBranchLike} />
- {isLoggedIn(currentUser) && (
- <Favorite
- className="spacer-left"
- component={component.key}
- favorite={Boolean(component.isFavorite)}
- qualifier={component.qualifier}
- />
- )}
+ <div className="sw-flex sw-flex-shrink sw-items-center">
+ <Breadcrumb component={component} currentUser={currentUser} />
{currentBranchLike && (
<>
+ <span className="slash-separator sw-ml-2" />
<BranchLikeNavigation
branchLikes={branchLikes}
component={component}
currentBranchLike={currentBranchLike}
projectBinding={projectBinding}
/>
- <CurrentBranchLikeMergeInformation currentBranchLike={currentBranchLike} />
</>
)}
</div>
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/Breadcrumb-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/Breadcrumb-test.tsx
deleted file mode 100644
index 25074c59040..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/Breadcrumb-test.tsx
+++ /dev/null
@@ -1,73 +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 { screen } from '@testing-library/react';
-import * as React from 'react';
-import { mockBranch, mockMainBranch } from '../../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../../helpers/mocks/component';
-import { renderComponent } from '../../../../../helpers/testReactTestingUtils';
-import { ComponentQualifier } from '../../../../../types/component';
-import { Breadcrumb, BreadcrumbProps } from '../Breadcrumb';
-
-it('should render correctly', () => {
- renderBreadcrumb();
- expect(screen.getByRole('link', { name: 'Parent portfolio' })).toBeInTheDocument();
- expect(screen.getByRole('heading', { name: 'Child portfolio' })).toBeInTheDocument();
-});
-
-it('should render correctly when not on a main branch', () => {
- renderBreadcrumb({
- component: mockComponent({
- breadcrumbs: [
- {
- key: 'project',
- name: 'My Project',
- qualifier: ComponentQualifier.Project,
- },
- ],
- }),
- currentBranchLike: mockBranch(),
- });
- expect(
- screen.getByRole('link', { name: `qualifier.${ComponentQualifier.Project} My Project` })
- ).toBeInTheDocument();
-});
-
-function renderBreadcrumb(props: Partial<BreadcrumbProps> = {}) {
- return renderComponent(
- <Breadcrumb
- component={mockComponent({
- breadcrumbs: [
- {
- key: 'parent-portfolio',
- name: 'Parent portfolio',
- qualifier: ComponentQualifier.Portfolio,
- },
- {
- key: 'child-portfolio',
- name: 'Child portfolio',
- qualifier: ComponentQualifier.SubPortfolio,
- },
- ],
- })}
- currentBranchLike={mockMainBranch()}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/Header-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/Header-test.tsx
index b1f3942d0b6..5add2af3e0e 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/Header-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/Header-test.tsx
@@ -17,34 +17,178 @@
* 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 { screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import * as React from 'react';
-import Favorite from '../../../../../components/controls/Favorite';
-import { mockSetOfBranchAndPullRequest } from '../../../../../helpers/mocks/branch-like';
+import {
+ mockMainBranch,
+ mockPullRequest,
+ mockSetOfBranchAndPullRequestForBranchSelector,
+} from '../../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../../helpers/mocks/component';
-import { mockCurrentUser } from '../../../../../helpers/testMocks';
+import { mockCurrentUser, mockLoggedInUser } from '../../../../../helpers/testMocks';
+import { renderApp } from '../../../../../helpers/testReactTestingUtils';
+import { AlmKeys } from '../../../../../types/alm-settings';
+import { Feature } from '../../../../../types/features';
+import { BranchStatusContext } from '../../../branch-status/BranchStatusContext';
import { Header, HeaderProps } from '../Header';
-it('should render correctly', () => {
- const wrapper = shallowRender({ currentUser: mockCurrentUser({ isLoggedIn: true }) });
- expect(wrapper).toMatchSnapshot();
+jest.mock('../../../../../api/favorites', () => ({
+ addFavorite: jest.fn().mockResolvedValue({}),
+ removeFavorite: jest.fn().mockResolvedValue({}),
+}));
+
+it('should render correctly when there is only 1 branch', () => {
+ renderHeader({ branchLikes: [mockMainBranch()] });
+ expect(screen.getByText('project')).toBeInTheDocument();
+ expect(screen.getByLabelText('help-tooltip')).toBeInTheDocument();
+ expect(
+ screen.getByRole('button', { name: 'branch-1 overview.quality_gate_x.OK' })
+ ).toBeDisabled();
+});
+
+it('should render correctly when there are multiple branch', async () => {
+ const user = userEvent.setup();
+ renderHeader();
+ expect(screen.getByRole('button', { name: 'branch-1 overview.quality_gate_x.OK' })).toBeEnabled();
+ expect(screen.queryByLabelText('help-tooltip')).not.toBeInTheDocument();
+
+ await user.click(screen.getByRole('button', { name: 'branch-1 overview.quality_gate_x.OK' }));
+ expect(screen.getByText('branches.main_branch')).toBeInTheDocument();
+ expect(
+ screen.getByRole('menuitem', { name: 'branch-2 overview.quality_gate_x.ERROR ERROR' })
+ ).toBeInTheDocument();
+ expect(screen.getByRole('menuitem', { name: 'branch-3' })).toBeInTheDocument();
+ expect(screen.getByRole('menuitem', { name: '1 – PR-1' })).toBeInTheDocument();
+ expect(screen.getByRole('menuitem', { name: '2 – PR-2' })).toBeInTheDocument();
+
+ await user.click(
+ screen.getByRole('menuitem', { name: 'branch-2 overview.quality_gate_x.ERROR ERROR' })
+ );
+ expect(screen.getByText('/dashboard?branch=branch-2&id=my-project')).toBeInTheDocument();
});
-it('should not render favorite button if the user is not logged in', () => {
- const wrapper = shallowRender();
- expect(wrapper.find(Favorite).exists()).toBe(false);
+it('should show manage branch and pull request button for admin', async () => {
+ const user = userEvent.setup();
+ renderHeader({
+ currentUser: mockLoggedInUser(),
+ component: mockComponent({
+ configuration: { showSettings: true },
+ breadcrumbs: [{ name: 'project', key: 'project', qualifier: 'TRK' }],
+ }),
+ });
+ await user.click(screen.getByRole('button', { name: 'branch-1 overview.quality_gate_x.OK' }));
+
+ expect(screen.getByRole('link', { name: 'branch_like_navigation.manage' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: 'branch_like_navigation.manage' })).toHaveAttribute(
+ 'href',
+ '/project/branches?id=my-project'
+ );
});
-function shallowRender(props?: Partial<HeaderProps>) {
- const branchLikes = mockSetOfBranchAndPullRequest();
-
- return shallow(
- <Header
- branchLikes={branchLikes}
- component={mockComponent()}
- currentBranchLike={branchLikes[0]}
- currentUser={mockCurrentUser()}
- {...props}
- />
+it('should render favorite button if the user is logged in', async () => {
+ const user = userEvent.setup();
+ renderHeader({ currentUser: mockLoggedInUser() });
+ expect(screen.getByRole('button', { name: 'favorite.action.TRK.add' })).toBeInTheDocument();
+
+ await user.click(screen.getByRole('button', { name: 'favorite.action.TRK.add' }));
+ expect(
+ await screen.findByRole('button', { name: 'favorite.action.TRK.remove' })
+ ).toBeInTheDocument();
+
+ await user.click(screen.getByRole('button', { name: 'favorite.action.TRK.remove' }));
+ expect(screen.getByRole('button', { name: 'favorite.action.TRK.add' })).toBeInTheDocument();
+});
+
+it.each([['github'], ['gitlab'], ['bitbucket'], ['azure']])(
+ 'should show correct %s links for a PR',
+ (alm: string) => {
+ renderHeader({
+ currentUser: mockLoggedInUser(),
+ currentBranchLike: mockPullRequest({
+ key: '1',
+ title: 'PR-1',
+ status: { qualityGateStatus: 'OK' },
+ url: alm,
+ }),
+ branchLikes: [
+ mockPullRequest({
+ key: '1',
+ title: 'PR-1',
+ status: { qualityGateStatus: 'OK' },
+ url: alm,
+ }),
+ ],
+ });
+ const image = screen.getByAltText(alm);
+ expect(image).toBeInTheDocument();
+ expect(image).toHaveAttribute('src', `/images/alm/${alm}.svg`);
+ }
+);
+
+it('should show the correct help tooltip for applications', () => {
+ renderHeader({
+ currentUser: mockLoggedInUser(),
+ component: mockComponent({
+ configuration: { showSettings: true },
+ breadcrumbs: [{ name: 'project', key: 'project', qualifier: 'APP' }],
+ qualifier: 'APP',
+ }),
+ branchLikes: [mockMainBranch()],
+ });
+ expect(screen.getByText('application.branches.help')).toBeInTheDocument();
+ expect(screen.getByText('application.branches.link')).toBeInTheDocument();
+});
+
+it('should show the correct help tooltip when branch support is not enabled', () => {
+ renderHeader(
+ {
+ currentUser: mockLoggedInUser(),
+ projectBinding: { alm: AlmKeys.GitLab, key: 'key', monorepo: true },
+ },
+ []
+ );
+ expect(screen.getByText('branch_like_navigation.no_branch_support.title.mr')).toBeInTheDocument();
+ expect(
+ screen.getByText('branch_like_navigation.no_branch_support.content_x.mr.alm.gitlab')
+ ).toBeInTheDocument();
+});
+
+function renderHeader(props?: Partial<HeaderProps>, featureList = [Feature.BranchSupport]) {
+ const branchLikes = mockSetOfBranchAndPullRequestForBranchSelector();
+
+ return renderApp(
+ '/',
+ <BranchStatusContext.Provider
+ value={{
+ branchStatusByComponent: {
+ 'my-project': {
+ 'branch-branch-1': {
+ status: 'OK',
+ },
+ 'branch-branch-2': {
+ status: 'ERROR',
+ },
+ },
+ },
+ fetchBranchStatus: () => {
+ /*noop*/
+ },
+ updateBranchStatus: () => {
+ /*noop*/
+ },
+ }}
+ >
+ <Header
+ branchLikes={branchLikes}
+ component={mockComponent({
+ breadcrumbs: [{ name: 'project', key: 'project', qualifier: 'TRK' }],
+ })}
+ currentBranchLike={branchLikes[0]}
+ currentUser={mockCurrentUser()}
+ {...props}
+ />
+ </BranchStatusContext.Provider>,
+ { featureList }
);
}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Header-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Header-test.tsx.snap
deleted file mode 100644
index bac9e18453c..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Header-test.tsx.snap
+++ /dev/null
@@ -1,153 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<div
- className="display-flex-center flex-shrink"
->
- <Breadcrumb
- 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": [],
- }
- }
- currentBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- />
- <Favorite
- className="spacer-left"
- component="my-project"
- favorite={false}
- qualifier="TRK"
- />
- <withAvailableFeaturesContext(Component)
- branchLikes={
- [
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-1",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "1",
- "target": "master",
- "title": "PR-1",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-12",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "2",
- "target": "master",
- "title": "PR-2",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-3",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-2",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "isOrphan": true,
- "key": "2",
- "target": "llb-100",
- "title": "PR-2",
- },
- ]
- }
- 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": [],
- }
- }
- currentBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- />
- <Memo(CurrentBranchLikeMergeInformation)
- currentBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchHelpTooltip.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchHelpTooltip.tsx
new file mode 100644
index 00000000000..160b46a5ccf
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchHelpTooltip.tsx
@@ -0,0 +1,130 @@
+/*
+ * 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 { HelperHintIcon } from 'design-system';
+import React from 'react';
+import DocumentationTooltip from '../../../../../components/common/DocumentationTooltip';
+import Link from '../../../../../components/common/Link';
+import HelpTooltip from '../../../../../components/controls/HelpTooltip';
+import { translate, translateWithParameters } from '../../../../../helpers/l10n';
+import { getApplicationAdminUrl } from '../../../../../helpers/urls';
+import { ProjectAlmBindingResponse } from '../../../../../types/alm-settings';
+import { Component } from '../../../../../types/types';
+
+interface Props {
+ component: Component;
+ isApplication: boolean;
+ projectBinding?: ProjectAlmBindingResponse;
+ hasManyBranches: boolean;
+ canAdminComponent?: boolean;
+ branchSupportEnabled: boolean;
+ isGitLab: boolean;
+}
+
+export default function BranchHelpTooltip({
+ component,
+ isApplication,
+ projectBinding,
+ hasManyBranches,
+ canAdminComponent,
+ branchSupportEnabled,
+ isGitLab,
+}: Props) {
+ const helpIcon = <HelperHintIcon aria-label="help-tooltip" />;
+
+ if (isApplication) {
+ if (!hasManyBranches && canAdminComponent) {
+ return (
+ <HelpTooltip
+ overlay={
+ <>
+ <p>{translate('application.branches.help')}</p>
+ <hr className="spacer-top spacer-bottom" />
+ <Link to={getApplicationAdminUrl(component.key)}>
+ {translate('application.branches.link')}
+ </Link>
+ </>
+ }
+ >
+ {helpIcon}
+ </HelpTooltip>
+ );
+ }
+ } else {
+ if (!branchSupportEnabled) {
+ return (
+ <DocumentationTooltip
+ content={
+ projectBinding !== undefined
+ ? translateWithParameters(
+ `branch_like_navigation.no_branch_support.content_x.${isGitLab ? 'mr' : 'pr'}`,
+ translate('alm', projectBinding.alm)
+ )
+ : translate('branch_like_navigation.no_branch_support.content')
+ }
+ data-test="branches-support-disabled"
+ links={[
+ {
+ href: 'https://www.sonarsource.com/plans-and-pricing/developer/',
+ label: translate('learn_more'),
+ doc: false,
+ },
+ ]}
+ title={
+ projectBinding !== undefined
+ ? translate('branch_like_navigation.no_branch_support.title', isGitLab ? 'mr' : 'pr')
+ : translate('branch_like_navigation.no_branch_support.title')
+ }
+ >
+ {helpIcon}
+ </DocumentationTooltip>
+ );
+ }
+
+ if (!hasManyBranches) {
+ return (
+ <DocumentationTooltip
+ content={translate('branch_like_navigation.only_one_branch.content')}
+ data-test="only-one-branch-like"
+ links={[
+ {
+ href: '/analyzing-source-code/branches/branch-analysis/',
+ label: translate('branch_like_navigation.only_one_branch.documentation'),
+ },
+ {
+ href: '/analyzing-source-code/pull-request-analysis',
+ label: translate('branch_like_navigation.only_one_branch.pr_analysis'),
+ },
+ {
+ href: `/tutorials?id=${component.key}`,
+ label: translate('branch_like_navigation.tutorial_for_ci'),
+ inPlace: true,
+ doc: false,
+ },
+ ]}
+ title={translate('branch_like_navigation.only_one_branch.title')}
+ >
+ {helpIcon}
+ </DocumentationTooltip>
+ );
+ }
+ }
+
+ return null;
+}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.css b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.css
deleted file mode 100644
index b96f85754b4..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.css
+++ /dev/null
@@ -1,78 +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.
- */
-.branch-like-navigation-toggler {
- padding: 4px 8px;
- border: 1px solid transparent;
- border-radius: 2px;
-}
-
-.branch-like-navigation-toggler:hover {
- border-color: var(--blacka38);
- color: inherit !important;
-}
-
-.branch-like-navigation-toggler:active,
-.branch-like-navigation-toggler.open {
- border-color: var(--primary);
-}
-
-.branch-like-navigation-toggler-container {
- height: 26px;
-}
-
-.branch-like-navigation-toggler-container .popup {
- min-width: 430px;
- max-width: 650px;
-}
-
-.branch-like-navigation-menu .search-box-container {
- padding: var(--gridSize);
-}
-
-.branch-like-navigation-menu .search-box-container .search-box,
-.branch-like-navigation-menu .search-box-container .search-box-input {
- max-width: initial !important;
-}
-
-.branch-like-navigation-menu .item-list {
- padding-bottom: var(--gridSize);
- max-height: 300px;
- overflow-y: auto;
-}
-
-.branch-like-navigation-menu .item {
- padding: calc(var(--gridSize) / 2) var(--gridSize);
-}
-
-.branch-like-navigation-menu .item.header {
- color: var(--secondFontColor);
-}
-
-.branch-like-navigation-menu .item:not(.header):hover,
-.branch-like-navigation-menu .item:not(.header).active {
- background-color: var(--barBackgroundColor);
- cursor: pointer;
-}
-
-.branch-like-navigation-menu .hint-container {
- padding: var(--gridSize);
- background-color: var(--barBackgroundColor);
- border-top: 1px solid var(--barBorderColor);
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.tsx
index d4e761b60f5..65d4741665d 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/BranchLikeNavigation.tsx
@@ -17,20 +17,21 @@
* 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 { ButtonSecondary, PopupPlacement, PopupZLevel, PortalPopup } from 'design-system';
import * as React from 'react';
-import { ButtonPlain } from '../../../../../components/controls/buttons';
-import Toggler from '../../../../../components/controls/Toggler';
-import { ProjectAlmBindingResponse } from '../../../../../types/alm-settings';
+import OutsideClickHandler from '../../../../../components/controls/OutsideClickHandler';
+import { AlmKeys, ProjectAlmBindingResponse } from '../../../../../types/alm-settings';
import { BranchLike } from '../../../../../types/branch-like';
+import { ComponentQualifier } from '../../../../../types/component';
import { Feature } from '../../../../../types/features';
import { Component } from '../../../../../types/types';
import withAvailableFeatures, {
WithAvailableFeaturesProps,
} from '../../../available-features/withAvailableFeatures';
-import './BranchLikeNavigation.css';
+import BranchHelpTooltip from './BranchHelpTooltip';
import CurrentBranchLike from './CurrentBranchLike';
import Menu from './Menu';
+import PRLink from './PRLink';
export interface BranchLikeNavigationProps extends WithAvailableFeaturesProps {
branchLikes: BranchLike[];
@@ -48,59 +49,72 @@ export function BranchLikeNavigation(props: BranchLikeNavigationProps) {
projectBinding,
} = props;
+ const isApplication = component.qualifier === ComponentQualifier.Application;
+ const isGitLab = projectBinding !== undefined && projectBinding.alm === AlmKeys.GitLab;
+
const [isMenuOpen, setIsMenuOpen] = React.useState(false);
const branchSupportEnabled = props.hasFeature(Feature.BranchSupport);
-
- const canAdminComponent = configuration && configuration.showSettings;
+ const canAdminComponent = configuration?.showSettings;
const hasManyBranches = branchLikes.length >= 2;
const isMenuEnabled = branchSupportEnabled && hasManyBranches;
const currentBranchLikeElement = (
- <CurrentBranchLike
- branchesEnabled={branchSupportEnabled}
- component={component}
- currentBranchLike={currentBranchLike}
- hasManyBranches={hasManyBranches}
- projectBinding={projectBinding}
- />
+ <CurrentBranchLike component={component} currentBranchLike={currentBranchLike} />
);
return (
- <span
- className={classNames(
- 'big-spacer-left flex-0 branch-like-navigation-toggler-container display-flex-center',
- {
- dropdown: isMenuEnabled,
- }
- )}
- >
- {isMenuEnabled ? (
- <Toggler
- onRequestClose={() => setIsMenuOpen(false)}
- open={isMenuOpen}
+ <div className="sw-flex sw-items-center sw-ml-2 it__branch-like-navigation-toggler-container">
+ <OutsideClickHandler
+ onClickOutside={() => {
+ setIsMenuOpen(false);
+ }}
+ >
+ <PortalPopup
+ allowResizing={true}
overlay={
- <Menu
- branchLikes={branchLikes}
- canAdminComponent={canAdminComponent}
- component={component}
- currentBranchLike={currentBranchLike}
- onClose={() => setIsMenuOpen(false)}
- />
+ isMenuOpen && (
+ <Menu
+ branchLikes={branchLikes}
+ canAdminComponent={canAdminComponent}
+ component={component}
+ currentBranchLike={currentBranchLike}
+ onClose={() => {
+ setIsMenuOpen(false);
+ }}
+ />
+ )
}
+ placement={PopupPlacement.BottomLeft}
+ zLevel={PopupZLevel.Global}
>
- <ButtonPlain
- className={classNames('branch-like-navigation-toggler', { open: isMenuOpen })}
- onClick={() => setIsMenuOpen(!isMenuOpen)}
+ <ButtonSecondary
+ className="sw-max-w-abs-350"
+ onClick={() => {
+ setIsMenuOpen(!isMenuOpen);
+ }}
+ disabled={!isMenuEnabled}
aria-expanded={isMenuOpen}
aria-haspopup="menu"
>
{currentBranchLikeElement}
- </ButtonPlain>
- </Toggler>
- ) : (
- currentBranchLikeElement
- )}
- </span>
+ </ButtonSecondary>
+ </PortalPopup>
+ </OutsideClickHandler>
+
+ <div className="sw-ml-2">
+ <BranchHelpTooltip
+ component={component}
+ isApplication={isApplication}
+ projectBinding={projectBinding}
+ hasManyBranches={hasManyBranches}
+ canAdminComponent={canAdminComponent}
+ branchSupportEnabled={branchSupportEnabled}
+ isGitLab={isGitLab}
+ />
+ </div>
+
+ <PRLink currentBranchLike={currentBranchLike} component={component} />
+ </div>
);
}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/CurrentBranchLike.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/CurrentBranchLike.tsx
index 589b1219abb..2de026da87e 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/CurrentBranchLike.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/CurrentBranchLike.tsx
@@ -17,147 +17,31 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { ChevronDownIcon, TextMuted } from 'design-system';
import * as React from 'react';
-import DocumentationTooltip from '../../../../../components/common/DocumentationTooltip';
-import Link from '../../../../../components/common/Link';
-import HelpTooltip from '../../../../../components/controls/HelpTooltip';
import BranchLikeIcon from '../../../../../components/icons/BranchLikeIcon';
-import DropdownIcon from '../../../../../components/icons/DropdownIcon';
-import PlusCircleIcon from '../../../../../components/icons/PlusCircleIcon';
import { getBranchLikeDisplayName } from '../../../../../helpers/branch-like';
-import { translate, translateWithParameters } from '../../../../../helpers/l10n';
-import { getApplicationAdminUrl } from '../../../../../helpers/urls';
-import { AlmKeys, ProjectAlmBindingResponse } from '../../../../../types/alm-settings';
-import { BranchLike } from '../../../../../types/branch-like';
-import { ComponentQualifier } from '../../../../../types/component';
+import { BranchLike, BranchStatusData } from '../../../../../types/branch-like';
import { Component } from '../../../../../types/types';
-import { colors } from '../../../../theme';
+import QualityGateStatus from './QualityGateStatus';
-export interface CurrentBranchLikeProps {
- branchesEnabled: boolean;
+export interface CurrentBranchLikeProps extends Pick<BranchStatusData, 'status'> {
component: Component;
currentBranchLike: BranchLike;
- hasManyBranches: boolean;
- projectBinding?: ProjectAlmBindingResponse;
}
export function CurrentBranchLike(props: CurrentBranchLikeProps) {
- const {
- branchesEnabled,
- component,
- component: { configuration },
- currentBranchLike,
- hasManyBranches,
- projectBinding,
- } = props;
+ const { component, currentBranchLike } = props;
const displayName = getBranchLikeDisplayName(currentBranchLike);
- const isApplication = component.qualifier === ComponentQualifier.Application;
- const canAdminComponent = configuration && configuration.showSettings;
- const isGitLab = projectBinding !== undefined && projectBinding.alm === AlmKeys.GitLab;
-
- const additionalIcon = () => {
- if (branchesEnabled && hasManyBranches) {
- return <DropdownIcon />;
- }
-
- const plusIcon = <PlusCircleIcon fill={colors.info500} size={12} />;
-
- if (isApplication) {
- if (!hasManyBranches && canAdminComponent) {
- return (
- <HelpTooltip
- overlay={
- <>
- <p>{translate('application.branches.help')}</p>
- <hr className="spacer-top spacer-bottom" />
- <Link to={getApplicationAdminUrl(component.key)}>
- {translate('application.branches.link')}
- </Link>
- </>
- }
- >
- {plusIcon}
- </HelpTooltip>
- );
- }
- } else {
- if (!branchesEnabled) {
- return (
- <DocumentationTooltip
- content={
- projectBinding !== undefined
- ? translateWithParameters(
- `branch_like_navigation.no_branch_support.content_x.${isGitLab ? 'mr' : 'pr'}`,
- translate('alm', projectBinding.alm)
- )
- : translate('branch_like_navigation.no_branch_support.content')
- }
- data-test="branches-support-disabled"
- links={[
- {
- href: 'https://www.sonarsource.com/plans-and-pricing/developer/',
- label: translate('learn_more'),
- doc: false,
- },
- ]}
- title={
- projectBinding !== undefined
- ? translate(
- 'branch_like_navigation.no_branch_support.title',
- isGitLab ? 'mr' : 'pr'
- )
- : translate('branch_like_navigation.no_branch_support.title')
- }
- >
- {plusIcon}
- </DocumentationTooltip>
- );
- }
-
- if (!hasManyBranches) {
- return (
- <DocumentationTooltip
- content={translate('branch_like_navigation.only_one_branch.content')}
- data-test="only-one-branch-like"
- links={[
- {
- href: '/analyzing-source-code/branches/branch-analysis/',
- label: translate('branch_like_navigation.only_one_branch.documentation'),
- },
- {
- href: '/analyzing-source-code/pull-request-analysis',
- label: translate('branch_like_navigation.only_one_branch.pr_analysis'),
- },
- {
- href: `/tutorials?id=${component.key}`,
- label: translate('branch_like_navigation.tutorial_for_ci'),
- inPlace: true,
- doc: false,
- },
- ]}
- title={translate('branch_like_navigation.only_one_branch.title')}
- >
- {plusIcon}
- </DocumentationTooltip>
- );
- }
- }
-
- return null;
- };
return (
- <span className="display-flex-center flex-shrink text-ellipsis">
- <BranchLikeIcon branchLike={currentBranchLike} fill={colors.info500} />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title={displayName}
- >
- {displayName}
- </span>
- {additionalIcon()}
- </span>
+ <div className="sw-flex sw-items-center text-ellipsis">
+ <BranchLikeIcon branchLike={currentBranchLike} />
+ <TextMuted text={displayName} className="sw-ml-3" />
+ <QualityGateStatus branchLike={currentBranchLike} component={component} className="sw-ml-4" />
+ <ChevronDownIcon className="sw-ml-1" />
+ </div>
);
}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/Menu.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/Menu.tsx
index e1eaf9af75a..bab191696bb 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/Menu.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/Menu.tsx
@@ -17,10 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { DropdownMenu, InputSearch, ItemDivider, Link } from 'design-system';
import * as React from 'react';
-import Link from '../../../../../components/common/Link';
-import { DropdownOverlay } from '../../../../../components/controls/Dropdown';
-import SearchBox from '../../../../../components/controls/SearchBox';
import { Router, withRouter } from '../../../../../components/hoc/withRouter';
import {
getBrancheLikesAsTree,
@@ -156,43 +154,49 @@ export class Menu extends React.PureComponent<Props, State> {
const { canAdminComponent, component, onClose } = this.props;
const { branchLikesToDisplay, branchLikesToDisplayTree, query, selectedBranchLike } =
this.state;
-
const showManageLink = component.qualifier === ComponentQualifier.Project && canAdminComponent;
const hasResults = branchLikesToDisplay.length > 0;
return (
- <DropdownOverlay className="branch-like-navigation-menu" noPadding={true}>
- <div className="search-box-container">
- <SearchBox
- autoFocus={true}
- onChange={this.handleSearchChange}
- onKeyDown={this.handleKeyDown}
- placeholder={translate('branch_like_navigation.search_for_branch_like')}
- value={query}
- />
- </div>
-
- <div className="item-list-container">
- <MenuItemList
- branchLikeTree={branchLikesToDisplayTree}
- component={component}
- hasResults={hasResults}
- onSelect={this.handleOnSelect}
- selectedBranchLike={selectedBranchLike}
- />
- </div>
-
+ <DropdownMenu
+ className="sw-overflow-y-auto sw-overflow-x-hidden it__branch-like-navigation-menu"
+ maxHeight="38rem"
+ size="auto"
+ >
+ <InputSearch
+ className="sw-mx-3 sw-my-2"
+ autoFocus={true}
+ onChange={this.handleSearchChange}
+ onKeyDown={this.handleKeyDown}
+ placeholder={translate('branch_like_navigation.search_for_branch_like')}
+ size="auto"
+ value={query}
+ searchInputAriaLabel={translate('search_verb')}
+ clearIconAriaLabel={translate('clear')}
+ />
+ <MenuItemList
+ branchLikeTree={branchLikesToDisplayTree}
+ component={component}
+ hasResults={hasResults}
+ onSelect={this.handleOnSelect}
+ selectedBranchLike={selectedBranchLike}
+ />
{showManageLink && (
- <div className="hint-container text-right">
- <Link
- onClick={() => onClose()}
- to={{ pathname: '/project/branches', search: queryToSearch({ id: component.key }) }}
- >
- {translate('branch_like_navigation.manage')}
- </Link>
- </div>
+ <>
+ <ItemDivider />
+ <li className="sw-px-3 sw-py-2">
+ <Link
+ onClick={() => {
+ onClose();
+ }}
+ to={{ pathname: '/project/branches', search: queryToSearch({ id: component.key }) }}
+ >
+ {translate('branch_like_navigation.manage')}
+ </Link>
+ </li>
+ </>
)}
- </DropdownOverlay>
+ </DropdownMenu>
);
}
}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx
index 2cc14207c37..421addeaa93 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx
@@ -18,52 +18,57 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import classNames from 'classnames';
+import { Badge, ItemButton, TextBold, TextMuted } from 'design-system';
import * as React from 'react';
-import BranchStatus from '../../../../../components/common/BranchStatus';
import BranchLikeIcon from '../../../../../components/icons/BranchLikeIcon';
import { getBranchLikeDisplayName, isMainBranch } from '../../../../../helpers/branch-like';
import { translate } from '../../../../../helpers/l10n';
import { BranchLike } from '../../../../../types/branch-like';
import { Component } from '../../../../../types/types';
+import QualityGateStatus from './QualityGateStatus';
export interface MenuItemProps {
branchLike: BranchLike;
component: Component;
- indent?: boolean;
onSelect: (branchLike: BranchLike) => void;
selected: boolean;
setSelectedNode?: (node: HTMLLIElement) => void;
}
export function MenuItem(props: MenuItemProps) {
- const { branchLike, component, indent, setSelectedNode, onSelect, selected } = props;
+ const { branchLike, component, setSelectedNode, onSelect, selected } = props;
const displayName = getBranchLikeDisplayName(branchLike);
return (
- <li
- className={classNames('item', {
- active: selected,
- })}
- onClick={() => onSelect(branchLike)}
- ref={selected ? setSelectedNode : undefined}
+ <ItemButton
+ className={classNames({ active: selected })}
+ innerRef={selected ? setSelectedNode : undefined}
+ onClick={() => {
+ onSelect(branchLike);
+ }}
>
- <div
- className={classNames('display-flex-center display-flex-space-between', {
- 'big-spacer-left': indent,
- })}
- >
- <div className="item-name text-ellipsis" title={displayName}>
+ <div className="sw-flex sw-items-center sw-justify-between text-ellipsis sw-flex-1">
+ <div className="sw-flex sw-items-center">
<BranchLikeIcon branchLike={branchLike} />
- <span className="spacer-left">{displayName}</span>
+
{isMainBranch(branchLike) && (
- <span className="badge spacer-left">{translate('branches.main_branch')}</span>
+ <>
+ <TextBold name={displayName} className="sw-ml-4 sw-mr-2" />
+ <Badge variant="default">{translate('branches.main_branch')}</Badge>
+ </>
+ )}
+ {!isMainBranch(branchLike) && (
+ <TextMuted text={displayName} className="sw-ml-3 sw-mr-2" />
)}
</div>
- <div className="spacer-left">
- <BranchStatus branchLike={branchLike} component={component} />
- </div>
+ <QualityGateStatus
+ branchLike={branchLike}
+ component={component}
+ className="sw-flex sw-items-center sw-w-24"
+ showStatusText={true}
+ />
</div>
- </li>
+ </ItemButton>
);
}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItemList.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItemList.tsx
index f6c749f926a..ee21a7a07bc 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItemList.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItemList.tsx
@@ -17,11 +17,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { HelperHintIcon, ItemDivider, ItemHeader } from 'design-system';
import * as React from 'react';
import HelpTooltip from '../../../../../components/controls/HelpTooltip';
import { getBranchLikeKey, isSameBranchLike } from '../../../../../helpers/branch-like';
import { translate } from '../../../../../helpers/l10n';
-import { scrollToElement } from '../../../../../helpers/scrolling';
import { isDefined } from '../../../../../helpers/types';
import { BranchLike, BranchLikeTree } from '../../../../../types/branch-like';
import { Component } from '../../../../../types/types';
@@ -36,22 +36,21 @@ export interface MenuItemListProps {
}
export function MenuItemList(props: MenuItemListProps) {
- let listNode: HTMLUListElement | null = null;
let selectedNode: HTMLLIElement | null = null;
React.useEffect(() => {
- if (listNode && selectedNode) {
- scrollToElement(selectedNode, { parent: listNode, smooth: false });
+ if (selectedNode) {
+ selectedNode.scrollIntoView({ block: 'center' });
+ selectedNode.focus();
}
});
const { branchLikeTree, component, hasResults, onSelect, selectedBranchLike } = props;
- const renderItem = (branchLike: BranchLike, indent?: boolean) => (
+ const renderItem = (branchLike: BranchLike) => (
<MenuItem
branchLike={branchLike}
component={component}
- indent={indent}
key={getBranchLikeKey(branchLike)}
onSelect={onSelect}
selected={isSameBranchLike(branchLike, selectedBranchLike)}
@@ -60,11 +59,11 @@ export function MenuItemList(props: MenuItemListProps) {
);
return (
- <ul className="item-list" ref={(node) => (listNode = node)}>
+ <ul className="item-list sw-overflow-scroll">
{!hasResults && (
- <li className="item">
- <span className="note">{translate('no_results')}</span>
- </li>
+ <div className="sw-px-3 sw-py-2">
+ <span>{translate('no_results')}</span>
+ </div>
)}
{/* BRANCHES & PR */}
@@ -75,22 +74,21 @@ export function MenuItemList(props: MenuItemListProps) {
{renderItem(tree.branch)}
{tree.pullRequests.length > 0 && (
<>
- <li className="item header">
- <span className="big-spacer-left">
- {translate('branch_like_navigation.pull_requests')}
- </span>
- </li>
- {tree.pullRequests.map((pr) => renderItem(pr, true))}
+ <ItemDivider />
+ <ItemHeader>{translate('branch_like_navigation.pull_requests')}</ItemHeader>
+ <ItemDivider />
+ {tree.pullRequests.map((pr) => renderItem(pr))}
</>
)}
- <hr />
</React.Fragment>
))}
{/* PARENTLESS PR (for display during search) */}
{branchLikeTree.parentlessPullRequests.length > 0 && (
<>
- <li className="item header">{translate('branch_like_navigation.pull_requests')}</li>
+ <ItemDivider />
+ <ItemHeader>{translate('branch_like_navigation.pull_requests')}</ItemHeader>
+ <ItemDivider />
{branchLikeTree.parentlessPullRequests.map((pr) => renderItem(pr))}
</>
)}
@@ -98,13 +96,17 @@ export function MenuItemList(props: MenuItemListProps) {
{/* ORPHAN PR */}
{branchLikeTree.orphanPullRequests.length > 0 && (
<>
- <li className="item header">
+ <ItemDivider />
+ <ItemHeader>
{translate('branch_like_navigation.orphan_pull_requests')}
<HelpTooltip
className="little-spacer-left"
overlay={translate('branch_like_navigation.orphan_pull_requests.tooltip')}
- />
- </li>
+ >
+ <HelperHintIcon />
+ </HelpTooltip>
+ </ItemHeader>
+ <ItemDivider />
{branchLikeTree.orphanPullRequests.map((pr) => renderItem(pr))}
</>
)}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/PRLink.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/PRLink.tsx
new file mode 100644
index 00000000000..43b590e6ed7
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/PRLink.tsx
@@ -0,0 +1,83 @@
+/*
+ * 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 { Link } from 'design-system';
+import React from 'react';
+import { isPullRequest } from '../../../../../helpers/branch-like';
+import { translate, translateWithParameters } from '../../../../../helpers/l10n';
+import { getBaseUrl } from '../../../../../helpers/system';
+import { AlmKeys } from '../../../../../types/alm-settings';
+import { BranchLike } from '../../../../../types/branch-like';
+import { Component } from '../../../../../types/types';
+
+function getPRUrlAlmKey(url = '') {
+ const lowerCaseUrl = url.toLowerCase();
+ if (lowerCaseUrl.includes(AlmKeys.GitHub)) {
+ return AlmKeys.GitHub;
+ } else if (lowerCaseUrl.includes(AlmKeys.GitLab)) {
+ return AlmKeys.GitLab;
+ } else if (lowerCaseUrl.includes(AlmKeys.BitbucketServer)) {
+ return AlmKeys.BitbucketServer;
+ } else if (
+ lowerCaseUrl.includes(AlmKeys.Azure) ||
+ lowerCaseUrl.includes('microsoft') ||
+ lowerCaseUrl.includes('visualstudio')
+ ) {
+ return AlmKeys.Azure;
+ }
+ return undefined;
+}
+
+export default function PRLink({
+ currentBranchLike,
+ component,
+}: {
+ currentBranchLike: BranchLike;
+ component: Component;
+}) {
+ if (!isPullRequest(currentBranchLike)) {
+ return null;
+ }
+
+ const almKey =
+ component.alm?.key ||
+ (isPullRequest(currentBranchLike) && getPRUrlAlmKey(currentBranchLike.url));
+ return (
+ <div>
+ {currentBranchLike.url !== undefined && (
+ <Link
+ icon={
+ almKey && (
+ <img
+ alt={almKey}
+ height={16}
+ src={`${getBaseUrl()}/images/alm/${almKey}.svg`}
+ title={translateWithParameters('branches.see_the_pr_on_x', translate(almKey))}
+ />
+ )
+ }
+ key={currentBranchLike.key}
+ to={currentBranchLike.url}
+ >
+ {!almKey && translate('branches.see_the_pr')}
+ </Link>
+ )}
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/QualityGateStatus.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/QualityGateStatus.tsx
new file mode 100644
index 00000000000..66daeb57842
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/QualityGateStatus.tsx
@@ -0,0 +1,63 @@
+/*
+ * 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 classNames from 'classnames';
+import { QualityGateIndicator } from 'design-system';
+import React, { useContext } from 'react';
+import { getBranchStatusByBranchLike } from '../../../../../helpers/branch-like';
+import { translateWithParameters } from '../../../../../helpers/l10n';
+import { formatMeasure } from '../../../../../helpers/measures';
+import { BranchLike } from '../../../../../types/branch-like';
+import { Component } from '../../../../../types/types';
+import { BranchStatusContext } from '../../../branch-status/BranchStatusContext';
+
+interface Props {
+ component: Component;
+ branchLike: BranchLike;
+ className: string;
+ showStatusText?: boolean;
+}
+
+export default function QualityGateStatus({
+ component,
+ branchLike,
+ className,
+ showStatusText,
+}: Props) {
+ const { branchStatusByComponent } = useContext(BranchStatusContext);
+ const branchStatus = getBranchStatusByBranchLike(
+ branchStatusByComponent,
+ component.key,
+ branchLike
+ );
+
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain, @typescript-eslint/no-unnecessary-condition
+ if (!branchStatus || !branchStatus.status) {
+ return null;
+ }
+ const { status } = branchStatus;
+ const formatted = formatMeasure(status, 'LEVEL');
+ const ariaLabel = translateWithParameters('overview.quality_gate_x', formatted);
+ return (
+ <div className={classNames(className, `it__level-${status}`)}>
+ <QualityGateIndicator status={status} className="sw-mr-2" ariaLabel={ariaLabel} />
+ {showStatusText && <span>{formatted}</span>}
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/BranchLikeNavigation-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/BranchLikeNavigation-test.tsx
deleted file mode 100644
index 8b3b4bd9c40..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/BranchLikeNavigation-test.tsx
+++ /dev/null
@@ -1,73 +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 { ButtonPlain } from '../../../../../../components/controls/buttons';
-import Toggler from '../../../../../../components/controls/Toggler';
-import { mockSetOfBranchAndPullRequest } from '../../../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { click } from '../../../../../../helpers/testUtils';
-import { BranchLikeNavigation, BranchLikeNavigationProps } from '../BranchLikeNavigation';
-
-it('should render correctly', () => {
- const wrapper = shallowRender();
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should render the menu trigger if branches are enabled', () => {
- const wrapper = shallowRender({ hasFeature: () => true });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should properly toggle menu opening when clicking the anchor', () => {
- const wrapper = shallowRender({ hasFeature: () => true });
- expect(wrapper.find(Toggler).props().open).toBe(false);
-
- click(wrapper.find(ButtonPlain));
- expect(wrapper.find(Toggler).props().open).toBe(true);
-
- click(wrapper.find(ButtonPlain));
- expect(wrapper.find(Toggler).props().open).toBe(false);
-});
-
-it('should properly close menu when toggler asks for', () => {
- const wrapper = shallowRender({ hasFeature: () => true });
- expect(wrapper.find(Toggler).props().open).toBe(false);
-
- click(wrapper.find(ButtonPlain));
- expect(wrapper.find(Toggler).props().open).toBe(true);
-
- wrapper.find(Toggler).props().onRequestClose();
- expect(wrapper.find(Toggler).props().open).toBe(false);
-});
-
-function shallowRender(props?: Partial<BranchLikeNavigationProps>) {
- const branchLikes = mockSetOfBranchAndPullRequest();
-
- return shallow(
- <BranchLikeNavigation
- hasFeature={jest.fn().mockReturnValue(false)}
- branchLikes={branchLikes}
- component={mockComponent()}
- currentBranchLike={branchLikes[0]}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/CurrentBranchLike-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/CurrentBranchLike-test.tsx
deleted file mode 100644
index 973cdc0c4f2..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/CurrentBranchLike-test.tsx
+++ /dev/null
@@ -1,129 +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 {
- mockProjectGithubBindingResponse,
- mockProjectGitLabBindingResponse,
-} from '../../../../../../helpers/mocks/alm-settings';
-import { mockMainBranch } from '../../../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { ComponentQualifier } from '../../../../../../types/component';
-import { CurrentBranchLike, CurrentBranchLikeProps } from '../CurrentBranchLike';
-
-describe('applications', () => {
- it('should render correctly when there is only one branch and the user can admin the application', () => {
- const wrapper = shallowRender({
- component: mockComponent({
- configuration: { showSettings: true },
- qualifier: ComponentQualifier.Application,
- }),
- hasManyBranches: false,
- });
- expect(wrapper).toMatchSnapshot();
- });
-
- it("should render correctly when there is only one branch and the user CAN'T admin the application", () => {
- const wrapper = shallowRender({
- component: mockComponent({
- configuration: { showSettings: false },
- qualifier: ComponentQualifier.Application,
- }),
- hasManyBranches: false,
- });
- expect(wrapper).toMatchSnapshot();
- });
-
- it('should render correctly when there are many branchlikes', () => {
- const wrapper = shallowRender({
- branchesEnabled: true,
- component: mockComponent({
- qualifier: ComponentQualifier.Application,
- }),
- hasManyBranches: true,
- });
- expect(wrapper).toMatchSnapshot();
- });
-});
-
-describe('projects', () => {
- it('should render correctly when branches support is disabled', () => {
- expect(
- shallowRender({
- branchesEnabled: false,
- component: mockComponent({
- qualifier: ComponentQualifier.Project,
- }),
- })
- ).toMatchSnapshot('default');
- expect(
- shallowRender({
- branchesEnabled: false,
- component: mockComponent({
- qualifier: ComponentQualifier.Project,
- }),
- projectBinding: mockProjectGithubBindingResponse(),
- })
- ).toMatchSnapshot('alm with prs');
- expect(
- shallowRender({
- branchesEnabled: false,
- component: mockComponent({
- qualifier: ComponentQualifier.Project,
- }),
- projectBinding: mockProjectGitLabBindingResponse(),
- })
- ).toMatchSnapshot('alm with mrs');
- });
-
- it('should render correctly when there is only one branchlike', () => {
- const wrapper = shallowRender({
- branchesEnabled: true,
- component: mockComponent({
- qualifier: ComponentQualifier.Project,
- }),
- hasManyBranches: false,
- });
- expect(wrapper).toMatchSnapshot();
- });
-
- it('should render correctly when there are many branchlikes', () => {
- const wrapper = shallowRender({
- branchesEnabled: true,
- component: mockComponent({
- qualifier: ComponentQualifier.Project,
- }),
- hasManyBranches: true,
- });
- expect(wrapper).toMatchSnapshot();
- });
-});
-
-function shallowRender(props?: Partial<CurrentBranchLikeProps>) {
- return shallow(
- <CurrentBranchLike
- branchesEnabled={false}
- component={mockComponent()}
- currentBranchLike={mockMainBranch()}
- hasManyBranches={false}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/Menu-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/Menu-test.tsx
deleted file mode 100644
index 4a95f97830c..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/Menu-test.tsx
+++ /dev/null
@@ -1,116 +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 Link from '../../../../../../components/common/Link';
-import SearchBox from '../../../../../../components/controls/SearchBox';
-import { KeyboardKeys } from '../../../../../../helpers/keycodes';
-import {
- mockPullRequest,
- mockSetOfBranchAndPullRequest,
-} from '../../../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { mockRouter } from '../../../../../../helpers/testMocks';
-import { click, mockEvent } from '../../../../../../helpers/testUtils';
-import { queryToSearch } from '../../../../../../helpers/urls';
-import { Menu } from '../Menu';
-import { MenuItemList } from '../MenuItemList';
-
-it('should render correctly', () => {
- const wrapper = shallowRender();
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should render correctly with no current branch like', () => {
- const wrapper = shallowRender({ currentBranchLike: undefined });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should close the menu when "manage branches" link is clicked', () => {
- const onClose = jest.fn();
- const wrapper = shallowRender({ onClose });
-
- click(wrapper.find(Link));
- expect(onClose).toHaveBeenCalled();
-});
-
-it('should change url and close menu when an element is selected', () => {
- const onClose = jest.fn();
- const push = jest.fn();
- const router = mockRouter({ push });
- const component = mockComponent();
- const pr = mockPullRequest();
-
- const wrapper = shallowRender({ component, onClose, router });
-
- wrapper.find(MenuItemList).props().onSelect(pr);
-
- expect(onClose).toHaveBeenCalled();
- expect(push).toHaveBeenCalledWith(
- expect.objectContaining({
- search: queryToSearch({
- id: component.key,
- pullRequest: pr.key,
- }),
- })
- );
-});
-
-it('should filter branchlike list correctly', () => {
- const wrapper = shallowRender();
-
- wrapper.find(SearchBox).props().onChange('PR');
-
- expect(wrapper.state().branchLikesToDisplay.length).toBe(3);
-});
-
-it('should handle keyboard shortcut correctly', () => {
- const push = jest.fn();
- const router = mockRouter({ push });
- const wrapper = shallowRender({ currentBranchLike: branchLikes[1], router });
-
- const { onKeyDown } = wrapper.find(SearchBox).props();
-
- onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.UpArrow } }));
- expect(wrapper.state().selectedBranchLike).toBe(branchLikes[3]);
-
- onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.DownArrow } }));
- onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.DownArrow } }));
- expect(wrapper.state().selectedBranchLike).toBe(branchLikes[0]);
-
- onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.Enter } }));
- expect(push).toHaveBeenCalled();
-});
-
-const branchLikes = mockSetOfBranchAndPullRequest();
-
-function shallowRender(props?: Partial<Menu['props']>) {
- return shallow<Menu>(
- <Menu
- branchLikes={branchLikes}
- canAdminComponent={true}
- component={mockComponent()}
- currentBranchLike={branchLikes[2]}
- onClose={jest.fn()}
- router={mockRouter()}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItem-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItem-test.tsx
deleted file mode 100644
index a5ce319f57f..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItem-test.tsx
+++ /dev/null
@@ -1,56 +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 { mockMainBranch, mockPullRequest } from '../../../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { click } from '../../../../../../helpers/testUtils';
-import { MenuItem, MenuItemProps } from '../MenuItem';
-
-it('should render a main branch correctly', () => {
- const wrapper = shallowRender({ branchLike: mockMainBranch() });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should render a non-main branch, indented and selected item correctly', () => {
- const wrapper = shallowRender({ branchLike: mockPullRequest(), indent: true, selected: true });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should propagate click event correctly', () => {
- const onSelect = jest.fn();
- const wrapper = shallowRender({ onSelect });
-
- click(wrapper.find('li'));
- expect(onSelect).toHaveBeenCalled();
-});
-
-function shallowRender(props?: Partial<MenuItemProps>) {
- return shallow(
- <MenuItem
- branchLike={mockMainBranch()}
- component={mockComponent()}
- onSelect={jest.fn()}
- selected={false}
- setSelectedNode={jest.fn()}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItemList-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItemList-test.tsx
deleted file mode 100644
index d448b0af2aa..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/MenuItemList-test.tsx
+++ /dev/null
@@ -1,52 +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 { getBrancheLikesAsTree } from '../../../../../../helpers/branch-like';
-import {
- mockPullRequest,
- mockSetOfBranchAndPullRequest,
-} from '../../../../../../helpers/mocks/branch-like';
-import { mockComponent } from '../../../../../../helpers/mocks/component';
-import { MenuItemList, MenuItemListProps } from '../MenuItemList';
-
-it('should render correctly', () => {
- const wrapper = shallowRender();
- expect(wrapper).toMatchSnapshot();
-});
-
-function shallowRender(props?: Partial<MenuItemListProps>) {
- const branchLikes = [
- ...mockSetOfBranchAndPullRequest(),
- mockPullRequest({ base: 'not-in-the-list' }),
- ];
- const branchLikeTree = getBrancheLikesAsTree(branchLikes);
-
- return shallow(
- <MenuItemList
- branchLikeTree={branchLikeTree}
- component={mockComponent()}
- hasResults={false}
- onSelect={jest.fn()}
- selectedBranchLike={branchLikes[0]}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/BranchLikeNavigation-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/BranchLikeNavigation-test.tsx.snap
deleted file mode 100644
index ba319b91b1d..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/BranchLikeNavigation-test.tsx.snap
+++ /dev/null
@@ -1,195 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<span
- className="big-spacer-left flex-0 branch-like-navigation-toggler-container display-flex-center"
->
- <Memo(CurrentBranchLike)
- branchesEnabled={false}
- 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": [],
- }
- }
- currentBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- hasManyBranches={true}
- />
-</span>
-`;
-
-exports[`should render the menu trigger if branches are enabled 1`] = `
-<span
- className="big-spacer-left flex-0 branch-like-navigation-toggler-container display-flex-center dropdown"
->
- <Toggler
- onRequestClose={[Function]}
- open={false}
- overlay={
- <withRouter(Menu)
- branchLikes={
- [
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-1",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "1",
- "target": "master",
- "title": "PR-1",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-12",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "2",
- "target": "master",
- "title": "PR-2",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-3",
- },
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-2",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "isOrphan": true,
- "key": "2",
- "target": "llb-100",
- "title": "PR-2",
- },
- ]
- }
- 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": [],
- }
- }
- currentBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- onClose={[Function]}
- />
- }
- >
- <ButtonPlain
- aria-expanded={false}
- aria-haspopup="menu"
- className="branch-like-navigation-toggler"
- onClick={[Function]}
- >
- <Memo(CurrentBranchLike)
- branchesEnabled={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": [],
- }
- }
- currentBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- hasManyBranches={true}
- />
- </ButtonPlain>
- </Toggler>
-</span>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap
deleted file mode 100644
index 8026ce65c2b..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap
+++ /dev/null
@@ -1,307 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`applications should render correctly when there are many branchlikes 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
- <DropdownIcon />
-</span>
-`;
-
-exports[`applications should render correctly when there is only one branch and the user CAN'T admin the application 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
-</span>
-`;
-
-exports[`applications should render correctly when there is only one branch and the user can admin the application 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
- <HelpTooltip
- overlay={
- <React.Fragment>
- <p>
- application.branches.help
- </p>
- <hr
- className="spacer-top spacer-bottom"
- />
- <ForwardRef(Link)
- to={
- {
- "pathname": "/project/admin/extension/developer-server/application-console",
- "search": "?id=my-project",
- }
- }
- >
- application.branches.link
- </ForwardRef(Link)>
- </React.Fragment>
- }
- >
- <PlusCircleIcon
- fill="#0271B9"
- size={12}
- />
- </HelpTooltip>
-</span>
-`;
-
-exports[`projects should render correctly when branches support is disabled: alm with mrs 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
- <DocumentationTooltip
- content="branch_like_navigation.no_branch_support.content_x.mr.alm.gitlab"
- data-test="branches-support-disabled"
- links={
- [
- {
- "doc": false,
- "href": "https://www.sonarsource.com/plans-and-pricing/developer/",
- "label": "learn_more",
- },
- ]
- }
- title="branch_like_navigation.no_branch_support.title.mr"
- >
- <PlusCircleIcon
- fill="#0271B9"
- size={12}
- />
- </DocumentationTooltip>
-</span>
-`;
-
-exports[`projects should render correctly when branches support is disabled: alm with prs 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
- <DocumentationTooltip
- content="branch_like_navigation.no_branch_support.content_x.pr.alm.github"
- data-test="branches-support-disabled"
- links={
- [
- {
- "doc": false,
- "href": "https://www.sonarsource.com/plans-and-pricing/developer/",
- "label": "learn_more",
- },
- ]
- }
- title="branch_like_navigation.no_branch_support.title.pr"
- >
- <PlusCircleIcon
- fill="#0271B9"
- size={12}
- />
- </DocumentationTooltip>
-</span>
-`;
-
-exports[`projects should render correctly when branches support is disabled: default 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
- <DocumentationTooltip
- content="branch_like_navigation.no_branch_support.content"
- data-test="branches-support-disabled"
- links={
- [
- {
- "doc": false,
- "href": "https://www.sonarsource.com/plans-and-pricing/developer/",
- "label": "learn_more",
- },
- ]
- }
- title="branch_like_navigation.no_branch_support.title"
- >
- <PlusCircleIcon
- fill="#0271B9"
- size={12}
- />
- </DocumentationTooltip>
-</span>
-`;
-
-exports[`projects should render correctly when there are many branchlikes 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
- <DropdownIcon />
-</span>
-`;
-
-exports[`projects should render correctly when there is only one branchlike 1`] = `
-<span
- className="display-flex-center flex-shrink text-ellipsis"
->
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- fill="#0271B9"
- />
- <span
- className="spacer-left spacer-right flex-shrink text-ellipsis js-branch-like-name"
- title="master"
- >
- master
- </span>
- <DocumentationTooltip
- content="branch_like_navigation.only_one_branch.content"
- data-test="only-one-branch-like"
- links={
- [
- {
- "href": "/analyzing-source-code/branches/branch-analysis/",
- "label": "branch_like_navigation.only_one_branch.documentation",
- },
- {
- "href": "/analyzing-source-code/pull-request-analysis",
- "label": "branch_like_navigation.only_one_branch.pr_analysis",
- },
- {
- "doc": false,
- "href": "/tutorials?id=my-project",
- "inPlace": true,
- "label": "branch_like_navigation.tutorial_for_ci",
- },
- ]
- }
- title="branch_like_navigation.only_one_branch.title"
- >
- <PlusCircleIcon
- fill="#0271B9"
- size={12}
- />
- </DocumentationTooltip>
-</span>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/Menu-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/Menu-test.tsx.snap
deleted file mode 100644
index 9afa94a156d..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/Menu-test.tsx.snap
+++ /dev/null
@@ -1,323 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<DropdownOverlay
- className="branch-like-navigation-menu"
- noPadding={true}
->
- <div
- className="search-box-container"
- >
- <SearchBox
- autoFocus={true}
- onChange={[Function]}
- onKeyDown={[Function]}
- placeholder="branch_like_navigation.search_for_branch_like"
- value=""
- />
- </div>
- <div
- className="item-list-container"
- >
- <Memo(MenuItemList)
- branchLikeTree={
- {
- "branchTree": [
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-1",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-12",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-2",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-3",
- },
- "pullRequests": [],
- },
- ],
- "mainBranchTree": {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- },
- "pullRequests": [
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "2",
- "target": "master",
- "title": "PR-2",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "1",
- "target": "master",
- "title": "PR-1",
- },
- ],
- },
- "orphanPullRequests": [
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "isOrphan": true,
- "key": "2",
- "target": "llb-100",
- "title": "PR-2",
- },
- ],
- "parentlessPullRequests": [],
- }
- }
- 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": [],
- }
- }
- hasResults={true}
- onSelect={[Function]}
- selectedBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- />
- </div>
- <div
- className="hint-container text-right"
- >
- <ForwardRef(Link)
- onClick={[Function]}
- to={
- {
- "pathname": "/project/branches",
- "search": "?id=my-project",
- }
- }
- >
- branch_like_navigation.manage
- </ForwardRef(Link)>
- </div>
-</DropdownOverlay>
-`;
-
-exports[`should render correctly with no current branch like 1`] = `
-<DropdownOverlay
- className="branch-like-navigation-menu"
- noPadding={true}
->
- <div
- className="search-box-container"
- >
- <SearchBox
- autoFocus={true}
- onChange={[Function]}
- onKeyDown={[Function]}
- placeholder="branch_like_navigation.search_for_branch_like"
- value=""
- />
- </div>
- <div
- className="item-list-container"
- >
- <Memo(MenuItemList)
- branchLikeTree={
- {
- "branchTree": [
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-1",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-12",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-2",
- },
- "pullRequests": [],
- },
- {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-3",
- },
- "pullRequests": [],
- },
- ],
- "mainBranchTree": {
- "branch": {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- },
- "pullRequests": [
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "2",
- "target": "master",
- "title": "PR-2",
- },
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "1",
- "target": "master",
- "title": "PR-1",
- },
- ],
- },
- "orphanPullRequests": [
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "isOrphan": true,
- "key": "2",
- "target": "llb-100",
- "title": "PR-2",
- },
- ],
- "parentlessPullRequests": [],
- }
- }
- 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": [],
- }
- }
- hasResults={true}
- onSelect={[Function]}
- selectedBranchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- />
- </div>
- <div
- className="hint-container text-right"
- >
- <ForwardRef(Link)
- onClick={[Function]}
- to={
- {
- "pathname": "/project/branches",
- "search": "?id=my-project",
- }
- }
- >
- branch_like_navigation.manage
- </ForwardRef(Link)>
- </div>
-</DropdownOverlay>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap
deleted file mode 100644
index 57f5a7527b9..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap
+++ /dev/null
@@ -1,146 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render a main branch correctly 1`] = `
-<li
- className="item"
- onClick={[Function]}
->
- <div
- className="display-flex-center display-flex-space-between"
- >
- <div
- className="item-name text-ellipsis"
- title="master"
- >
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- />
- <span
- className="spacer-left"
- >
- master
- </span>
- <span
- className="badge spacer-left"
- >
- branches.main_branch
- </span>
- </div>
- <div
- className="spacer-left"
- >
- <withBranchStatus(BranchStatus)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- 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": [],
- }
- }
- />
- </div>
- </div>
-</li>
-`;
-
-exports[`should render a non-main branch, indented and selected item correctly 1`] = `
-<li
- className="item active"
- onClick={[Function]}
->
- <div
- className="display-flex-center display-flex-space-between big-spacer-left"
- >
- <div
- className="item-name text-ellipsis"
- title="1001 – Foo Bar feature"
- >
- <BranchLikeIcon
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "1001",
- "target": "master",
- "title": "Foo Bar feature",
- }
- }
- />
- <span
- className="spacer-left"
- >
- 1001 – Foo Bar feature
- </span>
- </div>
- <div
- className="spacer-left"
- >
- <withBranchStatus(BranchStatus)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "1001",
- "target": "master",
- "title": "Foo Bar feature",
- }
- }
- 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": [],
- }
- }
- />
- </div>
- </div>
-</li>
-`;
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItemList-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItemList-test.tsx.snap
deleted file mode 100644
index 408f21b26a3..00000000000
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItemList-test.tsx.snap
+++ /dev/null
@@ -1,417 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<ul
- className="item-list"
->
- <li
- className="item"
- >
- <span
- className="note"
- >
- no_results
- </span>
- </li>
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": true,
- "name": "master",
- }
- }
- 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": [],
- }
- }
- key="branch-master"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <li
- className="item header"
- >
- <span
- className="big-spacer-left"
- >
- branch_like_navigation.pull_requests
- </span>
- </li>
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "2",
- "target": "master",
- "title": "PR-2",
- }
- }
- 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": [],
- }
- }
- indent={true}
- key="pull-request-2"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "key": "1",
- "target": "master",
- "title": "PR-1",
- }
- }
- 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": [],
- }
- }
- indent={true}
- key="pull-request-1"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <hr />
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-1",
- }
- }
- 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": [],
- }
- }
- key="branch-branch-1"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <hr />
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-11",
- }
- }
- 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": [],
- }
- }
- key="branch-branch-11"
- onSelect={[MockFunction]}
- selected={true}
- setSelectedNode={[Function]}
- />
- <hr />
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-12",
- }
- }
- 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": [],
- }
- }
- key="branch-branch-12"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <hr />
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-2",
- }
- }
- 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": [],
- }
- }
- key="branch-branch-2"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <hr />
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "excludedFromPurge": true,
- "isMain": false,
- "name": "branch-3",
- }
- }
- 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": [],
- }
- }
- key="branch-branch-3"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <hr />
- <li
- className="item header"
- >
- branch_like_navigation.pull_requests
- </li>
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "base": "not-in-the-list",
- "branch": "feature/foo/bar",
- "key": "1001",
- "target": "master",
- "title": "Foo Bar feature",
- }
- }
- 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": [],
- }
- }
- key="pull-request-1001"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
- <li
- className="item header"
- >
- branch_like_navigation.orphan_pull_requests
- <HelpTooltip
- className="little-spacer-left"
- overlay="branch_like_navigation.orphan_pull_requests.tooltip"
- />
- </li>
- <Memo(MenuItem)
- branchLike={
- {
- "analysisDate": "2018-01-01",
- "base": "master",
- "branch": "feature/foo/bar",
- "isOrphan": true,
- "key": "2",
- "target": "llb-100",
- "title": "PR-2",
- }
- }
- 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": [],
- }
- }
- key="pull-request-2"
- onSelect={[MockFunction]}
- selected={false}
- setSelectedNode={[Function]}
- />
-</ul>
-`;
diff --git a/server/sonar-web/src/main/js/components/common/DocumentationTooltip.tsx b/server/sonar-web/src/main/js/components/common/DocumentationTooltip.tsx
index 9c799d8921c..cd75a88aa40 100644
--- a/server/sonar-web/src/main/js/components/common/DocumentationTooltip.tsx
+++ b/server/sonar-web/src/main/js/components/common/DocumentationTooltip.tsx
@@ -34,7 +34,7 @@ export interface DocumentationTooltipProps {
export default function DocumentationTooltip(props: DocumentationTooltipProps) {
const nextSelectableNode = React.useRef<HTMLElement | undefined | null>();
- const linksRef = React.useRef<(HTMLAnchorElement | null)[]>([]);
+ const linksRef = React.useRef<Array<HTMLAnchorElement | null>>([]);
const helpRef = React.useRef<HTMLElement>(null);
const { className, children, content, links, title } = props;
@@ -49,7 +49,7 @@ export default function DocumentationTooltip(props: DocumentationTooltipProps) {
function handleTabPress(event: KeyboardEvent) {
if (event.code === KeyboardKeys.Tab) {
- if (event.shiftKey === true) {
+ if (event.shiftKey) {
if (event.target === first(linksRef.current)) {
helpRef.current?.focus();
}
diff --git a/server/sonar-web/src/main/js/components/icons/BranchLikeIcon.tsx b/server/sonar-web/src/main/js/components/icons/BranchLikeIcon.tsx
index 754acf2a4a6..a5d48bd0d62 100644
--- a/server/sonar-web/src/main/js/components/icons/BranchLikeIcon.tsx
+++ b/server/sonar-web/src/main/js/components/icons/BranchLikeIcon.tsx
@@ -17,20 +17,22 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { BranchIcon, MainBranchIcon, PullRequestIcon, ThemeColors } from 'design-system';
import * as React from 'react';
-import BranchIcon from '../../components/icons/BranchIcon';
import { IconProps } from '../../components/icons/Icon';
-import PullRequestIcon from '../../components/icons/PullRequestIcon';
-import { isPullRequest } from '../../helpers/branch-like';
+import { isMainBranch, isPullRequest } from '../../helpers/branch-like';
import { BranchLike } from '../../types/branch-like';
-export interface BranchLikeIconProps extends IconProps {
+export interface BranchLikeIconProps extends Omit<IconProps, 'fill'> {
branchLike: BranchLike;
+ fill?: ThemeColors;
}
export default function BranchLikeIcon({ branchLike, ...props }: BranchLikeIconProps) {
if (isPullRequest(branchLike)) {
- return <PullRequestIcon {...props} />;
+ return <PullRequestIcon fill="pageContentLight" {...props} />;
+ } else if (isMainBranch(branchLike)) {
+ return <MainBranchIcon fill="pageContentLight" {...props} />;
}
- return <BranchIcon {...props} />;
+ return <BranchIcon fill="pageContentLight" {...props} />;
}
diff --git a/server/sonar-web/src/main/js/components/icons/__tests__/__snapshots__/BranchLikeIcon-test.tsx.snap b/server/sonar-web/src/main/js/components/icons/__tests__/__snapshots__/BranchLikeIcon-test.tsx.snap
index dfe0b95f619..561ef92174d 100644
--- a/server/sonar-web/src/main/js/components/icons/__tests__/__snapshots__/BranchLikeIcon-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/icons/__tests__/__snapshots__/BranchLikeIcon-test.tsx.snap
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should render branch icon correctly 1`] = `"<div><svg height="16" style="fill-rule: evenodd; clip-rule: evenodd; stroke-linejoin: round; stroke-miterlimit: 1.41421;" version="1.1" viewBox="0 0 16 16" width="16" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"><path d="M12.5 6.5c0-1.1-.9-2-2-2s-2 .9-2 2c0 .8.5 1.5 1.2 1.8-.3.6-.7 1.1-1.2 1.4-.9.5-1.9.5-2.5.4V4c.9-.2 1.5-1 1.5-1.9 0-1.1-.9-2-2-2s-2 .9-2 2C3.5 3 4.1 3.8 5 4v8c-.9.2-1.5 1-1.5 1.9 0 1.1.9 2 2 2s2-.9 2-2c0-.9-.6-1.7-1.5-1.9v-1c.2 0 .5.1.7.1.7 0 1.5-.1 2.2-.6.8-.5 1.4-1.2 1.7-2.1 1.1 0 1.9-.9 1.9-1.9zm-8-4.4c0-.6.4-1 1-1s1 .4 1 1-.4 1-1 1-1-.5-1-1zm2 11.9c0 .6-.4 1-1 1s-1-.4-1-1 .4-1 1-1 1 .4 1 1zm4-6.5c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" style="fill: #236a97;"></path></svg></div>"`;
+exports[`should render branch icon correctly 1`] = `"<div><svg aria-hidden="true" focusable="false" role="img" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="rgb(106,117,144)" style="display: inline-block; user-select: none; vertical-align: middle; overflow: visible;"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></div>"`;
-exports[`should render pull request icon correctly 1`] = `"<div><svg height="16" style="fill-rule: evenodd; clip-rule: evenodd; stroke-linejoin: round; stroke-miterlimit: 1.41421;" version="1.1" viewBox="0 0 16 16" width="16" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"><path d="M13,11.9L13,5.5C13,5.4 13.232,1.996 7.9,2L9.1,0.8L8.5,0.1L5.9,2.6L8.5,5.1L9.2,4.4L7.905,3.008C12.256,2.99 12,5.4 12,5.5L12,11.9C11.1,12.1 10.5,12.9 10.5,13.8C10.5,14.9 11.4,15.8 12.5,15.8C13.6,15.8 14.5,14.9 14.5,13.8C14.5,12.9 13.9,12.2 13,11.9ZM4,11.9C4.9,12.2 5.5,12.9 5.5,13.8C5.5,14.9 4.6,15.8 3.5,15.8C2.4,15.8 1.5,14.9 1.5,13.8C1.5,12.9 2.1,12.1 3,11.9L3,4.1C2.1,3.9 1.5,3.1 1.5,2.2C1.5,1.1 2.4,0.2 3.5,0.2C4.6,0.2 5.5,1.1 5.5,2.2C5.5,3.1 4.9,3.9 4,4.1L4,11.9ZM12.5,14.9C11.9,14.9 11.5,14.5 11.5,13.9C11.5,13.3 11.9,12.9 12.5,12.9C13.1,12.9 13.5,13.3 13.5,13.9C13.5,14.5 13.1,14.9 12.5,14.9ZM3.5,14.9C2.9,14.9 2.5,14.5 2.5,13.9C2.5,13.3 2.9,12.9 3.5,12.9C4.1,12.9 4.5,13.3 4.5,13.9C4.5,14.5 4.1,14.9 3.5,14.9ZM2.5,2.2C2.5,1.6 2.9,1.2 3.5,1.2C4.1,1.2 4.5,1.6 4.5,2.2C4.5,2.8 4.1,3.2 3.5,3.2C2.9,3.2 2.5,2.8 2.5,2.2Z" style="fill: #236a97;"></path></svg></div>"`;
+exports[`should render pull request icon correctly 1`] = `"<div><svg aria-hidden="true" focusable="false" role="img" class="octicon octicon-git-pull-request" viewBox="0 0 16 16" width="16" height="16" fill="rgb(106,117,144)" style="display: inline-block; user-select: none; vertical-align: middle; overflow: visible;"><path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path></svg></div>"`;
diff --git a/server/sonar-web/src/main/js/helpers/mocks/branch-like.ts b/server/sonar-web/src/main/js/helpers/mocks/branch-like.ts
index becee29b800..30cb65c1a7a 100644
--- a/server/sonar-web/src/main/js/helpers/mocks/branch-like.ts
+++ b/server/sonar-web/src/main/js/helpers/mocks/branch-like.ts
@@ -59,6 +59,22 @@ export function mockSetOfBranchAndPullRequest(): BranchLike[] {
mockPullRequest({ key: '2', title: 'PR-2' }),
mockBranch({ name: 'branch-3' }),
mockBranch({ name: 'branch-2' }),
- mockPullRequest({ key: '2', title: 'PR-2', target: 'llb-100', isOrphan: true }),
+ mockPullRequest({
+ key: '2',
+ title: 'PR-2',
+ target: 'llb-100',
+ isOrphan: true,
+ }),
+ ];
+}
+
+export function mockSetOfBranchAndPullRequestForBranchSelector(): BranchLike[] {
+ return [
+ mockBranch({ name: 'branch-1', status: { qualityGateStatus: 'OK' } }),
+ mockMainBranch(),
+ mockPullRequest({ key: '1', title: 'PR-1', status: { qualityGateStatus: 'OK' } }),
+ mockBranch({ name: 'branch-2', status: { qualityGateStatus: 'OK' } }),
+ mockPullRequest({ key: '2', title: 'PR-2', status: { qualityGateStatus: 'OK' } }),
+ mockBranch({ name: 'branch-3', status: { qualityGateStatus: 'OK' } }),
];
}