]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14640 Add sonar.projectName scanner parameter in tutorials
authorstanislavh <stanislav.honcharov@sonarsource.com>
Wed, 15 Feb 2023 09:25:20 +0000 (10:25 +0100)
committersonartech <sonartech@sonarsource.com>
Fri, 17 Feb 2023 20:02:54 +0000 (20:02 +0000)
48 files changed:
server/sonar-web/src/main/js/api/mocks/UserTokensMock.ts
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/BranchAnalysisStepContent.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/AzurePipelinesTutorial-it.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/__snapshots__/AzurePipelinesTutorial-it.tsx.snap
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaGradle.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaMaven.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PrepareAnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/AnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/PreambuleYaml-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/commands/Maven.ts
server/sonar-web/src/main/js/components/tutorials/github-action/commands/Gradle.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/commands/JavaMaven.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/Gradle-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/gitlabci/GitLabCITutorial.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/YmlFileStep.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/YmlFileStep-test.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/__snapshots__/GitLabCITutorial-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/gitlabci/commands/PipeCommand.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/commands/__tests__/PipeCommand-test.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/commands/__tests__/__snapshots__/PipeCommand-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Gradle-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/Maven-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/other/TokenStep.tsx
server/sonar-web/src/main/js/components/tutorials/other/__tests__/BuildToolForm-test.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/DoneNextSteps-test.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-test.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/ProjectAnalysisStep-test.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/TokenStep-test.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/BuildToolForm-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/DoneNextSteps-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/OtherTutorial-it.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/OtherTutorial-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/ProjectAnalysisStep-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/TokenStep-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx
server/sonar-web/src/main/js/components/tutorials/other/commands/JavaMaven.tsx
server/sonar-web/src/main/js/components/tutorials/other/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/other/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/test-utils.ts
server/sonar-web/src/main/js/components/tutorials/utils.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 347e6733ba3d0c82c8b14e8401cb428ec953e480..4c6de69c5d9512f80a3c11d1f035169e27609629 100644 (file)
@@ -22,9 +22,6 @@ import { mockUserToken } from '../../helpers/mocks/token';
 import { NewUserToken, TokenType, UserToken } from '../../types/token';
 import { generateToken, getTokens, revokeToken } from '../user-tokens';
 
-const RANDOM_RADIX = 36;
-const RANDOM_PREFIX = 2;
-
 const defaultTokens = [
   mockUserToken({
     name: 'local-scanner',
@@ -77,7 +74,7 @@ export default class UserTokensMock {
       type,
       projectKey,
       isExpired: false,
-      token: Math.random().toString(RANDOM_RADIX).slice(RANDOM_PREFIX),
+      token: `generatedtoken${this.tokens.length}`,
       createdAt: '2022-04-04T04:04:04+0000',
       expirationDate,
     };
index d4d6c83708a5f7b90445f661b535c70cec0b2419..8b74202c41e0c66419f7174e96a3afd42aac7903 100644 (file)
@@ -62,6 +62,7 @@ export function BranchAnalysisStepContent(props: BranchesAnalysisStepProps) {
         onStepValidationChange={onStepValidationChange}
         buildTool={buildTechnology}
         projectKey={component.key}
+        projectName={component.name}
       />
     </>
   );
index 234a84bebbb7ee4cfa49ab049c275269ceca1f7f..ed24e8b5b7f8913a8a781c0c592f5098e0f19039 100644 (file)
@@ -27,6 +27,7 @@ import { mockLanguage, mockLoggedInUser } from '../../../../helpers/testMocks';
 import { renderApp, RenderContext } from '../../../../helpers/testReactTestingUtils';
 import { Permissions } from '../../../../types/permissions';
 import { TokenType } from '../../../../types/token';
+import { getCopyToClipboardValue } from '../../test-utils';
 import { OSs } from '../../types';
 import AzurePipelinesTutorial, { AzurePipelinesTutorialProps } from '../AzurePipelinesTutorial';
 
@@ -250,7 +251,3 @@ async function clickButton(user: UserEvent, name: string, context?: HTMLElement)
 async function goToNextStep(user: UserEvent) {
   await clickButton(user, 'continue');
 }
-
-function getCopyToClipboardValue(i = 0, name = 'copy_to_clipboard') {
-  return screen.getAllByRole('button', { name })[i].getAttribute('data-clipboard-text');
-}
index f02fe7b96215fae3ad3068e70606ae1ac16c77f4..cba7e2bcd1284c31d5ab23faff75a151153fa850 100644 (file)
@@ -31,12 +31,16 @@ exports[`should render correctly and allow navigating between the different step
 "# Additional properties that will be passed to the scanner,
 # Put one key=value per line, example:
 # sonar.exclusions=**/*.bin
-sonar.projectKey=foo"
+sonar.projectKey=foo
+sonar.projectName=MyProject
+"
 `;
 
 exports[`should render correctly and allow navigating between the different steps: maven, copy additional properties 1`] = `
 "# Additional properties that will be passed to the scanner,
 # Put one key=value per line, example:
 # sonar.exclusions=**/*.bin
-sonar.projectKey=foo"
+sonar.projectKey=foo
+sonar.projectName=MyProject
+"
 `;
index 31db342133b8ebe04f70678337dfe422e2fe1c1a..9b2078e5941ca2084fd0ba640c2701f5b11e101b 100644 (file)
@@ -27,12 +27,13 @@ import Other from './Other';
 
 export interface AnalysisCommandProps {
   projectKey: string;
+  projectName: string;
   buildTool?: BuildTools;
   onStepValidationChange: (isValid: boolean) => void;
 }
 
 export default function AnalysisCommand(props: AnalysisCommandProps) {
-  const { buildTool, projectKey } = props;
+  const { buildTool, projectKey, projectName } = props;
 
   React.useEffect(() => {
     if (buildTool && buildTool !== BuildTools.CFamily) {
@@ -45,10 +46,10 @@ export default function AnalysisCommand(props: AnalysisCommandProps) {
   }
   switch (buildTool) {
     case BuildTools.Maven:
-      return <JavaMaven projectKey={projectKey} />;
+      return <JavaMaven projectKey={projectKey} projectName={projectName} />;
 
     case BuildTools.Gradle:
-      return <JavaGradle projectKey={projectKey} />;
+      return <JavaGradle projectKey={projectKey} projectName={projectName} />;
 
     case BuildTools.DotNet:
       return <DotNet projectKey={projectKey} />;
index 4ad6263d34eb67b0220988bb92f96dc5c0f2b901..5e098e2a243fad0b9c58429f3ba85cb0d4bf5487 100644 (file)
@@ -28,10 +28,11 @@ import PublishSteps from './PublishSteps';
 
 export interface JavaGradleProps {
   projectKey: string;
+  projectName: string;
 }
 
 export default function JavaGradle(props: JavaGradleProps) {
-  const { projectKey } = props;
+  const { projectKey, projectName } = props;
 
   return (
     <>
@@ -46,6 +47,7 @@ export default function JavaGradle(props: JavaGradleProps) {
             buildTool={BuildTools.Gradle}
             kind={PrepareType.JavaMavenGradle}
             projectKey={projectKey}
+            projectName={projectName}
           />
         </li>
 
index 3ef4d3847a0e738f6712b743151f5f60866da6fc..a7e7f9941bf5787035c38f3473b4719e70a004c1 100644 (file)
@@ -28,10 +28,11 @@ import PublishSteps from './PublishSteps';
 
 export interface JavaMavenProps {
   projectKey: string;
+  projectName: string;
 }
 
 export default function JavaMaven(props: JavaMavenProps) {
-  const { projectKey } = props;
+  const { projectKey, projectName } = props;
   return (
     <>
       <AlertClassicEditor />
@@ -45,6 +46,7 @@ export default function JavaMaven(props: JavaMavenProps) {
             buildTool={BuildTools.Gradle}
             kind={PrepareType.JavaMavenGradle}
             projectKey={projectKey}
+            projectName={projectName}
           />
         </li>
 
index cc7f878b1d12797e60b44646d84d71364106f0c5..dc6e5975f2fb60ec62fa8521ab38898cd1f2ac8c 100644 (file)
@@ -35,17 +35,20 @@ export interface PrepareAnalysisCommandProps {
   buildTool: BuildTools;
   kind: PrepareType;
   projectKey: string;
+  projectName?: string;
 }
 
 export default function PrepareAnalysisCommand(props: PrepareAnalysisCommandProps) {
-  const { buildTool, kind, projectKey } = props;
+  const { buildTool, kind, projectKey, projectName } = props;
 
   const ADDITIONAL_PROPERTY = 'sonar.cfamily.build-wrapper-output=bw-output';
 
   const MAVEN_GRADLE_PROPS_SNIPPET = `# Additional properties that will be passed to the scanner,
 # Put one key=value per line, example:
 # sonar.exclusions=**/*.bin
-sonar.projectKey=${projectKey}`;
+sonar.projectKey=${projectKey}
+sonar.projectName=${projectName}
+`;
 
   return (
     <ul className="list-styled list-alpha spacer-top">
index 80a5189645ed427aff7620b4245cd7ad52756f9b..3998cb59bccb4344d40749862128057c17e90595 100644 (file)
@@ -41,7 +41,12 @@ export interface AnalysisCommandProps extends WithAvailableFeaturesProps {
 }
 
 const YamlTemplate: Dictionary<
-  (branchesEnabled?: boolean, mainBranchName?: string, projectKey?: string) => string
+  (
+    branchesEnabled?: boolean,
+    mainBranchName?: string,
+    projectKey?: string,
+    projectName?: string
+  ) => string
 > = {
   [BuildTools.Gradle]: gradleExample,
   [BuildTools.Maven]: mavenExample,
@@ -58,7 +63,12 @@ export function AnalysisCommand(props: AnalysisCommandProps) {
     return null;
   }
 
-  const yamlTemplate = YamlTemplate[buildTool](branchSupportEnabled, mainBranchName, component.key);
+  const yamlTemplate = YamlTemplate[buildTool](
+    branchSupportEnabled,
+    mainBranchName,
+    component.key,
+    component.name
+  );
 
   return (
     <>
index 55e1d3f0380758b8c7ae863c2ff2bf62a3ca1324..d54087fa9f14025e0d128da02e4d316e6dba8e65 100644 (file)
@@ -51,7 +51,7 @@ export function PreambuleYaml(props: PreambuleYamlProps) {
               sq: <code className="rule">org.sonarqube</code>,
             }}
           />
-          <CodeSnippet snippet={buildGradleSnippet(component.key)} />
+          <CodeSnippet snippet={buildGradleSnippet(component.key, component.name)} />
         </li>
       );
     case BuildTools.CFamily:
index 2b454e96ca63cca5200b7eb118b8561fe81c786f..ac895b8390a1f147a11c7e050c83c746694ed87b 100644 (file)
@@ -402,7 +402,7 @@ definitions:
           - maven
           - sonar
         script:
-          - mvn verify sonar:sonar -Dsonar.projectKey=my-project
+          - mvn verify sonar:sonar -Dsonar.projectKey=my-project -Dsonar.projectName='MyProject'
   caches:
     sonar: ~/.sonar
 
@@ -457,7 +457,7 @@ definitions:
           - maven
           - sonar
         script:
-          - mvn verify sonar:sonar -Dsonar.projectKey=my-project
+          - mvn verify sonar:sonar -Dsonar.projectKey=my-project -Dsonar.projectName='MyProject'
   caches:
     sonar: ~/.sonar
 
index 267f1b54a7a5ddebdad3dceac0d761a5883215fc..f4662e442ec84ccb4333dbdfdc8edca4790dedac 100644 (file)
@@ -64,6 +64,7 @@ exports[`should render correctly for gradle 1`] = `
 sonar {
   properties {
     property "sonar.projectKey", "my-project"
+    property "sonar.projectName", "MyProject"
   }
 }"
   />
index e67693b01380eed69f4416d93b4e1d8139b89e31..16f1b7a920bff56804fa56af6f34b73e5fb8abe0 100644 (file)
@@ -20,7 +20,8 @@
 export default function mavenExample(
   branchesEnabled: boolean,
   mainBranchName: string,
-  projectKey: string
+  projectKey: string,
+  projectName: string
 ) {
   return `image: maven:3-openjdk-11
 
@@ -32,7 +33,7 @@ definitions:
           - maven
           - sonar
         script:
-          - mvn verify sonar:sonar -Dsonar.projectKey=${projectKey}
+          - mvn verify sonar:sonar -Dsonar.projectKey=${projectKey} -Dsonar.projectName='${projectName}'
   caches:
     sonar: ~/.sonar
 
index 17874ed23f8db9629a9636b52054e66ccef5e411..7d1a8247e219bf125c1233222e9b670b946e2c9e 100644 (file)
@@ -79,7 +79,7 @@ export default function Gradle(props: GradleProps) {
             sq: <code className="rule">org.sonarqube</code>,
           }}
         />
-        <CodeSnippet snippet={buildGradleSnippet(component.key)} />
+        <CodeSnippet snippet={buildGradleSnippet(component.key, component.name)} />
       </li>
       <CreateYmlFile
         yamlFileName=".github/workflows/build.yml"
index 9f748a8d3d02ad0bdb26c26552d5849332e58ed0..c9b253dd3e840b848dd1bf900125f6e5fa497956 100644 (file)
@@ -31,7 +31,7 @@ export interface JavaMavenProps {
   onDone: () => void;
 }
 
-function mavenYamlSteps(projectKey: string) {
+function mavenYamlSteps(projectKey: string, projectName: string) {
   return `
       - name: Set up JDK 11
         uses: actions/setup-java@v1
@@ -54,7 +54,7 @@ function mavenYamlSteps(projectKey: string) {
           GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
           SONAR_TOKEN: \${{ secrets.SONAR_TOKEN }}
           SONAR_HOST_URL: \${{ secrets.SONAR_HOST_URL }}
-        run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=${projectKey}`;
+        run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=${projectKey} -Dsonar.projectName='${projectName}'`;
 }
 
 export default function JavaMaven(props: JavaMavenProps) {
@@ -67,7 +67,7 @@ export default function JavaMaven(props: JavaMavenProps) {
           mainBranchName,
           !!branchesEnabled,
           GITHUB_ACTIONS_RUNS_ON_LINUX,
-          mavenYamlSteps(component.key)
+          mavenYamlSteps(component.key, component.name)
         )}
       />
       <FinishButton onClick={props.onDone} />
index 10bac0a5d7a97946472073c5c17f808d28bd4d98..c57af2d85a55c0b0f95a3fae361a2eff06e497cc 100644 (file)
@@ -36,6 +36,7 @@ exports[`should render correctly 1`] = `
 sonar {
   properties {
     property "sonar.projectKey", "my-project"
+    property "sonar.projectName", "MyProject"
   }
 }"
     />
@@ -124,6 +125,7 @@ exports[`should render correctly: without branch enabled 1`] = `
 sonar {
   properties {
     property "sonar.projectKey", "my-project"
+    property "sonar.projectName", "MyProject"
   }
 }"
     />
index c26604e439ebad031954b01ea0c7491b14efe991..4b5b2b2a6db2a1dc018c181bb7d314b78ca2220b 100644 (file)
@@ -42,7 +42,7 @@ jobs:
           GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
           SONAR_TOKEN: \${{ secrets.SONAR_TOKEN }}
           SONAR_HOST_URL: \${{ secrets.SONAR_HOST_URL }}
-        run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=my-project"
+        run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=my-project -Dsonar.projectName='MyProject'"
   />
   <FinishButton
     onClick={[MockFunction]}
@@ -91,7 +91,7 @@ jobs:
           GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
           SONAR_TOKEN: \${{ secrets.SONAR_TOKEN }}
           SONAR_HOST_URL: \${{ secrets.SONAR_HOST_URL }}
-        run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=my-project"
+        run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=my-project -Dsonar.projectName='MyProject'"
   />
   <FinishButton
     onClick={[MockFunction]}
index 27fd8574f56e4eeaab43c64bf2d28acbf153464a..ce390a784d74e55659137d343b0d2c2636a3c6b3 100644 (file)
@@ -68,7 +68,6 @@ export default function GitLabCITutorial(props: GitLabCITutorialProps) {
         onDone={() => setStep(Steps.ALL_SET)}
         onOpen={() => setStep(Steps.YML)}
         open={step === Steps.YML}
-        projectKey={component.key}
       />
 
       <AllSetStep
index 7c3a5ad5ec21b3f29686af139e2978a6437b5b23..e66962d295ca631ccae2a0e9027b72fb3b0cbd11 100644 (file)
@@ -43,7 +43,6 @@ export interface YmlFileStepProps extends WithAvailableFeaturesProps {
   onDone: () => void;
   onOpen: () => void;
   open: boolean;
-  projectKey: string;
   mainBranchName: string;
 }
 
@@ -51,13 +50,14 @@ const mavenSnippet = () => `<properties>
   <sonar.qualitygate.wait>true</sonar.qualitygate.wait>
 </properties>`;
 
-const gradleSnippet = (key: string) => `plugins {
+const gradleSnippet = (key: string, name: string) => `plugins {
   id "org.sonarqube" version "${GRADLE_SCANNER_VERSION}"
 }
 
 sonar {
   properties {
     property "sonar.projectKey", "${key}"
+    property "sonar.projectName", "${name}"
     property "sonar.qualitygate.wait", true 
   }
 }`;
@@ -81,7 +81,7 @@ const filenameForBuildTool = {
 };
 
 export function YmlFileStep(props: YmlFileStepProps) {
-  const { open, finished, projectKey, mainBranchName, hasCLanguageFeature, component } = props;
+  const { open, finished, mainBranchName, hasCLanguageFeature, component } = props;
   const branchSupportEnabled = props.hasFeature(Feature.BranchSupport);
 
   const [buildTool, setBuildTool] = React.useState<BuildTools>();
@@ -130,7 +130,7 @@ export function YmlFileStep(props: YmlFileStepProps) {
                 ),
               }}
             />
-            <CodeSnippet snippet={snippetForBuildTool[buildTool](component.key)} />
+            <CodeSnippet snippet={snippetForBuildTool[buildTool](component.key, component.name)} />
           </li>
         )}
         {buildTool && (
@@ -159,7 +159,8 @@ export function YmlFileStep(props: YmlFileStepProps) {
                 buildTool={buildTool}
                 branchesEnabled={branchSupportEnabled}
                 mainBranchName={mainBranchName}
-                projectKey={projectKey}
+                projectKey={component.key}
+                projectName={component.name}
               />
             </div>
             <p className="little-spacer-bottom">
index 27f622a561468fd240d080e4d2824fc750871820..ecb14c207c92b4bb81300b87406b2f4e2dfb4cc1 100644 (file)
@@ -36,7 +36,6 @@ function shallowRender(props: Partial<YmlFileStepProps> = {}) {
       component={mockComponent()}
       hasFeature={jest.fn().mockReturnValue(true)}
       open={true}
-      projectKey="test"
       finished={true}
       mainBranchName="main"
       onDone={jest.fn()}
index 43c6bf6c5bd97ea3b0a7a48f99f3b1066902b0ea..ce506bca402306c30f83fe0454bb8b36d2965102 100644 (file)
@@ -80,7 +80,6 @@ exports[`should render correctly 1`] = `
     onDone={[Function]}
     onOpen={[Function]}
     open={false}
-    projectKey="my-project"
   />
   <AllSetStep
     alm="gitlab"
index 4b2d787d7ad38fc7f9fe61cc9deee1b84a093b48..a97667611612929b29f67950e8130a3a5ac157eb 100644 (file)
@@ -27,14 +27,15 @@ export interface PipeCommandProps {
   buildTool: BuildTools;
   mainBranchName: string;
   projectKey: string;
+  projectName: string;
 }
 
 const BUILD_TOOL_SPECIFIC = {
   [BuildTools.Gradle]: { image: 'gradle:jre11-slim', script: () => 'gradle sonar' },
   [BuildTools.Maven]: {
     image: 'maven:3.6.3-jdk-11',
-    script: (projectKey: string) => `
-    - mvn verify sonar:sonar -Dsonar.projectKey=${projectKey}`,
+    script: (projectKey: string, projectName: string) => `
+    - mvn verify sonar:sonar -Dsonar.projectKey=${projectKey} -Dsonar.projectName='${projectName}'`,
   },
   [BuildTools.DotNet]: {
     image: 'mcr.microsoft.com/dotnet/core/sdk:latest',
@@ -57,7 +58,7 @@ const BUILD_TOOL_SPECIFIC = {
 };
 
 export default function PipeCommand(props: PipeCommandProps) {
-  const { projectKey, branchesEnabled, buildTool, mainBranchName } = props;
+  const { projectKey, branchesEnabled, buildTool, mainBranchName, projectName } = props;
   let command: string;
   if (buildTool === BuildTools.CFamily) {
     command = `image: <image ready for your build toolchain>
@@ -108,7 +109,7 @@ sonarqube-check:
     key: "\${CI_JOB_NAME}"
     paths:
       - .sonar/cache
-  script: ${script(projectKey)}
+  script: ${script(projectKey, projectName)}
   allow_failure: true
   rules:
     ${onlyBlock}
index e4befcf613f64cfb64c3ae2ab093a70c104e1b64..1715a1fc1cbefabb01cd9cab4bfd59f1ea25e45f 100644 (file)
@@ -36,6 +36,7 @@ it.each([
         branchesEnabled={true}
         mainBranchName="main"
         projectKey="test"
+        projectName="Test Project"
       />
     )
   ).toMatchSnapshot('branches enabled');
@@ -46,6 +47,7 @@ it.each([
         branchesEnabled={true}
         mainBranchName="main"
         projectKey="test"
+        projectName="Test Project"
       />
     )
   ).toMatchSnapshot('branches not enabled');
index 607b06e2437774d84626ac67b1e3c661ddc9a942..b079bcadbc1bc269fdd1011756f59f7ed148722e 100644 (file)
@@ -195,7 +195,7 @@ exports[`should render correctly for maven: branches enabled 1`] = `
     paths:
       - .sonar/cache
   script: 
-    - mvn verify sonar:sonar -Dsonar.projectKey=test
+    - mvn verify sonar:sonar -Dsonar.projectKey=test -Dsonar.projectName='Test Project'
   allow_failure: true
   rules:
     - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
@@ -219,7 +219,7 @@ exports[`should render correctly for maven: branches not enabled 1`] = `
     paths:
       - .sonar/cache
   script: 
-    - mvn verify sonar:sonar -Dsonar.projectKey=test
+    - mvn verify sonar:sonar -Dsonar.projectKey=test -Dsonar.projectName='Test Project'
   allow_failure: true
   rules:
     - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
index ca2267f64e15a1268caff0a3c94ee52acd2e25db..478ae99d2dddd11ebcc56e34c17cf595bfe0089f 100644 (file)
@@ -45,7 +45,7 @@ export default function Gradle(props: LanguageProps) {
           filename="build.gradle"
           translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2"
         />
-        <CodeSnippet snippet={buildGradleSnippet(component.key)} />
+        <CodeSnippet snippet={buildGradleSnippet(component.key, component.name)} />
       </li>
       <CreateJenkinsfileBulletPoint snippet={JENKINSFILE_SNIPPET} />
       <FinishButton onClick={props.onDone} />
index 1287fb24877673eba0b8669c129b5f1f2046c682..b35210eeb2c774e0bc696b20392aad63c6255b0e 100644 (file)
@@ -22,7 +22,7 @@ import FinishButton from '../../components/FinishButton';
 import { LanguageProps } from '../JenkinsfileStep';
 import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint';
 
-function jenkinsfileSnippet(projectKey: string) {
+function jenkinsfileSnippet(projectKey: string, projectName: string) {
   return `node {
   stage('SCM') {
     checkout scm
@@ -30,7 +30,7 @@ function jenkinsfileSnippet(projectKey: string) {
   stage('SonarQube Analysis') {
     def mvn = tool 'Default Maven';
     withSonarQubeEnv() {
-      sh "\${mvn}/bin/mvn clean verify sonar:sonar -Dsonar.projectKey=${projectKey}"
+      sh "\${mvn}/bin/mvn clean verify sonar:sonar -Dsonar.projectKey=${projectKey} -Dsonar.projectName='${projectName}'"
     }
   }
 }`;
@@ -41,7 +41,7 @@ export default function Maven({ component, onDone }: LanguageProps) {
     <>
       <CreateJenkinsfileBulletPoint
         alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3"
-        snippet={jenkinsfileSnippet(component.key)}
+        snippet={jenkinsfileSnippet(component.key, component.name)}
       />
       <FinishButton onClick={onDone} />
     </>
index b35f87d237e46c3c6af7c49e8870299eeab7bd54..b231c344316a5b1529b090ee37ab9f503786c85b 100644 (file)
@@ -17,6 +17,7 @@ exports[`should render correctly 1`] = `
 sonar {
   properties {
     property "sonar.projectKey", "my-project"
+    property "sonar.projectName", "MyProject"
   }
 }"
     />
index 6b438876f92471a974cbee71405da6f932682d13..185cf0bacfd5533169c798998d6a59ffed696611 100644 (file)
@@ -11,7 +11,7 @@ exports[`should render correctly 1`] = `
   stage('SonarQube Analysis') {
     def mvn = tool 'Default Maven';
     withSonarQubeEnv() {
-      sh "\${mvn}/bin/mvn clean verify sonar:sonar -Dsonar.projectKey=my-project"
+      sh "\${mvn}/bin/mvn clean verify sonar:sonar -Dsonar.projectKey=my-project -Dsonar.projectName='MyProject'"
     }
   }
 }"
index 44d942e5a4916992d8db541bd67fd610b3e0b8ff..dd1e30b8d7a2ac4f3405011e66464fd34b87c88b 100644 (file)
@@ -323,7 +323,11 @@ export default class TokenStep extends React.PureComponent<Props, State> {
             {loading ? (
               <i className="spinner text-middle" />
             ) : (
-              <DeleteButton className="button-small text-middle" onClick={this.handleTokenRevoke} />
+              <DeleteButton
+                className="button-small text-middle"
+                aria-label={translate('onboarding.token.delete')}
+                onClick={this.handleTokenRevoke}
+              />
             )}
           </form>
         ) : (
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/BuildToolForm-test.tsx b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/BuildToolForm-test.tsx
deleted file mode 100644 (file)
index 1f0a889..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { BuildTools, OSs } from '../../types';
-import { BuildToolForm } from '../BuildToolForm';
-
-it('renders correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(shallowRender({ hasCLanguageFeature: false })).toMatchSnapshot('without C');
-  expect(shallowRender().setState({ config: { buildTool: BuildTools.Maven } })).toMatchSnapshot(
-    'with "maven" selected'
-  );
-  expect(shallowRender().setState({ config: { buildTool: BuildTools.Other } })).toMatchSnapshot(
-    'with "other" selected'
-  );
-});
-
-it('correctly calls the onDone prop', () => {
-  const onDone = jest.fn();
-  const wrapper = shallowRender({ onDone });
-
-  wrapper.instance().handleBuildToolChange(BuildTools.Gradle);
-  expect(onDone).toHaveBeenCalledWith(expect.objectContaining({ buildTool: BuildTools.Gradle }));
-
-  wrapper.setState({ config: { buildTool: BuildTools.Other } });
-  wrapper.instance().handleOSChange(OSs.Windows);
-  expect(onDone).toHaveBeenCalledWith(
-    expect.objectContaining({ os: OSs.Windows, buildTool: BuildTools.Other })
-  );
-});
-
-function shallowRender(props: Partial<BuildToolForm['props']> = {}) {
-  return shallow<BuildToolForm>(
-    <BuildToolForm onDone={jest.fn()} hasCLanguageFeature={true} {...props} />
-  );
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/DoneNextSteps-test.tsx b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/DoneNextSteps-test.tsx
deleted file mode 100644 (file)
index b31e34d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import DoneNextSteps, { DoneNextStepsProps } from '../DoneNextSteps';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-  expect(
-    shallowRender({ component: mockComponent({ configuration: { showSettings: true } }) })
-  ).toMatchSnapshot('project admin');
-});
-
-function shallowRender(props: Partial<DoneNextStepsProps> = {}) {
-  return shallow<DoneNextStepsProps>(<DoneNextSteps component={mockComponent()} {...props} />);
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx
new file mode 100644 (file)
index 0000000..d7c7133
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+import userEvent from '@testing-library/user-event';
+import React from 'react';
+import selectEvent from 'react-select-event';
+import { byRole, byText } from 'testing-library-selector';
+import UserTokensMock from '../../../../api/mocks/UserTokensMock';
+import { mockComponent } from '../../../../helpers/mocks/component';
+import { mockLanguage, mockLoggedInUser } from '../../../../helpers/testMocks';
+import { renderApp, RenderContext } from '../../../../helpers/testReactTestingUtils';
+import { getCopyToClipboardValue, getTutorialBuildButtons } from '../../test-utils';
+import OtherTutorial from '../OtherTutorial';
+
+jest.mock('../../../../api/user-tokens');
+
+jest.mock('../../../../api/settings', () => ({
+  getAllValues: jest.fn().mockResolvedValue([]),
+}));
+
+const tokenMock = new UserTokensMock();
+
+afterEach(() => {
+  tokenMock.reset();
+});
+
+const ui = {
+  provideTokenTitle: byRole('heading', { name: 'onboarding.token.header' }),
+  runAnalysisTitle: byRole('heading', { name: 'onboarding.analysis.header' }),
+  generateTokenRadio: byRole('radio', { name: 'onboarding.token.generate.PROJECT_ANALYSIS_TOKEN' }),
+  existingTokenRadio: byRole('radio', { name: 'onboarding.token.use_existing_token' }),
+  tokenNameInput: byRole('textbox', { name: 'onboarding.token.name.label' }),
+  expiresInSelect: byRole('combobox', { name: '' }),
+  generateTokenButton: byRole('button', { name: 'onboarding.token.generate' }),
+  deleteTokenButton: byRole('button', { name: 'onboarding.token.delete' }),
+  tokenValueInput: byRole('textbox', { name: 'onboarding.token.use_existing_token.label' }),
+  invalidTokenValueMessage: byText('onboarding.token.invalid_format'),
+  continueButton: byRole('button', { name: 'continue' }),
+  ...getTutorialBuildButtons(),
+};
+
+it('should generate/delete a new token or use existing one', async () => {
+  const user = userEvent.setup();
+  renderOtherTutorial();
+
+  // Verify that pages is rendered and includes 2 steps
+  expect(await ui.provideTokenTitle.find()).toBeInTheDocument();
+  expect(ui.runAnalysisTitle.get()).toBeInTheDocument();
+
+  // Generating token
+  user.type(ui.tokenNameInput.get(), 'Testing token');
+  await selectEvent.select(ui.expiresInSelect.get(), 'users.tokens.expiration.365');
+  await user.click(ui.generateTokenButton.get());
+
+  expect(ui.continueButton.get()).toBeEnabled();
+
+  // Deleting generated token & switchning to existing one
+  await user.click(ui.deleteTokenButton.get());
+
+  await user.click(ui.existingTokenRadio.get());
+  await user.type(ui.tokenValueInput.get(), 'INVALID TOKEN VALUE');
+  expect(ui.invalidTokenValueMessage.get()).toBeInTheDocument();
+
+  user.clear(ui.tokenValueInput.get());
+  await user.type(ui.tokenValueInput.get(), 'validtokenvalue');
+  expect(ui.continueButton.get()).toBeEnabled();
+
+  // navigate to 'Run analysis' step
+  await user.click(ui.continueButton.get());
+  expect(ui.describeBuildTitle.get()).toBeInTheDocument();
+
+  // navigate to previous step
+  await user.click(ui.provideTokenTitle.get());
+  expect(ui.continueButton.get()).toBeEnabled();
+});
+
+it('can choose build tools and copy provided settings', async () => {
+  const user = userEvent.setup();
+  renderOtherTutorial();
+
+  await user.click(ui.generateTokenButton.get());
+  await user.click(ui.continueButton.get());
+
+  // Maven
+  await user.click(ui.mavenBuildButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('maven: execute scanner');
+
+  // Gradle
+  await user.click(ui.gradleBuildButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('gradle: sonarqube plugin');
+  expect(getCopyToClipboardValue(1)).toMatchSnapshot('gradle: execute scanner');
+
+  // Dotnet - Core
+  await user.click(ui.dotnetBuildButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('dotnet core: install scanner globally');
+  expect(getCopyToClipboardValue(1)).toMatchSnapshot('dotnet core: execute command 1');
+  expect(getCopyToClipboardValue(2)).toMatchSnapshot('dotnet core: execute command 2');
+  expect(getCopyToClipboardValue(3)).toMatchSnapshot('dotnet core: execute command 3');
+
+  // Dotnet - Framework
+  await user.click(ui.dotnetFrameworkButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('dotnet framework: execute command 1');
+  expect(getCopyToClipboardValue(1)).toMatchSnapshot('dotnet framework: execute command 2');
+  expect(getCopyToClipboardValue(2)).toMatchSnapshot('dotnet framework: execute command 3');
+
+  // C Family - Linux
+  await user.click(ui.cFamilyBuildButton.get());
+  await user.click(ui.linuxButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('cfamily linux: execute build wrapper');
+  expect(getCopyToClipboardValue(1)).toMatchSnapshot('cfamily linux: execute scanner');
+
+  // C Family - Windows
+  await user.click(ui.windowsButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('cfamily windows: execute build wrapper');
+  expect(getCopyToClipboardValue(1)).toMatchSnapshot('cfamily windows: execute scanner');
+
+  // C Family - MacOS
+  await user.click(ui.macosButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('cfamily macos: execute build wrapper');
+  expect(getCopyToClipboardValue(1)).toMatchSnapshot('cfamily macos: execute scanner');
+
+  // Other - Linux
+  await user.click(ui.otherBuildButton.get());
+  await user.click(ui.linuxButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('other linux: execute scanner');
+
+  // Other - Windows
+  await user.click(ui.windowsButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('other windows: execute scanner');
+
+  // Other - MacOS
+  await user.click(ui.macosButton.get());
+  expect(getCopyToClipboardValue()).toMatchSnapshot('other macos: execute scanner');
+});
+
+function renderOtherTutorial({
+  languages = { c: mockLanguage({ key: 'c' }) },
+}: RenderContext = {}) {
+  return renderApp(
+    '/',
+    <OtherTutorial
+      baseUrl="http://localhost:9000"
+      component={mockComponent()}
+      currentUser={mockLoggedInUser()}
+    />,
+    { languages }
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-test.tsx b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-test.tsx
deleted file mode 100644 (file)
index 0983f0e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import { mockLoggedInUser } from '../../../../helpers/testMocks';
-import OtherTutorial from '../OtherTutorial';
-import ProjectAnalysisStep from '../ProjectAnalysisStep';
-import TokenStep from '../TokenStep';
-
-it('renders correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('default');
-});
-
-it('allows to navigate between steps', () => {
-  const wrapper = shallowRender();
-  const instance = wrapper.instance();
-
-  expect(wrapper.find(TokenStep).props().open).toBe(true);
-
-  instance.handleTokenDone('foo');
-  expect(wrapper.find(TokenStep).props().open).toBe(false);
-  expect(wrapper.find(ProjectAnalysisStep).props().open).toBe(true);
-
-  instance.handleTokenOpen();
-  expect(wrapper.find(TokenStep).props().open).toBe(true);
-  expect(wrapper.find(ProjectAnalysisStep).props().open).toBe(false);
-});
-
-function shallowRender(props: Partial<OtherTutorial['props']> = {}) {
-  return shallow<OtherTutorial>(
-    <OtherTutorial
-      component={mockComponent()}
-      baseUrl="http://example.com"
-      currentUser={mockLoggedInUser()}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/ProjectAnalysisStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/ProjectAnalysisStep-test.tsx
deleted file mode 100644 (file)
index 1cabe5f..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockComponent } from '../../../../helpers/mocks/component';
-import ProjectAnalysisStep from '../ProjectAnalysisStep';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-function shallowRender() {
-  return shallow(
-    <ProjectAnalysisStep
-      component={mockComponent()}
-      isLocal={true}
-      baseUrl="http://example.com"
-      open={true}
-      stepNumber={2}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/TokenStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/TokenStep-test.tsx
deleted file mode 100644 (file)
index e9de063..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { getTokens } from '../../../../api/user-tokens';
-import { mockLoggedInUser } from '../../../../helpers/testMocks';
-import { change, click, submit, waitAndUpdate } from '../../../../helpers/testUtils';
-import TokenStep from '../TokenStep';
-
-jest.mock('../../../../api/user-tokens', () => ({
-  getTokens: jest.fn().mockResolvedValue([{ name: 'foo' }]),
-  generateToken: jest.fn().mockResolvedValue({ token: 'abcd1234' }),
-  revokeToken: jest.fn().mockResolvedValue(null),
-}));
-
-jest.mock('../../../../api/settings', () => {
-  return {
-    ...jest.requireActual('../../../../api/settings'),
-    getAllValues: jest.fn().mockResolvedValue([
-      {
-        key: 'sonar.auth.token.max.allowed.lifetime',
-        value: 'No expiration',
-      },
-    ]),
-  };
-});
-
-it('sets an initial token name', async () => {
-  (getTokens as jest.Mock).mockResolvedValueOnce([{ name: 'fôo' }]);
-  const wrapper = shallowRender({ initialTokenName: 'fôo' });
-  await waitAndUpdate(wrapper);
-  expect(wrapper.dive().find('input').props().value).toBe('fôo 1');
-});
-
-it('generates token', async () => {
-  const wrapper = shallowRender();
-  await waitAndUpdate(wrapper);
-  expect(wrapper.dive()).toMatchSnapshot();
-  change(wrapper.dive().find('input'), 'my token');
-  submit(wrapper.dive().find('form'));
-  expect(wrapper.dive()).toMatchSnapshot(); // spinner
-  await waitAndUpdate(wrapper);
-  expect(wrapper.dive()).toMatchSnapshot();
-});
-
-it('revokes token', async () => {
-  const wrapper = shallowRender();
-  await new Promise(setImmediate);
-  wrapper.setState({ token: 'abcd1234', tokenName: 'my token' });
-  expect(wrapper.dive()).toMatchSnapshot();
-  (wrapper.dive().find('DeleteButton').prop('onClick') as Function)();
-  wrapper.update();
-  expect(wrapper.dive()).toMatchSnapshot(); // spinner
-  await waitAndUpdate(wrapper);
-  expect(wrapper.dive()).toMatchSnapshot();
-});
-
-it('continues', async () => {
-  const onContinue = jest.fn();
-  const wrapper = shallowRender({ onContinue });
-  await new Promise(setImmediate);
-  wrapper.setState({ token: 'abcd1234', tokenName: 'my token' });
-  click(wrapper.dive().find('[className="js-continue"]'));
-  expect(onContinue).toHaveBeenCalledWith('abcd1234');
-});
-
-it('uses existing token', async () => {
-  const onContinue = jest.fn();
-  const wrapper = shallowRender({ onContinue });
-  await new Promise(setImmediate);
-  wrapper.setState({ existingToken: 'abcd1234', selection: 'use-existing' });
-  click(wrapper.dive().find('[className="js-continue"]'));
-  expect(onContinue).toHaveBeenCalledWith('abcd1234');
-});
-
-function shallowRender(props: Partial<TokenStep['props']> = {}) {
-  return shallow<TokenStep>(
-    <TokenStep
-      currentUser={mockLoggedInUser({ login: 'user' })}
-      finished={false}
-      onContinue={jest.fn()}
-      onOpen={jest.fn()}
-      open={true}
-      projectKey="foo"
-      stepNumber={1}
-      {...props}
-    />
-  );
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/BuildToolForm-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/BuildToolForm-test.tsx.snap
deleted file mode 100644 (file)
index ed38c39..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`renders correctly: default 1`] = `
-<Fragment>
-  <div>
-    <h4
-      className="spacer-bottom"
-    >
-      onboarding.build
-    </h4>
-    <ButtonToggle
-      label="onboarding.build"
-      onCheck={[Function]}
-      options={
-        [
-          {
-            "label": "onboarding.build.maven",
-            "value": "maven",
-          },
-          {
-            "label": "onboarding.build.gradle",
-            "value": "gradle",
-          },
-          {
-            "label": "onboarding.build.dotnet",
-            "value": "dotnet",
-          },
-          {
-            "label": "onboarding.build.cfamily",
-            "value": "cfamily",
-          },
-          {
-            "label": "onboarding.build.other",
-            "value": "other",
-          },
-        ]
-      }
-    />
-  </div>
-</Fragment>
-`;
-
-exports[`renders correctly: with "maven" selected 1`] = `
-<Fragment>
-  <div>
-    <h4
-      className="spacer-bottom"
-    >
-      onboarding.build
-    </h4>
-    <ButtonToggle
-      label="onboarding.build"
-      onCheck={[Function]}
-      options={
-        [
-          {
-            "label": "onboarding.build.maven",
-            "value": "maven",
-          },
-          {
-            "label": "onboarding.build.gradle",
-            "value": "gradle",
-          },
-          {
-            "label": "onboarding.build.dotnet",
-            "value": "dotnet",
-          },
-          {
-            "label": "onboarding.build.cfamily",
-            "value": "cfamily",
-          },
-          {
-            "label": "onboarding.build.other",
-            "value": "other",
-          },
-        ]
-      }
-      value="maven"
-    />
-  </div>
-</Fragment>
-`;
-
-exports[`renders correctly: with "other" selected 1`] = `
-<Fragment>
-  <div>
-    <h4
-      className="spacer-bottom"
-    >
-      onboarding.build
-    </h4>
-    <ButtonToggle
-      label="onboarding.build"
-      onCheck={[Function]}
-      options={
-        [
-          {
-            "label": "onboarding.build.maven",
-            "value": "maven",
-          },
-          {
-            "label": "onboarding.build.gradle",
-            "value": "gradle",
-          },
-          {
-            "label": "onboarding.build.dotnet",
-            "value": "dotnet",
-          },
-          {
-            "label": "onboarding.build.cfamily",
-            "value": "cfamily",
-          },
-          {
-            "label": "onboarding.build.other",
-            "value": "other",
-          },
-        ]
-      }
-      value="other"
-    />
-  </div>
-  <RenderOptions
-    label="onboarding.build.other.os"
-    onCheck={[Function]}
-    optionLabelKey="onboarding.build.other.os"
-    options={
-      [
-        "linux",
-        "win",
-        "mac",
-      ]
-    }
-    titleLabelKey="onboarding.build.other.os"
-  />
-</Fragment>
-`;
-
-exports[`renders correctly: without C 1`] = `
-<Fragment>
-  <div>
-    <h4
-      className="spacer-bottom"
-    >
-      onboarding.build
-    </h4>
-    <ButtonToggle
-      label="onboarding.build"
-      onCheck={[Function]}
-      options={
-        [
-          {
-            "label": "onboarding.build.maven",
-            "value": "maven",
-          },
-          {
-            "label": "onboarding.build.gradle",
-            "value": "gradle",
-          },
-          {
-            "label": "onboarding.build.dotnet",
-            "value": "dotnet",
-          },
-          {
-            "label": "onboarding.build.other",
-            "value": "other",
-          },
-        ]
-      }
-    />
-  </div>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/DoneNextSteps-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/DoneNextSteps-test.tsx.snap
deleted file mode 100644 (file)
index b7363c4..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: default 1`] = `
-<Fragment>
-  <hr
-    className="big-spacer-top big-spacer-bottom"
-  />
-  <p>
-    <strong>
-      onboarding.analysis.auto_refresh_after_analysis.done
-    </strong>
-     
-    onboarding.analysis.auto_refresh_after_analysis.auto_refresh
-  </p>
-  <p
-    className="big-spacer-top"
-  >
-    onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci
-  </p>
-  <p
-    className="big-spacer-top"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
-      id="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
-      values={
-        {
-          "link_branches": <withAppStateContext(DocLink)
-            to="/analyzing-source-code/branches/branch-analysis/"
-          >
-            onboarding.analysis.auto_refresh_after_analysis.check_these_links.branches
-          </withAppStateContext(DocLink)>,
-          "link_pr_analysis": <withAppStateContext(DocLink)
-            to="/analyzing-source-code/pull-request-analysis"
-          >
-            onboarding.analysis.auto_refresh_after_analysis.check_these_links.pr_analysis
-          </withAppStateContext(DocLink)>,
-        }
-      }
-    />
-  </p>
-</Fragment>
-`;
-
-exports[`should render correctly: project admin 1`] = `
-<Fragment>
-  <hr
-    className="big-spacer-top big-spacer-bottom"
-  />
-  <p>
-    <strong>
-      onboarding.analysis.auto_refresh_after_analysis.done
-    </strong>
-     
-    onboarding.analysis.auto_refresh_after_analysis.auto_refresh
-  </p>
-  <p
-    className="big-spacer-top"
-  >
-    onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.admin
-  </p>
-  <p
-    className="big-spacer-top"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
-      id="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
-      values={
-        {
-          "link_branches": <withAppStateContext(DocLink)
-            to="/analyzing-source-code/branches/branch-analysis/"
-          >
-            onboarding.analysis.auto_refresh_after_analysis.check_these_links.branches
-          </withAppStateContext(DocLink)>,
-          "link_pr_analysis": <withAppStateContext(DocLink)
-            to="/analyzing-source-code/pull-request-analysis"
-          >
-            onboarding.analysis.auto_refresh_after_analysis.check_these_links.pr_analysis
-          </withAppStateContext(DocLink)>,
-        }
-      }
-    />
-  </p>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/OtherTutorial-it.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/OtherTutorial-it.tsx.snap
new file mode 100644 (file)
index 0000000..eb2ecbd
--- /dev/null
@@ -0,0 +1,132 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`can choose build tools and copy provided settings: cfamily linux: execute build wrapper 1`] = `
+"curl --create-dirs -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip http://localhost:9000/static/cpp/build-wrapper-linux-x86.zip
+unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/
+export PATH=$HOME/.sonar/build-wrapper-linux-x86:$PATH
+"
+`;
+
+exports[`can choose build tools and copy provided settings: cfamily linux: execute scanner 1`] = `
+"export SONAR_SCANNER_VERSION=4.7.0.2747
+export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
+curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
+unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+export PATH=$SONAR_SCANNER_HOME/bin:$PATH
+export SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: cfamily macos: execute build wrapper 1`] = `
+"curl --create-dirs -sSLo $HOME/.sonar/build-wrapper-macosx-x86.zip http://localhost:9000/static/cpp/build-wrapper-macosx-x86.zip
+unzip -o $HOME/.sonar/build-wrapper-macosx-x86.zip -d $HOME/.sonar/
+export PATH=$HOME/.sonar/build-wrapper-macosx-x86:$PATH
+"
+`;
+
+exports[`can choose build tools and copy provided settings: cfamily macos: execute scanner 1`] = `
+"export SONAR_SCANNER_VERSION=4.7.0.2747
+export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-macosx
+curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-macosx.zip
+unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+export PATH=$SONAR_SCANNER_HOME/bin:$PATH
+export SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: cfamily windows: execute build wrapper 1`] = `
+"$env:SONAR_DIRECTORY = [System.IO.Path]::Combine($(get-location).Path,".sonar")
+rm "$env:SONAR_DIRECTORY/build-wrapper-win-x86" -Force -Recurse -ErrorAction SilentlyContinue
+New-Item -path $env:SONAR_DIRECTORY/build-wrapper-win-x86 -type directory
+(New-Object System.Net.WebClient).DownloadFile("http://localhost:9000/static/cpp/build-wrapper-win-x86.zip", "$env:SONAR_DIRECTORY/build-wrapper-win-x86.zip")
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+[System.IO.Compression.ZipFile]::ExtractToDirectory("$env:SONAR_DIRECTORY/build-wrapper-win-x86.zip", "$env:SONAR_DIRECTORY")
+$env:Path += ";$env:SONAR_DIRECTORY/build-wrapper-win-x86"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: cfamily windows: execute scanner 1`] = `
+"$env:SONAR_SCANNER_VERSION = "4.7.0.2747"
+$env:SONAR_DIRECTORY = [System.IO.Path]::Combine($(get-location).Path,".sonar")
+$env:SONAR_SCANNER_HOME = "$env:SONAR_DIRECTORY/sonar-scanner-$env:SONAR_SCANNER_VERSION-windows"
+rm $env:SONAR_SCANNER_HOME -Force -Recurse -ErrorAction SilentlyContinue
+New-Item -path $env:SONAR_SCANNER_HOME -type directory
+(New-Object System.Net.WebClient).DownloadFile("https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$env:SONAR_SCANNER_VERSION-windows.zip", "$env:SONAR_DIRECTORY/sonar-scanner.zip")
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+[System.IO.Compression.ZipFile]::ExtractToDirectory("$env:SONAR_DIRECTORY/sonar-scanner.zip", "$env:SONAR_DIRECTORY")
+rm ./.sonar/sonar-scanner.zip -Force -ErrorAction SilentlyContinue
+$env:Path += ";$env:SONAR_SCANNER_HOME/bin"
+$env:SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: dotnet core: execute command 1 1`] = `"dotnet sonarscanner begin /k:"my-project" /d:sonar.host.url="http://localhost:9000"  /d:sonar.login="generatedtoken2""`;
+
+exports[`can choose build tools and copy provided settings: dotnet core: execute command 2 1`] = `"dotnet build"`;
+
+exports[`can choose build tools and copy provided settings: dotnet core: execute command 3 1`] = `"dotnet sonarscanner end /d:sonar.login="generatedtoken2""`;
+
+exports[`can choose build tools and copy provided settings: dotnet core: install scanner globally 1`] = `"dotnet tool install --global dotnet-sonarscanner"`;
+
+exports[`can choose build tools and copy provided settings: dotnet framework: execute command 1 1`] = `"SonarScanner.MSBuild.exe begin /k:"my-project" /d:sonar.host.url="http://localhost:9000" /d:sonar.login="generatedtoken2""`;
+
+exports[`can choose build tools and copy provided settings: dotnet framework: execute command 2 1`] = `"MsBuild.exe /t:Rebuild"`;
+
+exports[`can choose build tools and copy provided settings: dotnet framework: execute command 3 1`] = `"SonarScanner.MSBuild.exe end /d:sonar.login="generatedtoken2""`;
+
+exports[`can choose build tools and copy provided settings: gradle: execute scanner 1`] = `
+"./gradlew sonar \\
+  -Dsonar.projectKey=my-project \\
+  -Dsonar.projectName='MyProject' \\
+  -Dsonar.host.url=http://localhost:9000 \\
+  -Dsonar.login=generatedtoken2"
+`;
+
+exports[`can choose build tools and copy provided settings: gradle: sonarqube plugin 1`] = `
+"plugins {
+  id "org.sonarqube" version "3.5.0.2730"
+}"
+`;
+
+exports[`can choose build tools and copy provided settings: maven: execute scanner 1`] = `
+"mvn clean verify sonar:sonar \\
+  -Dsonar.projectKey=my-project \\
+  -Dsonar.projectName='MyProject' \\
+  -Dsonar.host.url=http://localhost:9000 \\
+  -Dsonar.login=generatedtoken2"
+`;
+
+exports[`can choose build tools and copy provided settings: other linux: execute scanner 1`] = `
+"export SONAR_SCANNER_VERSION=4.7.0.2747
+export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
+curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
+unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+export PATH=$SONAR_SCANNER_HOME/bin:$PATH
+export SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: other macos: execute scanner 1`] = `
+"export SONAR_SCANNER_VERSION=4.7.0.2747
+export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-macosx
+curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-macosx.zip
+unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+export PATH=$SONAR_SCANNER_HOME/bin:$PATH
+export SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: other windows: execute scanner 1`] = `
+"$env:SONAR_SCANNER_VERSION = "4.7.0.2747"
+$env:SONAR_DIRECTORY = [System.IO.Path]::Combine($(get-location).Path,".sonar")
+$env:SONAR_SCANNER_HOME = "$env:SONAR_DIRECTORY/sonar-scanner-$env:SONAR_SCANNER_VERSION-windows"
+rm $env:SONAR_SCANNER_HOME -Force -Recurse -ErrorAction SilentlyContinue
+New-Item -path $env:SONAR_SCANNER_HOME -type directory
+(New-Object System.Net.WebClient).DownloadFile("https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$env:SONAR_SCANNER_VERSION-windows.zip", "$env:SONAR_DIRECTORY/sonar-scanner.zip")
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+[System.IO.Compression.ZipFile]::ExtractToDirectory("$env:SONAR_DIRECTORY/sonar-scanner.zip", "$env:SONAR_DIRECTORY")
+rm ./.sonar/sonar-scanner.zip -Force -ErrorAction SilentlyContinue
+$env:Path += ";$env:SONAR_SCANNER_HOME/bin"
+$env:SONAR_SCANNER_OPTS="-server"
+"
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/OtherTutorial-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/OtherTutorial-test.tsx.snap
deleted file mode 100644 (file)
index 5caa5c3..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`renders correctly: default 1`] = `
-<Fragment>
-  <div
-    className="page-header big-spacer-bottom"
-  >
-    <h2
-      className="page-title"
-    >
-      onboarding.project_analysis.header
-    </h2>
-    <p
-      className="page-description"
-    >
-      <InstanceMessage
-        message="onboarding.project_analysis.description"
-      />
-    </p>
-  </div>
-  <TokenStep
-    currentUser={
-      {
-        "dismissedNotices": {
-          "educationPrinciples": false,
-        },
-        "groups": [],
-        "isLoggedIn": true,
-        "login": "luke",
-        "name": "Skywalker",
-        "scmAccounts": [],
-      }
-    }
-    finished={false}
-    initialTokenName="Analyze "MyProject""
-    onContinue={[Function]}
-    onOpen={[Function]}
-    open={true}
-    projectKey="my-project"
-    stepNumber={1}
-  />
-  <ProjectAnalysisStep
-    baseUrl="http://example.com"
-    component={
-      {
-        "breadcrumbs": [],
-        "key": "my-project",
-        "name": "MyProject",
-        "qualifier": "TRK",
-        "qualityGate": {
-          "isDefault": true,
-          "key": "30",
-          "name": "Sonar way",
-        },
-        "qualityProfiles": [
-          {
-            "deleted": false,
-            "key": "my-qp",
-            "language": "ts",
-            "name": "Sonar way",
-          },
-        ],
-        "tags": [],
-      }
-    }
-    isLocal={false}
-    open={false}
-    stepNumber={2}
-  />
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/ProjectAnalysisStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/ProjectAnalysisStep-test.tsx.snap
deleted file mode 100644 (file)
index 8183963..0000000
+++ /dev/null
@@ -1,13 +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={2}
-  stepTitle="onboarding.analysis.header"
-/>
-`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/TokenStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/TokenStep-test.tsx.snap
deleted file mode 100644 (file)
index 183856a..0000000
+++ /dev/null
@@ -1,693 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`generates token 1`] = `
-<div
-  className="boxed-group onboarding-step is-open"
->
-  <div
-    className="onboarding-step-number"
-  >
-    1
-  </div>
-  <div
-    className="boxed-group-header"
-  >
-    <h2>
-      onboarding.token.header
-    </h2>
-  </div>
-  <div>
-    <div
-      className="boxed-group-inner"
-    >
-      <div>
-        <div>
-          <Radio
-            checked={true}
-            onCheck={[Function]}
-            value="generate"
-          >
-            onboarding.token.generate.PROJECT_ANALYSIS_TOKEN
-          </Radio>
-          <div
-            className="big-spacer-top"
-          >
-            <form
-              className="display-flex-center"
-              onSubmit={[Function]}
-            >
-              <div
-                className="display-flex-column"
-              >
-                <label
-                  className="h3"
-                  htmlFor="generate-token-input"
-                >
-                  onboarding.token.name.label
-                  <DocumentationTooltip
-                    className="spacer-left"
-                    content="onboarding.token.name.help"
-                    links={
-                      [
-                        {
-                          "href": "/user-guide/user-account/generating-and-using-tokens/",
-                          "label": "learn_more",
-                        },
-                      ]
-                    }
-                  />
-                </label>
-                <input
-                  autoFocus={true}
-                  className="input-super-large spacer-right spacer-top text-middle"
-                  id="generate-token-input"
-                  onChange={[Function]}
-                  required={true}
-                  type="text"
-                  value=""
-                />
-              </div>
-              <div
-                className="display-flex-column spacer-left big-spacer-right"
-              >
-                <label
-                  className="h3"
-                  htmlFor="token-select-expiration"
-                >
-                  users.tokens.expires_in
-                </label>
-                <div
-                  className="display-flex-center"
-                >
-                  <Select
-                    className="spacer-top abs-width-100 spacer-right"
-                    id="token-select-expiration"
-                    isSearchable={false}
-                    onChange={[Function]}
-                    options={
-                      [
-                        {
-                          "label": "users.tokens.expiration.30",
-                          "value": 30,
-                        },
-                        {
-                          "label": "users.tokens.expiration.90",
-                          "value": 90,
-                        },
-                        {
-                          "label": "users.tokens.expiration.365",
-                          "value": 365,
-                        },
-                        {
-                          "label": "users.tokens.expiration.0",
-                          "value": 0,
-                        },
-                      ]
-                    }
-                    value={
-                      {
-                        "label": "users.tokens.expiration.30",
-                        "value": 30,
-                      }
-                    }
-                  />
-                  <SubmitButton
-                    className="text-middle spacer-top"
-                    disabled={true}
-                  >
-                    onboarding.token.generate
-                  </SubmitButton>
-                </div>
-              </div>
-            </form>
-            <ProjectTokenScopeInfo
-              className="width-50"
-            />
-          </div>
-        </div>
-        <div
-          className="big-spacer-top"
-        >
-          <Radio
-            checked={false}
-            onCheck={[Function]}
-            value="use-existing"
-          >
-            onboarding.token.use_existing_token
-          </Radio>
-        </div>
-      </div>
-      <div
-        className="note big-spacer-top width-50"
-      >
-        <FormattedMessage
-          defaultMessage="onboarding.token.text"
-          id="onboarding.token.text"
-          values={
-            {
-              "link": <ForwardRef(Link)
-                target="_blank"
-                to="/account/security"
-              >
-                onboarding.token.text.user_account
-              </ForwardRef(Link)>,
-            }
-          }
-        />
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`generates token 2`] = `
-<div
-  className="boxed-group onboarding-step is-open"
->
-  <div
-    className="onboarding-step-number"
-  >
-    1
-  </div>
-  <div
-    className="boxed-group-header"
-  >
-    <h2>
-      onboarding.token.header
-    </h2>
-  </div>
-  <div>
-    <div
-      className="boxed-group-inner"
-    >
-      <div>
-        <div>
-          <Radio
-            checked={true}
-            onCheck={[Function]}
-            value="generate"
-          >
-            onboarding.token.generate.PROJECT_ANALYSIS_TOKEN
-          </Radio>
-          <div
-            className="big-spacer-top"
-          >
-            <form
-              className="display-flex-center"
-              onSubmit={[Function]}
-            >
-              <div
-                className="display-flex-column"
-              >
-                <label
-                  className="h3"
-                  htmlFor="generate-token-input"
-                >
-                  onboarding.token.name.label
-                  <DocumentationTooltip
-                    className="spacer-left"
-                    content="onboarding.token.name.help"
-                    links={
-                      [
-                        {
-                          "href": "/user-guide/user-account/generating-and-using-tokens/",
-                          "label": "learn_more",
-                        },
-                      ]
-                    }
-                  />
-                </label>
-                <input
-                  autoFocus={true}
-                  className="input-super-large spacer-right spacer-top text-middle"
-                  id="generate-token-input"
-                  onChange={[Function]}
-                  required={true}
-                  type="text"
-                  value="my token"
-                />
-              </div>
-              <div
-                className="display-flex-column spacer-left big-spacer-right"
-              >
-                <label
-                  className="h3"
-                  htmlFor="token-select-expiration"
-                >
-                  users.tokens.expires_in
-                </label>
-                <div
-                  className="display-flex-center"
-                >
-                  <Select
-                    className="spacer-top abs-width-100 spacer-right"
-                    id="token-select-expiration"
-                    isSearchable={false}
-                    onChange={[Function]}
-                    options={
-                      [
-                        {
-                          "label": "users.tokens.expiration.30",
-                          "value": 30,
-                        },
-                        {
-                          "label": "users.tokens.expiration.90",
-                          "value": 90,
-                        },
-                        {
-                          "label": "users.tokens.expiration.365",
-                          "value": 365,
-                        },
-                        {
-                          "label": "users.tokens.expiration.0",
-                          "value": 0,
-                        },
-                      ]
-                    }
-                    value={
-                      {
-                        "label": "users.tokens.expiration.30",
-                        "value": 30,
-                      }
-                    }
-                  />
-                  <i
-                    className="spinner text-middle"
-                  />
-                </div>
-              </div>
-            </form>
-            <ProjectTokenScopeInfo
-              className="width-50"
-            />
-          </div>
-        </div>
-        <div
-          className="big-spacer-top"
-        >
-          <Radio
-            checked={false}
-            onCheck={[Function]}
-            value="use-existing"
-          >
-            onboarding.token.use_existing_token
-          </Radio>
-        </div>
-      </div>
-      <div
-        className="note big-spacer-top width-50"
-      >
-        <FormattedMessage
-          defaultMessage="onboarding.token.text"
-          id="onboarding.token.text"
-          values={
-            {
-              "link": <ForwardRef(Link)
-                target="_blank"
-                to="/account/security"
-              >
-                onboarding.token.text.user_account
-              </ForwardRef(Link)>,
-            }
-          }
-        />
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`generates token 3`] = `
-<div
-  className="boxed-group onboarding-step is-open"
->
-  <div
-    className="onboarding-step-number"
-  >
-    1
-  </div>
-  <div
-    className="boxed-group-header"
-  >
-    <h2>
-      onboarding.token.header
-    </h2>
-  </div>
-  <div>
-    <div
-      className="boxed-group-inner"
-    >
-      <form
-        onSubmit={[Function]}
-      >
-        <span
-          className="text-middle"
-        >
-          my token
-          : 
-        </span>
-        <strong
-          className="spacer-right text-middle"
-        >
-          abcd1234
-        </strong>
-        <DeleteButton
-          className="button-small text-middle"
-          onClick={[Function]}
-        />
-      </form>
-      <div
-        className="note big-spacer-top width-50"
-      >
-        <FormattedMessage
-          defaultMessage="onboarding.token.text"
-          id="onboarding.token.text"
-          values={
-            {
-              "link": <ForwardRef(Link)
-                target="_blank"
-                to="/account/security"
-              >
-                onboarding.token.text.user_account
-              </ForwardRef(Link)>,
-            }
-          }
-        />
-      </div>
-      <div
-        className="big-spacer-top"
-      >
-        <Button
-          className="js-continue"
-          onClick={[Function]}
-        >
-          continue
-        </Button>
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`revokes token 1`] = `
-<div
-  className="boxed-group onboarding-step is-open"
->
-  <div
-    className="onboarding-step-number"
-  >
-    1
-  </div>
-  <div
-    className="boxed-group-header"
-  >
-    <h2>
-      onboarding.token.header
-    </h2>
-  </div>
-  <div>
-    <div
-      className="boxed-group-inner"
-    >
-      <form
-        onSubmit={[Function]}
-      >
-        <span
-          className="text-middle"
-        >
-          my token
-          : 
-        </span>
-        <strong
-          className="spacer-right text-middle"
-        >
-          abcd1234
-        </strong>
-        <DeleteButton
-          className="button-small text-middle"
-          onClick={[Function]}
-        />
-      </form>
-      <div
-        className="note big-spacer-top width-50"
-      >
-        <FormattedMessage
-          defaultMessage="onboarding.token.text"
-          id="onboarding.token.text"
-          values={
-            {
-              "link": <ForwardRef(Link)
-                target="_blank"
-                to="/account/security"
-              >
-                onboarding.token.text.user_account
-              </ForwardRef(Link)>,
-            }
-          }
-        />
-      </div>
-      <div
-        className="big-spacer-top"
-      >
-        <Button
-          className="js-continue"
-          onClick={[Function]}
-        >
-          continue
-        </Button>
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`revokes token 2`] = `
-<div
-  className="boxed-group onboarding-step is-open"
->
-  <div
-    className="onboarding-step-number"
-  >
-    1
-  </div>
-  <div
-    className="boxed-group-header"
-  >
-    <h2>
-      onboarding.token.header
-    </h2>
-  </div>
-  <div>
-    <div
-      className="boxed-group-inner"
-    >
-      <form
-        onSubmit={[Function]}
-      >
-        <span
-          className="text-middle"
-        >
-          my token
-          : 
-        </span>
-        <strong
-          className="spacer-right text-middle"
-        >
-          abcd1234
-        </strong>
-        <i
-          className="spinner text-middle"
-        />
-      </form>
-      <div
-        className="note big-spacer-top width-50"
-      >
-        <FormattedMessage
-          defaultMessage="onboarding.token.text"
-          id="onboarding.token.text"
-          values={
-            {
-              "link": <ForwardRef(Link)
-                target="_blank"
-                to="/account/security"
-              >
-                onboarding.token.text.user_account
-              </ForwardRef(Link)>,
-            }
-          }
-        />
-      </div>
-      <div
-        className="big-spacer-top"
-      >
-        <Button
-          className="js-continue"
-          onClick={[Function]}
-        >
-          continue
-        </Button>
-      </div>
-    </div>
-  </div>
-</div>
-`;
-
-exports[`revokes token 3`] = `
-<div
-  className="boxed-group onboarding-step is-open"
->
-  <div
-    className="onboarding-step-number"
-  >
-    1
-  </div>
-  <div
-    className="boxed-group-header"
-  >
-    <h2>
-      onboarding.token.header
-    </h2>
-  </div>
-  <div>
-    <div
-      className="boxed-group-inner"
-    >
-      <div>
-        <div>
-          <Radio
-            checked={true}
-            onCheck={[Function]}
-            value="generate"
-          >
-            onboarding.token.generate.PROJECT_ANALYSIS_TOKEN
-          </Radio>
-          <div
-            className="big-spacer-top"
-          >
-            <form
-              className="display-flex-center"
-              onSubmit={[Function]}
-            >
-              <div
-                className="display-flex-column"
-              >
-                <label
-                  className="h3"
-                  htmlFor="generate-token-input"
-                >
-                  onboarding.token.name.label
-                  <DocumentationTooltip
-                    className="spacer-left"
-                    content="onboarding.token.name.help"
-                    links={
-                      [
-                        {
-                          "href": "/user-guide/user-account/generating-and-using-tokens/",
-                          "label": "learn_more",
-                        },
-                      ]
-                    }
-                  />
-                </label>
-                <input
-                  autoFocus={true}
-                  className="input-super-large spacer-right spacer-top text-middle"
-                  id="generate-token-input"
-                  onChange={[Function]}
-                  required={true}
-                  type="text"
-                  value=""
-                />
-              </div>
-              <div
-                className="display-flex-column spacer-left big-spacer-right"
-              >
-                <label
-                  className="h3"
-                  htmlFor="token-select-expiration"
-                >
-                  users.tokens.expires_in
-                </label>
-                <div
-                  className="display-flex-center"
-                >
-                  <Select
-                    className="spacer-top abs-width-100 spacer-right"
-                    id="token-select-expiration"
-                    isSearchable={false}
-                    onChange={[Function]}
-                    options={
-                      [
-                        {
-                          "label": "users.tokens.expiration.30",
-                          "value": 30,
-                        },
-                        {
-                          "label": "users.tokens.expiration.90",
-                          "value": 90,
-                        },
-                        {
-                          "label": "users.tokens.expiration.365",
-                          "value": 365,
-                        },
-                        {
-                          "label": "users.tokens.expiration.0",
-                          "value": 0,
-                        },
-                      ]
-                    }
-                    value={
-                      {
-                        "label": "users.tokens.expiration.30",
-                        "value": 30,
-                      }
-                    }
-                  />
-                  <SubmitButton
-                    className="text-middle spacer-top"
-                    disabled={true}
-                  >
-                    onboarding.token.generate
-                  </SubmitButton>
-                </div>
-              </div>
-            </form>
-            <ProjectTokenScopeInfo
-              className="width-50"
-            />
-          </div>
-        </div>
-        <div
-          className="big-spacer-top"
-        >
-          <Radio
-            checked={false}
-            onCheck={[Function]}
-            value="use-existing"
-          >
-            onboarding.token.use_existing_token
-          </Radio>
-        </div>
-      </div>
-      <div
-        className="note big-spacer-top width-50"
-      >
-        <FormattedMessage
-          defaultMessage="onboarding.token.text"
-          id="onboarding.token.text"
-          values={
-            {
-              "link": <ForwardRef(Link)
-                target="_blank"
-                to="/account/security"
-              >
-                onboarding.token.text.user_account
-              </ForwardRef(Link)>,
-            }
-          }
-        />
-      </div>
-    </div>
-  </div>
-</div>
-`;
index fe771eb94388a64973d4c28f1870e7b923799fa9..7fe32b990e6b0f56fe588cf9f229de5ce94baaa4 100644 (file)
@@ -42,6 +42,7 @@ export default function JavaGradle(props: JavaGradleProps) {
   const command = [
     './gradlew sonar',
     `-Dsonar.projectKey=${component.key}`,
+    `-Dsonar.projectName='${component.name}'`,
     `-Dsonar.host.url=${baseUrl}`,
     `-Dsonar.login=${token}`,
   ];
index 5d74ecd77e07872d8ef9945d1c40f4077894c47c..869c9e66329d31f34c8afa070427a73b8a1bd0d8 100644 (file)
@@ -37,6 +37,7 @@ export default function JavaMaven(props: JavaMavenProps) {
   const command = [
     'mvn clean verify sonar:sonar',
     `-Dsonar.projectKey=${component.key}`,
+    `-Dsonar.projectName='${component.name}'`,
     `-Dsonar.host.url=${baseUrl}`,
     `-Dsonar.login=${token}`,
   ];
index e9fb519228251893f689ca5b2adb4a2a74fdfae7..15ad59728f8afd71b225162d96466a9d38f8d526 100644 (file)
@@ -48,6 +48,7 @@ exports[`renders correctly 1`] = `
       [
         "./gradlew sonar",
         "-Dsonar.projectKey=projectKey",
+        "-Dsonar.projectName='MyProject'",
         "-Dsonar.host.url=host",
         "-Dsonar.login=token",
       ]
index 2ff25f85ea706992658e6e642ec9a5c4081dccc2..687972992575a2243c6f61ada1cc445f40a47113 100644 (file)
@@ -19,6 +19,7 @@ exports[`renders correctly 1`] = `
       [
         "mvn clean verify sonar:sonar",
         "-Dsonar.projectKey=projectKey",
+        "-Dsonar.projectName='MyProject'",
         "-Dsonar.host.url=host",
         "-Dsonar.login=token",
       ]
index 1358a9ad2827fdeba4b881f811ff9adb7bc96b99..5ef1aa0f40719a8d184840dcbbb2db019a37618a 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { screen } from '@testing-library/react';
 import { ShallowWrapper } from 'enzyme';
+import { byRole } from 'testing-library-selector';
 import Step from './components/Step';
+import { BuildTools, OSs } from './types';
 
 export function renderStepContent(wrapper: ShallowWrapper<React.ReactNode>, n = 0) {
   return wrapper.find(Step).at(n).props().renderForm();
 }
+
+export function getCopyToClipboardValue(i = 0, name = 'copy_to_clipboard') {
+  return screen.getAllByRole('button', { name })[i].getAttribute('data-clipboard-text');
+}
+
+export function getTutorialBuildButtons() {
+  return {
+    describeBuildTitle: byRole('heading', { name: 'onboarding.build' }),
+    mavenBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Maven}` }),
+    gradleBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Gradle}` }),
+    dotnetBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.DotNet}` }),
+    cFamilyBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.CFamily}` }),
+    otherBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Other}` }),
+    dotnetCoreButton: byRole('button', { name: 'onboarding.build.dotnet.variant.dotnet_core' }),
+    dotnetFrameworkButton: byRole('button', {
+      name: 'onboarding.build.dotnet.variant.dotnet_framework',
+    }),
+    linuxButton: byRole('button', { name: `onboarding.build.other.os.${OSs.Linux}` }),
+    windowsButton: byRole('button', { name: `onboarding.build.other.os.${OSs.Windows}` }),
+    macosButton: byRole('button', { name: `onboarding.build.other.os.${OSs.MacOS}` }),
+  };
+}
index 33c9fdacdbe33d9182e3089568212578c28d5408..7d271864828b948ecb687addfa5e152b57a32239 100644 (file)
@@ -26,7 +26,7 @@ export function quote(os: string): (s: string) => string {
   return os === 'win' ? (s: string) => `"${s}"` : (s: string) => s;
 }
 
-export function buildGradleSnippet(key: string) {
+export function buildGradleSnippet(key: string, name: string) {
   return `plugins {
   id "org.sonarqube" version "${GRADLE_SCANNER_VERSION}"
 }
@@ -34,6 +34,7 @@ export function buildGradleSnippet(key: string) {
 sonar {
   properties {
     property "sonar.projectKey", "${key}"
+    property "sonar.projectName", "${name}"
   }
 }`;
 }
index f2b0b5cdebd90c5a7b2d7728faa1082c6d412a67..c358a27b23f6b6758ec55de9307b27a23ba50091 100644 (file)
@@ -3698,6 +3698,7 @@ onboarding.token.name.label=Token name
 onboarding.token.name.placeholder=Enter a name for your token
 onboarding.token.name.help=Enter a name for your project token
 onboarding.token.invalid_format=The token you have entered has invalid format.
+onboarding.token.delete=Delete the token
 
 onboarding.tutorial.env_variables=In the {field} field, enter {value} {extra}
 onboarding.tutorial.env_variables.field=Value