From b7d68dca795cf2127efbaa8b5c2cba0ee32192ee Mon Sep 17 00:00:00 2001 From: Wouter Admiraal Date: Tue, 21 Apr 2020 17:42:30 +0200 Subject: [PATCH] SONAR-13296 Add new Jenkins tutorial for Bitbucket Server --- .../public/images/tutorials/commit.svg | 1 + .../public/images/tutorials/jenkins.svg | 1 + .../public/images/tutorials/refresh.svg | 1 + .../sonar-web/src/main/js/api/alm-settings.ts | 6 +- .../overview/components/EmptyOverview.tsx | 4 +- .../__snapshots__/EmptyOverview-test.tsx.snap | 2 +- .../main/js/components/common/CodeSnippet.css | 1 + .../tutorials/TutorialSelection.tsx | 109 ++++ .../tutorials/TutorialSelectionRenderer.tsx | 101 ++++ .../__tests__/TutorialSelection-test.tsx | 109 ++++ .../TutorialSelectionRenderer-test.tsx | 70 +++ .../TutorialSelection-test.tsx.snap | 41 ++ .../TutorialSelectionRenderer-test.tsx.snap | 145 +++++ .../tutorials/components/LabelActionPair.tsx | 33 ++ .../tutorials/components/LabelValuePair.tsx | 36 ++ .../components/SentenceWithFilename.tsx | 44 ++ .../components/SentenceWithHighlights.tsx | 44 ++ .../components/tutorials/components/Step.css | 42 ++ .../components/tutorials/components/Step.tsx | 28 +- .../__tests__/LabelActionPair-test.tsx | 31 ++ .../__tests__/LabelValuePair-test.tsx | 33 ++ .../__tests__/SentenceWithFilename-test.tsx | 33 ++ .../__tests__/SentenceWithHighlights-test.tsx | 33 ++ .../LabelActionPair-test.tsx.snap | 12 + .../LabelValuePair-test.tsx.snap | 20 + .../SentenceWithFilename-test.tsx.snap | 19 + .../SentenceWithHighlights-test.tsx.snap | 18 + .../jenkins/BitbucketWebhookStep.tsx | 143 +++++ .../tutorials/jenkins/JenkinsTutorial.tsx | 89 +++ .../tutorials/jenkins/JenkinsfileStep.tsx | 126 +++++ .../jenkins/MultiBranchPipelineStep.tsx | 113 ++++ .../tutorials/jenkins/PreRequisitesStep.tsx | 79 +++ .../__tests__/BitbucketWebhookStep-test.tsx | 51 ++ .../__tests__/JenkinsTutorial-test.tsx | 91 +++ .../__tests__/JenkinsfileStep-test.tsx | 73 +++ .../MultiBranchPipelineStep-test.tsx | 44 ++ .../__tests__/PreRequisitesStep-test.tsx | 36 ++ .../BitbucketWebhookStep-test.tsx.snap | 228 ++++++++ .../JenkinsTutorial-test.tsx.snap | 82 +++ .../JenkinsfileStep-test.tsx.snap | 526 ++++++++++++++++++ .../MultiBranchPipelineStep-test.tsx.snap | 119 ++++ .../PreRequisitesStep-test.tsx.snap | 70 +++ .../CreateJenkinsfileBulletPoint.tsx | 73 +++ .../jenkins/buildtool-steps/Gradle.tsx | 64 +++ .../jenkins/buildtool-steps/MSBuild.tsx | 90 +++ .../jenkins/buildtool-steps/Maven.tsx | 62 +++ .../jenkins/buildtool-steps/Other.tsx | 60 ++ .../CreateJenkinsfileBulletPoint-test.tsx | 36 ++ .../buildtool-steps/__tests__/Gradle-test.tsx | 32 ++ .../__tests__/MSBuild-test.tsx | 32 ++ .../buildtool-steps/__tests__/Maven-test.tsx | 32 ++ .../buildtool-steps/__tests__/Other-test.tsx | 32 ++ ...CreateJenkinsfileBulletPoint-test.tsx.snap | 77 +++ .../__snapshots__/Gradle-test.tsx.snap | 37 ++ .../__snapshots__/MSBuild-test.tsx.snap | 91 +++ .../__snapshots__/Maven-test.tsx.snap | 33 ++ .../__snapshots__/Other-test.tsx.snap | 31 ++ .../tutorials/jenkins/test-utils.ts | 28 + .../tutorials/manual/ManualTutorial.tsx | 17 +- .../manual/__tests__/ManualTutorial-test.tsx | 1 - .../ManualTutorial-test.tsx.snap | 77 --- .../main/js/components/tutorials/styles.css | 23 + .../src/main/js/components/tutorials/types.ts | 31 ++ .../src/main/js/components/tutorials/utils.ts | 8 +- .../main/js/helpers/__tests__/alm-settings.ts | 41 ++ .../src/main/js/helpers/alm-settings.ts | 38 ++ .../src/main/js/helpers/mocks/alm-settings.ts | 26 +- .../src/main/js/types/alm-settings.ts | 6 + .../resources/org/sonar/l10n/core.properties | 99 ++++ 69 files changed, 3946 insertions(+), 118 deletions(-) create mode 100644 server/sonar-web/public/images/tutorials/commit.svg create mode 100644 server/sonar-web/public/images/tutorials/jenkins.svg create mode 100644 server/sonar-web/public/images/tutorials/refresh.svg create mode 100644 server/sonar-web/src/main/js/components/tutorials/TutorialSelection.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelection-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelectionRenderer-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelection-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/LabelActionPair.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/LabelValuePair.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/SentenceWithFilename.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/SentenceWithHighlights.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelActionPair-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelValuePair-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithFilename-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithHighlights-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelActionPair-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelValuePair-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithFilename-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithHighlights-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/BitbucketWebhookStep.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/MultiBranchPipelineStep.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/BitbucketWebhookStep-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/MultiBranchPipelineStep-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/BitbucketWebhookStep-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/MultiBranchPipelineStep-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/MSBuild.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CreateJenkinsfileBulletPoint-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/MSBuild-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Gradle-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/MSBuild-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Maven-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Other-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/components/tutorials/jenkins/test-utils.ts create mode 100644 server/sonar-web/src/main/js/components/tutorials/styles.css create mode 100644 server/sonar-web/src/main/js/components/tutorials/types.ts create mode 100644 server/sonar-web/src/main/js/helpers/__tests__/alm-settings.ts create mode 100644 server/sonar-web/src/main/js/helpers/alm-settings.ts diff --git a/server/sonar-web/public/images/tutorials/commit.svg b/server/sonar-web/public/images/tutorials/commit.svg new file mode 100644 index 00000000000..f60f7e5500e --- /dev/null +++ b/server/sonar-web/public/images/tutorials/commit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/server/sonar-web/public/images/tutorials/jenkins.svg b/server/sonar-web/public/images/tutorials/jenkins.svg new file mode 100644 index 00000000000..3ffa20bced1 --- /dev/null +++ b/server/sonar-web/public/images/tutorials/jenkins.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/server/sonar-web/public/images/tutorials/refresh.svg b/server/sonar-web/public/images/tutorials/refresh.svg new file mode 100644 index 00000000000..04579ae7e54 --- /dev/null +++ b/server/sonar-web/public/images/tutorials/refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/server/sonar-web/src/main/js/api/alm-settings.ts b/server/sonar-web/src/main/js/api/alm-settings.ts index 5b70298a7c4..56691948c8c 100644 --- a/server/sonar-web/src/main/js/api/alm-settings.ts +++ b/server/sonar-web/src/main/js/api/alm-settings.ts @@ -34,7 +34,11 @@ import { } from '../types/alm-settings'; export function getAlmDefinitions(): Promise { - return getJSON('/api/alm_settings/list_definitions').catch(throwGlobalError); + return getAlmDefinitionsNoCatch().catch(throwGlobalError); +} + +export function getAlmDefinitionsNoCatch(): Promise { + return getJSON('/api/alm_settings/list_definitions'); } export function getAlmSettings(project?: string): Promise { diff --git a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx index c60873f126c..278ab8ea5cb 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/EmptyOverview.tsx @@ -22,7 +22,7 @@ import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { Alert } from 'sonar-ui-common/components/ui/Alert'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import AnalyzeTutorial from '../../../components/tutorials/manual/AnalyzeTutorial'; +import TutorialSelection from '../../../components/tutorials/TutorialSelection'; import { getBranchLikeDisplayName, isBranch, isMainBranch } from '../../../helpers/branch-like'; import { isLoggedIn } from '../../../helpers/users'; import { getCurrentUser, Store } from '../../../store/rootReducer'; @@ -87,7 +87,7 @@ export function EmptyOverview(props: Props) { {isLoggedIn(currentUser) ? ( <> {showWarning && {warning}} - {showTutorial && } + {showTutorial && } ) : ( {warning} diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap index b26d0feb600..7dc937d251d 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/components/__tests__/__snapshots__/EmptyOverview-test.tsx.snap @@ -4,7 +4,7 @@ exports[`renders correctly 1`] = `
- button:hover, diff --git a/server/sonar-web/src/main/js/components/tutorials/TutorialSelection.tsx b/server/sonar-web/src/main/js/components/tutorials/TutorialSelection.tsx new file mode 100644 index 00000000000..44891c3a6ff --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/TutorialSelection.tsx @@ -0,0 +1,109 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { WithRouterProps } from 'react-router'; +import { getAlmDefinitionsNoCatch, getProjectAlmBinding } from '../../api/alm-settings'; +import { AlmBindingDefinition, AlmKeys, ProjectAlmBindingResponse } from '../../types/alm-settings'; +import { withRouter } from '../hoc/withRouter'; +import './styles.css'; +import TutorialSelectionRenderer from './TutorialSelectionRenderer'; +import { TutorialModes } from './types'; + +interface Props extends Pick { + component: T.Component; + currentUser: T.LoggedInUser; +} + +interface State { + almBinding?: AlmBindingDefinition; + forceManual: boolean; + loading: boolean; + projectBinding?: ProjectAlmBindingResponse; +} + +export class TutorialSelection extends React.PureComponent { + mounted = false; + state: State = { + forceManual: true, + loading: true + }; + + componentDidMount() { + this.mounted = true; + this.fetchAlmBindings(); + } + + fetchAlmBindings = async () => { + const { component } = this.props; + + const [almDefinitions, projectBinding] = await Promise.all([ + getAlmDefinitionsNoCatch().catch(() => undefined), + getProjectAlmBinding(component.key).catch(() => undefined) + ]); + + if (this.mounted) { + // We only support Bitbucket for now. + if (projectBinding === undefined || projectBinding.alm !== AlmKeys.Bitbucket) { + this.setState({ loading: false, forceManual: true }); + } else { + let almBinding; + if (almDefinitions !== undefined) { + almBinding = almDefinitions[projectBinding.alm].find(d => d.key === projectBinding.key); + } + this.setState({ almBinding, forceManual: false, projectBinding, loading: false }); + } + } + }; + + handleSelectTutorial = (selectedTutorial: TutorialModes) => { + const { + router, + location: { pathname, query } + } = this.props; + + router.push({ + pathname, + query: { ...query, selectedTutorial } + }); + }; + + render() { + const { component, currentUser, location } = this.props; + const { almBinding, forceManual, loading, projectBinding } = this.state; + + const selectedTutorial: TutorialModes | undefined = forceManual + ? TutorialModes.Manual + : location.query?.selectedTutorial; + + return ( + + ); + } +} + +export default withRouter(TutorialSelection); diff --git a/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx b/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx new file mode 100644 index 00000000000..ca68491326e --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx @@ -0,0 +1,101 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import * as React from 'react'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; +import { AlmBindingDefinition, ProjectAlmBindingResponse } from '../../types/alm-settings'; +import JenkinsTutorial from './jenkins/JenkinsTutorial'; +import ManualTutorial from './manual/ManualTutorial'; +import { TutorialModes } from './types'; + +export interface TutorialSelectionRendererProps { + almBinding?: AlmBindingDefinition; + component: T.Component; + currentUser: T.LoggedInUser; + loading: boolean; + onSelectTutorial: (mode: TutorialModes) => void; + projectBinding?: ProjectAlmBindingResponse; + selectedTutorial?: TutorialModes; +} + +export default function TutorialSelectionRenderer(props: TutorialSelectionRendererProps) { + const { almBinding, component, currentUser, loading, projectBinding, selectedTutorial } = props; + + if (loading) { + return ; + } + + return ( + <> + {selectedTutorial === undefined && ( +
+
+

+ {translate('onboarding.tutorial.choose_method')} +

+
+ +
+ + + +
+
+ )} + + {selectedTutorial === TutorialModes.Manual && ( + + )} + + {selectedTutorial === TutorialModes.Jenkins && projectBinding !== undefined && ( + + )} + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelection-test.tsx b/server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelection-test.tsx new file mode 100644 index 00000000000..77290701736 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelection-test.tsx @@ -0,0 +1,109 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; +import { getAlmDefinitionsNoCatch, getProjectAlmBinding } from '../../../api/alm-settings'; +import { mockBitbucketBindingDefinition } from '../../../helpers/mocks/alm-settings'; +import { + mockComponent, + mockLocation, + mockLoggedInUser, + mockRouter +} from '../../../helpers/testMocks'; +import { AlmKeys } from '../../../types/alm-settings'; +import { TutorialSelection } from '../TutorialSelection'; +import { TutorialModes } from '../types'; + +jest.mock('../../../api/alm-settings', () => ({ + getProjectAlmBinding: jest.fn().mockRejectedValue(null), + getAlmDefinitionsNoCatch: jest.fn().mockRejectedValue(null) +})); + +beforeEach(jest.clearAllMocks); + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +it('should select manual if project is not bound', async () => { + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + expect(wrapper.state().forceManual).toBe(true); +}); + +it('should not select anything if project is bound to Bitbucket', async () => { + (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.Bitbucket }); + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + expect(wrapper.state().forceManual).toBe(false); +}); + +it('should select manual if project is bound to any other ALM', async () => { + (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.GitLab }); + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + expect(wrapper.state().forceManual).toBe(true); +}); + +it('should correctly find the global ALM binding definition', async () => { + const key = 'foo'; + const almBinding = mockBitbucketBindingDefinition({ key }); + (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.Bitbucket, key }); + (getAlmDefinitionsNoCatch as jest.Mock).mockResolvedValueOnce({ + [AlmKeys.Bitbucket]: [almBinding] + }); + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + expect(wrapper.state().almBinding).toBe(almBinding); +}); + +it('should handle selection', () => { + const push = jest.fn(); + const wrapper = shallowRender({ router: mockRouter({ push }) }); + const instance = wrapper.instance(); + + instance.handleSelectTutorial(TutorialModes.Manual); + expect(push).toHaveBeenLastCalledWith( + expect.objectContaining({ + query: { selectedTutorial: TutorialModes.Manual } + }) + ); + + instance.handleSelectTutorial(TutorialModes.Jenkins); + expect(push).toHaveBeenLastCalledWith( + expect.objectContaining({ + query: { selectedTutorial: TutorialModes.Jenkins } + }) + ); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelectionRenderer-test.tsx b/server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelectionRenderer-test.tsx new file mode 100644 index 00000000000..151db95278f --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelectionRenderer-test.tsx @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { click } from 'sonar-ui-common/helpers/testUtils'; +import { + mockBitbucketBindingDefinition, + mockProjectBitbucketBindingGet +} from '../../../helpers/mocks/alm-settings'; +import { mockComponent, mockLoggedInUser } from '../../../helpers/testMocks'; +import TutorialSelectionRenderer, { + TutorialSelectionRendererProps +} from '../TutorialSelectionRenderer'; +import { TutorialModes } from '../types'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('selection'); + expect(shallowRender({ loading: true })).toMatchSnapshot('loading'); + expect(shallowRender({ selectedTutorial: TutorialModes.Manual })).toMatchSnapshot( + 'manual tutorial' + ); + expect( + shallowRender({ + selectedTutorial: TutorialModes.Jenkins, + projectBinding: mockProjectBitbucketBindingGet() + }) + ).toMatchSnapshot('jenkins tutorial'); +}); + +it('should allow mode selection', () => { + const onSelectTutorial = jest.fn(); + const wrapper = shallowRender({ onSelectTutorial }); + + click(wrapper.find('button.tutorial-mode-jenkins')); + expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins); + + click(wrapper.find('button.tutorial-mode-manual')); + expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelection-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelection-test.tsx.snap new file mode 100644 index 00000000000..ecdac5be7ad --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelection-test.tsx.snap @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap new file mode 100644 index 00000000000..b78bf9196d3 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap @@ -0,0 +1,145 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: jenkins tutorial 1`] = ` + + + +`; + +exports[`should render correctly: loading 1`] = ` + +`; + +exports[`should render correctly: manual tutorial 1`] = ` + + + +`; + +exports[`should render correctly: selection 1`] = ` + +
+
+

+ onboarding.tutorial.choose_method +

+
+
+ + +
+
+
+`; diff --git a/server/sonar-web/src/main/js/components/tutorials/components/LabelActionPair.tsx b/server/sonar-web/src/main/js/components/tutorials/components/LabelActionPair.tsx new file mode 100644 index 00000000000..b26c13f3d7d --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/LabelActionPair.tsx @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { translate } from 'sonar-ui-common/helpers/l10n'; + +export interface LabelActionPairProps { + translationKey: string; +} + +export default function LabelActionPair({ translationKey }: LabelActionPairProps) { + return ( + <> + {translate(translationKey, 'label')}: {translate(translationKey, 'action')} + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/LabelValuePair.tsx b/server/sonar-web/src/main/js/components/tutorials/components/LabelValuePair.tsx new file mode 100644 index 00000000000..68ab8ebf920 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/LabelValuePair.tsx @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard'; +import { translate } from 'sonar-ui-common/helpers/l10n'; + +export interface LabelValuePairProps { + translationKey: string; + value: string; +} + +export default function LabelValuePair({ translationKey, value }: LabelValuePairProps) { + return ( +
+ {translate(translationKey, 'label')}: {value} + +
+ ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/SentenceWithFilename.tsx b/server/sonar-web/src/main/js/components/tutorials/components/SentenceWithFilename.tsx new file mode 100644 index 00000000000..0e4c6696f8c --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/SentenceWithFilename.tsx @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { translate } from 'sonar-ui-common/helpers/l10n'; + +export interface SentenceWithFilenameProps { + filename: string; + translationKey: string; +} + +export default function SentenceWithFilename({ + filename, + translationKey +}: SentenceWithFilenameProps) { + return ( + + {filename} + }} + /> + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/SentenceWithHighlights.tsx b/server/sonar-web/src/main/js/components/tutorials/components/SentenceWithHighlights.tsx new file mode 100644 index 00000000000..45c6a28d67e --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/SentenceWithHighlights.tsx @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { translate } from 'sonar-ui-common/helpers/l10n'; + +export interface SentenceWithHighlightsProps { + highlightKeys: string[]; + translationKey: string; +} + +export default function SentenceWithHighlights({ + highlightKeys, + translationKey +}: SentenceWithHighlightsProps) { + const values: T.Dict = {}; + highlightKeys.forEach(key => { + values[key] = {translate(translationKey, 'sentence', key)}; + }); + return ( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/Step.css b/server/sonar-web/src/main/js/components/tutorials/components/Step.css index ec206ba8afd..5e150f8b666 100644 --- a/server/sonar-web/src/main/js/components/tutorials/components/Step.css +++ b/server/sonar-web/src/main/js/components/tutorials/components/Step.css @@ -20,6 +20,11 @@ .onboarding-step { position: relative; padding-left: 34px; + margin-bottom: var(--gridSize); +} + +.onboarding-step.no-step-number { + padding-left: 0; } .onboarding-step:not(.is-open):not(.is-finished) { @@ -57,3 +62,40 @@ cursor: pointer; outline: none; } + +.onboarding-step ol.list-styled { + list-style: none; + padding-left: 0; + counter-reset: step-counter; +} + +.onboarding-step .markdown { + line-height: inherit; +} + +.onboarding-step ul.list-styled li { + margin-top: var(--gridSize); + margin-bottom: var(--gridSize); +} + +.onboarding-step ol.list-styled > li { + position: relative; + counter-increment: step-counter; + margin-bottom: calc(2 * var(--gridSize)); + padding-left: calc(4 * var(--gridSize)); +} + +.onboarding-step ol.list-styled > li::before { + content: counter(step-counter); + color: white; + background-color: var(--blue); + display: inline-flex; + border-radius: 50%; + width: 16px; + position: absolute; + left: 0; + font-size: 10px; + height: 16px; + justify-content: center; + align-items: center; +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/Step.tsx b/server/sonar-web/src/main/js/components/tutorials/components/Step.tsx index 106d8c3b6a7..dba05b1bedc 100644 --- a/server/sonar-web/src/main/js/components/tutorials/components/Step.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/components/Step.tsx @@ -24,25 +24,29 @@ import './Step.css'; interface Props { finished?: boolean; - onOpen: VoidFunction; + onOpen?: VoidFunction; open: boolean; renderForm: () => React.ReactNode; - renderResult: () => React.ReactNode; - stepNumber: number; + renderResult?: () => React.ReactNode; + stepNumber?: number; stepTitle: React.ReactNode; } export default function Step(props: Props) { + const { finished, open, stepNumber, stepTitle } = props; const className = classNames('boxed-group', 'onboarding-step', { - 'is-open': props.open, - 'is-finished': props.finished + 'is-open': open, + 'is-finished': finished, + 'no-step-number': stepNumber === undefined }); - const clickable = !props.open && props.finished; + const clickable = !open && finished && props.onOpen !== undefined; const handleClick = (event: React.MouseEvent) => { event.preventDefault(); - props.onOpen(); + if (props.onOpen !== undefined) { + props.onOpen(); + } }; return ( @@ -51,13 +55,13 @@ export default function Step(props: Props) { onClick={clickable ? handleClick : undefined} role={clickable ? 'button' : undefined} tabIndex={clickable ? 0 : undefined}> -
{props.stepNumber}
- {!props.open && props.renderResult()} + {stepNumber !== undefined &&
{stepNumber}
} + {!open && props.renderResult && props.renderResult()}
-

{props.stepTitle}

+

{stepTitle}

- {!props.open &&
} -
{props.renderForm()}
+ {!open &&
} +
{props.renderForm()}
); } diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelActionPair-test.tsx b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelActionPair-test.tsx new file mode 100644 index 00000000000..4e38e3616bf --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelActionPair-test.tsx @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import LabelActionPair, { LabelActionPairProps } from '../LabelActionPair'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelValuePair-test.tsx b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelValuePair-test.tsx new file mode 100644 index 00000000000..3794e837de6 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/LabelValuePair-test.tsx @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import LabelValuePair, { LabelValuePairProps } from '../LabelValuePair'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithFilename-test.tsx b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithFilename-test.tsx new file mode 100644 index 00000000000..0271f218975 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithFilename-test.tsx @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import SentenceWithFilename, { SentenceWithFilenameProps } from '../SentenceWithFilename'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithHighlights-test.tsx b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithHighlights-test.tsx new file mode 100644 index 00000000000..005656b4423 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/SentenceWithHighlights-test.tsx @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import SentenceWithHighlights, { SentenceWithHighlightsProps } from '../SentenceWithHighlights'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelActionPair-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelActionPair-test.tsx.snap new file mode 100644 index 00000000000..574d189ee6a --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelActionPair-test.tsx.snap @@ -0,0 +1,12 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + + + foo.label + : + + + foo.action + +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelValuePair-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelValuePair-test.tsx.snap new file mode 100644 index 00000000000..99305242996 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/LabelValuePair-test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` +
+ + foo.label + : + + + bar + +
+`; diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithFilename-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithFilename-test.tsx.snap new file mode 100644 index 00000000000..54c401e7633 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithFilename-test.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + + + foo.txt + , + } + } + /> + +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithHighlights-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithHighlights-test.tsx.snap new file mode 100644 index 00000000000..dc9ab667a9d --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/SentenceWithHighlights-test.tsx.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + + foo.sentence.hello + , + "world": + foo.sentence.world + , + } + } +/> +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/BitbucketWebhookStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/BitbucketWebhookStep.tsx new file mode 100644 index 00000000000..5ce09416424 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/BitbucketWebhookStep.tsx @@ -0,0 +1,143 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { Button, ButtonLink } from 'sonar-ui-common/components/controls/buttons'; +import { Alert } from 'sonar-ui-common/components/ui/Alert'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { + BitbucketBindingDefinition, + ProjectBitbucketBindingResponse +} from '../../../types/alm-settings'; +import CodeSnippet from '../../common/CodeSnippet'; +import LabelActionPair from '../components/LabelActionPair'; +import SentenceWithHighlights from '../components/SentenceWithHighlights'; +import Step from '../components/Step'; + +export interface BitbucketWebhookStepProps { + almBinding?: BitbucketBindingDefinition; + finished: boolean; + onDone: () => void; + onOpen: () => void; + open: boolean; + projectBinding: ProjectBitbucketBindingResponse; +} + +export default function BitbucketWebhookStep(props: BitbucketWebhookStepProps) { + const { almBinding, finished, open, projectBinding } = props; + return ( + ( +
+

+ + {translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link')} + + ) + }} + /> +

+
    +
  1. + + {translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link')} + + ) : ( + translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link') + ) + }} + /> +
      +
    • + +
    • +
    • +

      + +

      + + + {translate( + 'onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning' + )} + +
    • +
    +
  2. +
  3. + +
      +
    • + +
    • +
    • + +
    • +
    +
  4. +
  5. + +
  6. +
+ +
+ )} + stepNumber={2} + stepTitle={translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.title')} + /> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx new file mode 100644 index 00000000000..47d994cc6aa --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx @@ -0,0 +1,89 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Alert } from 'sonar-ui-common/components/ui/Alert'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { + isBitbucketBindingDefinition, + isProjectBitbucketBindingResponse +} from '../../../helpers/alm-settings'; +import { AlmBindingDefinition, ProjectAlmBindingResponse } from '../../../types/alm-settings'; +import BitbucketWebhookStep from './BitbucketWebhookStep'; +import JenkinsfileStep from './JenkinsfileStep'; +import MultiBranchPipelineStep from './MultiBranchPipelineStep'; +import PreRequisitesStep from './PreRequisitesStep'; + +export interface JenkinsTutorialProps { + almBinding?: AlmBindingDefinition; + component: T.Component; + projectBinding: ProjectAlmBindingResponse; +} + +enum Steps { + PreRequisites = 0, + MultiBranchPipeline = 1, + BitbucketWebhook = 2, + Jenkinsfile = 3 +} + +export default function JenkinsTutorial(props: JenkinsTutorialProps) { + const { almBinding, component, projectBinding } = props; + const [step, setStep] = React.useState(Steps.PreRequisites); + + // Failsafe; should never happen. + if (!isProjectBitbucketBindingResponse(projectBinding)) { + return ( + {translate('onboarding.tutorial.with.jenkins.only_bitbucket')} + ); + } + + return ( + <> +
+

{translate('onboarding.tutorial.with.jenkins.title')}

+
+ + setStep(Steps.MultiBranchPipeline)} + onOpen={() => setStep(Steps.PreRequisites)} + open={step === Steps.PreRequisites} + /> + + Steps.MultiBranchPipeline} + onDone={() => setStep(Steps.BitbucketWebhook)} + onOpen={() => setStep(Steps.MultiBranchPipeline)} + open={step === Steps.MultiBranchPipeline} + projectBinding={projectBinding} + /> + + Steps.BitbucketWebhook} + onDone={() => setStep(Steps.Jenkinsfile)} + onOpen={() => setStep(Steps.BitbucketWebhook)} + open={step === Steps.BitbucketWebhook} + projectBinding={projectBinding} + /> + + + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx new file mode 100644 index 00000000000..7873a2e9f51 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx @@ -0,0 +1,126 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; +import RenderOptions from '../components/RenderOptions'; +import SentenceWithHighlights from '../components/SentenceWithHighlights'; +import Step from '../components/Step'; +import Gradle from './buildtool-steps/Gradle'; +import Maven from './buildtool-steps/Maven'; +import MSBuild from './buildtool-steps/MSBuild'; +import Other from './buildtool-steps/Other'; + +export interface JenkinsfileStepProps { + component: T.Component; + open: boolean; +} + +export enum BuildTools { + Maven = 'maven', + Gradle = 'gradle', + MSBuild = 'msbuild', + Other = 'other' +} + +const BUILDTOOL_COMPONENT_MAP: { + [x in BuildTools]: React.ComponentType<{ component: T.Component }>; +} = { + [BuildTools.Maven]: Maven, + [BuildTools.Gradle]: Gradle, + [BuildTools.MSBuild]: MSBuild, + [BuildTools.Other]: Other +}; + +export default function JenkinsfileStep(props: JenkinsfileStepProps) { + const { component, open } = props; + const [buildTool, setBuildTool] = React.useState(undefined); + return ( + ( +
+
    +
  1. + {translate('onboarding.build')} + setBuildTool(value as BuildTools)} + optionLabelKey="onboarding.build" + options={Object.values(BuildTools)} + /> +
  2. + {buildTool !== undefined && + React.createElement(BUILDTOOL_COMPONENT_MAP[buildTool], { component })} +
+ {buildTool !== undefined && ( + <> +
+
+

+ +

+
+
+ +
+
+

+ {translate('onboarding.tutorial.with.jenkins.commit')} +

+

{translate('onboarding.tutorial.with.jenkins.commit.why')}

+
+
+
+
+ +
+
+

+ {translate('onboarding.tutorial.with.jenkins.refresh')} +

+

{translate('onboarding.tutorial.with.jenkins.refresh.why')}

+
+
+
+ + )} +
+ )} + stepNumber={3} + stepTitle={translate('onboarding.tutorial.with.jenkins.jenkinsfile.title')} + /> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/MultiBranchPipelineStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/MultiBranchPipelineStep.tsx new file mode 100644 index 00000000000..6deaaca4ac2 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/MultiBranchPipelineStep.tsx @@ -0,0 +1,113 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Button } from 'sonar-ui-common/components/controls/buttons'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { ProjectBitbucketBindingResponse } from '../../../types/alm-settings'; +import LabelActionPair from '../components/LabelActionPair'; +import LabelValuePair from '../components/LabelValuePair'; +import SentenceWithHighlights from '../components/SentenceWithHighlights'; +import Step from '../components/Step'; + +export interface MultiBranchPipelineStepProps { + finished: boolean; + onDone: () => void; + onOpen: () => void; + open: boolean; + projectBinding: ProjectBitbucketBindingResponse; +} + +export default function MultiBranchPipelineStep(props: MultiBranchPipelineStepProps) { + const { finished, open, projectBinding } = props; + return ( + ( +
+

+ {translate('onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro')} +

+
    +
  1. + +
  2. +
  3. + +
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    +
  4. +
  5. + +
      +
    • + +
    • +
    • + +
    • +
    +
  6. +
  7. + +
  8. +
+ +
+ )} + stepNumber={1} + stepTitle={translate('onboarding.tutorial.with.jenkins.multi_branch_pipeline.title')} + /> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx new file mode 100644 index 00000000000..5dbe039be20 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx @@ -0,0 +1,79 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { Link } from 'react-router'; +import { Button } from 'sonar-ui-common/components/controls/buttons'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import SentenceWithHighlights from '../components/SentenceWithHighlights'; +import Step from '../components/Step'; + +export interface PreRequisitesStepProps { + onDone: () => void; + onOpen: () => void; + open: boolean; +} + +export default function PreRequisitesStep(props: PreRequisitesStepProps) { + const { open } = props; + return ( + ( +
+

+ +

+
    +
  • {translate('onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source')}
  • +
  • {translate('onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner')}
  • +
+

+ + {translate('onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link')} + + ) + }} + /> +

+

+ {translate('onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations')} +

+ +
+ )} + stepTitle={translate('onboarding.tutorial.with.jenkins.prereqs.title')} + /> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/BitbucketWebhookStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/BitbucketWebhookStep-test.tsx new file mode 100644 index 00000000000..6b9ed13c361 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/BitbucketWebhookStep-test.tsx @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { + mockBitbucketBindingDefinition, + mockProjectBitbucketBindingGet +} from '../../../../helpers/mocks/alm-settings'; +import BitbucketWebhookStep, { BitbucketWebhookStepProps } from '../BitbucketWebhookStep'; +import { renderStepContent } from '../test-utils'; + +it('should render correctly', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot('Step wrapper'); + expect(renderStepContent(wrapper)).toMatchSnapshot('content'); + expect(renderStepContent(wrapper.setProps({ almBinding: undefined }))).toMatchSnapshot( + 'no alm binding' + ); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx new file mode 100644 index 00000000000..495218b8a49 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { + mockProjectAlmBindingResponse, + mockProjectBitbucketBindingGet +} from '../../../../helpers/mocks/alm-settings'; +import { mockComponent } from '../../../../helpers/testMocks'; +import BitbucketWebhookStep from '../BitbucketWebhookStep'; +import JenkinsfileStep from '../JenkinsfileStep'; +import JenkinsTutorial, { JenkinsTutorialProps } from '../JenkinsTutorial'; +import MultiBranchPipelineStep from '../MultiBranchPipelineStep'; +import PreRequisitesStep from '../PreRequisitesStep'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender({ projectBinding: mockProjectAlmBindingResponse() })).toMatchSnapshot( + 'not Bitbucket binding' + ); +}); + +it('should correctly navigate between steps', () => { + const wrapper = shallowRender(); + + expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(true); + expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(false); + expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(false); + expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(false); + + // Pre-reqs done. + wrapper.find(PreRequisitesStep).prop('onDone')(); + expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(false); + expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(true); + expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(false); + expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(false); + + // Multibranch done. + wrapper.find(MultiBranchPipelineStep).prop('onDone')(); + expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(false); + expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(false); + expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(true); + expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(false); + + // Webhook done. + wrapper.find(BitbucketWebhookStep).prop('onDone')(); + expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(false); + expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(false); + expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(false); + expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(true); + + // Open Pre-reqs. + wrapper.find(PreRequisitesStep).prop('onOpen')(); + expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(true); + + // Open Multibranch. + wrapper.find(MultiBranchPipelineStep).prop('onOpen')(); + expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(true); + + // Open Webhook. + wrapper.find(BitbucketWebhookStep).prop('onOpen')(); + expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(true); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx new file mode 100644 index 00000000000..d3dc2e7fbe1 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow, ShallowWrapper } from 'enzyme'; +import * as React from 'react'; +import { mockComponent } from '../../../../helpers/testMocks'; +import RenderOptions from '../../components/RenderOptions'; +import Step from '../../components/Step'; +import JenkinsfileStep, { BuildTools, JenkinsfileStepProps } from '../JenkinsfileStep'; +import { renderStepContent } from '../test-utils'; + +it('should render correctly', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot('Step wrapper'); + expect(renderStepContent(wrapper)).toMatchSnapshot('initial content'); +}); + +it('should render correctly for Maven', () => { + const wrapper = shallowRender(); + selectBuildTool(wrapper, BuildTools.Maven); + expect( + wrapper + .find(Step) + .props() + .renderForm() + ).toMatchSnapshot(); +}); + +it('should render correctly for Gradle', () => { + const wrapper = shallowRender(); + selectBuildTool(wrapper, BuildTools.Gradle); + expect(renderStepContent(wrapper)).toMatchSnapshot(); +}); + +it('should render correctly for MSBuild', () => { + const wrapper = shallowRender(); + selectBuildTool(wrapper, BuildTools.MSBuild); + expect(renderStepContent(wrapper)).toMatchSnapshot(); +}); + +it('should render correctly for Other', () => { + const wrapper = shallowRender(); + selectBuildTool(wrapper, BuildTools.Other); + expect(renderStepContent(wrapper)).toMatchSnapshot(); +}); + +function selectBuildTool(wrapper: ShallowWrapper, tool: BuildTools) { + const content = new ShallowWrapper(renderStepContent(wrapper) as JSX.Element); + content.find(RenderOptions).prop('onCheck')(tool); +} + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/MultiBranchPipelineStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/MultiBranchPipelineStep-test.tsx new file mode 100644 index 00000000000..85f5e7e7e15 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/MultiBranchPipelineStep-test.tsx @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockProjectBitbucketBindingGet } from '../../../../helpers/mocks/alm-settings'; +import MultiBranchPipelineStep, { MultiBranchPipelineStepProps } from '../MultiBranchPipelineStep'; +import { renderStepContent } from '../test-utils'; + +it('should render correctly', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot('Step wrapper'); + expect(renderStepContent(wrapper)).toMatchSnapshot('content'); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx new file mode 100644 index 00000000000..fcfcda72e88 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import PreRequisitesStep, { PreRequisitesStepProps } from '../PreRequisitesStep'; +import { renderStepContent } from '../test-utils'; + +it('should render correctly', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot('Step wrapper'); + expect(renderStepContent(wrapper)).toMatchSnapshot('content'); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/BitbucketWebhookStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/BitbucketWebhookStep-test.tsx.snap new file mode 100644 index 00000000000..c736b265b92 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/BitbucketWebhookStep-test.tsx.snap @@ -0,0 +1,228 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: Step wrapper 1`] = ` + +`; + +exports[`should render correctly: content 1`] = ` +
+

+ + onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link + , + } + } + /> +

+
    +
  1. + + onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link + , + } + } + /> +
      +
    • + +
    • +
    • +

      + +

      + + + onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning + +
    • +
    +
  2. +
  3. + +
      +
    • + +
    • +
    • + +
    • +
    +
  4. +
  5. + +
  6. +
+ +
+`; + +exports[`should render correctly: no alm binding 1`] = ` +
+

+ + onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link + , + } + } + /> +

+
    +
  1. + +
      +
    • + +
    • +
    • +

      + +

      + + + onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning + +
    • +
    +
  2. +
  3. + +
      +
    • + +
    • +
    • + +
    • +
    +
  4. +
  5. + +
  6. +
+ +
+`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap new file mode 100644 index 00000000000..7e1ac0e500c --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap @@ -0,0 +1,82 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: default 1`] = ` + +
+

+ onboarding.tutorial.with.jenkins.title +

+
+ + + + +
+`; + +exports[`should render correctly: not Bitbucket binding 1`] = ` + + onboarding.tutorial.with.jenkins.only_bitbucket + +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap new file mode 100644 index 00000000000..2ef32e08297 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap @@ -0,0 +1,526 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly for Gradle 1`] = ` +
+
    +
  1. + onboarding.build + +
  2. + +
+ +
+
+

+ +

+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.commit + +

+

+ onboarding.tutorial.with.jenkins.commit.why +

+
+
+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.refresh + +

+

+ onboarding.tutorial.with.jenkins.refresh.why +

+
+
+
+
+
+`; + +exports[`should render correctly for MSBuild 1`] = ` +
+
    +
  1. + onboarding.build + +
  2. + +
+ +
+
+

+ +

+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.commit + +

+

+ onboarding.tutorial.with.jenkins.commit.why +

+
+
+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.refresh + +

+

+ onboarding.tutorial.with.jenkins.refresh.why +

+
+
+
+
+
+`; + +exports[`should render correctly for Maven 1`] = ` +
+
    +
  1. + onboarding.build + +
  2. + +
+ +
+
+

+ +

+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.commit + +

+

+ onboarding.tutorial.with.jenkins.commit.why +

+
+
+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.refresh + +

+

+ onboarding.tutorial.with.jenkins.refresh.why +

+
+
+
+
+
+`; + +exports[`should render correctly for Other 1`] = ` +
+
    +
  1. + onboarding.build + +
  2. + +
+ +
+
+

+ +

+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.commit + +

+

+ onboarding.tutorial.with.jenkins.commit.why +

+
+
+
+
+ +
+
+

+ + onboarding.tutorial.with.jenkins.refresh + +

+

+ onboarding.tutorial.with.jenkins.refresh.why +

+
+
+
+
+
+`; + +exports[`should render correctly: Step wrapper 1`] = ` + +`; + +exports[`should render correctly: initial content 1`] = ` +
+
    +
  1. + onboarding.build + +
  2. +
+
+`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/MultiBranchPipelineStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/MultiBranchPipelineStep-test.tsx.snap new file mode 100644 index 00000000000..ba91752f0fc --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/MultiBranchPipelineStep-test.tsx.snap @@ -0,0 +1,119 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: Step wrapper 1`] = ` + +`; + +exports[`should render correctly: content 1`] = ` +
+

+ onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro +

+
    +
  1. + +
  2. +
  3. + +
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    +
  4. +
  5. + +
      +
    • + +
    • +
    • + +
    • +
    +
  6. +
  7. + +
  8. +
+ +
+`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap new file mode 100644 index 00000000000..01eb4afe997 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap @@ -0,0 +1,70 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: Step wrapper 1`] = ` + +`; + +exports[`should render correctly: content 1`] = ` +
+

+ +

+
    +
  • + onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source +
  • +
  • + onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner +
  • +
+

+ + onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link + , + } + } + /> +

+

+ onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations +

+ +
+`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx new file mode 100644 index 00000000000..0afb84c644a --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip'; +import { Alert } from 'sonar-ui-common/components/ui/Alert'; +import CodeSnippet from '../../../common/CodeSnippet'; +import SentenceWithFilename from '../../components/SentenceWithFilename'; +import SentenceWithHighlights from '../../components/SentenceWithHighlights'; + +export interface CreateJenkinsfileBulletPointProps { + snippet: string; + alertTranslationKeyPart?: string; +} + +export default function CreateJenkinsfileBulletPoint(props: CreateJenkinsfileBulletPointProps) { + const { snippet, alertTranslationKeyPart } = props; + + return ( +
  • + + {alertTranslationKeyPart !== undefined && ( + +

    + + +

    + +

    +

    + +

    + + } + /> +

    +
    + )} + +
  • + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx new file mode 100644 index 00000000000..acf803a44fe --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import * as React from 'react'; +import CodeSnippet from '../../../common/CodeSnippet'; +import SentenceWithFilename from '../../components/SentenceWithFilename'; +import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; + +export interface GradleProps { + component: T.Component; +} + +const buildGradleSnippet = (key: string) => `plugins { + id "org.sonarqube" version "2.7" +} + +sonarqube { + properties { + property "sonar.projectKey", "${key}" + } +}`; + +const JENKINSFILE_SNIPPET = `node { + stage('SCM') { + checkout scm + } + stage('SonarQube Analysis') { + withSonarQubeEnv() { + sh "./gradlew sonarqube" + } + } +}`; + +export default function Gradle({ component }: GradleProps) { + return ( + <> +
  • + + +
  • + + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/MSBuild.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/MSBuild.tsx new file mode 100644 index 00000000000..3200d3eb3f2 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/MSBuild.tsx @@ -0,0 +1,90 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip'; +import { Alert } from 'sonar-ui-common/components/ui/Alert'; +import CodeSnippet from '../../../common/CodeSnippet'; +import SentenceWithFilename from '../../components/SentenceWithFilename'; +import SentenceWithHighlights from '../../components/SentenceWithHighlights'; + +export interface MSBuildProps { + component: T.Component; +} + +const jenkinsfileSnippet = (key: string) => `node { + stage('SCM') { + checkout scm + } + stage('SonarQube Analysis') { + def msbuildHome = tool 'Default MSBuild' + def scannerHome = tool 'SonarScanner for MSBuild' + withSonarQubeEnv() { + bat "\\"\${scannerHome}\\\\SonarScanner.MSBuild.exe\\" begin /k:\\"${key}\\"" + bat "\\"\${msbuildHome}\\\\MSBuild.exe\\" /t:Rebuild" + bat "\\"\${scannerHome}\\\\SonarScanner.MSBuild.exe\\" end" + } + } +} +`; + +export default function MSBuild({ component }: MSBuildProps) { + return ( +
  • + + +

    + + +

    + +

    +

    + +

    +

    + +

    + + } + /> +

    +
    + +
  • + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx new file mode 100644 index 00000000000..98a018dc5a0 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx @@ -0,0 +1,62 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import * as React from 'react'; +import CodeSnippet from '../../../common/CodeSnippet'; +import SentenceWithFilename from '../../components/SentenceWithFilename'; +import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; + +export interface MavenProps { + component: T.Component; +} + +const pomSnippet = (key: string) => ` + ${key} +`; + +const JENKINSFILE_SNIPPET = `node { + stage('SCM') { + checkout scm + } + stage('SonarQube Analysis') { + def mvn = tool 'Default Maven'; + withSonarQubeEnv() { + sh "\${mvn}/bin/mvn sonar:sonar" + } + } +}`; + +export default function Maven({ component }: MavenProps) { + return ( + <> +
  • + + +
  • + + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx new file mode 100644 index 00000000000..aa4f20748f3 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx @@ -0,0 +1,60 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import * as React from 'react'; +import CodeSnippet from '../../../common/CodeSnippet'; +import SentenceWithFilename from '../../components/SentenceWithFilename'; +import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; + +export interface OtherProps { + component: T.Component; +} + +const sonarProjectSnippet = (key: string) => `sonar.projectKey=${key}`; + +const JENKINSFILE_SNIPPET = `node { + stage('SCM') { + checkout scm + } + stage('SonarQube Analysis') { + def scannerHome = tool 'SonarScanner'; + withSonarQubeEnv() { + sh "\${scannerHome}/bin/sonar-scanner" + } + } +}`; + +export default function Other({ component }: OtherProps) { + return ( + <> +
  • + + +
  • + + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CreateJenkinsfileBulletPoint-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CreateJenkinsfileBulletPoint-test.tsx new file mode 100644 index 00000000000..69fc5bae206 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CreateJenkinsfileBulletPoint-test.tsx @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import CreateJenkinsfileBulletPoint, { + CreateJenkinsfileBulletPointProps +} from '../CreateJenkinsfileBulletPoint'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender({ alertTranslationKeyPart: 'baz' })).toMatchSnapshot('with alert'); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx new file mode 100644 index 00000000000..5bc3adf1a49 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockComponent } from '../../../../../helpers/testMocks'; +import Gradle, { GradleProps } from '../Gradle'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/MSBuild-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/MSBuild-test.tsx new file mode 100644 index 00000000000..a391815e625 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/MSBuild-test.tsx @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockComponent } from '../../../../../helpers/testMocks'; +import MSBuild, { MSBuildProps } from '../MSBuild'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx new file mode 100644 index 00000000000..13632ee97b9 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockComponent } from '../../../../../helpers/testMocks'; +import Maven, { MavenProps } from '../Maven'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx new file mode 100644 index 00000000000..c9c5b30e297 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockComponent } from '../../../../../helpers/testMocks'; +import Other, { OtherProps } from '../Other'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap new file mode 100644 index 00000000000..b56d3e42589 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap @@ -0,0 +1,77 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: default 1`] = ` +
  • + + +
  • +`; + +exports[`should render correctly: with alert 1`] = ` +
  • + + +

    + + +

    + +

    +

    + +

    + + } + /> +

    +
    + +
  • +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Gradle-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Gradle-test.tsx.snap new file mode 100644 index 00000000000..db1fcec352e --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Gradle-test.tsx.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + +
  • + + +
  • + +
    +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/MSBuild-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/MSBuild-test.tsx.snap new file mode 100644 index 00000000000..822c34ce98e --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/MSBuild-test.tsx.snap @@ -0,0 +1,91 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` +
  • + + +

    + + +

    + +

    +

    + +

    +

    + +

    + + } + /> +

    +
    + +
  • +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Maven-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Maven-test.tsx.snap new file mode 100644 index 00000000000..a619e3b65a0 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Maven-test.tsx.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + +
  • + + +
  • + +
    +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Other-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Other-test.tsx.snap new file mode 100644 index 00000000000..c5a549388dd --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Other-test.tsx.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + +
  • + + +
  • + +
    +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/test-utils.ts b/server/sonar-web/src/main/js/components/tutorials/jenkins/test-utils.ts new file mode 100644 index 00000000000..572caf9b5d1 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/test-utils.ts @@ -0,0 +1,28 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { ShallowWrapper } from 'enzyme'; +import Step from '../components/Step'; + +export function renderStepContent(wrapper: ShallowWrapper) { + return wrapper + .find(Step) + .props() + .renderForm(); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/ManualTutorial.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/ManualTutorial.tsx index f1b4c1dcee3..1714244e00e 100644 --- a/server/sonar-web/src/main/js/components/tutorials/manual/ManualTutorial.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/manual/ManualTutorial.tsx @@ -18,8 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; -import BackIcon from 'sonar-ui-common/components/icons/BackIcon'; import { translate } from 'sonar-ui-common/helpers/l10n'; import { isVSTS } from '../../../helpers/almIntegrations'; import InstanceMessage from '../../common/InstanceMessage'; @@ -34,7 +32,6 @@ export enum Steps { interface Props { component: T.Component; currentUser: T.LoggedInUser; - onBack?: () => void; } interface State { @@ -61,19 +58,7 @@ export default class ManualTutorial extends React.PureComponent { return ( <>
    -

    - {this.props.onBack !== undefined && ( - - - - - - )} - {translate('onboarding.project_analysis.header')} -

    +

    {translate('onboarding.project_analysis.header')}

    diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/ManualTutorial-test.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/ManualTutorial-test.tsx index 79a269a35c4..188227b8db9 100644 --- a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/ManualTutorial-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/ManualTutorial-test.tsx @@ -26,7 +26,6 @@ import TokenStep from '../TokenStep'; it('renders correctly', () => { expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ onBack: jest.fn() })).toMatchSnapshot('with back button'); }); it('allows to navigate between steps', () => { diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/ManualTutorial-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/ManualTutorial-test.tsx.snap index cc1cf2fc27a..77e51dfb064 100644 --- a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/ManualTutorial-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/ManualTutorial-test.tsx.snap @@ -65,80 +65,3 @@ exports[`renders correctly: default 1`] = ` /> `; - -exports[`renders correctly: with back button 1`] = ` - -
    -

    - - - - - - onboarding.project_analysis.header -

    -

    - -

    -
    - - -
    -`; diff --git a/server/sonar-web/src/main/js/components/tutorials/styles.css b/server/sonar-web/src/main/js/components/tutorials/styles.css new file mode 100644 index 00000000000..295fb42fd23 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/styles.css @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +.tutorial-selection { + margin: 0 auto; + max-width: 500px; +} diff --git a/server/sonar-web/src/main/js/components/tutorials/types.ts b/server/sonar-web/src/main/js/components/tutorials/types.ts new file mode 100644 index 00000000000..2ad939070bc --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/types.ts @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +export enum TutorialModes { + Manual = 'manual', + Jenkins = 'jenkins' +} + +export interface LanguageConfig { + language?: string; + javaBuild?: string; + cFamilyCompiler?: string; + os?: string; + projectKey?: string; +} diff --git a/server/sonar-web/src/main/js/components/tutorials/utils.ts b/server/sonar-web/src/main/js/components/tutorials/utils.ts index a1a28edc712..89394ecb80b 100644 --- a/server/sonar-web/src/main/js/components/tutorials/utils.ts +++ b/server/sonar-web/src/main/js/components/tutorials/utils.ts @@ -17,13 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -export interface LanguageConfig { - language?: string; - javaBuild?: string; - cFamilyCompiler?: string; - os?: string; - projectKey?: string; -} +import { LanguageConfig } from './types'; export function isLanguageConfigured(config?: LanguageConfig) { if (!config) { diff --git a/server/sonar-web/src/main/js/helpers/__tests__/alm-settings.ts b/server/sonar-web/src/main/js/helpers/__tests__/alm-settings.ts new file mode 100644 index 00000000000..f6be96670fa --- /dev/null +++ b/server/sonar-web/src/main/js/helpers/__tests__/alm-settings.ts @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { isBitbucketBindingDefinition, isProjectBitbucketBindingResponse } from '../alm-settings'; +import { + mockBitbucketBindingDefinition, + mockGithubBindingDefinition, + mockProjectAlmBindingResponse, + mockProjectBitbucketBindingGet +} from '../mocks/alm-settings'; + +describe('isProjectBitbucketBindingResponse', () => { + it('works as expected', () => { + expect(isProjectBitbucketBindingResponse(mockProjectAlmBindingResponse())).toBe(false); + expect(isProjectBitbucketBindingResponse(mockProjectBitbucketBindingGet())).toBe(true); + }); +}); + +describe('isBitbucketBindingDefinition', () => { + it('works as expected', () => { + expect(isBitbucketBindingDefinition(mockGithubBindingDefinition())).toBe(false); + expect(isBitbucketBindingDefinition(mockBitbucketBindingDefinition())).toBe(true); + }); +}); diff --git a/server/sonar-web/src/main/js/helpers/alm-settings.ts b/server/sonar-web/src/main/js/helpers/alm-settings.ts new file mode 100644 index 00000000000..0bb508267ab --- /dev/null +++ b/server/sonar-web/src/main/js/helpers/alm-settings.ts @@ -0,0 +1,38 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { + AlmBindingDefinition, + AlmKeys, + BitbucketBindingDefinition, + ProjectAlmBindingResponse, + ProjectBitbucketBindingResponse +} from '../types/alm-settings'; + +export function isProjectBitbucketBindingResponse( + binding: ProjectAlmBindingResponse +): binding is ProjectBitbucketBindingResponse { + return binding.alm === AlmKeys.Bitbucket; +} + +export function isBitbucketBindingDefinition( + binding: AlmBindingDefinition & { url?: string; personalAccessToken?: string } +): binding is BitbucketBindingDefinition { + return binding.url !== undefined && binding.personalAccessToken !== undefined; +} diff --git a/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts b/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts index 2eab0248c9d..2a495addc9d 100644 --- a/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts +++ b/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts @@ -23,7 +23,9 @@ import { AzureBindingDefinition, BitbucketBindingDefinition, GithubBindingDefinition, - GitlabBindingDefinition + GitlabBindingDefinition, + ProjectAlmBindingResponse, + ProjectBitbucketBindingResponse } from '../../types/alm-settings'; export function mockAlmSettingsInstance( @@ -78,3 +80,25 @@ export function mockGitlabBindingDefinition( ...overrides }; } + +export function mockProjectAlmBindingResponse( + overrides: Partial = {} +): ProjectAlmBindingResponse { + return { + alm: AlmKeys.GitHub, + key: 'foo', + ...overrides + }; +} + +export function mockProjectBitbucketBindingGet( + overrides: Partial = {} +): ProjectBitbucketBindingResponse { + return { + alm: AlmKeys.Bitbucket, + key: 'foo', + repository: 'PROJECT_KEY', + slug: 'repo-slug', + ...overrides + }; +} diff --git a/server/sonar-web/src/main/js/types/alm-settings.ts b/server/sonar-web/src/main/js/types/alm-settings.ts index 1fbff623de2..534471f4741 100644 --- a/server/sonar-web/src/main/js/types/alm-settings.ts +++ b/server/sonar-web/src/main/js/types/alm-settings.ts @@ -56,6 +56,12 @@ export interface ProjectAlmBindingResponse { summaryCommentEnabled?: boolean; } +export interface ProjectBitbucketBindingResponse extends ProjectAlmBindingResponse { + alm: AlmKeys.Bitbucket; + repository: string; + slug: string; +} + export interface ProjectAlmBindingParams { almSetting: string; project: string; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index d111d22a497..d13c038a540 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3180,6 +3180,7 @@ onboarding.build=What is your build technology? onboarding.build.maven=Maven onboarding.build.gradle=Gradle onboarding.build.make=Make +onboarding.build.msbuild=MSBuild onboarding.build.other=Other (for JS, TS, Go, Python, PHP, ...) onboarding.language=What is your project's main language? @@ -3252,6 +3253,104 @@ onboarding.analysis.sqscanner.docs.gradle.example_project.title=live Gradle-base onboarding.tutorial.return_to_list=Choose another option +onboarding.tutorial.choose_method=How do you want to analyze your repository? +onboarding.tutorial.choose_method.manual=Manually +onboarding.tutorial.choose_method.jenkins=With Jenkins + +onboarding.tutorial.with.jenkins.title=Analyze your project with Jenkins +onboarding.tutorial.with.jenkins.only_bitbucket=This tutorial is only available for projects bound to Bitbucket Server. +onboarding.tutorial.with.jenkins.prereqs.title=Prerequisites +onboarding.tutorial.with.jenkins.prereqs.intro.sentence=To run your project analyses with Jenkins, the following plugins {must_have} +onboarding.tutorial.with.jenkins.prereqs.intro.sentence.must_have=must be installed and configured: +onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source=Bitbucket Branch Source plugin for Jenkins - version 2.7 or later +onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner=SonarQube Scanner plugin for Jenkins - version 2.11 or later +onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide=For a step by step guide on installing and configuring those plugins in Jenkins, visit the {link} documentation page. +onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link=Analysis Prerequisites +onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations=We recommend using the configuration in the following steps for the best results, but you can customize it as needed. +onboarding.tutorial.with.jenkins.prereqs.done=Configure Analysis +onboarding.tutorial.with.jenkins.multi_branch_pipeline.title=Create a Multibranch Pipeline Job +onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro=Create a Multibranch Pipeline in order to automatically analyze all your branches and pull requests. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence=From Jenkins' dashboard, click {new_item} and create a {type}. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence.new_item=New Item +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence.type=Multibranch Pipeline Job +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.sentence=Under {tab}, add a Bitbucket source and enter the following information: +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.sentence.tab=Branch Sources +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.server.label=Server +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.server.action=select the instance hosting the repository you want to analyze. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.creds.label=Credentials +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.creds.action=select the Bitbucket Server credentials. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.owner.label=Owner +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.owner.action=enter your project key. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.repo.label=Repository +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.repo.action=select the repository you want to analyze. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour.label=Behavior +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour.action=select Exclude branches that are also filed as PRs. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.sentence=Jump to the {tab} section and set the following parameters: +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.sentence.tab=Build Configuration +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.mode.label=Mode +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.mode.action=by Jenkinsfile +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path.label=Script Path +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path.action=Jenkinsfile +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4.sentence=Click {save}. +onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4.sentence.save=Save +onboarding.tutorial.with.jenkins.bitbucket_webhook.title=Create a Bitbucket Server Webhook +onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence=Create a Webhook in your repository to trigger the Jenkins job on push. Already have a Webhook configured? {link} +onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link=Skip this step. +onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence=Go to the {link} and enter the following information: +onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link=Bitbucket Server Webhook creation page for your repository +onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.name.label=Name +onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.name.action=give a unique name. +onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.label=URL +onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.action=Enter the following URL, replacing the tokens as needed: +onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning=The Bitbucket Server URL must be identical to the one in your Jenkins configuration. Watch out for any missing or extra "/" at the end. +onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.sentence=Under {events}, make sure the following options are checked: +onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.sentence.events=Events +onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.repo.label=Repository +onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.repo.action=Push +onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.pr.label=Pull Request +onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.pr.action=Opened +onboarding.tutorial.with.jenkins.bitbucket_webhook.step3.sentence=Click {create}. +onboarding.tutorial.with.jenkins.bitbucket_webhook.step3.sentence.create=Create +onboarding.tutorial.with.jenkins.jenkinsfile.title=Create a Jenkinsfile +onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step.sentence=Create a {file} file in your repository and paste the following code: +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step2.sentence=Add the following to your {file} file: +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.replace.sentence=Make sure to replace {default} with the name you gave to your Maven tool {in_jenkins}. +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.replace.sentence.default=Default Maven +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.replace.sentence.in_jenkins=in Jenkins +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help1.sentence=To get the name of your Maven tool in Jenkins, navigate to {path}. +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help1.sentence.path=Manage Jenkins > Global Tool Configuration +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help2.sentence=The name is located under the {path} section, in the {name} field. +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help2.sentence.path=Maven > Maven installations +onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help2.sentence.name=Name +onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2.sentence=Add the following to your {file} file: +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence=Make sure to replace {default_msbuild} and {default_scanner} with the names you gave to your MSBuild and SonarScanner for MSBuild tools {in_jenkins}. +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence.default_msbuild=Default MSBuild +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence.default_scanner=SonarScanner for MSBuild +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence.in_jenkins=in Jenkins +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help1.sentence=To get the name of these tools in Jenkins, navigate to {path}. +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help1.sentence.path=Manage Jenkins > Global Tool Configuration +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2.sentence=For your MSBuild tool, the name is located under the {path} section, in the {name} field. +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2.sentence.path=MSBuild > MSBuild installations +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2.sentence.name=Name +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3.sentence=For your SonarScanner for MSBuild tool, the name is located under the {path} section, in the {name} field. +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3.sentence.path=SonarScanner for MSBuild > SonarScanner for MSBuild installations +onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3.sentence.name=Name +onboarding.tutorial.with.jenkins.jenkinsfile.other.step2.sentence=Create a {file} file in your repository and paste the following code: +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence=Make sure to replace {default} with the name you gave to your SonarQube Scanner tool {in_jenkins}. +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence.default=SonarScanner +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence.in_jenkins=in Jenkins +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence=To get the name of your SonarQube Scanner tool in Jenkins, navigate to {path}. +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence.path=Manage Jenkins > Global Tool Configuration +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence=The name is located under the {path} section, in the {name} field. +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.path=SonarQube Scanner > SonarQube Scanner installations +onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.name=Name +onboarding.tutorial.with.jenkins.all_set.sentence={all_set} and ready to improve the quality and security of your code! +onboarding.tutorial.with.jenkins.all_set.sentence.all_set=You're all set +onboarding.tutorial.with.jenkins.commit=Commit and push your code to start the analysis. +onboarding.tutorial.with.jenkins.commit.why=Each new push you make on your branches or pull requests will trigger a new analysis in SonarQube. +onboarding.tutorial.with.jenkins.refresh=This page will then refresh with your analysis results. +onboarding.tutorial.with.jenkins.refresh.why=If the page doesn't refresh after a while, please double-check the analysis configuration. + #------------------------------------------------------------------------------ # # BRANCHES -- 2.39.5