Browse Source

Drop SonarCloud components from tutorials

tags/8.4.0.35506
Wouter Admiraal 4 years ago
parent
commit
a39da3564b
100 changed files with 37 additions and 7740 deletions
  1. 1
    2
      server/sonar-web/src/main/js/api/alm-integration.ts
  2. 16
    77
      server/sonar-web/src/main/js/app/components/StartupModal.tsx
  3. 3
    34
      server/sonar-web/src/main/js/app/components/__tests__/StartupModal-test.tsx
  4. 1
    2
      server/sonar-web/src/main/js/app/utils/startReactApp.tsx
  5. 0
    33
      server/sonar-web/src/main/js/apps/tutorials/ProjectOnboardingPage.tsx
  6. 0
    118
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSonarCloud.css
  7. 0
    364
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSonarCloud.tsx
  8. 0
    102
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSuggestion.tsx
  9. 0
    174
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/AnalyzeTutorialSonarCloud-test.tsx
  10. 0
    60
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/AnalyzeTutorialSuggestion-test.tsx
  11. 0
    294
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSonarCloud-test.tsx.snap
  12. 0
    80
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSuggestion-test.tsx.snap
  13. 0
    59
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/utils-test.tsx
  14. 0
    55
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/AutoScanAlert.tsx
  15. 0
    126
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithAutoScan.tsx
  16. 0
    54
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithLocalScanner.tsx
  17. 0
    54
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithOtherCI.tsx
  18. 0
    119
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithTravis.tsx
  19. 0
    30
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/AutoScanAlert-test.tsx
  20. 0
    41
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureOtherCI-test.tsx
  21. 0
    41
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureWithAutoScan-test.tsx
  22. 0
    41
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureWithLocalScanner-test.tsx
  23. 0
    71
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureWithTravis-test.tsx
  24. 0
    37
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/AutoScanAlert-test.tsx.snap
  25. 0
    53
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureOtherCI-test.tsx.snap
  26. 0
    40
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureWithAutoScan-test.tsx.snap
  27. 0
    53
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureWithLocalScanner-test.tsx.snap
  28. 0
    84
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureWithTravis-test.tsx.snap
  29. 0
    93
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/CreateSonarPropertiesStep.tsx
  30. 0
    235
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/EditTokenModal.tsx
  31. 0
    111
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/EditTravisYmlStep.tsx
  32. 0
    112
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/EncryptYourTokenStep.tsx
  33. 0
    39
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/CreateSonarPropertiesStep-test.tsx
  34. 0
    132
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/EditTokenModal-test.tsx
  35. 0
    49
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/EditTravisYmlStep-test.tsx
  36. 0
    43
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/EncryptYourTokenStep-test.tsx
  37. 0
    27
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/CreateSonarPropertiesStep-test.tsx.snap
  38. 0
    56
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/EditTokenModal-test.tsx.snap
  39. 0
    59
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/EditTravisYmlStep-test.tsx.snap
  40. 0
    13
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/EncryptYourTokenStep-test.tsx.snap
  41. 0
    118
      server/sonar-web/src/main/js/apps/tutorials/analyzeProject/utils.ts
  42. 0
    72
      server/sonar-web/src/main/js/apps/tutorials/components/AnalyzeTutorialDone.tsx
  43. 0
    39
      server/sonar-web/src/main/js/apps/tutorials/components/BuildSystemForm.tsx
  44. 5
    57
      server/sonar-web/src/main/js/apps/tutorials/components/LanguageForm.tsx
  45. 0
    150
      server/sonar-web/src/main/js/apps/tutorials/components/NewProjectForm.tsx
  46. 1
    1
      server/sonar-web/src/main/js/apps/tutorials/components/ProjectAnalysisStep.tsx
  47. 0
    148
      server/sonar-web/src/main/js/apps/tutorials/components/ProjectAnalysisStepFromBuildTool.tsx
  48. 0
    26
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/AnalyzeTutorialDone-test.tsx
  49. 0
    28
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/BuildSystemForm-test.tsx
  50. 10
    23
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/LanguageForm-test.tsx
  51. 0
    53
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/NewProjectForm-test.tsx
  52. 0
    69
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/ProjectAnalysisStepFromBuildTool-test.tsx
  53. 0
    64
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/AnalyzeTutorialDone-test.tsx.snap
  54. 0
    19
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/BuildSystemForm-test.tsx.snap
  55. 0
    54
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/LanguageForm-test.tsx.snap
  56. 0
    177
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/NewProjectForm-test.tsx.snap
  57. 0
    91
      server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/ProjectAnalysisStepFromBuildTool-test.tsx.snap
  58. 0
    41
      server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommand.tsx
  59. 0
    175
      server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommandCustom.tsx
  60. 0
    174
      server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommandOtherCI.tsx
  61. 0
    207
      server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommandTravis.tsx
  62. 0
    63
      server/sonar-web/src/main/js/apps/tutorials/components/commands/BuildWrapper.tsx
  63. 0
    89
      server/sonar-web/src/main/js/apps/tutorials/components/commands/ClangGCC.tsx
  64. 0
    132
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/ClangGCCCustom.tsx
  65. 0
    69
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/JavaGradleCustom.tsx
  66. 0
    130
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/JavaMavenCustom.tsx
  67. 0
    96
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/OtherCustom.tsx
  68. 0
    58
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/ClangGCCCustom-test.tsx
  69. 0
    67
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/JavaGradleCustom-test.tsx
  70. 0
    80
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/JavaMavenCustom-test.tsx
  71. 0
    43
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/OtherCustom-test.tsx
  72. 0
    85
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/ClangGCCCustom-test.tsx.snap
  73. 0
    68
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/JavaGradleCustom-test.tsx.snap
  74. 0
    83
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/JavaMavenCustom-test.tsx.snap
  75. 0
    54
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/OtherCustom-test.tsx.snap
  76. 0
    82
      server/sonar-web/src/main/js/apps/tutorials/components/commands/Msvc.tsx
  77. 0
    108
      server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/ClangGCCOtherCI.tsx
  78. 0
    110
      server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/OtherOtherCI.tsx
  79. 0
    39
      server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/ClangGCCOtherCI-test.tsx
  80. 0
    41
      server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/OtherOtherCI-test.tsx
  81. 0
    45
      server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/__snapshots__/ClangGCCOtherCI-test.tsx.snap
  82. 0
    67
      server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/__snapshots__/OtherOtherCI-test.tsx.snap
  83. 0
    57
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/ClangGCCTravisSonarCloud.tsx
  84. 0
    115
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/JavaGradleTravisSonarCloud.tsx
  85. 0
    78
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/JavaMavenTravisSonarCloud.tsx
  86. 0
    43
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/OtherTravisSonarCloud.tsx
  87. 0
    37
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/ClangGCCTravisSonarCloud-test.tsx
  88. 0
    35
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/JavaGradleTravisSonarCloud-test.tsx
  89. 0
    35
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/JavaMavenTravisSonarCloud-test.tsx
  90. 0
    36
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/OtherTravisSonarCloud-test.tsx
  91. 0
    23
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/ClangGCCTravisSonarCloud-test.tsx.snap
  92. 0
    89
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/JavaGradleTravisSonarCloud-test.tsx.snap
  93. 0
    48
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/JavaMavenTravisSonarCloud-test.tsx.snap
  94. 0
    16
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/OtherTravisSonarCloud-test.tsx.snap
  95. 0
    72
      server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/utils.tsx
  96. 0
    22
      server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommand-test.tsx
  97. 0
    131
      server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommandCustom-test.tsx
  98. 0
    118
      server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommandOtherCI-test.tsx
  99. 0
    123
      server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommandTravis-test.tsx
  100. 0
    0
      server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/BuildWrapper-test.tsx

+ 1
- 2
server/sonar-web/src/main/js/api/alm-integration.ts View File

@@ -25,7 +25,6 @@ import {
requestTryAndRepeatUntil
} from 'sonar-ui-common/helpers/request';
import throwGlobalError from '../app/utils/throwGlobalError';
import { AlmLanguagesStats } from '../apps/tutorials/analyzeProject/utils';

export function bindAlmOrganization(data: { installationId: string; organization: string }) {
return post('/api/alm_integration/bind_organization', data).catch(throwGlobalError);
@@ -83,7 +82,7 @@ export function provisionProject(data: {
}).catch(throwGlobalError);
}

export function getGithubLanguages(url: string): Promise<AlmLanguagesStats> {
export function getGithubLanguages(url: string): Promise<T.Dict<number>> {
// We don't want to throwGlobalError
const apiUrl = url.replace('https://github.com/', 'https://api.github.com/repos/');
return getCorsJSON(`${apiUrl}/languages`);

+ 16
- 77
server/sonar-web/src/main/js/app/components/StartupModal.tsx View File

@@ -26,16 +26,11 @@ import { hasMessage } from 'sonar-ui-common/helpers/l10n';
import { get, save } from 'sonar-ui-common/helpers/storage';
import { showLicense } from '../../api/marketplace';
import { Location, Router, withRouter } from '../../components/hoc/withRouter';
import { isSonarCloud } from '../../helpers/system';
import { isLoggedIn } from '../../helpers/users';
import { getAppState, getCurrentUser, Store } from '../../store/rootReducer';
import { skipOnboarding } from '../../store/users';
import { EditionKey } from '../../types/editions';
import { OnboardingContext } from './OnboardingContext';

const OnboardingModal = lazyLoadComponent(() =>
import('../../apps/tutorials/onboarding/OnboardingModal')
);
const LicensePromptModal = lazyLoadComponent(
() => import('../../apps/marketplace/components/LicensePromptModal'),
'LicensePromptModal'
@@ -62,13 +57,8 @@ interface WithRouterProps {

type Props = StateProps & DispatchProps & OwnProps & WithRouterProps;

export enum ModalKey {
license,
onboarding
}

interface State {
modal?: ModalKey;
open?: boolean;
}

const LICENSE_PROMPT = 'sonarqube.license.prompt';
@@ -77,92 +67,41 @@ export class StartupModal extends React.PureComponent<Props, State> {
state: State = {};

componentDidMount() {
this.tryAutoOpenLicense().catch(this.tryAutoOpenOnboarding);
this.tryAutoOpenLicense();
}

closeOnboarding = () => {
this.setState(state => {
if (state.modal !== ModalKey.license) {
this.props.skipOnboarding();
return { modal: undefined };
}
return null;
});
};

closeLicense = () => {
this.setState(state => {
if (state.modal === ModalKey.license) {
return { modal: undefined };
}
return null;
});
};

openOnboarding = () => {
this.setState({ modal: ModalKey.onboarding });
};

openProjectOnboarding = (organization?: T.Organization) => {
this.setState({ modal: undefined });
const state: { organization?: string; tab?: string } = {};
if (organization) {
state.organization = organization.key;
state.tab = organization.alm ? 'auto' : 'manual';
}
this.props.router.push({ pathname: `/projects/create`, state });
this.setState({ open: false });
};

tryAutoOpenLicense = () => {
const { canAdmin, currentEdition, currentUser } = this.props;
const hasLicenseManager = hasMessage('license.prompt.title');
const hasLicensedEdition = currentEdition && currentEdition !== 'community';
const hasLicensedEdition = currentEdition && currentEdition !== EditionKey.community;

if (canAdmin && hasLicensedEdition && isLoggedIn(currentUser) && hasLicenseManager) {
const lastPrompt = get(LICENSE_PROMPT, currentUser.login);

if (!lastPrompt || differenceInDays(new Date(), parseDate(lastPrompt)) >= 1) {
return showLicense().then(license => {
if (!license || !license.isValidEdition) {
save(LICENSE_PROMPT, toShortNotSoISOString(new Date()), currentUser.login);
this.setState({ modal: ModalKey.license });
}
return Promise.reject();
});
showLicense()
.then(license => {
if (!license || !license.isValidEdition) {
save(LICENSE_PROMPT, toShortNotSoISOString(new Date()), currentUser.login);
this.setState({ open: true });
}
})
.catch(() => {});
}
}
return Promise.reject();
};

tryAutoOpenOnboarding = () => {
if (
isSonarCloud() &&
this.props.currentUser.showOnboardingTutorial &&
![
'/about',
'/documentation',
'/onboarding',
'/projects/create',
'/create-organization'
].some(path => this.props.location.pathname.startsWith(path))
) {
this.openOnboarding();
}
};

render() {
const { modal } = this.state;
const { open } = this.state;
return (
<OnboardingContext.Provider value={this.openProjectOnboarding}>
<>
{this.props.children}
{modal === ModalKey.license && <LicensePromptModal onClose={this.closeLicense} />}
{modal === ModalKey.onboarding && (
<OnboardingModal
onClose={this.closeOnboarding}
onOpenProjectOnboarding={this.openProjectOnboarding}
/>
)}
</OnboardingContext.Provider>
{open && <LicensePromptModal onClose={this.closeLicense} />}
</>
);
}
}

+ 3
- 34
server/sonar-web/src/main/js/app/components/__tests__/StartupModal-test.tsx View File

@@ -25,9 +25,8 @@ import { hasMessage } from 'sonar-ui-common/helpers/l10n';
import { get, save } from 'sonar-ui-common/helpers/storage';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { showLicense } from '../../../api/marketplace';
import { mockOrganization, mockRouter } from '../../../helpers/testMocks';
import { EditionKey } from '../../../types/editions';
import { ModalKey, StartupModal } from '../StartupModal';
import { StartupModal } from '../StartupModal';

jest.mock('../../../api/marketplace', () => ({
showLicense: jest.fn().mockResolvedValue(undefined)
@@ -87,7 +86,7 @@ it('should render only the children', async () => {
await shouldNotHaveModals(
getWrapper({
canAdmin: false,
currentUser: { ...LOGGED_IN_USER, showOnboardingTutorial: true },
currentUser: { ...LOGGED_IN_USER },
location: { pathname: '/documentation/' }
})
);
@@ -95,7 +94,7 @@ it('should render only the children', async () => {
await shouldNotHaveModals(
getWrapper({
canAdmin: false,
currentUser: { ...LOGGED_IN_USER, showOnboardingTutorial: true },
currentUser: { ...LOGGED_IN_USER },
location: { pathname: '/create-organization' }
})
);
@@ -113,36 +112,6 @@ it('should render license prompt', async () => {
await shouldDisplayLicense(getWrapper());
});

describe('closeOnboarding', () => {
it('should set state and skip onboarding', () => {
const skipOnboarding = jest.fn();
const wrapper = getWrapper({ skipOnboarding });

wrapper.setState({ modal: ModalKey.onboarding });
wrapper.instance().closeOnboarding();

expect(wrapper.state('modal')).toBeUndefined();

expect(skipOnboarding).toHaveBeenCalledTimes(1);
});
});

describe('openProjectOnboarding', () => {
it('should set state and redirect', () => {
const push = jest.fn();
const wrapper = getWrapper({ router: mockRouter({ push }) });

wrapper.instance().openProjectOnboarding(mockOrganization());

expect(wrapper.state('modal')).toBeUndefined();

expect(push).toHaveBeenCalledWith({
pathname: `/projects/create`,
state: { organization: 'foo', tab: 'manual' }
});
});
});

async function shouldNotHaveModals(wrapper: ShallowWrapper) {
await waitAndUpdate(wrapper);
expect(wrapper.find('LicensePromptModal').exists()).toBe(false);

+ 1
- 2
server/sonar-web/src/main/js/app/utils/startReactApp.tsx View File

@@ -62,7 +62,6 @@ import qualityProfilesRoutes from '../../apps/quality-profiles/routes';
import sessionsRoutes from '../../apps/sessions/routes';
import settingsRoutes from '../../apps/settings/routes';
import systemRoutes from '../../apps/system/routes';
import onboardingRoutes from '../../apps/tutorials/routes';
import usersRoutes from '../../apps/users/routes';
import webAPIRoutes from '../../apps/web-api/routes';
import webhooksRoutes from '../../apps/webhooks/routes';
@@ -143,6 +142,7 @@ function renderRedirects() {
<Redirect from="/system/index" to="/admin/system" />
<Redirect from="/view" to="/portfolio" />
<Redirect from="/users" to="/admin/users" />
<Redirect from="/onboarding" to="/projects/create" />
</>
);
}
@@ -301,7 +301,6 @@ export default function startReactApp(
)}
/>
<Route path="issues" component={Issues} />
<RouteWithChildRoutes path="onboarding" childRoutes={onboardingRoutes} />
<RouteWithChildRoutes path="organizations" childRoutes={organizationsRoutes} />
<RouteWithChildRoutes path="projects" childRoutes={projectsRoutes} />
<RouteWithChildRoutes path="quality_gates" childRoutes={qualityGatesRoutes} />

+ 0
- 33
server/sonar-web/src/main/js/apps/tutorials/ProjectOnboardingPage.tsx View File

@@ -1,33 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { withRouter, WithRouterProps } from 'react-router';

export class ProjectOnboardingPage extends React.PureComponent<WithRouterProps> {
componentDidMount() {
this.props.router.replace('/projects/create');
}

render() {
return null;
}
}

export default withRouter(ProjectOnboardingPage);

+ 0
- 118
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSonarCloud.css View File

@@ -1,118 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
.page-analysis {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0 auto;
}

.page-analysis .page-header {
text-align: center;
}

.page-analysis h1 {
font-weight: bold;
}

.page-analysis-container-sonarcloud .onboarding-step {
padding: 0 calc(var(--gridSize) * 4);
}

.analysis-selector {
display: flex;
flex-direction: column;
justify-content: space-around;
}

.analysis-modes {
display: flex;
justify-content: space-around;
width: 80%;
}

.mode-type {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.mode-type .icon {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
background-repeat: no-repeat;
background-position: center;
}

.mode-type .name {
font-weight: bold;
}

.mode-type-autoscan {
padding: calc(var(--gridSize) * 6) calc(var(--gridSize) * 10);
background: white;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3);
}

.mode-type-autoscan .icon {
background-image: url(/images/sonarcloud-square-logo.svg);
}

.mode-type-autoscan .icon .badge {
position: absolute;
top: 12px;
right: 0;
}

.mode-type-travis .icon {
background-image: url(/images/sonarcloud/analysis/helmet.svg);
}

.mode-type-other .icon {
background-image: url(/images/sonarcloud/analysis/galaxy.svg);
}

.mode-type-manual .icon {
background-image: url(/images/sonarcloud/analysis/manual.svg);
}

.step-selector {
display: flex;
}

.page-analysis-waiting {
text-align: center;
}

.page-analysis-waiting .links {
padding: calc(var(--gridSize) * 6) calc(var(--gridSize) * 10);
background: white;
}

.onboarding-step hr.no-horizontal-margins {
margin-left: 0;
margin-right: 0;
}

+ 0
- 364
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSonarCloud.tsx View File

@@ -1,364 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as classnames from 'classnames';
import * as React from 'react';
import BackButton from 'sonar-ui-common/components/controls/BackButton';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { get, remove, save } from 'sonar-ui-common/helpers/storage';
import { getGithubLanguages } from '../../../api/alm-integration';
import { generateToken, getTokens } from '../../../api/user-tokens';
import InstanceMessage from '../../../components/common/InstanceMessage';
import { isBitbucket, isGithub, isVSTS } from '../../../helpers/almIntegrations';
import { isSonarCloud } from '../../../helpers/system';
import AnalyzeTutorialDone from '../components/AnalyzeTutorialDone';
import ProjectAnalysisStep from '../components/ProjectAnalysisStep';
import TokenStep from '../components/TokenStep';
import '../styles.css';
import { getUniqueTokenName } from '../utils';
import './AnalyzeTutorialSonarCloud.css';
import { TutorialSuggestionBitbucket, TutorialSuggestionVSTS } from './AnalyzeTutorialSuggestion';
import ConfigureWithAutoScan from './configurations/ConfigureWithAutoScan';
import ConfigureWithLocalScanner from './configurations/ConfigureWithLocalScanner';
import ConfigureOtherCI from './configurations/ConfigureWithOtherCI';
import ConfigureWithTravis from './configurations/ConfigureWithTravis';
import {
Alm,
AlmLanguagesStats,
alms,
ALM_KEYS,
AnalysisMode,
autoScanMode,
isAutoScannable,
modes,
PROJECT_ONBOARDING_DONE,
PROJECT_ONBOARDING_MODE_ID,
PROJECT_STEP_PROGRESS,
TutorialProps
} from './utils';

interface Props {
component: T.Component;
currentUser: T.LoggedInUser;
}

const tutorials: {
[k: string]: (props: Props & TutorialProps) => JSX.Element;
} = {
autoscan: ConfigureWithAutoScan,
manual: ConfigureWithLocalScanner,
other: ConfigureOtherCI,
travis: ConfigureWithTravis
};

enum Steps {
ANALYSIS = 'ANALYSIS',
TOKEN = 'TOKEN'
}

interface State {
alm?: Alm;
almLanguageStats?: AlmLanguagesStats;
isTutorialDone: boolean;
mode?: AnalysisMode;
loading: boolean;
step: Steps;
token?: string;
}

export default class AnalyzeTutorialSonarCloud extends React.PureComponent<Props, State> {
mounted = false;

constructor(props: Props) {
super(props);
this.state = {
loading: true,
isTutorialDone: get(PROJECT_ONBOARDING_DONE, props.component.key) === 'true',
step: Steps.TOKEN
};
}

componentDidMount() {
this.mounted = true;
const { component, currentUser } = this.props;

const almKey = (component.alm && component.alm.key) || currentUser.externalProvider;

if (!almKey) {
return;
}

if (isBitbucket(almKey)) {
this.configureBitbucket();
} else if (isGithub(almKey)) {
this.configureGithub();
} else if (isVSTS(almKey)) {
this.configureMicrosoft();
}

if (currentUser) {
getTokens(currentUser.login).then(
t => {
this.getNewToken(getUniqueTokenName(t, `Analyze "${component.name}"`));
},
() => {}
);
}
}

componentWillUnmount() {
this.mounted = false;
}

stopLoading = () => {
this.setState({ loading: false });
};

configureBitbucket = () => {
this.setState({ alm: alms[ALM_KEYS.BITBUCKET], loading: false });
};

configureGithub = () => {
const { component } = this.props;

this.setState({
alm: alms[ALM_KEYS.GITHUB]
});

const savedModeId = get(PROJECT_ONBOARDING_MODE_ID, component.key);
const mode =
autoScanMode.id === savedModeId ? autoScanMode : modes.find(m => m.id === savedModeId);
if (mode) {
this.setState({ mode });
}

if (!component.alm) {
this.stopLoading();
return;
}

const { url } = component.alm;

if (!url) {
return;
}

getGithubLanguages(url).then(almLanguagesStats => {
if (this.mounted) {
this.setState({
almLanguageStats: almLanguagesStats,
loading: false
});
}
}, this.stopLoading);
};

configureMicrosoft = () => {
this.setState({ alm: alms[ALM_KEYS.MICROSOFT], loading: false });
};

getNewToken = (tokenName: string) => {
generateToken({ name: tokenName }).then(
({ token }: { token: string }) => {
this.setToken(token);
},
() => {}
);
};

setToken = (token: string) => {
if (this.mounted) {
this.setState({ token });
}
};

setTutorialDone = (value: boolean) => {
save(PROJECT_ONBOARDING_DONE, String(value), this.props.component.key);
this.setState({ isTutorialDone: value });
};

spinner = () => (
<div className="display-flex-justify-center spacer">
<i className="spinner global-loading-spinner" />
</div>
);

renderBitbucket = () => {
const { component, currentUser } = this.props;
const { step, token } = this.state;

const handleTokenDone = (t: string) => {
if (this.mounted) {
this.setState({
step: Steps.ANALYSIS,
token: t
});
}
};

const handleTokenOpen = () => {
this.setState({ step: Steps.TOKEN });
};

return (
<>
<TutorialSuggestionBitbucket />

<TokenStep
currentUser={currentUser}
finished={Boolean(token)}
initialTokenName={`Analyze "${component.name}"`}
onContinue={handleTokenDone}
onOpen={handleTokenOpen}
open={step === Steps.TOKEN}
stepNumber={1}
/>

<ProjectAnalysisStep
component={component}
displayRowLayout={true}
open={step === Steps.ANALYSIS}
organization={isSonarCloud() ? component.organization : undefined}
stepNumber={2}
token={token}
/>
</>
);
};

renderGithub = () => {
const { almLanguageStats, isTutorialDone, mode, token } = this.state;

if (isTutorialDone) {
return <AnalyzeTutorialDone setTutorialDone={this.setTutorialDone} />;
}

const { component, currentUser } = this.props;
const Tutorial = mode && tutorials[mode.id];

const getClassnames = (item: AnalysisMode) =>
classnames(`mode-type mode-type-${item.id}`, {
[`mode-type-selected`]: mode && mode.id === item.id
});

const isAutoScanEnabled =
almLanguageStats && isAutoScannable(almLanguageStats).withAllowedLanguages;

const setMode = (mode: AnalysisMode | undefined) => {
if (mode) {
save(PROJECT_ONBOARDING_MODE_ID, mode.id, component.key);
remove(PROJECT_STEP_PROGRESS, component.key);
} else {
remove(PROJECT_ONBOARDING_MODE_ID, component.key);
}

this.setState({ mode });
};

if (!mode || !Tutorial) {
return (
<div className="page-analysis-container page-analysis-container-sonarcloud">
<div className="page-analysis big-spacer-top big-spacer-bottom huge-spacer-left huge-spacer-right">
<div className="page-header big-spacer-bottom">
<h1 className="big-spacer-bottom">
{translate('onboarding.project_analysis.header')}
</h1>
<p>
<InstanceMessage message={translate('onboarding.project_analysis.description')} />
</p>
</div>

{isAutoScanEnabled && (
<div className={`${getClassnames(autoScanMode)} huge-spacer-top huge-spacer-bottom`}>
<div className="icon">
<div className="badge badge-info">BETA</div>
</div>
<p>{autoScanMode.name}</p>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={() => setMode(autoScanMode)}
type="button">
{translate('projects.configure_analysis')}
</button>
</div>
)}

<div className="analysis-modes">
{modes.map(el => (
<div className={getClassnames(el)} key={el.id}>
<div className="icon" />
<div className="name">{el.name}</div>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={() => setMode(el)}
type="button">
{translate('projects.configure_analysis')}
</button>
</div>
))}
</div>
</div>
</div>
);
}

return (
<div className="page-analysis-container page-analysis-container-sonarcloud">
<BackButton
onClick={() => setMode(undefined)}
tooltip={translate('onboarding.tutorial.return_to_list')}>
{translate('back')}
</BackButton>

<Tutorial
component={component}
currentUser={currentUser}
onDone={() => this.setTutorialDone(true)}
setToken={this.setToken}
token={token}
/>
</div>
);
};

renderMicrosoft = () => {
return <TutorialSuggestionVSTS />;
};

render() {
const { alm, loading } = this.state;

if (!alm) {
return null;
}

return (
<DeferredSpinner customSpinner={<this.spinner />} loading={loading}>
{!loading && (
<>
{alm.id === ALM_KEYS.BITBUCKET && this.renderBitbucket()}
{alm.id === ALM_KEYS.GITHUB && this.renderGithub()}
{alm.id === ALM_KEYS.MICROSOFT && this.renderMicrosoft()}
</>
)}
</DeferredSpinner>
);
}
}

+ 0
- 102
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/AnalyzeTutorialSuggestion.tsx View File

@@ -1,102 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { isBitbucket, isGithub, isVSTS } from '../../../helpers/almIntegrations';

export function TutorialSuggestionBitbucket() {
return (
<Alert className="big-spacer-bottom" variant="info">
<FormattedMessage
defaultMessage={translate('onboarding.project_analysis.suggestions.bitbucket')}
id="onboarding.project_analysis.suggestions.bitbucket"
values={{
link: (
<a
href={getBaseUrl() + '/documentation/integrations/bitbucketcloud/'}
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.project_analysis.guide_to_integrate_bitbucket_cloud')}
</a>
)
}}
/>
<p>{translate('onboarding.project_analysis.suggestions.bitbucket_extra')}</p>
</Alert>
);
}

export function TutorialSuggestionGithub() {
return (
<Alert className="big-spacer-bottom" variant="info">
<p>{translate('onboarding.project_analysis.commands_for_analysis')} </p>
<p>{translate('onboarding.project_analysis.suggestions.github')}</p>
<FormattedMessage
defaultMessage={translate('onboarding.project_analysis.simply_link')}
id="onboarding.project_analysis.simply_link"
values={{
link: (
<a
href="https://docs.travis-ci.com/user/sonarcloud/"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.project_analysis.guide_to_integrate_travis')}
</a>
)
}}
/>
</Alert>
);
}

export function TutorialSuggestionVSTS() {
return (
<Alert className="big-spacer-bottom" variant="info">
<FormattedMessage
defaultMessage={translate('onboarding.project_analysis.simply_link')}
id="onboarding.project_analysis.simply_link"
values={{
link: (
<a
href={getBaseUrl() + '/documentation/integrations/vsts/'}
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.project_analysis.guide_to_integrate_vsts')}
</a>
)
}}
/>
</Alert>
);
}

export default function AnalyzeTutorialSuggestion({ almKey }: { almKey?: string }) {
if (isBitbucket(almKey)) {
return <TutorialSuggestionBitbucket />;
} else if (isGithub(almKey)) {
return <TutorialSuggestionGithub />;
} else if (isVSTS(almKey)) {
return <TutorialSuggestionVSTS />;
}
return null;
}

+ 0
- 174
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/AnalyzeTutorialSonarCloud-test.tsx View File

@@ -1,174 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { get } from 'sonar-ui-common/helpers/storage';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { generateToken, getTokens } from '../../../../api/user-tokens';
import { mockComponent, mockLoggedInUser } from '../../../../helpers/testMocks';
import { getUniqueTokenName } from '../../utils';
import AnalyzeTutorialSonarCloud from '../AnalyzeTutorialSonarCloud';

jest.mock('sonar-ui-common/helpers/storage', () => ({
get: jest.fn(),
remove: jest.fn(),
save: jest.fn()
}));

jest.mock('../../../../api/alm-integration', () => ({
getGithubLanguages: jest.fn().mockResolvedValue({
JavaScript: 512636,
TypeScript: 425475,
HTML: 390075,
CSS: 14099,
Makefile: 536,
Dockerfile: 319
})
}));

jest.mock('../../../../api/user-tokens', () => ({
generateToken: jest.fn().mockResolvedValue({
name: 'baz',
createdAt: '2019-01-21T08:06:00+0100',
login: 'luke',
token: 'token_value'
}),
getTokens: jest.fn().mockResolvedValue([
{
name: 'foo',
createdAt: '2019-01-15T15:06:33+0100',
lastConnectionDate: '2019-01-18T15:06:33+0100'
},
{ name: 'bar', createdAt: '2019-01-18T15:06:33+0100' }
]),
revokeToken: jest.fn().mockResolvedValue(Promise.resolve())
}));

jest.mock('../../utils', () => ({
getUniqueTokenName: jest.fn().mockReturnValue('lightsaber-9000')
}));

const component = mockComponent();

beforeEach(() => {
jest.clearAllMocks();
});

const compGitHub = {
...component,
alm: { key: 'github', url: 'https://github.com/luke/lightsaber' }
};

it('shows a loading screen', () => {
const wrapper = shallowRender({ component: compGitHub });
expect(wrapper.find('DeferredSpinner').prop('loading') as boolean).toBe(true);
});

it('renders for GitHub', async () => {
const wrapper = shallowRender({ component: compGitHub });
await waitAndUpdate(wrapper);

expect(wrapper).toMatchSnapshot();

wrapper
.find('button')
.first()
.simulate('click');
expect(wrapper.state('mode')).toEqual({
id: 'autoscan',
name: 'SonarCloud Automatic Analysis'
});
});

it('renders for BitBucket', () => {
const comp = {
...component,
alm: { key: 'bitbucket', url: 'https://bitbucket.com/luke/lightsaber' }
};
const wrapper = shallowRender({ component: comp });

expect(wrapper).toMatchSnapshot();

(wrapper.find('TokenStep').prop('onContinue') as Function)('abc123');

expect(wrapper.state('token')).toBe('abc123');
expect(wrapper.state('step')).toBe('ANALYSIS');
});

it('renders for Azure', () => {
const comp = {
...component,
alm: { key: 'microsoft', url: 'https://azuredevops.com/luke/lightsaber' }
};
expect(shallowRender({ component: comp })).toMatchSnapshot();
});

it('renders for a manual project', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('renders the finished state', async () => {
(get as jest.Mock).mockReturnValue('true');

const comp = {
...component,
alm: { key: 'github', url: 'https://github.com/luke/lightsaber' }
};
const wrapper = shallowRender({ component: comp });
await waitAndUpdate(wrapper);
expect(wrapper.find('AnalyzeTutorialDone').exists()).toBe(true);
});

it('should get tokens and unique name', async () => {
const wrapper = shallowRender();
await waitAndUpdate(wrapper);

expect(getTokens).toHaveBeenCalled();
expect(getUniqueTokenName).toHaveBeenCalled();
expect(generateToken).toHaveBeenCalled();
expect(wrapper.state('token')).toBe('token_value');
});

it('should set tutorial done', () => {
const wrapper = shallowRender();
const instance = wrapper.instance();

instance.setTutorialDone(false);
expect(wrapper.state('isTutorialDone')).toBe(false);

instance.setTutorialDone(true);
expect(wrapper.state('isTutorialDone')).toBe(true);
});

it('should have a spinner', () => {
const wrapper = shallowRender();
const instance = wrapper.instance();
expect(instance.spinner()).toMatchSnapshot();
});

function shallowRender(props: Partial<AnalyzeTutorialSonarCloud['props']> = {}) {
return shallow<AnalyzeTutorialSonarCloud>(
<AnalyzeTutorialSonarCloud
component={component}
currentUser={mockLoggedInUser({ externalProvider: 'github' })}
{...props}
/>
);
}

+ 0
- 60
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/AnalyzeTutorialSuggestion-test.tsx View File

@@ -1,60 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import AnalyzeTutorialSuggestion, {
TutorialSuggestionBitbucket,
TutorialSuggestionGithub,
TutorialSuggestionVSTS
} from '../AnalyzeTutorialSuggestion';

it('should not render', () => {
expect(shallow(<AnalyzeTutorialSuggestion almKey={undefined} />).type()).toBeNull();
});

it('renders bitbucket suggestions correctly', () => {
expect(
shallow(<AnalyzeTutorialSuggestion almKey="bitbucket" />).find(TutorialSuggestionBitbucket)
).toHaveLength(1);
});

it('renders github suggestions correctly', () => {
expect(
shallow(<AnalyzeTutorialSuggestion almKey="github" />).find(TutorialSuggestionGithub)
).toHaveLength(1);
});

it('renders vsts suggestions correctly', () => {
expect(
shallow(<AnalyzeTutorialSuggestion almKey="microsoft" />).find(TutorialSuggestionVSTS)
).toHaveLength(1);
});

it('renders bitbucket tutorial correctly', () => {
expect(shallow(<TutorialSuggestionBitbucket />)).toMatchSnapshot();
});

it('renders github tutorial correctly', () => {
expect(shallow(<TutorialSuggestionGithub />)).toMatchSnapshot();
});

it('renders microsoft tutorial correctly', () => {
expect(shallow(<TutorialSuggestionVSTS />)).toMatchSnapshot();
});

+ 0
- 294
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSonarCloud-test.tsx.snap View File

@@ -1,294 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders for Azure 1`] = `
<DeferredSpinner
customSpinner={<Unknown />}
loading={false}
timeout={100}
>
<TutorialSuggestionVSTS />
</DeferredSpinner>
`;

exports[`renders for BitBucket 1`] = `
<DeferredSpinner
customSpinner={<Unknown />}
loading={false}
timeout={100}
>
<TutorialSuggestionBitbucket />
<TokenStep
currentUser={
Object {
"externalProvider": "github",
"groups": Array [],
"isLoggedIn": true,
"login": "luke",
"name": "Skywalker",
"scmAccounts": Array [],
}
}
finished={false}
initialTokenName="Analyze \\"MyProject\\""
onContinue={[Function]}
onOpen={[Function]}
open={true}
stepNumber={1}
/>
<ProjectAnalysisStep
component={
Object {
"alm": Object {
"key": "bitbucket",
"url": "https://bitbucket.com/luke/lightsaber",
},
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"organization": "foo",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
}
}
displayRowLayout={true}
open={false}
stepNumber={2}
/>
</DeferredSpinner>
`;

exports[`renders for GitHub 1`] = `
<DeferredSpinner
customSpinner={<Unknown />}
loading={false}
timeout={100}
>
<div
className="page-analysis-container page-analysis-container-sonarcloud"
>
<div
className="page-analysis big-spacer-top big-spacer-bottom huge-spacer-left huge-spacer-right"
>
<div
className="page-header big-spacer-bottom"
>
<h1
className="big-spacer-bottom"
>
onboarding.project_analysis.header
</h1>
<p>
<InstanceMessage
message="onboarding.project_analysis.description"
/>
</p>
</div>
<div
className="mode-type mode-type-autoscan huge-spacer-top huge-spacer-bottom"
>
<div
className="icon"
>
<div
className="badge badge-info"
>
BETA
</div>
</div>
<p>
SonarCloud Automatic Analysis
</p>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={[Function]}
type="button"
>
projects.configure_analysis
</button>
</div>
<div
className="analysis-modes"
>
<div
className="mode-type mode-type-travis"
key="travis"
>
<div
className="icon"
/>
<div
className="name"
>
With Travis CI
</div>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={[Function]}
type="button"
>
projects.configure_analysis
</button>
</div>
<div
className="mode-type mode-type-other"
key="other"
>
<div
className="icon"
/>
<div
className="name"
>
With other CI tools
</div>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={[Function]}
type="button"
>
projects.configure_analysis
</button>
</div>
<div
className="mode-type mode-type-manual"
key="manual"
>
<div
className="icon"
/>
<div
className="name"
>
Manually
</div>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={[Function]}
type="button"
>
projects.configure_analysis
</button>
</div>
</div>
</div>
</div>
</DeferredSpinner>
`;

exports[`renders for a manual project 1`] = `
<DeferredSpinner
customSpinner={<Unknown />}
loading={false}
timeout={100}
>
<div
className="page-analysis-container page-analysis-container-sonarcloud"
>
<div
className="page-analysis big-spacer-top big-spacer-bottom huge-spacer-left huge-spacer-right"
>
<div
className="page-header big-spacer-bottom"
>
<h1
className="big-spacer-bottom"
>
onboarding.project_analysis.header
</h1>
<p>
<InstanceMessage
message="onboarding.project_analysis.description"
/>
</p>
</div>
<div
className="analysis-modes"
>
<div
className="mode-type mode-type-travis"
key="travis"
>
<div
className="icon"
/>
<div
className="name"
>
With Travis CI
</div>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={[Function]}
type="button"
>
projects.configure_analysis
</button>
</div>
<div
className="mode-type mode-type-other"
key="other"
>
<div
className="icon"
/>
<div
className="name"
>
With other CI tools
</div>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={[Function]}
type="button"
>
projects.configure_analysis
</button>
</div>
<div
className="mode-type mode-type-manual"
key="manual"
>
<div
className="icon"
/>
<div
className="name"
>
Manually
</div>
<button
className="button big-spacer-top big-spacer-bottom"
onClick={[Function]}
type="button"
>
projects.configure_analysis
</button>
</div>
</div>
</div>
</div>
</DeferredSpinner>
`;

exports[`should have a spinner 1`] = `
<div
className="display-flex-justify-center spacer"
>
<i
className="spinner global-loading-spinner"
/>
</div>
`;

+ 0
- 80
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/__snapshots__/AnalyzeTutorialSuggestion-test.tsx.snap View File

@@ -1,80 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders bitbucket tutorial correctly 1`] = `
<Alert
className="big-spacer-bottom"
variant="info"
>
<FormattedMessage
defaultMessage="onboarding.project_analysis.suggestions.bitbucket"
id="onboarding.project_analysis.suggestions.bitbucket"
values={
Object {
"link": <a
href="/documentation/integrations/bitbucketcloud/"
rel="noopener noreferrer"
target="_blank"
>
onboarding.project_analysis.guide_to_integrate_bitbucket_cloud
</a>,
}
}
/>
<p>
onboarding.project_analysis.suggestions.bitbucket_extra
</p>
</Alert>
`;

exports[`renders github tutorial correctly 1`] = `
<Alert
className="big-spacer-bottom"
variant="info"
>
<p>
onboarding.project_analysis.commands_for_analysis
</p>
<p>
onboarding.project_analysis.suggestions.github
</p>
<FormattedMessage
defaultMessage="onboarding.project_analysis.simply_link"
id="onboarding.project_analysis.simply_link"
values={
Object {
"link": <a
href="https://docs.travis-ci.com/user/sonarcloud/"
rel="noopener noreferrer"
target="_blank"
>
onboarding.project_analysis.guide_to_integrate_travis
</a>,
}
}
/>
</Alert>
`;

exports[`renders microsoft tutorial correctly 1`] = `
<Alert
className="big-spacer-bottom"
variant="info"
>
<FormattedMessage
defaultMessage="onboarding.project_analysis.simply_link"
id="onboarding.project_analysis.simply_link"
values={
Object {
"link": <a
href="/documentation/integrations/vsts/"
rel="noopener noreferrer"
target="_blank"
>
onboarding.project_analysis.guide_to_integrate_vsts
</a>,
}
}
/>
</Alert>
`;

+ 0
- 59
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/__tests__/utils-test.tsx View File

@@ -1,59 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { isAutoScannable } from '../utils';

it('should work for supported languages', () => {
expect(
isAutoScannable({
JavaScript: 512636,
TypeScript: 425475,
HTML: 390075,
CSS: 14099,
Makefile: 536,
Dockerfile: 319
})
).toEqual({
withAllowedLanguages: true,
withNotAllowedLanguages: false
});
});

it('should work for non supported languages', () => {
expect(
isAutoScannable({
Java: 434
})
).toEqual({
withAllowedLanguages: false,
withNotAllowedLanguages: true
});
});

it('should work for mixed languages', () => {
expect(
isAutoScannable({
JavaScript: 512636,
Java: 434
})
).toEqual({
withAllowedLanguages: true,
withNotAllowedLanguages: true
});
});

+ 0
- 55
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/AutoScanAlert.tsx View File

@@ -1,55 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
import DocTooltip from '../../../../components/docs/DocTooltip';

export function AutoScanAlert() {
return (
<Alert className="big-spacer-top" variant="info">
<div>
<FormattedMessage
defaultMessage={translate('onboarding.analysis.with.autoscan.alert')}
id="onboarding.analysis.with.autoscan.alert"
values={{
caveats: (
<>
<strong>{translate('onboarding.analysis.with.autoscan.alert.caveats')}</strong>{' '}
<DocTooltip
doc={import(/* webpackMode: "eager" */ 'Docs/tooltips/autoscan/caveats.md')}
/>
</>
),
scopes: (
<>
<strong>{translate('onboarding.analysis.with.autoscan.alert.scopes')}</strong>{' '}
<DocTooltip
doc={import(/* webpackMode: "eager" */ 'Docs/tooltips/autoscan/limited-scope.md')}
/>
</>
)
}}
/>
</div>
</Alert>
);
}

+ 0
- 126
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithAutoScan.tsx View File

@@ -1,126 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Button, ResetButtonLink } from 'sonar-ui-common/components/controls/buttons';
import DropdownIcon from 'sonar-ui-common/components/icons/DropdownIcon';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import Step from '../../components/Step';
import { TutorialProps } from '../utils';
import { AutoScanAlert } from './AutoScanAlert';

export default function ConfigureWithAutoScan({ onDone }: TutorialProps) {
const [showCustomizationOptions, setCustomizationOptions] = React.useState<boolean>(false);

const command = `# Path to sources
#sonar.sources=.
#sonar.exclusions=
#sonar.inclusions=

# Path to tests
#sonar.tests=
#sonar.test.exclusions=
#sonar.test.inclusions=

# Source encoding
#sonar.sourceEncoding=UTF-8

# Exclusions for copy-paste detection
#sonar.cpd.exclusions=`;

const renderForm = () => (
<div className="boxed-group-inner">
<div className="flex-columns">
<div className="flex-column-full">
<p className="spacer-bottom">
Add this file in the base directory of your default branch or on a PR.
</p>
<p className="spacer-bottom">
You can push an empty <code>.sonarcloud.properties</code> file, this will work fine. In
this case, every file in the repository will be considered as a source file.
</p>

<ResetButtonLink onClick={() => setCustomizationOptions(!showCustomizationOptions)}>
{showCustomizationOptions ? 'Hide customization options' : 'Show customization options'}
<DropdownIcon className="little-spacer-left" turned={showCustomizationOptions} />
</ResetButtonLink>

<div hidden={!showCustomizationOptions}>
<p>
Here are the supported optional settings for the <code>.sonarcloud.properties</code>{' '}
file:
</p>

<CodeSnippet snippet={command} />

<p>
Please refer to the{' '}
<a
href="https://sieg.eu.ngrok.io/documentation/autoscan/"
rel="noopener noreferrer"
target="_blank">
documentation
</a>{' '}
for more details.
</p>
</div>
</div>
</div>
<div className="big-spacer-top">
<Button className="js-continue" onClick={onDone}>
{translate('onboarding.finish')}
</Button>
</div>
</div>
);

const renderResult = () => null;

return (
<>
<h1 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.autoscan.title')}
</h1>

<p className="spacer-bottom">{translate('onboarding.analysis.with.autoscan.text')}</p>

<AutoScanAlert />

<Step
finished={false}
onOpen={() => {}}
open={true}
renderForm={renderForm}
renderResult={renderResult}
stepNumber={1}
stepTitle={
<FormattedMessage
defaultMessage={translate('onboarding.analysis.with.autoscan.filename')}
id="onboarding.analysis.with.autoscan.filename"
values={{
filename: <code className="rule">.sonarcloud.properties</code>
}}
/>
}
/>
</>
);
}

+ 0
- 54
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithLocalScanner.tsx View File

@@ -1,54 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { translate } from 'sonar-ui-common/helpers/l10n';
import ProjectAnalysisStepFromBuildTool, {
ProjectAnalysisModes
} from '../../components/ProjectAnalysisStepFromBuildTool';
import { TutorialProps } from '../utils';

export default function ConfigureWithLocalScanner({
component,
currentUser,
onDone,
setToken,
token
}: TutorialProps) {
return (
<>
<h1 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.local.title')}
</h1>

<ProjectAnalysisStepFromBuildTool
component={component}
currentUser={currentUser}
displayRowLayout={true}
mode={ProjectAnalysisModes.Custom}
onDone={onDone}
open={true}
organization={component.organization}
setToken={setToken}
stepNumber={1}
token={token}
/>
</>
);
}

+ 0
- 54
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithOtherCI.tsx View File

@@ -1,54 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { translate } from 'sonar-ui-common/helpers/l10n';
import ProjectAnalysisStepFromBuildTool, {
ProjectAnalysisModes
} from '../../components/ProjectAnalysisStepFromBuildTool';
import { TutorialProps } from '../utils';

export default function ConfigureWithOtherCI({
component,
currentUser,
onDone,
setToken,
token
}: TutorialProps) {
return (
<>
<h1 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.yourci.title')}
</h1>

<ProjectAnalysisStepFromBuildTool
component={component}
currentUser={currentUser}
displayRowLayout={true}
mode={ProjectAnalysisModes.CI}
onDone={onDone}
open={true}
organization={component.organization}
setToken={setToken}
stepNumber={1}
token={token}
/>
</>
);
}

+ 0
- 119
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/ConfigureWithTravis.tsx View File

@@ -1,119 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { get, save } from 'sonar-ui-common/helpers/storage';
import { isSonarCloud } from '../../../../helpers/system';
import CreateSonarPropertiesStep from '../steps/CreateSonarPropertiesStep';
import EditTravisYmlStep from '../steps/EditTravisYmlStep';
import EncryptYourTokenStep from '../steps/EncryptYourTokenStep';
import { PROJECT_STEP_PROGRESS, TutorialProps } from '../utils';

enum Steps {
ENCRYPT_TOKEN = 1,
EDIT_TRAVIS_YML = 2,
CREATE_SONAR_PROPERTIES = 3
}

export default function ConfigureWithTravis({
component,
currentUser,
onDone,
setToken,
token
}: TutorialProps) {
const [build, setBuild] = React.useState<string | undefined>(undefined);
const [step, setStep] = React.useState<Steps>(Steps.ENCRYPT_TOKEN);
const [hasStepAfterTravisYml, setHasStepAfterTravilYml] = React.useState<boolean>(false);

React.useEffect(() => {
const value = get(PROJECT_STEP_PROGRESS, component.key);
if (value) {
try {
const data = JSON.parse(value);
setBuild(data.build);
setStep(data.step);
setHasStepAfterTravilYml(data.hasStepAfterTravisYml);
} catch (e) {
// Let's start from scratch
}
}
}, [component.key]);

const saveAndFinish = () => {
save(
PROJECT_STEP_PROGRESS,
JSON.stringify({
build,
hasStepAfterTravisYml,
step
}),
component.key
);

onDone();
};

return (
<>
<h1 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.travis.title')}
</h1>

<EncryptYourTokenStep
component={component}
currentUser={currentUser}
onContinue={() => setStep(Steps.EDIT_TRAVIS_YML)}
onOpen={() => setStep(Steps.ENCRYPT_TOKEN)}
open={step === Steps.ENCRYPT_TOKEN}
setToken={setToken}
stepNumber={1}
token={token}
/>

<EditTravisYmlStep
buildCallback={setBuild}
buildType={build}
component={component}
finished={step >= 2}
hasStepAfter={setHasStepAfterTravilYml}
onContinue={() =>
hasStepAfterTravisYml ? setStep(Steps.CREATE_SONAR_PROPERTIES) : saveAndFinish()
}
onOpen={() => setStep(Steps.EDIT_TRAVIS_YML)}
open={step === Steps.EDIT_TRAVIS_YML}
organization={isSonarCloud() ? component.organization : undefined}
stepNumber={2}
token={token}
/>

{hasStepAfterTravisYml && (
<CreateSonarPropertiesStep
component={component}
finished={step >= 3}
onContinue={saveAndFinish}
onOpen={() => setStep(Steps.CREATE_SONAR_PROPERTIES)}
open={step === Steps.CREATE_SONAR_PROPERTIES}
stepNumber={3}
/>
)}
</>
);
}

+ 0
- 30
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/AutoScanAlert-test.tsx View File

@@ -1,30 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { AutoScanAlert } from '../AutoScanAlert';

it('should renders correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender() {
return shallow(<AutoScanAlert />);
}

+ 0
- 41
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureOtherCI-test.tsx View File

@@ -1,41 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { TutorialProps } from '../../utils';
import ConfigureWithOtherCI from '../ConfigureWithOtherCI';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender(props: Partial<TutorialProps> = {}) {
return shallow(
<ConfigureWithOtherCI
component={mockComponent()}
currentUser={mockLoggedInUser()}
onDone={jest.fn()}
setToken={jest.fn()}
token="token123"
{...props}
/>
);
}

+ 0
- 41
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureWithAutoScan-test.tsx View File

@@ -1,41 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { TutorialProps } from '../../utils';
import ConfigureWithAutoScan from '../ConfigureWithAutoScan';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender(props: Partial<TutorialProps> = {}) {
return shallow(
<ConfigureWithAutoScan
component={mockComponent()}
currentUser={mockLoggedInUser()}
onDone={jest.fn()}
setToken={jest.fn()}
token="token123"
{...props}
/>
);
}

+ 0
- 41
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureWithLocalScanner-test.tsx View File

@@ -1,41 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { TutorialProps } from '../../utils';
import ConfigureWithLocalScanner from '../ConfigureWithLocalScanner';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender(props: Partial<TutorialProps> = {}) {
return shallow(
<ConfigureWithLocalScanner
component={mockComponent()}
currentUser={mockLoggedInUser()}
onDone={jest.fn()}
setToken={jest.fn()}
token="token123"
{...props}
/>
);
}

+ 0
- 71
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/ConfigureWithTravis-test.tsx View File

@@ -1,71 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { TutorialProps } from '../../utils';
import ConfigureWithTravis from '../ConfigureWithTravis';

jest.mock('sonar-ui-common/helpers/storage', () => ({
get: jest.fn().mockReturnValue(
JSON.stringify({
build: 'maven',
hasStepAfterTravisYml: true,
step: 3
})
),
save: jest.fn()
}));

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should react to EditTravisYmlStep onContinue', () => {
const wrapper = shallowRender();
expect(wrapper.find('EditTravisYmlStep').prop('open') as Boolean).toBe(false);

(wrapper.find('EncryptYourTokenStep').prop('onContinue') as Function)();

expect(wrapper.find('EditTravisYmlStep').prop('open') as Boolean).toBe(true);
});

it('should react to EditTravisYmlStep onOpen', () => {
const wrapper = shallowRender();
(wrapper.find('EncryptYourTokenStep').prop('onContinue') as Function)();
expect(wrapper.find('EncryptYourTokenStep').prop('open') as Boolean).toBe(false);

(wrapper.find('EncryptYourTokenStep').prop('onOpen') as Function)();

expect(wrapper.find('EncryptYourTokenStep').prop('open') as Boolean).toBe(true);
});

function shallowRender(props: Partial<TutorialProps> = {}) {
return shallow(
<ConfigureWithTravis
component={mockComponent()}
currentUser={mockLoggedInUser()}
onDone={jest.fn()}
setToken={jest.fn()}
token="token123"
{...props}
/>
);
}

+ 0
- 37
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/AutoScanAlert-test.tsx.snap View File

@@ -1,37 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should renders correctly 1`] = `
<Alert
className="big-spacer-top"
variant="info"
>
<div>
<FormattedMessage
defaultMessage="onboarding.analysis.with.autoscan.alert"
id="onboarding.analysis.with.autoscan.alert"
values={
Object {
"caveats": <React.Fragment>
<strong>
onboarding.analysis.with.autoscan.alert.caveats
</strong>
<DocTooltip
doc={Promise {}}
/>
</React.Fragment>,
"scopes": <React.Fragment>
<strong>
onboarding.analysis.with.autoscan.alert.scopes
</strong>
<DocTooltip
doc={Promise {}}
/>
</React.Fragment>,
}
}
/>
</div>
</Alert>
`;

+ 0
- 53
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureOtherCI-test.tsx.snap View File

@@ -1,53 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Fragment>
<h1
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.yourci.title
</h1>
<ProjectAnalysisStepFromBuildTool
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"organization": "foo",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
}
}
currentUser={
Object {
"groups": Array [],
"isLoggedIn": true,
"login": "luke",
"name": "Skywalker",
"scmAccounts": Array [],
}
}
displayRowLayout={true}
mode="CI"
onDone={[MockFunction]}
open={true}
organization="foo"
setToken={[MockFunction]}
stepNumber={1}
token="token123"
/>
</Fragment>
`;

+ 0
- 40
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureWithAutoScan-test.tsx.snap View File

@@ -1,40 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Fragment>
<h1
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.autoscan.title
</h1>
<p
className="spacer-bottom"
>
onboarding.analysis.with.autoscan.text
</p>
<AutoScanAlert />
<Step
finished={false}
onOpen={[Function]}
open={true}
renderForm={[Function]}
renderResult={[Function]}
stepNumber={1}
stepTitle={
<FormattedMessage
defaultMessage="onboarding.analysis.with.autoscan.filename"
id="onboarding.analysis.with.autoscan.filename"
values={
Object {
"filename": <code
className="rule"
>
.sonarcloud.properties
</code>,
}
}
/>
}
/>
</Fragment>
`;

+ 0
- 53
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureWithLocalScanner-test.tsx.snap View File

@@ -1,53 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Fragment>
<h1
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.local.title
</h1>
<ProjectAnalysisStepFromBuildTool
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"organization": "foo",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
}
}
currentUser={
Object {
"groups": Array [],
"isLoggedIn": true,
"login": "luke",
"name": "Skywalker",
"scmAccounts": Array [],
}
}
displayRowLayout={true}
mode="Custom"
onDone={[MockFunction]}
open={true}
organization="foo"
setToken={[MockFunction]}
stepNumber={1}
token="token123"
/>
</Fragment>
`;

+ 0
- 84
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/configurations/__tests__/__snapshots__/ConfigureWithTravis-test.tsx.snap View File

@@ -1,84 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Fragment>
<h1
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.travis.title
</h1>
<EncryptYourTokenStep
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"organization": "foo",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
}
}
currentUser={
Object {
"groups": Array [],
"isLoggedIn": true,
"login": "luke",
"name": "Skywalker",
"scmAccounts": Array [],
}
}
onContinue={[Function]}
onOpen={[Function]}
open={true}
setToken={[MockFunction]}
stepNumber={1}
token="token123"
/>
<EditTravisYmlStep
buildCallback={[Function]}
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"organization": "foo",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
}
}
finished={false}
hasStepAfter={[Function]}
onContinue={[Function]}
onOpen={[Function]}
open={false}
stepNumber={2}
token="token123"
/>
</Fragment>
`;

+ 0
- 93
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/CreateSonarPropertiesStep.tsx View File

@@ -1,93 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Button } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import Step from '../../components/Step';
import { StepProps } from '../../utils';

export default function CreateSonarPropertiesStep({
component,
finished,
onContinue,
onOpen,
open,
stepNumber
}: StepProps) {
const command = `sonar.projectKey=${component ? component.key : 'my:project'}
# this is the name and version displayed in the SonarCloud UI.
sonar.projectName=${component ? component.name : 'My project'}
sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Replace "\\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8`;

const renderForm = () => (
<div className="boxed-group-inner">
<div className="flex-columns">
<div className="flex-column-full">
<p>
<FormattedMessage
defaultMessage={translate('onboarding.analysis.with.travis.sonar.properties.text')}
id="onboarding.analysis.with.travis.sonar.properties.text"
values={{
code: <code>sonar-project.properties</code>
}}
/>
</p>
<CodeSnippet snippet={command} />
</div>
</div>
<div className="big-spacer-top">
<Button className="js-continue" onClick={onContinue}>
{translate('onboarding.finish')}
</Button>
</div>
</div>
);

const renderResult = () => null;

return (
<Step
finished={Boolean(finished)}
onOpen={onOpen}
open={open}
renderForm={renderForm}
renderResult={renderResult}
stepNumber={stepNumber}
stepTitle={
<FormattedMessage
defaultMessage={translate('onboarding.analysis.with.travis.sonar.properties.title')}
id="onboarding.analysis.with.travis.sonar.properties.title"
values={{
filename: <code className="rule">sonar-project.properties</code>
}}
/>
}
/>
);
}

+ 0
- 235
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/EditTokenModal.tsx View File

@@ -1,235 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
import { Button, DeleteButton } from 'sonar-ui-common/components/controls/buttons';
import ConfirmModal from 'sonar-ui-common/components/controls/ConfirmModal';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
import { generateToken, getTokens, revokeToken } from '../../../../api/user-tokens';
import { RenderOptions } from '../../components/RenderOptions';
import { getUniqueTokenName } from '../../utils';

export enum TokenMode {
use_existing_token = 'use_existing_token',
generate_token = 'generate_token'
}

interface State {
existingToken?: string;
mode: TokenMode;
token?: string;
tokenName: string;
}

interface Props {
component: T.Component;
currentUser: T.LoggedInUser;
onClose: VoidFunction;
onSave: (token: string) => void;
}

export default class EditTokenModal extends React.PureComponent<Props, State> {
mounted = false;
initialTokenName = '';
state = {
mode: TokenMode.use_existing_token,
existingToken: '',
token: '',
tokenName: ''
};

componentDidMount() {
this.mounted = true;
const { component } = this.props;
this.initialTokenName = `Analyze "${component.name}"`;
this.getTokensAndName();
}

componentWillUnmount() {
this.mounted = false;
}

getTokensAndName = () => {
const { currentUser } = this.props;

getTokens(currentUser.login).then(
t => {
if (this.mounted) {
this.setState({ tokenName: getUniqueTokenName(t, this.initialTokenName) });
}
},
() => {}
);
};

getNewToken = () => {
const { tokenName = this.initialTokenName } = this.state;

generateToken({ name: tokenName }).then(
({ token }: { token: string }) => {
if (this.mounted) {
this.setState({
token,
tokenName
});
}
},
() => {}
);
};

handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (this.mounted) {
this.setState({
tokenName: event.target.value
});
}
};

handleTokenRevoke = () => {
const { tokenName } = this.state;

if (tokenName) {
revokeToken({ name: tokenName }).then(
() => {
if (this.mounted) {
this.setState({
mode: TokenMode.use_existing_token,
token: '',
tokenName: ''
});
}
},
() => {}
);
}
};

setExistingToken = (event: React.ChangeEvent<HTMLInputElement>) => {
if (this.mounted) {
this.setState({
existingToken: event.target.value
});
}
};

setMode = (mode: TokenMode) => {
this.setState({ mode });
};

render() {
const { onClose, onSave } = this.props;
const { existingToken, mode, token, tokenName } = this.state;

const header = translate('onboarding.token.header');

const isConfirmEnabled =
(mode === TokenMode.generate_token && token) ||
(mode === TokenMode.use_existing_token && existingToken);

const onConfirm = () => {
if (mode === TokenMode.generate_token && token) {
onSave(token);
} else if (mode === TokenMode.use_existing_token && existingToken) {
onSave(existingToken);
}
};

return (
<ConfirmModal
confirmButtonText={translate('save')}
confirmDisable={!isConfirmEnabled}
header={header}
onClose={onClose}
onConfirm={onConfirm}>
<p className="spacer-bottom">
<FormattedMessage
defaultMessage={translate('onboarding.token.text')}
id="onboarding.token.text"
values={{
link: (
<Link target="_blank" to="/account/security">
{translate('onboarding.token.text.user_account')}
</Link>
)
}}
/>
</p>

{token ? (
<>
<span className="text-middle">
{tokenName}
{': '}
</span>
<strong className="spacer-right text-middle">{token}</strong>

<DeleteButton className="button-small text-middle" onClick={this.handleTokenRevoke} />

<Alert className="big-spacer-top" variant="warning">
{translateWithParameters('users.tokens.new_token_created', token)}
</Alert>
</>
) : (
<>
<RenderOptions
checked={mode}
name="token-mode"
onCheck={this.setMode}
optionLabelKey="onboarding.token"
options={[TokenMode.use_existing_token, TokenMode.generate_token]}
/>

<div className="big-spacer-top">
{mode === TokenMode.generate_token && (
<>
<input
className="input-super-large spacer-right text-middle"
onChange={this.handleChange}
placeholder={translate('onboarding.token.generate_token.placeholder')}
required={true}
type="text"
value={tokenName}
/>
<Button className="text-middle" disabled={!tokenName} onClick={this.getNewToken}>
{translate('onboarding.token.generate')}
</Button>
</>
)}

{mode === TokenMode.use_existing_token && (
<input
className="input-super-large spacer-right text-middle"
onChange={this.setExistingToken}
placeholder={translate('onboarding.token.use_existing_token.placeholder')}
required={true}
type="text"
value={existingToken}
/>
)}
</div>
</>
)}
</ConfirmModal>
);
}
}

+ 0
- 111
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/EditTravisYmlStep.tsx View File

@@ -1,111 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Button } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import BuildSystemForm from '../../components/BuildSystemForm';
import AnalysisCommandTravis from '../../components/commands/AnalysisCommandTravis';
import Step from '../../components/Step';
import { StepProps } from '../../utils';

interface BuildProps {
buildCallback: (build: string) => void;
buildType?: string;
}

export default function EditTravisYmlStep({
buildCallback,
buildType,
component,
finished,
hasStepAfter,
onContinue,
onOpen,
open,
organization,
stepNumber,
token
}: StepProps & BuildProps) {
const [build, setBuild] = React.useState<string | undefined>(buildType || undefined);

if (!build && buildType) {
setBuild(buildType);
}

const isJavaBuild = build && ['gradle', 'maven'].includes(build);

if (hasStepAfter && build) {
hasStepAfter(!isJavaBuild);
}

const chooseBuild = (build: string) => {
buildCallback(build);
setBuild(build);
};

const renderForm = () => (
<div className="boxed-group-inner">
<div className="flex-columns">
<div className="flex-column-full">
<BuildSystemForm build={build} setBuild={chooseBuild} />

{build && (
<AnalysisCommandTravis
buildType={build}
component={component}
organization={organization}
token={token}
/>
)}
</div>
</div>
<div className="big-spacer-top">
{build && (
<Button className="js-continue" onClick={onContinue}>
{translate(isJavaBuild ? 'onboarding.finish' : 'continue')}
</Button>
)}
</div>
</div>
);

const renderResult = () => null;

return (
<Step
finished={Boolean(finished)}
onOpen={onOpen}
open={open}
renderForm={renderForm}
renderResult={renderResult}
stepNumber={stepNumber}
stepTitle={
<FormattedMessage
defaultMessage={translate('onboarding.analysis.travis.sonarcloud')}
id="onboarding.analysis.travis.sonarcloud"
values={{
filename: <code className="rule">.travis.yml</code>
}}
/>
}
/>
);
}

+ 0
- 112
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/EncryptYourTokenStep.tsx View File

@@ -1,112 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { Button, EditButton } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import Step from '../../components/Step';
import EditTokenModal from './EditTokenModal';

export interface YourTokenProps {
component: T.Component;
currentUser: T.LoggedInUser;
hasStepAfter?: (hasStepAfter: boolean) => void;
onContinue: VoidFunction;
onOpen: VoidFunction;
open: boolean;
organization?: string;
setToken: (token: string) => void;
stepNumber: number;
token?: string;
}

export default function EncryptYourTokenStep({
component,
currentUser,
onContinue,
onOpen,
open,
setToken,
stepNumber,
token
}: YourTokenProps) {
const [showModal, toggleModal] = React.useState<boolean>(false);

const close = () => toggleModal(!showModal);

const save = (token: string) => {
setToken(token);
close();
};

const command = `travis encrypt ${token}`;
const renderCommand = () => (
<div className="spacer-bottom">
travis encrypt {token}
<EditButton className="edit-token spacer-left" onClick={() => toggleModal(true)} />
</div>
);

const renderForm = () => (
<div className="boxed-group-inner">
{showModal && (
<EditTokenModal
component={component}
currentUser={currentUser}
onClose={close}
onSave={save}
/>
)}

<div className="display-flex-space-between">
<div className="display-inline-block">
<a
href="https://docs.travis-ci.com/user/encryption-keys/#usage"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.with.travis.encrypt.docs.link.label')}
</a>
<br />
<CodeSnippet isOneLine={true} render={renderCommand} snippet={command} wrap={true} />
</div>
</div>

<div className="big-spacer-top">
<Button className="js-continue" onClick={onContinue}>
{translate('continue')}
</Button>
</div>
</div>
);

const renderResult = () => null;

return (
<Step
finished={true}
onOpen={onOpen}
open={open}
renderForm={renderForm}
renderResult={renderResult}
stepNumber={stepNumber}
stepTitle={translate('onboarding.analysis.with.travis.encrypt.title')}
/>
);
}

+ 0
- 39
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/CreateSonarPropertiesStep-test.tsx View File

@@ -1,39 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { StepProps } from '../../../utils';
import CreateSonarPropertiesStep from '../CreateSonarPropertiesStep';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender(props: Partial<StepProps> = {}) {
return shallow(
<CreateSonarPropertiesStep
onContinue={jest.fn()}
onOpen={jest.fn()}
open={true}
stepNumber={1}
{...props}
/>
);
}

+ 0
- 132
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/EditTokenModal-test.tsx View File

@@ -1,132 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { generateToken, getTokens, revokeToken } from '../../../../../api/user-tokens';
import { mockComponent, mockEvent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { getUniqueTokenName } from '../../../utils';
import EditTokenModal, { TokenMode } from '../EditTokenModal';

jest.mock('../../../../../api/user-tokens', () => ({
generateToken: jest.fn().mockResolvedValue({
name: 'baz',
createdAt: '2019-01-21T08:06:00+0100',
login: 'luke',
token: 'token_value'
}),
getTokens: jest.fn().mockResolvedValue([
{
name: 'foo',
createdAt: '2019-01-15T15:06:33+0100',
lastConnectionDate: '2019-01-18T15:06:33+0100'
},
{ name: 'bar', createdAt: '2019-01-18T15:06:33+0100' }
]),
revokeToken: jest.fn().mockResolvedValue(Promise.resolve())
}));

jest.mock('../../../utils', () => ({
getUniqueTokenName: jest.fn().mockReturnValue('lightsaber-9000')
}));

beforeEach(() => {
jest.clearAllMocks();
});

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should get tokens and unique name', async () => {
const wrapper = shallowRender();
const { getTokensAndName } = wrapper.instance();

getTokensAndName();
await waitAndUpdate(wrapper);

expect(getTokens).toHaveBeenCalled();
expect(getUniqueTokenName).toHaveBeenCalled();
expect(wrapper.state('tokenName')).toBe('lightsaber-9000');
});

it('should get a new token', async () => {
const wrapper = shallowRender();
const { getNewToken } = wrapper.instance();

getNewToken();
await waitAndUpdate(wrapper);

expect(generateToken).toHaveBeenCalled();
expect(wrapper.state('token')).toBe('token_value');
});

it('should handle token revocation', async () => {
const wrapper = shallowRender();
const { getTokensAndName, handleTokenRevoke } = wrapper.instance();

getTokensAndName();
await waitAndUpdate(wrapper);
handleTokenRevoke();
await waitAndUpdate(wrapper);

expect(revokeToken).toHaveBeenCalled();
expect(wrapper.state('token')).toBe('');
expect(wrapper.state('tokenName')).toBe('');
});

it('should handle change on user input', () => {
const wrapper = shallowRender();
const instance = wrapper.instance();

instance.handleChange(mockEvent({ target: { value: 'my-token' } }));
expect(wrapper.state('tokenName')).toBe('my-token');
});

it('should set existing token', () => {
const wrapper = shallowRender();
const instance = wrapper.instance();

instance.setExistingToken(mockEvent({ target: { value: 'my-token' } }));
expect(wrapper.state('existingToken')).toBe('my-token');
});

it('should set mode', () => {
const wrapper = shallowRender();
const instance = wrapper.instance();

instance.setMode(TokenMode.generate_token);
expect(wrapper.state('mode')).toBe(TokenMode.generate_token);
instance.setMode(TokenMode.use_existing_token);
expect(wrapper.state('mode')).toBe(TokenMode.use_existing_token);
});

it('should call onSave with the token', () => {});

function shallowRender() {
return shallow<EditTokenModal>(
<EditTokenModal
component={mockComponent()}
currentUser={mockLoggedInUser()}
onClose={jest.fn()}
onSave={jest.fn()}
/>
);
}

+ 0
- 49
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/EditTravisYmlStep-test.tsx View File

@@ -1,49 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { StepProps } from '../../../utils';
import EditTravisYmlStep from '../EditTravisYmlStep';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should render the form correctly', () => {
expect(
shallowRender()
.find('Step')
.prop<Function>('renderForm')()
).toMatchSnapshot();
});

function shallowRender(props: Partial<StepProps> = {}) {
return shallow(
<EditTravisYmlStep
buildCallback={jest.fn()}
buildType="maven"
onContinue={jest.fn()}
onOpen={jest.fn()}
open={true}
stepNumber={1}
{...props}
/>
);
}

+ 0
- 43
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/EncryptYourTokenStep-test.tsx View File

@@ -1,43 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { StepProps } from '../../../utils';
import EncryptYourTokenStep from '../EncryptYourTokenStep';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender(props: Partial<StepProps> = {}) {
return shallow(
<EncryptYourTokenStep
component={mockComponent()}
currentUser={mockLoggedInUser()}
onContinue={jest.fn()}
onOpen={jest.fn()}
open={true}
setToken={jest.fn()}
stepNumber={1}
{...props}
/>
);
}

+ 0
- 27
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/CreateSonarPropertiesStep-test.tsx.snap View File

@@ -1,27 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Step
finished={false}
onOpen={[MockFunction]}
open={true}
renderForm={[Function]}
renderResult={[Function]}
stepNumber={1}
stepTitle={
<FormattedMessage
defaultMessage="onboarding.analysis.with.travis.sonar.properties.title"
id="onboarding.analysis.with.travis.sonar.properties.title"
values={
Object {
"filename": <code
className="rule"
>
sonar-project.properties
</code>,
}
}
/>
}
/>
`;

+ 0
- 56
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/EditTokenModal-test.tsx.snap View File

@@ -1,56 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<ConfirmModal
confirmButtonText="save"
confirmDisable={true}
header="onboarding.token.header"
onClose={[MockFunction]}
onConfirm={[Function]}
>
<p
className="spacer-bottom"
>
<FormattedMessage
defaultMessage="onboarding.token.text"
id="onboarding.token.text"
values={
Object {
"link": <Link
onlyActiveOnIndex={false}
style={Object {}}
target="_blank"
to="/account/security"
>
onboarding.token.text.user_account
</Link>,
}
}
/>
</p>
<RenderOptions
checked="use_existing_token"
name="token-mode"
onCheck={[Function]}
optionLabelKey="onboarding.token"
options={
Array [
"use_existing_token",
"generate_token",
]
}
/>
<div
className="big-spacer-top"
>
<input
className="input-super-large spacer-right text-middle"
onChange={[Function]}
placeholder="onboarding.token.use_existing_token.placeholder"
required={true}
type="text"
value=""
/>
</div>
</ConfirmModal>
`;

+ 0
- 59
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/EditTravisYmlStep-test.tsx.snap View File

@@ -1,59 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Step
finished={false}
onOpen={[MockFunction]}
open={true}
renderForm={[Function]}
renderResult={[Function]}
stepNumber={1}
stepTitle={
<FormattedMessage
defaultMessage="onboarding.analysis.travis.sonarcloud"
id="onboarding.analysis.travis.sonarcloud"
values={
Object {
"filename": <code
className="rule"
>
.travis.yml
</code>,
}
}
/>
}
/>
`;

exports[`should render the form correctly 1`] = `
<div
className="boxed-group-inner"
>
<div
className="flex-columns"
>
<div
className="flex-column-full"
>
<BuildSystemForm
build="maven"
setBuild={[Function]}
/>
<AnalysisCommandTravis
buildType="maven"
/>
</div>
</div>
<div
className="big-spacer-top"
>
<Button
className="js-continue"
onClick={[MockFunction]}
>
onboarding.finish
</Button>
</div>
</div>
`;

+ 0
- 13
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/steps/__tests__/__snapshots__/EncryptYourTokenStep-test.tsx.snap View File

@@ -1,13 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Step
finished={true}
onOpen={[MockFunction]}
open={true}
renderForm={[Function]}
renderResult={[Function]}
stepNumber={1}
stepTitle="onboarding.analysis.with.travis.encrypt.title"
/>
`;

+ 0
- 118
server/sonar-web/src/main/js/apps/tutorials/analyzeProject/utils.ts View File

@@ -1,118 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
export const PROJECT_ONBOARDING_DONE = 'sonarcloud.project.onboarding.finished';
export const PROJECT_ONBOARDING_MODE_ID = 'sonarcloud.project.onboarding.mode.id';
export const PROJECT_STEP_PROGRESS = 'sonarcloud.project.onboarding.step.progress';

export interface AlmLanguagesStats {
[k: string]: number;
}

export interface Alm {
id: string;
name: string;
}

export interface AnalysisMode {
icon?: string;
id: string;
name: string;
}

export enum ALM_KEYS {
BITBUCKET = 'BITBUCKET',
GITHUB = 'GITHUB',
MICROSOFT = 'MICROSOFT'
}

export const alms: { [k: string]: Alm } = {
[ALM_KEYS.BITBUCKET]: {
id: ALM_KEYS.BITBUCKET,
name: 'BitBucket'
},
[ALM_KEYS.GITHUB]: {
id: ALM_KEYS.GITHUB,
name: 'GitHub'
},
[ALM_KEYS.MICROSOFT]: {
id: ALM_KEYS.MICROSOFT,
name: 'Microsoft'
}
};

export const modes: AnalysisMode[] = [
{
id: 'travis',
name: 'With Travis CI'
},
{
id: 'other',
name: 'With other CI tools'
},
{
id: 'manual',
name: 'Manually'
}
];

export const autoScanMode: AnalysisMode = {
id: 'autoscan',
name: 'SonarCloud Automatic Analysis'
};

export interface TutorialProps {
component: T.Component;
currentUser: T.LoggedInUser;
onDone: VoidFunction;
setToken: (token: string) => void;
style?: object;
token: string | undefined;
}

interface AutoScannableProps {
[k: string]: number;
}

export function isAutoScannable(languages: AutoScannableProps = {}) {
const allowed = [
'ABAP',
'Apex',
'CSS',
'Flex',
'Go',
'HTML',
'JavaScript',
'Kotlin',
'PHP',
'Python',
'Ruby',
'Scala',
'Swift',
'TypeScript',
'TSQL',
'XML'
];
const notAllowed = ['Java', 'C#', 'Visual Basic', 'C', 'C++', 'Objective-C'];

const withAllowedLanguages = !!Object.keys(languages).find(l => allowed.includes(l));
const withNotAllowedLanguages = !!Object.keys(languages).find(l => notAllowed.includes(l));

return { withAllowedLanguages, withNotAllowedLanguages };
}

+ 0
- 72
server/sonar-web/src/main/js/apps/tutorials/components/AnalyzeTutorialDone.tsx View File

@@ -1,72 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import BackButton from 'sonar-ui-common/components/controls/BackButton';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';

interface Props {
setTutorialDone: (done: boolean) => void;
}

export default function AnalyzeTutorialDone({ setTutorialDone }: Props) {
return (
<div className="page-analysis-container page-analysis-container-sonarcloud">
<BackButton
onClick={() => setTutorialDone(false)}
tooltip={translate('onboarding.tutorial.return_to_tutorial')}>
{translate('back')}
</BackButton>
<div className="page-analysis page-analysis-waiting huge-spacer-top huge-spacer-bottom">
<img
alt="SonarCloud"
src={`${getBaseUrl()}/images/sonarcloud/analysis/Waiting-for-analysis.svg`}
/>
<h1 className="big-spacer-bottom huge-spacer-top">
{translate('onboarding.finished.title')}
</h1>
<p>{translate('onboarding.finished.text')}</p>

<div className="links huge-spacer-top huge-spacer-bottom">
<h2 className="huge-spacer-bottom">{translate('onboarding.finished.links.title')}</h2>
<ul>
<li className="big-spacer-bottom">
<a
href="https://sonarcloud.io/documentation/user-guide/quality-gates/"
rel="noopener noreferrer"
target="_blank">
What is a Quality Gate?
</a>
</li>
<li className="big-spacer-bottom">
<a
href="https://sonarcloud.io/documentation/instance-administration/quality-profiles/"
rel="noopener noreferrer"
target="_blank">
Configure your Quality Profiles
</a>
.
</li>
</ul>
</div>
</div>
</div>
);
}

+ 0
- 39
server/sonar-web/src/main/js/apps/tutorials/components/BuildSystemForm.tsx View File

@@ -1,39 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { RenderOptions } from './RenderOptions';

interface Props {
build: string | undefined;
setBuild: (build: string) => void;
}

export default function BuildSystemForm({ build, setBuild }: Props) {
return (
<RenderOptions
checked={build}
name="build"
onCheck={setBuild}
optionLabelKey="onboarding.build"
options={['maven', 'gradle', 'make', 'other']}
titleLabelKey="onboarding.build"
/>
);
}

+ 5
- 57
server/sonar-web/src/main/js/apps/tutorials/components/LanguageForm.tsx View File

@@ -20,13 +20,11 @@
import * as React from 'react';
import RadioToggle from 'sonar-ui-common/components/controls/RadioToggle';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { isSonarCloud } from '../../../helpers/system';
import { isLanguageConfigured, LanguageConfig } from '../utils';
import NewProjectForm from './NewProjectForm';
import { RenderOptions } from './RenderOptions';

interface Props {
component?: T.Component;
component: T.Component;
config?: LanguageConfig;
onDone: (config: LanguageConfig) => void;
onReset: VoidFunction;
@@ -39,6 +37,7 @@ export interface RenderOSProps {
os: string | undefined;
setOS: (os: string) => void;
}

export function RenderOS(props: RenderOSProps) {
return (
<RenderOptions
@@ -77,22 +76,10 @@ export default class LanguageForm extends React.PureComponent<Props, State> {
this.setState({ javaBuild }, this.handleChange);
};

handleCFamilyCompilerChange = (cFamilyCompiler: string) => {
this.setState({ cFamilyCompiler }, this.handleChange);
};

handleOSChange = (os: string) => {
this.setState({ os }, this.handleChange);
};

handleProjectKeyDone = (projectKey: string) => {
this.setState({ projectKey }, this.handleChange);
};

handleProjectKeyDelete = () => {
this.setState({ projectKey: undefined }, this.handleChange);
};

renderJavaBuild = () => (
<RenderOptions
checked={this.state.javaBuild}
@@ -104,44 +91,9 @@ export default class LanguageForm extends React.PureComponent<Props, State> {
/>
);

renderCFamilyCompiler = () => (
<RenderOptions
checked={this.state.cFamilyCompiler}
name="c-family-compiler"
onCheck={this.handleCFamilyCompilerChange}
optionLabelKey="onboarding.language.c-family.compiler"
options={['msvc', 'clang-gcc']}
titleLabelKey="onboarding.language.c-family.compiler"
/>
);

renderProjectKey = () => {
const { cFamilyCompiler, language, os } = this.state;
const needProjectKey =
language === 'dotnet' ||
(language === 'c-family' &&
(cFamilyCompiler === 'msvc' || (cFamilyCompiler === 'clang-gcc' && os !== undefined))) ||
(language === 'other' && os !== undefined);

if (!needProjectKey || this.props.component) {
return null;
}

return (
<NewProjectForm
onDelete={this.handleProjectKeyDelete}
onDone={this.handleProjectKeyDone}
organization={this.props.organization}
projectKey={this.state.projectKey}
/>
);
};

render() {
const { cFamilyCompiler, language } = this.state;
const languages = isSonarCloud()
? ['java', 'dotnet', 'c-family', 'other']
: ['java', 'dotnet', 'other'];
const { language } = this.state;
const languages = ['java', 'dotnet', 'other'];

return (
<>
@@ -158,11 +110,7 @@ export default class LanguageForm extends React.PureComponent<Props, State> {
/>
</div>
{language === 'java' && this.renderJavaBuild()}
{language === 'c-family' && this.renderCFamilyCompiler()}
{((language === 'c-family' && cFamilyCompiler === 'clang-gcc') || language === 'other') && (
<RenderOS os={this.state.os} setOS={this.handleOSChange} />
)}
{this.renderProjectKey()}
{language === 'other' && <RenderOS os={this.state.os} setOS={this.handleOSChange} />}
</>
);
}

+ 0
- 150
server/sonar-web/src/main/js/apps/tutorials/components/NewProjectForm.tsx View File

@@ -1,150 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { DeleteButton, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { createProject, deleteProject } from '../../../api/components';

interface Props {
onDelete: VoidFunction;
onDone: (projectKey: string) => void;
organization?: string;
projectKey?: string;
}

interface State {
done: boolean;
loading: boolean;
projectKey: string;
}

export default class NewProjectForm extends React.PureComponent<Props, State> {
mounted = false;

constructor(props: Props) {
super(props);
this.state = {
done: props.projectKey != null,
loading: false,
projectKey: props.projectKey || ''
};
}

componentDidMount() {
this.mounted = true;
}

componentWillUnmount() {
this.mounted = false;
}

stopLoading = () => {
if (this.mounted) {
this.setState({ loading: false });
}
};

sanitizeProjectKey = (projectKey: string) => projectKey.replace(/[^-_a-zA-Z0-9.:]/, '');

handleProjectKeyChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ projectKey: this.sanitizeProjectKey(event.target.value) });
};

handleProjectCreate = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const { projectKey } = this.state;
const data: {
name: string;
project: string;
organization?: string;
} = {
name: projectKey,
project: projectKey
};
if (this.props.organization) {
data.organization = this.props.organization;
}
this.setState({ loading: true });
createProject(data).then(() => {
if (this.mounted) {
this.setState({ done: true, loading: false });
this.props.onDone(projectKey);
}
}, this.stopLoading);
};

handleProjectDelete = () => {
const { projectKey } = this.state;
this.setState({ loading: true });
deleteProject(projectKey).then(() => {
if (this.mounted) {
this.setState({ done: false, loading: false, projectKey: '' });
this.props.onDelete();
}
}, this.stopLoading);
};

render() {
const { done, loading, projectKey } = this.state;

const valid = projectKey.length > 0;

const form = done ? (
<div>
<span className="spacer-right text-middle">{projectKey}</span>
{loading ? (
<i className="spinner text-middle" />
) : (
<DeleteButton className="button-small text-middle" onClick={this.handleProjectDelete} />
)}
</div>
) : (
<form onSubmit={this.handleProjectCreate}>
<input
autoFocus={true}
className="input-large spacer-right text-middle"
maxLength={400}
minLength={1}
onChange={this.handleProjectKeyChange}
required={true}
type="text"
value={projectKey}
/>
{loading ? (
<i className="spinner text-middle" />
) : (
<SubmitButton className="text-middle" disabled={!valid}>
{translate('Done')}
</SubmitButton>
)}
<div className="note spacer-top abs-width-300">
{translate('onboarding.project_key_requirement')}
</div>
</form>
);

return (
<div className="big-spacer-top">
<h4 className="spacer-bottom">{translate('onboarding.language.project_key')}</h4>
{form}
</div>
);
}
}

+ 1
- 1
server/sonar-web/src/main/js/apps/tutorials/components/ProjectAnalysisStep.tsx View File

@@ -25,7 +25,7 @@ import LanguageForm from './LanguageForm';
import Step from './Step';

interface Props {
component?: T.Component;
component: T.Component;
displayRowLayout?: boolean;
onFinish?: (projectKey?: string) => void;
onReset?: VoidFunction;

+ 0
- 148
server/sonar-web/src/main/js/apps/tutorials/components/ProjectAnalysisStepFromBuildTool.tsx View File

@@ -1,148 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { get, save } from 'sonar-ui-common/helpers/storage';
import { PROJECT_STEP_PROGRESS } from '../analyzeProject/utils';
import BuildSystemForm from './BuildSystemForm';
import AnalysisCommandCustom from './commands/AnalysisCommandCustom';
import AnalysisCommandOtherCI from './commands/AnalysisCommandOtherCI';
import Step from './Step';

export enum ProjectAnalysisModes {
CI = 'CI',
Custom = 'Custom'
}

export interface Props {
component: T.Component;
currentUser: T.LoggedInUser;
displayRowLayout?: boolean;
mode: ProjectAnalysisModes;
onDone: VoidFunction;
onReset?: VoidFunction;
open: boolean;
organization?: string;
setToken: (token: string) => void;
stepNumber: number;
token?: string;
}

export default function ProjectAnalysisStepFromBuildTool({
component,
currentUser,
displayRowLayout,
mode,
onDone,
open,
organization,
setToken,
stepNumber,
token
}: Props) {
const [build, setBuild] = React.useState<string | undefined>(undefined);
const [os, setOS] = React.useState<string | undefined>(undefined);

React.useEffect(() => {
const value = get(PROJECT_STEP_PROGRESS, component.key);
if (value) {
try {
const data = JSON.parse(value);
setBuild(data.build);
setOS(data.os);
} catch (e) {
// Let's start from scratch
}
}
}, [component.key]);

const saveAndFinish = (data: object) => {
save(
PROJECT_STEP_PROGRESS,
JSON.stringify({
...data,
build
}),
component.key
);

onDone();
};

const renderForm = () => {
const languageComponent = <BuildSystemForm build={build} setBuild={setBuild} />;

let AnalysisComponent = null;

if (mode === ProjectAnalysisModes.Custom) {
AnalysisComponent = AnalysisCommandCustom;
} else if (mode === ProjectAnalysisModes.CI) {
AnalysisComponent = AnalysisCommandOtherCI;
}

if (displayRowLayout) {
return (
<div className="boxed-group-inner">
<div className="display-flex-column">
{languageComponent}
{AnalysisComponent && (
<div className="huge-spacer-top">
<AnalysisComponent
buildType={build}
component={component}
currentUser={currentUser}
onDone={saveAndFinish}
organization={organization}
os={os}
setToken={setToken}
small={true}
token={token}
/>
</div>
)}
</div>
</div>
);
}

return (
<div className="boxed-group-inner">
<div className="flex-columns">
<div className="flex-column flex-column-half bordered-right">{languageComponent}</div>
<div className="flex-column flex-column-half">{AnalysisComponent}</div>
</div>
</div>
);
};

const renderResult = () => null;

return (
<Step
finished={false}
onOpen={() => {}}
open={open}
renderForm={renderForm}
renderResult={renderResult}
stepNumber={stepNumber}
stepTitle={translate('onboarding.analysis.header')}
/>
);
}

+ 0
- 26
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/AnalyzeTutorialDone-test.tsx View File

@@ -1,26 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import AnalyzeTutorialDone from '../AnalyzeTutorialDone';

it('should render correctly', () => {
expect(shallow(<AnalyzeTutorialDone setTutorialDone={jest.fn()} />)).toMatchSnapshot();
});

+ 0
- 28
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/BuildSystemForm-test.tsx View File

@@ -1,28 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import BuildSystemForm from '../BuildSystemForm';

it('should render correctly', () => {
const build = 'maven';
const setBuild = jest.fn();
expect(shallow(<BuildSystemForm build={build} setBuild={setBuild} />)).toMatchSnapshot();
});

+ 10
- 23
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/LanguageForm-test.tsx View File

@@ -19,18 +19,14 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { isSonarCloud } from '../../../../helpers/system';
import { mockComponent } from '../../../../helpers/testMocks';
import LanguageForm from '../LanguageForm';

jest.mock('../../../../helpers/system', () => ({ isSonarCloud: jest.fn() }));

beforeEach(() => {
(isSonarCloud as jest.Mock<any>).mockImplementation(() => false);
});

it('selects java', () => {
const onDone = jest.fn();
const wrapper = shallow(<LanguageForm onDone={onDone} onReset={jest.fn()} />);
const wrapper = shallow(
<LanguageForm component={mockComponent()} onDone={onDone} onReset={jest.fn()} />
);

(wrapper.find('RadioToggle').prop('onCheck') as Function)('java');
wrapper.update();
@@ -39,29 +35,20 @@ it('selects java', () => {

it('selects c#', () => {
const onDone = jest.fn();
const wrapper = shallow(<LanguageForm onDone={onDone} onReset={jest.fn()} />);
const wrapper = shallow(
<LanguageForm component={mockComponent()} onDone={onDone} onReset={jest.fn()} />
);

(wrapper.find('RadioToggle').prop('onCheck') as Function)('dotnet');
wrapper.update();
expect(wrapper).toMatchSnapshot();

(wrapper.find('NewProjectForm').prop('onDone') as Function)('project-foo');
expect(onDone).lastCalledWith({ language: 'dotnet', projectKey: 'project-foo' });
});

it('selects c-family', () => {
(isSonarCloud as jest.Mock<any>).mockImplementation(() => true);
const onDone = jest.fn();
const wrapper = shallow(<LanguageForm onDone={onDone} onReset={jest.fn()} />);

(wrapper.find('RadioToggle').prop('onCheck') as Function)('c-family');
wrapper.update();
expect(wrapper).toMatchSnapshot();
});

it('selects other', () => {
const onDone = jest.fn();
const wrapper = shallow(<LanguageForm onDone={onDone} onReset={jest.fn()} />);
const wrapper = shallow(
<LanguageForm component={mockComponent()} onDone={onDone} onReset={jest.fn()} />
);

(wrapper.find('RadioToggle').prop('onCheck') as Function)('other');
wrapper.update();

+ 0
- 53
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/NewProjectForm-test.tsx View File

@@ -1,53 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { change, submit, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import NewProjectForm from '../NewProjectForm';

jest.mock('../../../../api/components', () => ({
createProject: () => Promise.resolve(),
deleteProject: () => Promise.resolve()
}));

it('creates new project', async () => {
const onDone = jest.fn();
const wrapper = shallow(<NewProjectForm onDelete={jest.fn()} onDone={onDone} />);
expect(wrapper).toMatchSnapshot();
change(wrapper.find('input'), 'foo');
submit(wrapper.find('form'));
expect(wrapper).toMatchSnapshot(); // spinner
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
expect(onDone).toBeCalledWith('foo');
});

it('deletes project', async () => {
const onDelete = jest.fn();
const wrapper = shallow(<NewProjectForm onDelete={onDelete} onDone={jest.fn()} />);
wrapper.setState({ done: true, loading: false, projectKey: 'foo' });
expect(wrapper).toMatchSnapshot();
(wrapper.find('DeleteButton').prop('onClick') as Function)();
wrapper.update();
expect(wrapper).toMatchSnapshot(); // spinner
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
expect(onDelete).toBeCalled();
});

+ 0
- 69
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/ProjectAnalysisStepFromBuildTool-test.tsx View File

@@ -1,69 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../helpers/testMocks';
import ProjectAnalysisStepFromBuildTool, {
ProjectAnalysisModes,
Props
} from '../ProjectAnalysisStepFromBuildTool';

jest.mock('sonar-ui-common/helpers/storage', () => ({
get: jest.fn().mockReturnValue(
JSON.stringify({
build: 'maven',
os: 'linux'
})
),
save: jest.fn()
}));

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should render the form correctly', () => {
expect(
shallowRender({ mode: ProjectAnalysisModes.CI })
.find('Step')
.prop<Function>('renderForm')()
).toMatchSnapshot();

expect(
shallowRender({ displayRowLayout: true })
.find('Step')
.prop<Function>('renderForm')()
).toMatchSnapshot();
});

function shallowRender(props: Partial<Props> = {}) {
return shallow(
<ProjectAnalysisStepFromBuildTool
component={mockComponent()}
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
open={true}
setToken={jest.fn()}
stepNumber={1}
{...props}
/>
);
}

+ 0
- 64
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/AnalyzeTutorialDone-test.tsx.snap View File

@@ -1,64 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
className="page-analysis-container page-analysis-container-sonarcloud"
>
<BackButton
onClick={[Function]}
tooltip="onboarding.tutorial.return_to_tutorial"
>
back
</BackButton>
<div
className="page-analysis page-analysis-waiting huge-spacer-top huge-spacer-bottom"
>
<img
alt="SonarCloud"
src="/images/sonarcloud/analysis/Waiting-for-analysis.svg"
/>
<h1
className="big-spacer-bottom huge-spacer-top"
>
onboarding.finished.title
</h1>
<p>
onboarding.finished.text
</p>
<div
className="links huge-spacer-top huge-spacer-bottom"
>
<h2
className="huge-spacer-bottom"
>
onboarding.finished.links.title
</h2>
<ul>
<li
className="big-spacer-bottom"
>
<a
href="https://sonarcloud.io/documentation/user-guide/quality-gates/"
rel="noopener noreferrer"
target="_blank"
>
What is a Quality Gate?
</a>
</li>
<li
className="big-spacer-bottom"
>
<a
href="https://sonarcloud.io/documentation/instance-administration/quality-profiles/"
rel="noopener noreferrer"
target="_blank"
>
Configure your Quality Profiles
</a>
.
</li>
</ul>
</div>
</div>
</div>
`;

+ 0
- 19
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/BuildSystemForm-test.tsx.snap View File

@@ -1,19 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<RenderOptions
checked="maven"
name="build"
onCheck={[MockFunction]}
optionLabelKey="onboarding.build"
options={
Array [
"maven",
"gradle",
"make",
"other",
]
}
titleLabelKey="onboarding.build"
/>
`;

+ 0
- 54
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/LanguageForm-test.tsx.snap View File

@@ -31,60 +31,6 @@ exports[`selects c# 1`] = `
value="dotnet"
/>
</div>
<NewProjectForm
onDelete={[Function]}
onDone={[Function]}
/>
</Fragment>
`;

exports[`selects c-family 1`] = `
<Fragment>
<div>
<h4
className="spacer-bottom"
>
onboarding.language
</h4>
<RadioToggle
disabled={false}
name="language"
onCheck={[Function]}
options={
Array [
Object {
"label": "onboarding.language.java",
"value": "java",
},
Object {
"label": "onboarding.language.dotnet",
"value": "dotnet",
},
Object {
"label": "onboarding.language.c-family",
"value": "c-family",
},
Object {
"label": "onboarding.language.other",
"value": "other",
},
]
}
value="c-family"
/>
</div>
<RenderOptions
name="c-family-compiler"
onCheck={[Function]}
optionLabelKey="onboarding.language.c-family.compiler"
options={
Array [
"msvc",
"clang-gcc",
]
}
titleLabelKey="onboarding.language.c-family.compiler"
/>
</Fragment>
`;


+ 0
- 177
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/NewProjectForm-test.tsx.snap View File

@@ -1,177 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`creates new project 1`] = `
<div
className="big-spacer-top"
>
<h4
className="spacer-bottom"
>
onboarding.language.project_key
</h4>
<form
onSubmit={[Function]}
>
<input
autoFocus={true}
className="input-large spacer-right text-middle"
maxLength={400}
minLength={1}
onChange={[Function]}
required={true}
type="text"
value=""
/>
<SubmitButton
className="text-middle"
disabled={true}
>
Done
</SubmitButton>
<div
className="note spacer-top abs-width-300"
>
onboarding.project_key_requirement
</div>
</form>
</div>
`;

exports[`creates new project 2`] = `
<div
className="big-spacer-top"
>
<h4
className="spacer-bottom"
>
onboarding.language.project_key
</h4>
<form
onSubmit={[Function]}
>
<input
autoFocus={true}
className="input-large spacer-right text-middle"
maxLength={400}
minLength={1}
onChange={[Function]}
required={true}
type="text"
value="foo"
/>
<i
className="spinner text-middle"
/>
<div
className="note spacer-top abs-width-300"
>
onboarding.project_key_requirement
</div>
</form>
</div>
`;

exports[`creates new project 3`] = `
<div
className="big-spacer-top"
>
<h4
className="spacer-bottom"
>
onboarding.language.project_key
</h4>
<div>
<span
className="spacer-right text-middle"
>
foo
</span>
<DeleteButton
className="button-small text-middle"
onClick={[Function]}
/>
</div>
</div>
`;

exports[`deletes project 1`] = `
<div
className="big-spacer-top"
>
<h4
className="spacer-bottom"
>
onboarding.language.project_key
</h4>
<div>
<span
className="spacer-right text-middle"
>
foo
</span>
<DeleteButton
className="button-small text-middle"
onClick={[Function]}
/>
</div>
</div>
`;

exports[`deletes project 2`] = `
<div
className="big-spacer-top"
>
<h4
className="spacer-bottom"
>
onboarding.language.project_key
</h4>
<div>
<span
className="spacer-right text-middle"
>
foo
</span>
<i
className="spinner text-middle"
/>
</div>
</div>
`;

exports[`deletes project 3`] = `
<div
className="big-spacer-top"
>
<h4
className="spacer-bottom"
>
onboarding.language.project_key
</h4>
<form
onSubmit={[Function]}
>
<input
autoFocus={true}
className="input-large spacer-right text-middle"
maxLength={400}
minLength={1}
onChange={[Function]}
required={true}
type="text"
value=""
/>
<SubmitButton
className="text-middle"
disabled={true}
>
Done
</SubmitButton>
<div
className="note spacer-top abs-width-300"
>
onboarding.project_key_requirement
</div>
</form>
</div>
`;

+ 0
- 91
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/ProjectAnalysisStepFromBuildTool-test.tsx.snap View File

@@ -1,91 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Step
finished={false}
onOpen={[Function]}
open={true}
renderForm={[Function]}
renderResult={[Function]}
stepNumber={1}
stepTitle="onboarding.analysis.header"
/>
`;

exports[`should render the form correctly 1`] = `
<div
className="boxed-group-inner"
>
<div
className="flex-columns"
>
<div
className="flex-column flex-column-half bordered-right"
>
<BuildSystemForm
setBuild={[Function]}
/>
</div>
<div
className="flex-column flex-column-half"
>
[Function]
</div>
</div>
</div>
`;

exports[`should render the form correctly 2`] = `
<div
className="boxed-group-inner"
>
<div
className="display-flex-column"
>
<BuildSystemForm
setBuild={[Function]}
/>
<div
className="huge-spacer-top"
>
<AnalysisCommandCustom
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"organization": "foo",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
}
}
currentUser={
Object {
"groups": Array [],
"isLoggedIn": true,
"login": "luke",
"name": "Skywalker",
"scmAccounts": Array [],
}
}
onDone={[Function]}
setToken={[MockFunction]}
small={true}
/>
</div>
</div>
</div>
`;

+ 0
- 41
server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommand.tsx View File

@@ -21,11 +21,9 @@ import * as React from 'react';
import { getHostUrl } from 'sonar-ui-common/helpers/urls';
import { LanguageConfig } from '../../utils';
import { getProjectKey } from '../ProjectAnalysisStep';
import ClangGCC from './ClangGCC';
import DotNet from './DotNet';
import JavaGradle from './JavaGradle';
import JavaMaven from './JavaMaven';
import Msvc from './Msvc';
import Other from './Other';

interface Props {
@@ -84,41 +82,6 @@ export default class AnalysisCommand extends React.PureComponent<Props> {
);
};

renderCommandForMSVC = () => {
const { component, languageConfig, small, token } = this.props;
const projectKey = getProjectKey(languageConfig, component);
if (!projectKey || !token) {
return null;
}
return (
<Msvc
host={getHostUrl()}
organization={this.props.organization}
projectKey={projectKey}
small={small}
token={token}
/>
);
};

renderCommandForClangGCC = () => {
const { component, languageConfig, small, token } = this.props;
const projectKey = getProjectKey(languageConfig, component);
if (!languageConfig || !projectKey || !languageConfig.os || !token) {
return null;
}
return (
<ClangGCC
host={getHostUrl()}
organization={this.props.organization}
os={languageConfig.os}
projectKey={projectKey}
small={small}
token={token}
/>
);
};

renderCommandForOther = () => {
const { component, languageConfig, token } = this.props;
const projectKey = getProjectKey(languageConfig, component);
@@ -145,10 +108,6 @@ export default class AnalysisCommand extends React.PureComponent<Props> {
: this.renderCommandForGradle();
} else if (languageConfig.language === 'dotnet') {
return this.renderCommandForDotNet();
} else if (languageConfig.language === 'c-family') {
return languageConfig.cFamilyCompiler === 'msvc'
? this.renderCommandForMSVC()
: this.renderCommandForClangGCC();
} else {
return this.renderCommandForOther();
}

+ 0
- 175
server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommandCustom.tsx View File

@@ -1,175 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { getHostUrl } from 'sonar-ui-common/helpers/urls';
import { RenderOS, RenderOSProps } from '../LanguageForm';
import { getProjectKey } from '../ProjectAnalysisStep';
import { ProjectAnalysisModes } from '../ProjectAnalysisStepFromBuildTool';
import { AnalysisCommandCommon } from './AnalysisCommandOtherCI';
import ClangGCCCustom from './Custom/ClangGCCCustom';
import JavaGradleCustom from './Custom/JavaGradleCustom';
import JavaMavenCustom from './Custom/JavaMavenCustom';
import OtherCustom from './Custom/OtherCustom';
import { AnalysisCommandProps, AnalysisCommandRenderProps } from './utils';

export function RenderCommandForMaven({
component,
mode,
onDone,
organization,
toggleModal,
token
}: AnalysisCommandRenderProps) {
if (!token) {
return null;
}

return (
<JavaMavenCustom
host={getHostUrl()}
mode={mode}
onDone={onDone}
organization={organization}
projectKey={component && component.key}
toggleModal={toggleModal}
token={token}
/>
);
}

export function RenderCommandForGradle({
component,
mode,
onDone,
organization,
toggleModal,
token
}: AnalysisCommandRenderProps) {
if (!token) {
return null;
}

return (
<JavaGradleCustom
host={getHostUrl()}
mode={mode}
onDone={onDone}
organization={organization}
projectKey={component && component.key}
toggleModal={toggleModal}
token={token}
/>
);
}

export function RenderCommandForClangOrGCC({
component,
mode,
onDone,
organization,
os,
small,
toggleModal,
token
}: AnalysisCommandRenderProps) {
const projectKey = getProjectKey(undefined, component);
if (!projectKey || !os || !token) {
return null;
}
return (
<ClangGCCCustom
host={getHostUrl()}
mode={mode}
onDone={onDone}
organization={organization}
os={os}
projectKey={projectKey}
small={small}
toggleModal={toggleModal}
token={token}
/>
);
}

export function RenderCommandForOther({
component,
currentUser,
mode,
onDone,
organization,
os,
toggleModal,
token
}: AnalysisCommandRenderProps) {
const projectKey = getProjectKey(undefined, component);
if (!component || !projectKey || !os || !token) {
return null;
}
return (
<OtherCustom
component={component}
currentUser={currentUser}
host={getHostUrl()}
mode={mode}
onDone={onDone}
organization={organization}
os={os}
projectKey={projectKey}
toggleModal={toggleModal}
token={token}
/>
);
}

function getBuildOptions({
os,
setOS
}: RenderOSProps): { [k: string]: (props: AnalysisCommandRenderProps) => JSX.Element | null } {
return {
gradle: RenderCommandForGradle,
make: function make(props: AnalysisCommandRenderProps) {
return (
<>
<RenderOS os={os} setOS={setOS} />
<RenderCommandForClangOrGCC {...props} />
</>
);
},
maven: RenderCommandForMaven,
other: function other(props: AnalysisCommandRenderProps) {
return (
<>
<RenderOS os={os} setOS={setOS} />
<RenderCommandForOther {...props} />
</>
);
}
};
}

export default function AnalysisCommandCustom(props: AnalysisCommandProps) {
return (
<AnalysisCommandCommon
{...props}
getBuildOptions={getBuildOptions}
mode={ProjectAnalysisModes.Custom}
/>
);
}

+ 0
- 174
server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommandOtherCI.tsx View File

@@ -1,174 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { getHostUrl } from 'sonar-ui-common/helpers/urls';
import EditTokenModal from '../../analyzeProject/steps/EditTokenModal';
import { RenderOS, RenderOSProps } from '../LanguageForm';
import { getProjectKey } from '../ProjectAnalysisStep';
import { ProjectAnalysisModes } from '../ProjectAnalysisStepFromBuildTool';
import { RenderCommandForGradle, RenderCommandForMaven } from './AnalysisCommandCustom';
import ClangGCCOtherCI from './OtherCI/ClangGCCOtherCI';
import OtherOtherCI from './OtherCI/OtherOtherCI';
import { AnalysisCommandProps, AnalysisCommandRenderProps } from './utils';

export function RenderCommandForClangOrGCC({
component,
onDone,
organization,
os,
small,
toggleModal,
token
}: AnalysisCommandRenderProps) {
const projectKey = getProjectKey(undefined, component);
if (!projectKey || !os || !token) {
return null;
}
return (
<ClangGCCOtherCI
host={getHostUrl()}
onDone={onDone}
organization={organization}
os={os}
projectKey={projectKey}
small={small}
toggleModal={toggleModal}
token={token}
/>
);
}

export function RenderCommandForOther({
component,
currentUser,
onDone,
organization,
os,
toggleModal,
token
}: AnalysisCommandRenderProps) {
const projectKey = getProjectKey(undefined, component);
if (!component || !projectKey || !os || !token) {
return null;
}
return (
<OtherOtherCI
component={component}
currentUser={currentUser}
host={getHostUrl()}
onDone={onDone}
organization={organization}
os={os}
projectKey={projectKey}
toggleModal={toggleModal}
token={token}
/>
);
}

function getBuildOptions({
os,
setOS
}: RenderOSProps): { [k: string]: (props: AnalysisCommandRenderProps) => JSX.Element | null } {
return {
gradle: RenderCommandForGradle,
make: function make(props) {
return (
<>
<RenderOS os={os} setOS={setOS} />
<RenderCommandForClangOrGCC {...props} />
</>
);
},
maven: RenderCommandForMaven,
other: function other(props) {
return (
<>
<RenderOS os={os} setOS={setOS} />
<RenderCommandForOther {...props} />
</>
);
}
};
}

interface AnalysisCommandExtraProps {
mode: ProjectAnalysisModes;
getBuildOptions: (
props: RenderOSProps
) => { [k: string]: (props: AnalysisCommandRenderProps) => JSX.Element | null };
}

export function AnalysisCommandCommon(props: AnalysisCommandProps & AnalysisCommandExtraProps) {
const [os, setOS] = React.useState<string | undefined>(undefined);
const [isModalVisible, toggleModal] = React.useState<boolean>(false);
const { buildType } = props;

if (!os && props.os) {
setOS(props.os);
}

const toggleTokenModal = () => toggleModal(!isModalVisible);

const close = () => toggleModal(false);

const save = (t: string) => {
props.setToken(t);
close();
};

const callOnDone = () => {
props.onDone({ os });
};

const Build = (buildType && props.getBuildOptions({ os, setOS })[buildType]) || undefined;

return Build ? (
<>
{isModalVisible && (
<EditTokenModal
component={props.component}
currentUser={props.currentUser}
onClose={close}
onSave={save}
/>
)}

<Build
{...props}
mode={props.mode}
onDone={callOnDone}
os={os}
toggleModal={toggleTokenModal}
token={props.token}
/>
</>
) : null;
}

export default function AnalysisCommandOtherCI(props: AnalysisCommandProps) {
return (
<AnalysisCommandCommon
{...props}
getBuildOptions={getBuildOptions}
mode={ProjectAnalysisModes.CI}
/>
);
}

+ 0
- 207
server/sonar-web/src/main/js/apps/tutorials/components/commands/AnalysisCommandTravis.tsx View File

@@ -1,207 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getHostUrl } from 'sonar-ui-common/helpers/urls';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import { getProjectKey } from '../ProjectAnalysisStep';
import { ClangGCCTravisSonarCloud } from './TravisSonarCloud/ClangGCCTravisSonarCloud';
import { JavaGradleTravisSonarCloud } from './TravisSonarCloud/JavaGradleTravisSonarCloud';
import { JavaMavenTravisSonarCloud } from './TravisSonarCloud/JavaMavenTravisSonarCloud';
import { OtherTravisSonarCloud } from './TravisSonarCloud/OtherTravisSonarCloud';

interface Props {
buildType: string | undefined;
component?: T.Component;
organization?: string;
small?: boolean;
token?: string;
}

interface RenderProps {
component?: T.Component;
organization?: string;
small?: boolean;
token?: string;
}

export function getSonarcloudAddonYml(organization: string = '') {
return `addons:
sonarcloud:
organization: ${organization ? `"${organization}"` : `"Add your organization key"`}
token:
secure: "**************************" # encrypted value of your token`;
}

export function getSonarcloudAddonYmlRender(organization: string = '') {
return (
<>
{`addons:
sonarcloud:
organization: ${organization ? `"${organization}"` : `"Add your organization key"`}
token:
secure: `}
{
<span className="highlight">
{'"**************************"'} # encrypted value of your token
</span>
}
<br />
</>
);
}

export function RequirementJavaBuild() {
return (
<>
<p className="spacer-bottom">{translate('onboarding.analysis.with.travis.environments')}</p>

<div className="flex-columns">
<div className="flex-column flex-column-half">
<a
href="https://docs.travis-ci.com/user/reference/precise/"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.with.travis.environment.image.java')}
</a>
<CodeSnippet isOneLine={true} noCopy={true} snippet="language: java" />
</div>

<div className="display-flex-stretch">
<div className="vertical-pipe-separator">
<div className="vertical-separator " />
<span className="note">{translate('or')}</span>
<div className="vertical-separator" />
</div>
</div>

<div className="flex-column flex-column-half">
<a
href="https://docs.travis-ci.com/user/reference/trusty/"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.with.travis.environment.image.ci')}
</a>
<CodeSnippet isOneLine={true} noCopy={true} snippet="dist: trusty" />
</div>
</div>
</>
);
}

export function RequirementOtherBuild() {
return (
<>
<p>
{translate('onboarding.analysis.with.travis.environment')}{' '}
<a
href="https://docs.travis-ci.com/user/reference/trusty/"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.with.travis.environment.image.ci')}
</a>
</p>

<CodeSnippet isOneLine={true} noCopy={true} snippet="dist: trusty" />
</>
);
}

export function RenderCommandForClangOrGCC({ component, organization, small, token }: RenderProps) {
const projectKey = getProjectKey(undefined, component);
if (!projectKey || !token) {
return null;
}
return (
<ClangGCCTravisSonarCloud
host={getHostUrl()}
organization={organization}
os="linux"
projectKey={projectKey}
small={small}
token={token}
/>
);
}

export function RenderCommandForGradle({ component, organization, token }: RenderProps) {
if (!token) {
return null;
}

return (
<JavaGradleTravisSonarCloud
host={getHostUrl()}
organization={organization}
projectKey={component && component.key}
token={token}
/>
);
}

export function RenderCommandForMaven({ component, organization, token }: RenderProps) {
if (!token) {
return null;
}

return (
<JavaMavenTravisSonarCloud
host={getHostUrl()}
organization={organization}
projectKey={component && component.key}
token={token}
/>
);
}

export function RenderCommandForOther({ component, organization, token }: RenderProps) {
const projectKey = getProjectKey(undefined, component);
if (!projectKey || !token) {
return null;
}
return (
<OtherTravisSonarCloud
host={getHostUrl()}
organization={organization}
os="linux"
projectKey={projectKey}
token={token}
/>
);
}

function getBuildOptions(): {
[k: string]: (props: Props) => JSX.Element | null;
} {
return {
gradle: RenderCommandForGradle,
make: RenderCommandForClangOrGCC,
maven: RenderCommandForMaven,
other: RenderCommandForOther
};
}

export default function AnalysisCommandTravis(props: Props) {
const { buildType } = props;

const Build = (buildType && getBuildOptions()[buildType]) || undefined;

return Build ? <Build {...props} /> : null;
}

+ 0
- 63
server/sonar-web/src/main/js/apps/tutorials/components/commands/BuildWrapper.tsx View File

@@ -1,63 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';

interface Props {
className?: string;
os: string;
}

const filenames: T.Dict<string> = {
win: 'build-wrapper-win-x86.zip',
linux: 'build-wrapper-linux-x86.zip',
mac: 'build-wrapper-macosx-x86.zip'
};

export default function BuildWrapper(props: Props) {
return (
<div className={props.className}>
<h4 className="spacer-bottom">
{translate('onboarding.analysis.build_wrapper.header', props.os)}
</h4>
<p className="spacer-bottom markdown">
<FormattedMessage
defaultMessage={translate('onboarding.analysis.build_wrapper.text')}
id="onboarding.analysis.build_wrapper.text"
values={{
env_var: <code>{props.os === 'win' ? '%PATH%' : 'PATH'}</code>
}}
/>
</p>
<p>
<a
className="button"
download={filenames[props.os]}
href={`${getBaseUrl()}/static/cpp/${filenames[props.os]}`}
target="_blank"
rel="noopener noreferrer">
{translate('download_verb')}
</a>
</p>
</div>
);
}

+ 0
- 89
server/sonar-web/src/main/js/apps/tutorials/components/commands/ClangGCC.tsx View File

@@ -1,89 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import { quote } from '../../utils';
import BuildWrapper from './BuildWrapper';
import SQScanner from './SQScanner';

export interface Props {
host: string;
os: string;
organization?: string;
projectKey: string;
small?: boolean;
token: string;
}

const executables: T.Dict<string> = {
linux: 'build-wrapper-linux-x86-64',
win: 'build-wrapper-win-x86-64.exe',
mac: 'build-wrapper-macosx-x86'
};

export default function ClangGCC(props: Props) {
const command1 = `${executables[props.os]} --out-dir bw-output make clean all`;

const q = quote(props.os);
const command2 = [
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner',
'-D' + q(`sonar.projectKey=${props.projectKey}`),
props.organization && '-D' + q(`sonar.organization=${props.organization}`),
'-D' + q('sonar.sources=.'),
'-D' + q('sonar.cfamily.build-wrapper-output=bw-output'),
'-D' + q(`sonar.host.url=${props.host}`),
'-D' + q(`sonar.login=${props.token}`)
];

return (
<div>
<SQScanner os={props.os} />
<BuildWrapper className="huge-spacer-top" os={props.os} />

<h4 className="huge-spacer-top spacer-bottom">
{translate('onboarding.analysis.sq_scanner.execute')}
</h4>
<InstanceMessage message={translate('onboarding.analysis.sq_scanner.execute.text')}>
{transformedMessage => <p className="spacer-bottom markdown">{transformedMessage}</p>}
</InstanceMessage>
<CodeSnippet isOneLine={props.small} snippet={command1} />
<CodeSnippet isOneLine={props.os === 'win'} snippet={command2} />
<p className="big-spacer-top markdown">
<FormattedMessage
defaultMessage={translate('onboarding.analysis.sq_scanner.docs')}
id="onboarding.analysis.sq_scanner.docs"
values={{
link: (
<a
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.sq_scanner.docs_link')}
</a>
)
}}
/>
</p>
</div>
);
}

+ 0
- 132
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/ClangGCCCustom.tsx View File

@@ -1,132 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Button, EditButton } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import { quote } from '../../../utils';
import { ProjectAnalysisModes } from '../../ProjectAnalysisStepFromBuildTool';
import BuildWrapper from '../BuildWrapper';
import SQScanner from '../SQScanner';

export interface Props {
host: string;
mode: ProjectAnalysisModes;
onDone: VoidFunction;
os: string;
organization?: string;
projectKey: string;
small?: boolean;
toggleModal: VoidFunction;
token: string;
}

const executables: T.Dict<string> = {
linux: 'build-wrapper-linux-x86-64',
win: 'build-wrapper-win-x86-64.exe',
mac: 'build-wrapper-macosx-x86'
};

interface ClangGCCProps extends Pick<Props, 'small' | 'onDone' | 'os'> {
command1: string;
command2: (string | undefined)[];
renderCommand2: () => JSX.Element;
}

export function ClangGCCCommon(props: ClangGCCProps) {
return (
<>
<h4 className="huge-spacer-top spacer-bottom">
{translate('onboarding.analysis.sq_scanner.execute')}
</h4>

<p className="spacer-bottom markdown">
{translate('onboarding.analysis.sq_scanner.execute.text.custom')}
</p>

<CodeSnippet isOneLine={props.small} snippet={props.command1} />

<CodeSnippet
isOneLine={props.os === 'win'}
render={props.renderCommand2}
snippet={props.command2}
wrap={true}
/>

<FormattedMessage
defaultMessage={translate('onboarding.analysis.sq_scanner.docs')}
id="onboarding.analysis.sq_scanner.docs"
values={{
link: (
<a
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.sq_scanner.docs_link')}
</a>
)
}}
/>

<div className="big-spacer-top">
<Button className="js-continue" onClick={props.onDone}>
{translate('onboarding.finish')}
</Button>
</div>
</>
);
}

export default function ClangGCCCustom(props: Props) {
const command1 = `${executables[props.os]} --out-dir bw-output make clean all`;

const q = quote(props.os);
const command2 = [
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner',
'-D' + q(`sonar.projectKey=${props.projectKey}`),
props.organization && '-D' + q(`sonar.organization=${props.organization}`),
'-D' + q('sonar.sources=.'),
'-D' + q('sonar.cfamily.build-wrapper-output=bw-output'),
'-D' + q(`sonar.host.url=${props.host}`),
'-D' + q(`sonar.login=${props.token}`)
];

const renderCommand2 = () => (
<>
{command2.join(' \\\n ')}{' '}
<EditButton className="edit-token spacer-left" onClick={props.toggleModal} />
</>
);

return (
<div className="huge-spacer-top">
<SQScanner os={props.os} />
<BuildWrapper className="huge-spacer-top" os={props.os} />
<ClangGCCCommon
command1={command1}
command2={command2}
onDone={props.onDone}
os={props.os}
renderCommand2={renderCommand2}
/>
</div>
);
}

+ 0
- 69
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/JavaGradleCustom.tsx View File

@@ -1,69 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import { ProjectAnalysisModes } from '../../ProjectAnalysisStepFromBuildTool';
import { JavaCustomProps, RenderCustomContent } from './JavaMavenCustom';

export default function JavaGradleCustom(props: JavaCustomProps) {
const suffix = props.mode === ProjectAnalysisModes.CI ? '.ci' : '';
const config = 'plugins {\n id "org.sonarqube" version "2.7"\n}';

const command = [
'./gradlew sonarqube',
props.projectKey && `-Dsonar.projectKey=${props.projectKey}`,
props.organization && `-Dsonar.organization=${props.organization}`,
`-Dsonar.host.url=${props.host}`,
`-Dsonar.login=${props.token}`
];

return (
<div>
<h4 className="spacer-bottom">
{translate(`onboarding.analysis.java.gradle.header${suffix}`)}
</h4>

<FormattedMessage
defaultMessage={translate('onboarding.analysis.java.gradle.text.1.sonarcloud')}
id="onboarding.analysis.java.gradle.text.1.sonarcloud"
values={{
file: <code>build.gradle</code>,
plugin: <code>org.sonarqube</code>
}}
/>

<CodeSnippet snippet={config} />

<p className="spacer-top spacer-bottom markdown">
{translate('onboarding.analysis.java.gradle.text.2')}
</p>

<RenderCustomContent
command={command}
linkText="onboarding.analysis.java.gradle.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/gradle.html"
onDone={props.onDone}
toggleModal={props.toggleModal}
/>
</div>
);
}

+ 0
- 130
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/JavaMavenCustom.tsx View File

@@ -1,130 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Button, EditButton } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../../components/common/InstanceMessage';
import { ProjectAnalysisModes } from '../../ProjectAnalysisStepFromBuildTool';

export interface JavaCustomProps {
host: string;
mode: ProjectAnalysisModes;
onDone: VoidFunction;
organization?: string;
projectKey?: string;
toggleModal: VoidFunction;
token: string;
}

interface RenderCustomCommandProps {
command: (string | undefined)[];
toggleModal: VoidFunction;
}

export function RenderCustomCommand({
command,
toggleModal
}: RenderCustomCommandProps): JSX.Element {
return (
<>
{command.join(' \\\n ')}{' '}
<EditButton className="edit-token spacer-left" onClick={toggleModal} />
</>
);
}

interface RenderCustomContent {
linkText: string;
linkUrl: string;
onDone: VoidFunction;
}

export function RenderCustomContent({
command,
linkText,
linkUrl,
onDone,
toggleModal
}: RenderCustomCommandProps & RenderCustomContent) {
return (
<>
<CodeSnippet
render={() => <RenderCustomCommand command={command} toggleModal={toggleModal} />}
snippet={command}
wrap={true}
/>

<p className="big-spacer-top markdown">
<FormattedMessage
defaultMessage={translate('onboarding.analysis.docs')}
id="onboarding.analysis.docs"
values={{
link: (
<a href={linkUrl} rel="noopener noreferrer" target="_blank">
{translate(linkText)}
</a>
)
}}
/>
</p>

<div className="big-spacer-top">
<Button className="js-continue" onClick={onDone}>
{translate('onboarding.finish')}
</Button>
</div>
</>
);
}

export default function JavaMavenCustom(props: JavaCustomProps) {
const suffix = props.mode === ProjectAnalysisModes.CI ? '.ci' : '';
const command = [
'mvn sonar:sonar',
props.projectKey && `-Dsonar.projectKey=${props.projectKey}`,
props.organization && `-Dsonar.organization=${props.organization}`,
`-Dsonar.host.url=${props.host}`,
`-Dsonar.login=${props.token}`
];

return (
<div>
<h4 className="spacer-bottom">
{translate(`onboarding.analysis.java.maven.header${suffix}`)}
</h4>

<p className="spacer-bottom markdown">
<InstanceMessage
message={translate(`onboarding.analysis.java.maven.text.custom${suffix}`)}
/>
</p>

<RenderCustomContent
command={command}
linkText="onboarding.analysis.java.maven.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html"
onDone={props.onDone}
toggleModal={props.toggleModal}
/>
</div>
);
}

+ 0
- 96
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/OtherCustom.tsx View File

@@ -1,96 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { Button, EditButton } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../../components/common/InstanceMessage';
import { quote } from '../../../utils';
import { ProjectAnalysisModes } from '../../ProjectAnalysisStepFromBuildTool';
import SQScanner from '../SQScanner';

export interface Props {
component: T.Component;
currentUser: T.LoggedInUser;
host: string;
mode: ProjectAnalysisModes;
onDone: VoidFunction;
organization?: string;
os: string;
projectKey: string;
toggleModal: VoidFunction;
token: string;
}

export default function OtherCustom(props: Props) {
const q = quote(props.os);
const command = [
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner',
'-D' + q(`sonar.projectKey=${props.projectKey}`),
props.organization && '-D' + q(`sonar.organization=${props.organization}`),
'-D' + q('sonar.sources=.'),
'-D' + q(`sonar.host.url=${props.host}`),
'-D' + q(`sonar.login=${props.token}`)
];

const renderCommand = () => (
<>
{command.join(' \\\n ')}{' '}
<EditButton className="edit-token spacer-left" onClick={props.toggleModal} />
</>
);

return (
<div className="huge-spacer-top">
<SQScanner os={props.os} />

<h4 className="huge-spacer-top spacer-bottom">
{translate('onboarding.analysis.sq_scanner.execute')}
</h4>

<InstanceMessage message={translate('onboarding.analysis.sq_scanner.execute.text.custom')}>
{transformedMessage => (
<p
className="spacer-bottom markdown"
dangerouslySetInnerHTML={{ __html: transformedMessage }}
/>
)}
</InstanceMessage>

<CodeSnippet
isOneLine={props.os === 'win'}
render={renderCommand}
snippet={command}
wrap={true}
/>

<p
className="big-spacer-top markdown"
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.standard.docs') }}
/>

<div className="big-spacer-top">
<Button className="js-continue" onClick={props.onDone}>
{translate('onboarding.finish')}
</Button>
</div>
</div>
);
}

+ 0
- 58
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/ClangGCCCustom-test.tsx View File

@@ -1,58 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { ProjectAnalysisModes } from '../../../ProjectAnalysisStepFromBuildTool';
import ClangGCCCustom, { ClangGCCCommon } from '../ClangGCCCustom';

it('should render correctly', () => {
expect(
shallow(
<ClangGCCCustom
host="https://sonarcloud.io"
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
organization="use-the-force"
os="linux"
projectKey="luke-lightsaber"
small={true}
toggleModal={jest.fn()}
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

it('should render common elements correctly', () => {
const command1 = `command1`;
const command2 = [`command2`];
const renderCommand2 = () => <>render command 2</>;
expect(
shallow(
<ClangGCCCommon
command1={command1}
command2={command2}
renderCommand2={renderCommand2}
onDone={jest.fn()}
os="linux"
/>
)
).toMatchSnapshot();
});

+ 0
- 67
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/JavaGradleCustom-test.tsx View File

@@ -1,67 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { ProjectAnalysisModes } from '../../../ProjectAnalysisStepFromBuildTool';
import JavaGradleCustom from '../JavaGradleCustom';
import { RenderCustomContent } from '../JavaMavenCustom';

const host = 'https://sonarcloud.io';
const organization = 'use-the-force';
const projectKey = 'luke-lightsaber';
const token = 'sonarsource123';

it('should render correctly', () => {
expect(
shallow(
<JavaGradleCustom
host={host}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
organization={organization}
projectKey={projectKey}
toggleModal={jest.fn()}
token={token}
/>
)
).toMatchSnapshot();
});

it('should render gradle custom content', () => {
const command = [
'./gradlew sonarqube',
projectKey && `-Dsonar.projectKey=${projectKey}`,
organization && `-Dsonar.organization=${organization}`,
`-Dsonar.host.url=${host}`,
`-Dsonar.login=${token}`
];
const onDone = jest.fn();
const toggleModal = jest.fn();

expect(
<RenderCustomContent
command={command}
linkText="onboarding.analysis.java.gradle.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/gradle.html"
onDone={onDone}
toggleModal={toggleModal}
/>
).toMatchSnapshot();
});

+ 0
- 80
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/JavaMavenCustom-test.tsx View File

@@ -1,80 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { ProjectAnalysisModes } from '../../../ProjectAnalysisStepFromBuildTool';
import JavaMavenCustom, { RenderCustomContent } from '../JavaMavenCustom';

const host = 'https://sonarcloud.io';
const organization = 'use-the-force';
const projectKey = 'luke-lightsaber';
const token = 'sonarsource123';

it('should render correctly', () => {
expect(
shallow(
<JavaMavenCustom
host={host}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
organization={organization}
projectKey={projectKey}
toggleModal={jest.fn()}
token={token}
/>
)
).toMatchSnapshot();
});

it('should render common elements correctly', () => {
expect(
shallow(
<JavaMavenCustom
host="sonarcloud"
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
toggleModal={jest.fn()}
token="123"
/>
)
).toMatchSnapshot();
});

it('should render maven custom content', () => {
const command = [
'mvn sonar:sonar',
projectKey && `-Dsonar.projectKey=${projectKey}`,
organization && `-Dsonar.organization=${organization}`,
`-Dsonar.host.url=${host}`,
`-Dsonar.login=${token}`
];
const onDone = jest.fn();
const toggleModal = jest.fn();

expect(
<RenderCustomContent
command={command}
linkText="onboarding.analysis.java.maven.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html"
onDone={onDone}
toggleModal={toggleModal}
/>
).toMatchSnapshot();
});

+ 0
- 43
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/OtherCustom-test.tsx View File

@@ -1,43 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../../helpers/testMocks';
import { ProjectAnalysisModes } from '../../../ProjectAnalysisStepFromBuildTool';
import OtherCustom from '../OtherCustom';

it('should render correctly', () => {
expect(
shallow(
<OtherCustom
component={mockComponent()}
currentUser={mockLoggedInUser()}
host="https://sonarcloud.io"
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
organization="use-the-force"
os="linux"
projectKey="luke-lightsaber"
toggleModal={jest.fn()}
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

+ 0
- 85
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/ClangGCCCustom-test.tsx.snap View File

@@ -1,85 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render common elements correctly 1`] = `
<Fragment>
<h4
className="huge-spacer-top spacer-bottom"
>
onboarding.analysis.sq_scanner.execute
</h4>
<p
className="spacer-bottom markdown"
>
onboarding.analysis.sq_scanner.execute.text.custom
</p>
<CodeSnippet
snippet="command1"
/>
<CodeSnippet
isOneLine={false}
render={[Function]}
snippet={
Array [
"command2",
]
}
wrap={true}
/>
<FormattedMessage
defaultMessage="onboarding.analysis.sq_scanner.docs"
id="onboarding.analysis.sq_scanner.docs"
values={
Object {
"link": <a
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
rel="noopener noreferrer"
target="_blank"
>
onboarding.analysis.sq_scanner.docs_link
</a>,
}
}
/>
<div
className="big-spacer-top"
>
<Button
className="js-continue"
onClick={[MockFunction]}
>
onboarding.finish
</Button>
</div>
</Fragment>
`;

exports[`should render correctly 1`] = `
<div
className="huge-spacer-top"
>
<SQScanner
os="linux"
/>
<BuildWrapper
className="huge-spacer-top"
os="linux"
/>
<ClangGCCCommon
command1="build-wrapper-linux-x86-64 --out-dir bw-output make clean all"
command2={
Array [
"sonar-scanner",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.sources=.",
"-Dsonar.cfamily.build-wrapper-output=bw-output",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
onDone={[MockFunction]}
os="linux"
renderCommand2={[Function]}
/>
</div>
`;

+ 0
- 68
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/JavaGradleCustom-test.tsx.snap View File

@@ -1,68 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div>
<h4
className="spacer-bottom"
>
onboarding.analysis.java.gradle.header
</h4>
<FormattedMessage
defaultMessage="onboarding.analysis.java.gradle.text.1.sonarcloud"
id="onboarding.analysis.java.gradle.text.1.sonarcloud"
values={
Object {
"file": <code>
build.gradle
</code>,
"plugin": <code>
org.sonarqube
</code>,
}
}
/>
<CodeSnippet
snippet="plugins {
id \\"org.sonarqube\\" version \\"2.7\\"
}"
/>
<p
className="spacer-top spacer-bottom markdown"
>
onboarding.analysis.java.gradle.text.2
</p>
<RenderCustomContent
command={
Array [
"./gradlew sonarqube",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
linkText="onboarding.analysis.java.gradle.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/gradle.html"
onDone={[MockFunction]}
toggleModal={[MockFunction]}
/>
</div>
`;

exports[`should render gradle custom content 1`] = `
<RenderCustomContent
command={
Array [
"./gradlew sonarqube",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
linkText="onboarding.analysis.java.gradle.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/gradle.html"
onDone={[MockFunction]}
toggleModal={[MockFunction]}
/>
`;

+ 0
- 83
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/JavaMavenCustom-test.tsx.snap View File

@@ -1,83 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render common elements correctly 1`] = `
<div>
<h4
className="spacer-bottom"
>
onboarding.analysis.java.maven.header
</h4>
<p
className="spacer-bottom markdown"
>
<InstanceMessage
message="onboarding.analysis.java.maven.text.custom"
/>
</p>
<RenderCustomContent
command={
Array [
"mvn sonar:sonar",
undefined,
undefined,
"-Dsonar.host.url=sonarcloud",
"-Dsonar.login=123",
]
}
linkText="onboarding.analysis.java.maven.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html"
onDone={[MockFunction]}
toggleModal={[MockFunction]}
/>
</div>
`;

exports[`should render correctly 1`] = `
<div>
<h4
className="spacer-bottom"
>
onboarding.analysis.java.maven.header
</h4>
<p
className="spacer-bottom markdown"
>
<InstanceMessage
message="onboarding.analysis.java.maven.text.custom"
/>
</p>
<RenderCustomContent
command={
Array [
"mvn sonar:sonar",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
linkText="onboarding.analysis.java.maven.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html"
onDone={[MockFunction]}
toggleModal={[MockFunction]}
/>
</div>
`;

exports[`should render maven custom content 1`] = `
<RenderCustomContent
command={
Array [
"mvn sonar:sonar",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
linkText="onboarding.analysis.java.maven.docs_link"
linkUrl="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html"
onDone={[MockFunction]}
toggleModal={[MockFunction]}
/>
`;

+ 0
- 54
server/sonar-web/src/main/js/apps/tutorials/components/commands/Custom/__tests__/__snapshots__/OtherCustom-test.tsx.snap View File

@@ -1,54 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
className="huge-spacer-top"
>
<SQScanner
os="linux"
/>
<h4
className="huge-spacer-top spacer-bottom"
>
onboarding.analysis.sq_scanner.execute
</h4>
<InstanceMessage
message="onboarding.analysis.sq_scanner.execute.text.custom"
>
<Component />
</InstanceMessage>
<CodeSnippet
isOneLine={false}
render={[Function]}
snippet={
Array [
"sonar-scanner",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.sources=.",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
wrap={true}
/>
<p
className="big-spacer-top markdown"
dangerouslySetInnerHTML={
Object {
"__html": "onboarding.analysis.standard.docs",
}
}
/>
<div
className="big-spacer-top"
>
<Button
className="js-continue"
onClick={[MockFunction]}
>
onboarding.finish
</Button>
</div>
</div>
`;

+ 0
- 82
server/sonar-web/src/main/js/apps/tutorials/components/commands/Msvc.tsx View File

@@ -1,82 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../components/common/InstanceMessage';
import BuildWrapper from './BuildWrapper';
import MSBuildScanner from './MSBuildScanner';

interface Props {
host: string;
organization?: string;
projectKey: string;
small?: boolean;
token: string;
}

export default function Msvc(props: Props) {
const command1 = [
'SonarQube.Scanner.MSBuild.exe begin',
`/k:"${props.projectKey}"`,
props.organization && `/d:sonar.organization="${props.organization}"`,
'/d:sonar.cfamily.build-wrapper-output=bw-output',
`/d:sonar.host.url="${props.host}"`,
`/d:sonar.login="${props.token}"`
];

const command2 = 'build-wrapper-win-x86-64.exe --out-dir bw-output MsBuild.exe /t:Rebuild';

const command3 = ['SonarQube.Scanner.MSBuild.exe end', `/d:sonar.login="${props.token}"`];

return (
<div>
<MSBuildScanner />
<BuildWrapper className="huge-spacer-top" os="win" />

<h4 className="huge-spacer-top spacer-bottom">
{translate('onboarding.analysis.msbuild.execute')}
</h4>
<InstanceMessage message={translate('onboarding.analysis.msbuild.execute.text')}>
{transformedMessage => <p className="spacer-bottom markdown">{transformedMessage}</p>}
</InstanceMessage>
<CodeSnippet isOneLine={true} snippet={command1} />
<CodeSnippet isOneLine={props.small} snippet={command2} />
<CodeSnippet isOneLine={props.small} snippet={command3} />
<p className="big-spacer-top markdown">
<FormattedMessage
defaultMessage={translate('onboarding.analysis.docs')}
id="onboarding.analysis.docs"
values={{
link: (
<a
href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.msbuild.docs_link')}
</a>
)
}}
/>
</p>
</div>
);
}

+ 0
- 108
server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/ClangGCCOtherCI.tsx View File

@@ -1,108 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { EditButton } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import { quote } from '../../../utils';
import BuildWrapper from '../BuildWrapper';
import { ClangGCCCommon } from '../Custom/ClangGCCCustom';
import SQScanner from '../SQScanner';

export interface Props {
host: string;
onDone: VoidFunction;
os: string;
organization?: string;
projectKey: string;
small?: boolean;
toggleModal: VoidFunction;
token: string;
}

const executables: T.Dict<string> = {
linux: 'build-wrapper-linux-x86-64',
win: 'build-wrapper-win-x86-64.exe',
mac: 'build-wrapper-macosx-x86'
};

export default function ClangGCCOtherCI(props: Props) {
const command1 = `${executables[props.os]} --out-dir bw-output make clean all`;

const q = quote(props.os);
const command2 = [
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner',
'-D' + q(`sonar.projectKey=${props.projectKey}`),
props.organization && '-D' + q(`sonar.organization=${props.organization}`),
'-D' + q('sonar.sources=.'),
'-D' + q('sonar.cfamily.build-wrapper-output=bw-output'),
'-D' + q(`sonar.host.url=${props.host}`),
'-D' + q(`sonar.login=${props.token}`)
];

const renderCommand2 = () => (
<>
{command2.join(' \\\n ')}{' '}
<EditButton className="edit-token spacer-left" onClick={props.toggleModal} />
</>
);

const commandLinuxMac = `
local SONAR_SCANNER_VERSION=${translate('onboarding.analysis.sonar_scanner_version')}
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION
rm -rf $SONAR_SCANNER_HOME
mkdir -p $SONAR_SCANNER_HOME
curl -sSLo $HOME/.sonar/sonar-scanner.zip http://repo1.maven.org/maven2/org/sonarsource/scanner/cli/sonar-scanner-cli/$SONAR_SCANNER_VERSION/sonar-scanner-cli-$SONAR_SCANNER_VERSION.zip
unzip $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
rm $HOME/.sonar/sonar-scanner.zip
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
export SONAR_SCANNER_OPTS="-server"

curl -LsS https://sonarcloud.io/static/cpp/build-wrapper-linux-x86.zip > build-wrapper-linux-x86.zip
unzip build-wrapper-linux-x86.zip`;

return (
<div className="huge-spacer-top">
{props.os === 'win' ? (
<>
<SQScanner os="ci" />

<BuildWrapper className="huge-spacer-top" os="ci" />
</>
) : (
<>
<h4 className="huge-spacer-top spacer-bottom">
{translate('onboarding.analysis.sq_scanner.header.ci')}
</h4>

<CodeSnippet snippet={commandLinuxMac} />
</>
)}

<ClangGCCCommon
command1={command1}
command2={command2}
onDone={props.onDone}
os={props.os}
renderCommand2={renderCommand2}
/>
</div>
);
}

+ 0
- 110
server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/OtherOtherCI.tsx View File

@@ -1,110 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { Button, EditButton } from 'sonar-ui-common/components/controls/buttons';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import InstanceMessage from '../../../../../components/common/InstanceMessage';
import { quote } from '../../../utils';
import SQScanner from '../SQScanner';

export interface Props {
component: T.Component;
currentUser: T.LoggedInUser;
host: string;
onDone: VoidFunction;
organization?: string;
os: string;
projectKey: string;
toggleModal: VoidFunction;
token: string;
}

export default function OtherOtherCI(props: Props) {
const q = quote(props.os);
const command = [
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner',
'-D' + q(`sonar.projectKey=${props.projectKey}`),
props.organization && '-D' + q(`sonar.organization=${props.organization}`),
'-D' + q('sonar.sources=.'),
'-D' + q(`sonar.host.url=${props.host}`),
'-D' + q(`sonar.login=${props.token}`)
];

const renderCommand = () => (
<>
{command.join(' \\\n ')}{' '}
<EditButton className="edit-token spacer-left" onClick={props.toggleModal} />
</>
);

const commandLinuxMac = `
local SONAR_SCANNER_VERSION=${translate('onboarding.analysis.sonar_scanner_version')}
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION
rm -rf $SONAR_SCANNER_HOME
mkdir -p $SONAR_SCANNER_HOME
curl -sSLo $HOME/.sonar/sonar-scanner.zip http://repo1.maven.org/maven2/org/sonarsource/scanner/cli/sonar-scanner-cli/$SONAR_SCANNER_VERSION/sonar-scanner-cli-$SONAR_SCANNER_VERSION.zip
unzip $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
rm $HOME/.sonar/sonar-scanner.zip
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
export SONAR_SCANNER_OPTS="-server"`;

return (
<div className="huge-spacer-top">
{props.os === 'win' ? (
<SQScanner os={props.os} />
) : (
<>
<h4 className="huge-spacer-top spacer-bottom">
{translate('onboarding.analysis.sq_scanner.header.ci')}
</h4>

<CodeSnippet snippet={commandLinuxMac} />
</>
)}

<h4 className="huge-spacer-top spacer-bottom">
{translate('onboarding.analysis.sq_scanner.execute.ci')}
</h4>

<InstanceMessage message={translate('onboarding.analysis.sq_scanner.execute.text.custom')}>
{transformedMessage => (
<p
className="spacer-bottom markdown"
dangerouslySetInnerHTML={{ __html: transformedMessage }}
/>
)}
</InstanceMessage>

<CodeSnippet isOneLine={props.os === 'win'} render={renderCommand} snippet={command} />

<p
className="big-spacer-top markdown"
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.standard.docs') }}
/>

<div className="big-spacer-top">
<Button className="js-continue" onClick={props.onDone}>
{translate('onboarding.finish')}
</Button>
</div>
</div>
);
}

+ 0
- 39
server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/ClangGCCOtherCI-test.tsx View File

@@ -1,39 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import ClangGCCOtherCI from '../ClangGCCOtherCI';

it('should render correctly', () => {
expect(
shallow(
<ClangGCCOtherCI
host="https://sonarcloud.io"
onDone={jest.fn()}
organization="use-the-force"
os="linux"
projectKey="luke-lightsaber"
small={true}
toggleModal={jest.fn()}
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

+ 0
- 41
server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/OtherOtherCI-test.tsx View File

@@ -1,41 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../../helpers/testMocks';
import OtherOtherCI from '../OtherOtherCI';

it('should render correctly', () => {
expect(
shallow(
<OtherOtherCI
component={mockComponent()}
currentUser={mockLoggedInUser()}
host="https://sonarcloud.io"
onDone={jest.fn()}
organization="use-the-force"
os="linux"
projectKey="luke-lightsaber"
toggleModal={jest.fn()}
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

+ 0
- 45
server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/__snapshots__/ClangGCCOtherCI-test.tsx.snap View File

@@ -1,45 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
className="huge-spacer-top"
>
<h4
className="huge-spacer-top spacer-bottom"
>
onboarding.analysis.sq_scanner.header.ci
</h4>
<CodeSnippet
snippet="
local SONAR_SCANNER_VERSION=onboarding.analysis.sonar_scanner_version
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION
rm -rf $SONAR_SCANNER_HOME
mkdir -p $SONAR_SCANNER_HOME
curl -sSLo $HOME/.sonar/sonar-scanner.zip http://repo1.maven.org/maven2/org/sonarsource/scanner/cli/sonar-scanner-cli/$SONAR_SCANNER_VERSION/sonar-scanner-cli-$SONAR_SCANNER_VERSION.zip
unzip $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
rm $HOME/.sonar/sonar-scanner.zip
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
export SONAR_SCANNER_OPTS=\\"-server\\"

curl -LsS https://sonarcloud.io/static/cpp/build-wrapper-linux-x86.zip > build-wrapper-linux-x86.zip
unzip build-wrapper-linux-x86.zip"
/>
<ClangGCCCommon
command1="build-wrapper-linux-x86-64 --out-dir bw-output make clean all"
command2={
Array [
"sonar-scanner",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.sources=.",
"-Dsonar.cfamily.build-wrapper-output=bw-output",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
onDone={[MockFunction]}
os="linux"
renderCommand2={[Function]}
/>
</div>
`;

+ 0
- 67
server/sonar-web/src/main/js/apps/tutorials/components/commands/OtherCI/__tests__/__snapshots__/OtherOtherCI-test.tsx.snap View File

@@ -1,67 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
className="huge-spacer-top"
>
<h4
className="huge-spacer-top spacer-bottom"
>
onboarding.analysis.sq_scanner.header.ci
</h4>
<CodeSnippet
snippet="
local SONAR_SCANNER_VERSION=onboarding.analysis.sonar_scanner_version
export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION
rm -rf $SONAR_SCANNER_HOME
mkdir -p $SONAR_SCANNER_HOME
curl -sSLo $HOME/.sonar/sonar-scanner.zip http://repo1.maven.org/maven2/org/sonarsource/scanner/cli/sonar-scanner-cli/$SONAR_SCANNER_VERSION/sonar-scanner-cli-$SONAR_SCANNER_VERSION.zip
unzip $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
rm $HOME/.sonar/sonar-scanner.zip
export PATH=$SONAR_SCANNER_HOME/bin:$PATH
export SONAR_SCANNER_OPTS=\\"-server\\""
/>
<h4
className="huge-spacer-top spacer-bottom"
>
onboarding.analysis.sq_scanner.execute.ci
</h4>
<InstanceMessage
message="onboarding.analysis.sq_scanner.execute.text.custom"
>
<Component />
</InstanceMessage>
<CodeSnippet
isOneLine={false}
render={[Function]}
snippet={
Array [
"sonar-scanner",
"-Dsonar.projectKey=luke-lightsaber",
"-Dsonar.organization=use-the-force",
"-Dsonar.sources=.",
"-Dsonar.host.url=https://sonarcloud.io",
"-Dsonar.login=sonarsource123",
]
}
/>
<p
className="big-spacer-top markdown"
dangerouslySetInnerHTML={
Object {
"__html": "onboarding.analysis.standard.docs",
}
}
/>
<div
className="big-spacer-top"
>
<Button
className="js-continue"
onClick={[MockFunction]}
>
onboarding.finish
</Button>
</div>
</div>
`;

+ 0
- 57
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/ClangGCCTravisSonarCloud.tsx View File

@@ -1,57 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { getSonarcloudAddonYml, getSonarcloudAddonYmlRender } from '../AnalysisCommandTravis';
import { Props } from '../ClangGCC';
import { CommonTravisSonarCloud } from './utils';

export function ClangGCCTravisSonarCloud(props: Props) {
const command = `${getSonarcloudAddonYml(props.organization)}

script:
- make clean
# Wraps the compilation with the Build Wrapper to generate configuration (used
# later by the SonarQube Scanner) into the "bw-output" folder
- build-wrapper-linux-x86-64 --out-dir bw-output make all
# Execute some tests
- make test
# And finally run the SonarQube analysis - read the "sonar-project.properties"
# file to see the specific configuration
- sonar-scanner`;

const renderCommand = () => (
<>
{getSonarcloudAddonYmlRender(props.organization)}
<br />
{`script:
- make clean
# Wraps the compilation with the Build Wrapper to generate configuration (used
# later by the SonarQube Scanner) into the "bw-output" folder
- build-wrapper-linux-x86-64 --out-dir bw-output make all
# Execute some tests
- make test
# And finally run the SonarQube analysis - read the "sonar-project.properties"
# file to see the specific configuration
- sonar-scanner`}
</>
);

return <CommonTravisSonarCloud command={command} renderCommand={renderCommand} />;
}

+ 0
- 115
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/JavaGradleTravisSonarCloud.tsx View File

@@ -1,115 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import {
getSonarcloudAddonYml,
getSonarcloudAddonYmlRender,
RequirementJavaBuild
} from '../AnalysisCommandTravis';
import { Props } from '../JavaGradle';

export function JavaGradleTravisSonarCloud(props: Props) {
const config = `plugins {
id "org.sonarqube" version "2.7"
}

sonarqube {
properties {
sonar.projectKey: ${props.projectKey}
}
}`;

const command = `${getSonarcloudAddonYml(props.organization)}

script:
- ./gradlew sonarqube`;

const renderCommand = () => (
<>
{getSonarcloudAddonYmlRender(props.organization)}
<br />
{`script:
- ./gradlew sonarqube`}
</>
);

return (
<div>
<h2 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.travis.setup.title.a')}
</h2>

<RequirementJavaBuild />

<hr className="no-horizontal-margins" />

<h2 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.travis.setup.title.b')}
</h2>

<FormattedMessage
defaultMessage={translate('onboarding.analysis.java.gradle.text.1.sonarcloud')}
id="onboarding.analysis.java.gradle.text.1.sonarcloud"
values={{
file: <code>build.gradle</code>,
plugin: <code>org.sonarqube</code>
}}
/>

<CodeSnippet snippet={config} />

<FormattedMessage
defaultMessage={translate('onboarding.analysis.java.gradle.text.2.sonarcloud')}
id="onboarding.analysis.java.gradle.text.2.sonarcloud"
values={{
file: <code>.travis.yml</code>
}}
/>

<CodeSnippet render={renderCommand} snippet={command} />

<FormattedMessage
defaultMessage={translate('onboarding.analysis.sq_scanner.docs_use_case')}
id="onboarding.analysis.sq_scanner.docs_use_case"
values={{
link: (
<a
href="http://redirect.sonarsource.com/doc/gradle.html"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.sqscanner.docs.gradle.title')}
</a>
),
useCaseLink: (
<a
href="https://github.com/SonarSource/sq-com_example_java-gradle-travis"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.sqscanner.docs.gradle.example_project.title')}
</a>
)
}}
/>
</div>
);
}

+ 0
- 78
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/JavaMavenTravisSonarCloud.tsx View File

@@ -1,78 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import {
getSonarcloudAddonYml,
getSonarcloudAddonYmlRender,
RequirementJavaBuild
} from '../AnalysisCommandTravis';
import { Props } from '../JavaMaven';

export function JavaMavenTravisSonarCloud(props: Props) {
const command = `${getSonarcloudAddonYml(props.organization)}

script:
# the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar`;

const renderCommand = () => (
<>
{getSonarcloudAddonYmlRender(props.organization)}
<br />
{`script:
# the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar -Dsonar.projectKey=${props.projectKey}`}
</>
);

return (
<div>
<h2 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.travis.setup.title.a')}
</h2>

<RequirementJavaBuild />

<hr className="no-horizontal-margins" />

<h2 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.travis.setup.title.b')}
</h2>

<p
className="spacer-bottom markdown"
dangerouslySetInnerHTML={{
__html: translate('onboarding.analysis.java.maven.text.sonarcloud')
}}
/>

<CodeSnippet render={renderCommand} snippet={command} />

<p
className="big-spacer-top markdown"
dangerouslySetInnerHTML={{
__html: translate('onboarding.analysis.java.maven.docs.sonarcloud')
}}
/>
</div>
);
}

+ 0
- 43
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/OtherTravisSonarCloud.tsx View File

@@ -1,43 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { getSonarcloudAddonYml, getSonarcloudAddonYmlRender } from '../AnalysisCommandTravis';
import { Props } from '../Other';
import { CommonTravisSonarCloud } from './utils';

export function OtherTravisSonarCloud(props: Props) {
const command = `${getSonarcloudAddonYml(props.organization)}

script:
# the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis
- sonar-scanner`;

const renderCommand = () => (
<>
{getSonarcloudAddonYmlRender(props.organization)}
<br />
{`script:
# the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis
- sonar-scanner`}
</>
);

return <CommonTravisSonarCloud command={command} renderCommand={renderCommand} />;
}

+ 0
- 37
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/ClangGCCTravisSonarCloud-test.tsx View File

@@ -1,37 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { ClangGCCTravisSonarCloud } from '../ClangGCCTravisSonarCloud';

it('should render correctly', () => {
expect(
shallow(
<ClangGCCTravisSonarCloud
host="https://sonarcloud.io"
organization="use-the-force"
os="linux"
projectKey="luke-lightsaber"
small={true}
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

+ 0
- 35
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/JavaGradleTravisSonarCloud-test.tsx View File

@@ -1,35 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { JavaGradleTravisSonarCloud } from '../JavaGradleTravisSonarCloud';

it('should render correctly', () => {
expect(
shallow(
<JavaGradleTravisSonarCloud
host="https://sonarcloud.io"
organization="use-the-force"
projectKey="luke-lightsaber"
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

+ 0
- 35
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/JavaMavenTravisSonarCloud-test.tsx View File

@@ -1,35 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { JavaMavenTravisSonarCloud } from '../JavaMavenTravisSonarCloud';

it('should render correctly', () => {
expect(
shallow(
<JavaMavenTravisSonarCloud
host="https://sonarcloud.io"
organization="use-the-force"
projectKey="luke-lightsaber"
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

+ 0
- 36
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/OtherTravisSonarCloud-test.tsx View File

@@ -1,36 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { OtherTravisSonarCloud } from '../OtherTravisSonarCloud';

it('should render correctly', () => {
expect(
shallow(
<OtherTravisSonarCloud
host="https://sonarcloud.io"
organization="use-the-force"
os="linux"
projectKey="luke-lightsaber"
token="sonarsource123"
/>
)
).toMatchSnapshot();
});

+ 0
- 23
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/ClangGCCTravisSonarCloud-test.tsx.snap View File

@@ -1,23 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<CommonTravisSonarCloud
command="addons:
sonarcloud:
organization: \\"use-the-force\\"
token:
secure: \\"**************************\\" # encrypted value of your token

script:
- make clean
# Wraps the compilation with the Build Wrapper to generate configuration (used
# later by the SonarQube Scanner) into the \\"bw-output\\" folder
- build-wrapper-linux-x86-64 --out-dir bw-output make all
# Execute some tests
- make test
# And finally run the SonarQube analysis - read the \\"sonar-project.properties\\"
# file to see the specific configuration
- sonar-scanner"
renderCommand={[Function]}
/>
`;

+ 0
- 89
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/JavaGradleTravisSonarCloud-test.tsx.snap View File

@@ -1,89 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div>
<h2
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.travis.setup.title.a
</h2>
<RequirementJavaBuild />
<hr
className="no-horizontal-margins"
/>
<h2
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.travis.setup.title.b
</h2>
<FormattedMessage
defaultMessage="onboarding.analysis.java.gradle.text.1.sonarcloud"
id="onboarding.analysis.java.gradle.text.1.sonarcloud"
values={
Object {
"file": <code>
build.gradle
</code>,
"plugin": <code>
org.sonarqube
</code>,
}
}
/>
<CodeSnippet
snippet="plugins {
id \\"org.sonarqube\\" version \\"2.7\\"
}

sonarqube {
properties {
sonar.projectKey: luke-lightsaber
}
}"
/>
<FormattedMessage
defaultMessage="onboarding.analysis.java.gradle.text.2.sonarcloud"
id="onboarding.analysis.java.gradle.text.2.sonarcloud"
values={
Object {
"file": <code>
.travis.yml
</code>,
}
}
/>
<CodeSnippet
render={[Function]}
snippet="addons:
sonarcloud:
organization: \\"use-the-force\\"
token:
secure: \\"**************************\\" # encrypted value of your token

script:
- ./gradlew sonarqube"
/>
<FormattedMessage
defaultMessage="onboarding.analysis.sq_scanner.docs_use_case"
id="onboarding.analysis.sq_scanner.docs_use_case"
values={
Object {
"link": <a
href="http://redirect.sonarsource.com/doc/gradle.html"
rel="noopener noreferrer"
target="_blank"
>
onboarding.analysis.sqscanner.docs.gradle.title
</a>,
"useCaseLink": <a
href="https://github.com/SonarSource/sq-com_example_java-gradle-travis"
rel="noopener noreferrer"
target="_blank"
>
onboarding.analysis.sqscanner.docs.gradle.example_project.title
</a>,
}
}
/>
</div>
`;

+ 0
- 48
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/JavaMavenTravisSonarCloud-test.tsx.snap View File

@@ -1,48 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div>
<h2
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.travis.setup.title.a
</h2>
<RequirementJavaBuild />
<hr
className="no-horizontal-margins"
/>
<h2
className="spacer-bottom spacer-top"
>
onboarding.analysis.with.travis.setup.title.b
</h2>
<p
className="spacer-bottom markdown"
dangerouslySetInnerHTML={
Object {
"__html": "onboarding.analysis.java.maven.text.sonarcloud",
}
}
/>
<CodeSnippet
render={[Function]}
snippet="addons:
sonarcloud:
organization: \\"use-the-force\\"
token:
secure: \\"**************************\\" # encrypted value of your token

script:
# the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar"
/>
<p
className="big-spacer-top markdown"
dangerouslySetInnerHTML={
Object {
"__html": "onboarding.analysis.java.maven.docs.sonarcloud",
}
}
/>
</div>
`;

+ 0
- 16
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/__tests__/__snapshots__/OtherTravisSonarCloud-test.tsx.snap View File

@@ -1,16 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<CommonTravisSonarCloud
command="addons:
sonarcloud:
organization: \\"use-the-force\\"
token:
secure: \\"**************************\\" # encrypted value of your token

script:
# the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis
- sonar-scanner"
renderCommand={[Function]}
/>
`;

+ 0
- 72
server/sonar-web/src/main/js/apps/tutorials/components/commands/TravisSonarCloud/utils.tsx View File

@@ -1,72 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../../../components/common/CodeSnippet';
import { RequirementOtherBuild } from '../AnalysisCommandTravis';

interface CommonTravisSonarCloudProps {
command: string;
renderCommand: () => JSX.Element;
}

export function CommonTravisSonarCloud({ command, renderCommand }: CommonTravisSonarCloudProps) {
return (
<div>
<h2 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.travis.setup.title.a')}
</h2>

<RequirementOtherBuild />

<hr className="no-horizontal-margins" />

<h2 className="spacer-bottom spacer-top">
{translate('onboarding.analysis.with.travis.setup.title.b')}
</h2>

<FormattedMessage
defaultMessage={translate('onboarding.analysis.sq_scanner.text.sonarcloud')}
id="onboarding.analysis.sq_scanner.text.sonarcloud"
values={{
file: <code>.travis.yml</code>
}}
/>

<CodeSnippet render={renderCommand} snippet={command} />

<FormattedMessage
defaultMessage={translate('onboarding.analysis.sq_scanner.docs')}
id="onboarding.analysis.sq_scanner.docs"
values={{
link: (
<a
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html"
rel="noopener noreferrer"
target="_blank">
{translate('onboarding.analysis.sq_scanner.docs_link')}
</a>
)
}}
/>
</div>
);
}

+ 0
- 22
server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommand-test.tsx View File

@@ -21,10 +21,6 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import AnalysisCommand from '../AnalysisCommand';

jest.mock('../../../../../helpers/system', () => ({
isSonarCloud: jest.fn().mockReturnValue(true)
}));

jest.mock('sonar-ui-common/helpers/urls', () => ({
getHostUrl: () => 'HOST'
}));
@@ -44,24 +40,6 @@ it('display c# command', () => {
).toMatchSnapshot();
});

it('display c-family command', () => {
expect(
getWrapper({
languageConfig: { language: 'c-family', cFamilyCompiler: 'msvc', projectKey: 'project-foo' }
})
).toMatchSnapshot();
expect(
getWrapper({
languageConfig: {
language: 'c-family',
cFamilyCompiler: 'clang-gcc',
os: 'linux',
projectKey: 'project-foo'
}
})
).toMatchSnapshot();
});

it('display others command', () => {
expect(
getWrapper({

+ 0
- 131
server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommandCustom-test.tsx View File

@@ -1,131 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { ProjectAnalysisModes } from '../../ProjectAnalysisStepFromBuildTool';
import AnalysisCommandTravis, {
RenderCommandForClangOrGCC,
RenderCommandForGradle,
RenderCommandForMaven,
RenderCommandForOther
} from '../AnalysisCommandCustom';

const organization = 'org';
const token = '123';

it('should render for Clang or GCC', () => {
expect(shallowRender('make')).toMatchSnapshot();
});

it('should render for Gradle', () => {
expect(shallowRender('gradle')).toMatchSnapshot();
});

it('should render for Maven', () => {
expect(shallowRender('maven')).toMatchSnapshot();
});

it('should render for other', () => {
expect(shallowRender('other')).toMatchSnapshot();
});

it('should render for unsupported build systems', () => {
expect(shallowRender('whatever')).toMatchSnapshot();
});

it('should render RenderCommandForClangOrGCC', () => {
const render = (token?: string) =>
shallow(
<RenderCommandForClangOrGCC
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
toggleModal={jest.fn()}
token={token}
/>
);

expect(render()).toMatchSnapshot();
expect(render('123')).toMatchSnapshot();
});

it('should render RenderCommandForGradle', () => {
const render = (token?: string) =>
shallow(
<RenderCommandForGradle
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
toggleModal={jest.fn()}
token={token}
/>
);

expect(render()).toMatchSnapshot();
expect(render('123')).toMatchSnapshot();
});

it('should render RenderCommandForMaven', () => {
const render = (token?: string) =>
shallow(
<RenderCommandForMaven
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
toggleModal={jest.fn()}
token={token}
/>
);

expect(render()).toMatchSnapshot();
expect(render('123')).toMatchSnapshot();
});

it('should render RenderCommandForOther', () => {
const render = (token?: string) =>
shallow(
<RenderCommandForOther
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
toggleModal={jest.fn()}
token={token}
/>
);

expect(render()).toMatchSnapshot();
expect(render('123')).toMatchSnapshot();
});

function shallowRender(buildType: string) {
return shallow(
<AnalysisCommandTravis
buildType={buildType}
component={mockComponent()}
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
organization={organization}
setToken={jest.fn()}
token={token}
/>
);
}

+ 0
- 118
server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommandOtherCI-test.tsx View File

@@ -1,118 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent, mockLoggedInUser } from '../../../../../helpers/testMocks';
import { ProjectAnalysisModes } from '../../ProjectAnalysisStepFromBuildTool';
import AnalysisCommandOtherCI, {
AnalysisCommandCommon,
RenderCommandForClangOrGCC,
RenderCommandForOther
} from '../AnalysisCommandOtherCI';

const organization = 'org';
const token = '123';

it('should render for Clang or GCC', () => {
expect(shallowRender('make')).toMatchSnapshot();
});

it('should render for Gradle', () => {
expect(shallowRender('gradle')).toMatchSnapshot();
});

it('should render for Maven', () => {
expect(shallowRender('maven')).toMatchSnapshot();
});

it('should render for other', () => {
expect(shallowRender('other')).toMatchSnapshot();
});

it('should render for unsupported build systems', () => {
expect(shallowRender('whatever')).toMatchSnapshot();
});

it('should render AnalysisCommandCustom correctly', () => {
const getBuildOptions = jest.fn().mockResolvedValue(null);
const wrapper = shallow(
<AnalysisCommandCommon
buildType="maven"
component={mockComponent()}
currentUser={mockLoggedInUser()}
getBuildOptions={getBuildOptions}
mode={ProjectAnalysisModes.CI}
onDone={jest.fn()}
organization={organization}
setToken={jest.fn()}
token={token}
/>
);

expect(wrapper).toMatchSnapshot();
expect(getBuildOptions).toHaveBeenCalled();
});

it('should render RenderCommandForClangOrGCC', () => {
const render = (token?: string) =>
shallow(
<RenderCommandForClangOrGCC
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
toggleModal={jest.fn()}
token={token}
/>
);

expect(render()).toMatchSnapshot();
expect(render('123')).toMatchSnapshot();
});

it('should render RenderCommandForOther', () => {
const render = (token?: string) =>
shallow(
<RenderCommandForOther
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.Custom}
onDone={jest.fn()}
toggleModal={jest.fn()}
token={token}
/>
);

expect(render()).toMatchSnapshot();
expect(render('123')).toMatchSnapshot();
});

function shallowRender(buildType: string) {
return shallow(
<AnalysisCommandOtherCI
buildType={buildType}
component={mockComponent()}
currentUser={mockLoggedInUser()}
mode={ProjectAnalysisModes.CI}
onDone={jest.fn()}
organization={organization}
setToken={jest.fn()}
token={token}
/>
);
}

+ 0
- 123
server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/AnalysisCommandTravis-test.tsx View File

@@ -1,123 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import AnalysisCommandTravis, {
getSonarcloudAddonYml,
getSonarcloudAddonYmlRender,
RenderCommandForClangOrGCC,
RenderCommandForGradle,
RenderCommandForMaven,
RenderCommandForOther,
RequirementJavaBuild,
RequirementOtherBuild
} from '../AnalysisCommandTravis';

const component = {
key: 'foo',
analysisDate: '2016-01-01',
breadcrumbs: [],
name: 'Foo',
organization: 'org',
qualifier: 'TRK',
version: '0.0.1'
};

const organization = 'org';
const token = '123';

it('should render for Clang or GCC', () => {
expect(
shallowRender('make')
.find(RenderCommandForClangOrGCC)
.exists()
).toBe(true);
});

it('should render for Gradle', () => {
expect(
shallowRender('gradle')
.find(RenderCommandForGradle)
.exists()
).toBe(true);
});

it('should render for Maven', () => {
expect(
shallowRender('maven')
.find(RenderCommandForMaven)
.exists()
).toBe(true);
});

it('should render for other', () => {
expect(
shallowRender('other')
.find(RenderCommandForOther)
.exists()
).toBe(true);
});

it('should render nothing for unsupported build', () => {
expect(
shallowRender()
.find(RenderCommandForOther)
.exists()
).toBe(false);

expect(
shallowRender('anotherBuild')
.find(RenderCommandForOther)
.exists()
).toBe(false);
});

it('should render nothing when there is no project key', () => {
expect(shallow(<RenderCommandForClangOrGCC />).html()).toBeNull();
expect(shallow(<RenderCommandForGradle />).html()).toBeNull();
expect(shallow(<RenderCommandForMaven />).html()).toBeNull();
expect(shallow(<RenderCommandForOther />).html()).toBeNull();
});

it('should render the sonarcloud yaml for travis', () => {
expect(getSonarcloudAddonYml()).toMatchSnapshot();
expect(getSonarcloudAddonYml('SonarSource')).toMatchSnapshot();
});

it('should render the sonarcloud yaml for travis - render', () => {
expect(getSonarcloudAddonYmlRender()).toMatchSnapshot();
expect(getSonarcloudAddonYmlRender('SonarSource')).toMatchSnapshot();
});

it('should render the requirements for builds', () => {
expect(shallow(<RequirementJavaBuild />)).toMatchSnapshot();
expect(shallow(<RequirementOtherBuild />)).toMatchSnapshot();
});

function shallowRender(buildType?: string) {
return shallow(
<AnalysisCommandTravis
buildType={buildType}
component={component}
organization={organization}
token={token}
/>
);
}

+ 0
- 0
server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/BuildWrapper-test.tsx View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save