]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14435 Add CFamily tutorial for manual setup
authorMathieu Suen <mathieu.suen@sonarsource.com>
Mon, 8 Feb 2021 10:09:44 +0000 (11:09 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 15 Feb 2021 20:07:05 +0000 (20:07 +0000)
25 files changed:
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/manual/BuildToolForm.tsx
server/sonar-web/src/main/js/components/tutorials/manual/__tests__/BuildToolForm-test.tsx
server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/BuildToolForm-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/manual/commands/AnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/manual/commands/ClangGCCCommand.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadBuildWrapper.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadScanner.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/ExecBuildWrapper.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/ExecScanner.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/Other.tsx
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/CLangGCCCommand-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/DownloadBuildWrapper-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/DownloadScanner-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/ExecBuildWrapper-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/ExecScanner-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/CLangGCCCommand-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/DownloadBuildWrapper-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/DownloadScanner-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/ExecBuildWrapper-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/ExecScanner-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/Other-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/types.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index e81304b0772e33bddce1c6e4d0158c4d68c52ba4..f80804519e82dc30caf22b10d628eca99925e9cb 100644 (file)
@@ -36,8 +36,11 @@ export interface JenkinsfileStepProps {
   open: boolean;
 }
 
+// To remove when CFamily is includ in this tutorial
+type BuildToolsWithoutCFamily = Exclude<BuildTools, BuildTools.CFamily>;
+
 const BUILDTOOL_COMPONENT_MAP: {
-  [x in BuildTools]: React.ComponentType<{ component: T.Component }>;
+  [x in BuildToolsWithoutCFamily]: React.ComponentType<{ component: T.Component }>;
 } = {
   [BuildTools.Maven]: Maven,
   [BuildTools.Gradle]: Gradle,
@@ -51,7 +54,7 @@ export function JenkinsfileStep(props: JenkinsfileStepProps) {
     component,
     open
   } = props;
-  const [buildTool, setBuildTool] = React.useState<BuildTools | undefined>(undefined);
+  const [buildTool, setBuildTool] = React.useState<BuildToolsWithoutCFamily | undefined>(undefined);
   return (
     <Step
       finished={false}
@@ -64,7 +67,7 @@ export function JenkinsfileStep(props: JenkinsfileStepProps) {
               <RenderOptions
                 checked={buildTool}
                 name="buildtool"
-                onCheck={value => setBuildTool(value as BuildTools)}
+                onCheck={value => setBuildTool(value as BuildToolsWithoutCFamily)}
                 optionLabelKey="onboarding.build"
                 options={Object.values(BuildTools)}
               />
index a4610804993e771ab532ea16ab98d72b52f31f9f..7f2f1394a90d1b1093f9dc3c33a66c0a55b06a1d 100644 (file)
@@ -18,6 +18,7 @@ exports[`should render correctly for .NET 1`] = `
           Array [
             "maven",
             "gradle",
+            "cfamily",
             "dotnet",
             "other",
           ]
@@ -139,6 +140,7 @@ exports[`should render correctly for Gradle 1`] = `
           Array [
             "maven",
             "gradle",
+            "cfamily",
             "dotnet",
             "other",
           ]
@@ -260,6 +262,7 @@ exports[`should render correctly for Maven 1`] = `
           Array [
             "maven",
             "gradle",
+            "cfamily",
             "dotnet",
             "other",
           ]
@@ -381,6 +384,7 @@ exports[`should render correctly for Other 1`] = `
           Array [
             "maven",
             "gradle",
+            "cfamily",
             "dotnet",
             "other",
           ]
@@ -502,6 +506,7 @@ exports[`should render correctly with no branches 1`] = `
           Array [
             "maven",
             "gradle",
+            "cfamily",
             "dotnet",
             "other",
           ]
@@ -632,6 +637,7 @@ exports[`should render correctly: initial content 1`] = `
           Array [
             "maven",
             "gradle",
+            "cfamily",
             "dotnet",
             "other",
           ]
index ae6acfbdd813f9242b0d25bfe4aa7c723be29eb1..f9bb51a0a97d3c115746bafa898619e8c4e86f59 100644 (file)
@@ -47,14 +47,23 @@ export default class BuildToolForm extends React.PureComponent<Props, State> {
   };
 
   handleOSChange = (os: OSs) => {
-    this.setState({ config: { buildTool: BuildTools.Other, os } }, () => {
-      this.props.onDone(this.state.config);
-    });
+    this.setState(
+      ({ config }) => ({ config: { buildTool: config.buildTool, os } }),
+      () => {
+        this.props.onDone(this.state.config);
+      }
+    );
   };
 
   render() {
     const { config } = this.state;
-    const buildTools = [BuildTools.Maven, BuildTools.Gradle, BuildTools.DotNet, BuildTools.Other];
+    const buildTools = [
+      BuildTools.Maven,
+      BuildTools.Gradle,
+      BuildTools.DotNet,
+      BuildTools.CFamily,
+      BuildTools.Other
+    ];
 
     return (
       <>
@@ -71,7 +80,7 @@ export default class BuildToolForm extends React.PureComponent<Props, State> {
           />
         </div>
 
-        {config.buildTool === BuildTools.Other && (
+        {(config.buildTool === BuildTools.Other || config.buildTool === BuildTools.CFamily) && (
           <RenderOptions
             checked={config.os}
             name="os"
index 5329c3632dd459cfd0b1c037ee26c13958afc429..cf789d91a2df15fb3163dcd34136911a386c544e 100644 (file)
@@ -39,6 +39,7 @@ it('correctly calls the onDone prop', () => {
   wrapper.instance().handleBuildToolChange(BuildTools.Gradle);
   expect(onDone).toBeCalledWith(expect.objectContaining({ buildTool: BuildTools.Gradle }));
 
+  wrapper.setState({ config: { buildTool: BuildTools.Other } });
   wrapper.instance().handleOSChange(OSs.Windows);
   expect(onDone).toBeCalledWith(
     expect.objectContaining({ os: OSs.Windows, buildTool: BuildTools.Other })
index 756cb8a109cde65760d38021967dc83eb5fa4c70..a478aa8017b664a268a1c073fbe99fbf007325ae 100644 (file)
@@ -26,6 +26,10 @@ exports[`renders correctly: default 1`] = `
             "label": "onboarding.build.dotnet",
             "value": "dotnet",
           },
+          Object {
+            "label": "onboarding.build.cfamily",
+            "value": "cfamily",
+          },
           Object {
             "label": "onboarding.build.other",
             "value": "other",
@@ -64,6 +68,10 @@ exports[`renders correctly: with "maven" selected 1`] = `
             "label": "onboarding.build.dotnet",
             "value": "dotnet",
           },
+          Object {
+            "label": "onboarding.build.cfamily",
+            "value": "cfamily",
+          },
           Object {
             "label": "onboarding.build.other",
             "value": "other",
@@ -102,6 +110,10 @@ exports[`renders correctly: with "other" selected 1`] = `
             "label": "onboarding.build.dotnet",
             "value": "dotnet",
           },
+          Object {
+            "label": "onboarding.build.cfamily",
+            "value": "cfamily",
+          },
           Object {
             "label": "onboarding.build.other",
             "value": "other",
index 321c23914784351678e30b214851f4057288ab35..e679a08c2fce1dc767d2de4c0d93ca369923a0c4 100644 (file)
@@ -20,6 +20,7 @@
 import * as React from 'react';
 import { getHostUrl } from 'sonar-ui-common/helpers/urls';
 import { BuildTools, ManualTutorialConfig } from '../../types';
+import ClangGCCCustom from './ClangGCCCommand';
 import DotNet from './DotNet';
 import JavaGradle from './JavaGradle';
 import JavaMaven from './JavaMaven';
@@ -51,6 +52,11 @@ export default function AnalysisCommand(props: AnalysisCommandProps) {
     case BuildTools.DotNet:
       return <DotNet host={host} projectKey={projectKey} token={token} />;
 
+    case BuildTools.CFamily:
+      return languageConfig.os !== undefined ? (
+        <ClangGCCCustom os={languageConfig.os} host={host} projectKey={projectKey} token={token} />
+      ) : null;
+
     case BuildTools.Other:
       return languageConfig.os !== undefined ? (
         <Other host={host} os={languageConfig.os} projectKey={projectKey} token={token} />
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/ClangGCCCommand.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/ClangGCCCommand.tsx
new file mode 100644 (file)
index 0000000..1fc693c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { OSs } from '../../types';
+import DownloadBuildWrapper from './DownloadBuildWrapper';
+import DownloadScanner from './DownloadScanner';
+import ExecBuildWrapper from './ExecBuildWrapper';
+import ExecScanner from './ExecScanner';
+
+export interface ClangGCCCustomProps {
+  host: string;
+  os: OSs;
+  projectKey: string;
+  token: string;
+}
+
+export default function ClangGCCCustom(props: ClangGCCCustomProps) {
+  const { os, host, projectKey, token } = props;
+
+  return (
+    <div>
+      <DownloadBuildWrapper os={os} />
+      <DownloadScanner os={os} />
+      <ExecBuildWrapper os={os} />
+      <ExecScanner host={host} projectKey={projectKey} os={os} token={token} cfamily={true} />
+    </div>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadBuildWrapper.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadBuildWrapper.tsx
new file mode 100644 (file)
index 0000000..0e8636b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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';
+import { OSs } from '../../types';
+
+export interface DownloadBuildWrapperProps {
+  os: OSs;
+}
+
+const filenames: { [x in OSs]: string } = {
+  win: 'build-wrapper-win-x86.zip',
+  linux: 'build-wrapper-linux-x86.zip',
+  mac: 'build-wrapper-macosx-x86.zip'
+};
+
+export default function DownloadBuildWrapper(props: DownloadBuildWrapperProps) {
+  const { os } = props;
+  return (
+    <div className="spacer-bottom">
+      <h4 className="spacer-bottom">{translate('onboarding.analysis.build_wrapper.header', 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>{os === 'win' ? '%PATH%' : 'PATH'}</code>
+          }}
+        />
+      </p>
+      <p>
+        <a
+          className="button"
+          download={filenames[os]}
+          href={`${getBaseUrl()}/static/cpp/${filenames[os]}`}
+          rel="noopener noreferrer"
+          target="_blank">
+          {translate('download_verb')}
+        </a>
+      </p>
+    </div>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadScanner.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadScanner.tsx
new file mode 100644 (file)
index 0000000..06bce10
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { translate } from 'sonar-ui-common/helpers/l10n';
+import { OSs } from '../../types';
+
+interface Props {
+  os: OSs;
+}
+
+export default function SQScanner(props: Props) {
+  const { os } = props;
+  return (
+    <div>
+      <h4 className="spacer-bottom">{translate('onboarding.analysis.sq_scanner.header', os)}</h4>
+      <p className="spacer-bottom markdown">
+        <FormattedMessage
+          defaultMessage={translate('onboarding.analysis.sq_scanner.text')}
+          id="onboarding.analysis.sq_scanner.text"
+          values={{
+            dir: <code>bin</code>,
+            env_var: <code>{os === OSs.Windows ? '%PATH%' : 'PATH'}</code>
+          }}
+        />
+      </p>
+      <p>
+        <Link className="button" to="/documentation/analysis/scan/sonarscanner/" target="_blank">
+          {translate('download_verb')}
+        </Link>
+      </p>
+    </div>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/ExecBuildWrapper.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/ExecBuildWrapper.tsx
new file mode 100644 (file)
index 0000000..677d22f
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { translate } from 'sonar-ui-common/helpers/l10n';
+import CodeSnippet from '../../../common/CodeSnippet';
+import { OSs } from '../../types';
+
+export interface ExecBuildWrapperProps {
+  os: OSs;
+}
+
+const executables: { [x in OSs]: string } = {
+  linux: 'build-wrapper-linux-x86-64',
+  win: 'build-wrapper-win-x86-64.exe',
+  mac: 'build-wrapper-macosx-x86'
+};
+
+export default function ExecBuildWrapper(props: ExecBuildWrapperProps) {
+  const { os } = props;
+
+  return (
+    <>
+      <h4 className="huge-spacer-top spacer-bottom">
+        {translate('onboarding.analysis.build_wrapper.execute')}
+      </h4>
+      <p className="spacer-bottom markdown">
+        {translate('onboarding.analysis.build_wrapper.execute_text')}
+      </p>
+      <CodeSnippet
+        snippet={`${executables[os]} --out-dir bw-output ${translate(
+          'onboarding.analysis.build_wrapper.execute_build_command'
+        )}`}
+      />
+      <p className="big-spacer-top markdown">
+        <FormattedMessage
+          defaultMessage={translate('onboarding.analysis.build_wrapper.docs')}
+          id="onboarding.analysis.build_wrapper.docs"
+          values={{
+            link: (
+              <Link to="/documentation/analysis/languages/cfamily/" target="_blank">
+                {translate('onboarding.analysis.build_wrapper.docs_link')}
+              </Link>
+            )
+          }}
+        />
+      </p>
+    </>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/ExecScanner.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/ExecScanner.tsx
new file mode 100644 (file)
index 0000000..cc595bb
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { translate } from 'sonar-ui-common/helpers/l10n';
+import CodeSnippet from '../../../common/CodeSnippet';
+import InstanceMessage from '../../../common/InstanceMessage';
+import { OSs } from '../../types';
+import { quote } from '../../utils';
+
+export interface ExecScannerProps {
+  host: string;
+  os: OSs;
+  projectKey: string;
+  token: string;
+  cfamily?: boolean;
+}
+
+export default function ExecScanner(props: ExecScannerProps) {
+  const { host, os, projectKey, token, cfamily } = props;
+
+  const q = quote(os);
+  const command = [
+    os === OSs.Windows ? 'sonar-scanner.bat' : 'sonar-scanner',
+    '-D' + q(`sonar.projectKey=${projectKey}`),
+    '-D' + q('sonar.sources=.'),
+    cfamily ? '-D' + q('sonar.cfamily.build-wrapper-output=bw-output') : undefined,
+    '-D' + q(`sonar.host.url=${host}`),
+    '-D' + q(`sonar.login=${token}`)
+  ];
+
+  return (
+    <div>
+      <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={os === OSs.Windows} snippet={command} />
+      <p className="big-spacer-top markdown">
+        <FormattedMessage
+          defaultMessage={translate('onboarding.analysis.sq_scanner.docs')}
+          id="onboarding.analysis.sq_scanner.docs"
+          values={{
+            link: (
+              <Link to="/documentation/analysis/scan/sonarscanner/" target="_blank">
+                {translate('onboarding.analysis.sq_scanner.docs_link')}
+              </Link>
+            )
+          }}
+        />
+      </p>
+      <p className="big-spacer-top markdown">
+        {translate('onboarding.analysis.auto_refresh_after_analysis')}
+      </p>
+    </div>
+  );
+}
index 7dd46b0698669537a0b0c6b51ec1d6ef8d6a33cf..7db9c3880bbc9704382ced90edf9140109b35aa7 100644 (file)
  * 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 { translate } from 'sonar-ui-common/helpers/l10n';
-import CodeSnippet from '../../../common/CodeSnippet';
-import InstanceMessage from '../../../common/InstanceMessage';
 import { OSs } from '../../types';
-import { quote } from '../../utils';
+import DownloadScanner from './DownloadScanner';
+import ExecScanner from './ExecScanner';
 
 export interface OtherProps {
   host: string;
@@ -36,56 +32,10 @@ export interface OtherProps {
 export default function Other(props: OtherProps) {
   const { host, os, projectKey, token } = props;
 
-  const q = quote(os);
-  const command = [
-    os === OSs.Windows ? 'sonar-scanner.bat' : 'sonar-scanner',
-    '-D' + q(`sonar.projectKey=${projectKey}`),
-    '-D' + q('sonar.sources=.'),
-    '-D' + q(`sonar.host.url=${host}`),
-    '-D' + q(`sonar.login=${token}`)
-  ];
-
   return (
     <div>
-      <div>
-        <h4 className="spacer-bottom">{translate('onboarding.analysis.sq_scanner.header', os)}</h4>
-        <p className="spacer-bottom markdown">
-          <FormattedMessage
-            defaultMessage={translate('onboarding.analysis.sq_scanner.text')}
-            id="onboarding.analysis.sq_scanner.text"
-            values={{
-              dir: <code>bin</code>,
-              env_var: <code>{os === OSs.Windows ? '%PATH%' : 'PATH'}</code>
-            }}
-          />
-        </p>
-        <p>
-          <Link className="button" to="/documentation/analysis/scan/sonarscanner/" target="_blank">
-            {translate('download_verb')}
-          </Link>
-        </p>
-      </div>
-
-      <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={os === OSs.Windows} snippet={command} />
-      <p className="big-spacer-top markdown">
-        <FormattedMessage
-          defaultMessage={translate('onboarding.analysis.sq_scanner.docs')}
-          id="onboarding.analysis.sq_scanner.docs"
-          values={{
-            link: (
-              <Link to="/documentation/analysis/scan/sonarscanner/" target="_blank">
-                {translate('onboarding.analysis.sq_scanner.docs_link')}
-              </Link>
-            )
-          }}
-        />
-      </p>
+      <DownloadScanner os={os} />
+      <ExecScanner host={host} os={os} projectKey={projectKey} token={token} />
     </div>
   );
 }
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/CLangGCCCommand-test.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/CLangGCCCommand-test.tsx
new file mode 100644 (file)
index 0000000..d35ea6b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { OSs } from '../../../types';
+import ClangGCCCommand from '../ClangGCCCommand';
+
+it('Shoud renders correctly', () => {
+  expect(
+    shallow(<ClangGCCCommand os={OSs.Linux} host="host" projectKey="projectKey" token="token" />)
+  ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/DownloadBuildWrapper-test.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/DownloadBuildWrapper-test.tsx
new file mode 100644 (file)
index 0000000..b7698fe
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { OSs } from '../../../types';
+import DownloadBuildWrapper from '../DownloadBuildWrapper';
+
+it.each([OSs.Linux, OSs.Windows, OSs.MacOS])('Shoud renders for %p correctly', os => {
+  expect(shallow(<DownloadBuildWrapper os={os} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/DownloadScanner-test.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/DownloadScanner-test.tsx
new file mode 100644 (file)
index 0000000..bc70cc7
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { OSs } from '../../../types';
+import DownloadScanner from '../DownloadScanner';
+
+it.each([OSs.Linux, OSs.Windows, OSs.MacOS])('Shoud renders for %p correctly', os => {
+  expect(shallow(<DownloadScanner os={os} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/ExecBuildWrapper-test.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/ExecBuildWrapper-test.tsx
new file mode 100644 (file)
index 0000000..80650f8
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { OSs } from '../../../types';
+import ExecBuildWrapper from '../ExecBuildWrapper';
+
+it.each([OSs.Linux, OSs.Windows, OSs.MacOS])('Shoud renders for %p correctly', os => {
+  expect(shallow(<ExecBuildWrapper os={os} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/ExecScanner-test.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/ExecScanner-test.tsx
new file mode 100644 (file)
index 0000000..02c3fee
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { OSs } from '../../../types';
+import ExecScanner, { ExecScannerProps } from '../ExecScanner';
+
+it.each([OSs.Linux, OSs.Windows, OSs.MacOS])('Shoud renders for %p correctly', os => {
+  expect(shallowRender({ os })).toMatchSnapshot();
+});
+
+it('Should render for cfamily', () => {
+  expect(shallowRender({ cfamily: true })).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<ExecScannerProps> = {}) {
+  return shallow<ExecScannerProps>(
+    <ExecScanner host="host" os={OSs.Linux} projectKey="projectKey" token="token" {...props} />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/CLangGCCCommand-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/CLangGCCCommand-test.tsx.snap
new file mode 100644 (file)
index 0000000..a1bc445
--- /dev/null
@@ -0,0 +1,22 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Shoud renders correctly 1`] = `
+<div>
+  <DownloadBuildWrapper
+    os="linux"
+  />
+  <SQScanner
+    os="linux"
+  />
+  <ExecBuildWrapper
+    os="linux"
+  />
+  <ExecScanner
+    cfamily={true}
+    host="host"
+    os="linux"
+    projectKey="projectKey"
+    token="token"
+  />
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/DownloadBuildWrapper-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/DownloadBuildWrapper-test.tsx.snap
new file mode 100644 (file)
index 0000000..2a44492
--- /dev/null
@@ -0,0 +1,115 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Shoud renders for "linux" correctly 1`] = `
+<div
+  className="spacer-bottom"
+>
+  <h4
+    className="spacer-bottom"
+  >
+    onboarding.analysis.build_wrapper.header.linux
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.build_wrapper.text"
+      id="onboarding.analysis.build_wrapper.text"
+      values={
+        Object {
+          "env_var": <code>
+            PATH
+          </code>,
+        }
+      }
+    />
+  </p>
+  <p>
+    <a
+      className="button"
+      download="build-wrapper-linux-x86.zip"
+      href="/static/cpp/build-wrapper-linux-x86.zip"
+      rel="noopener noreferrer"
+      target="_blank"
+    >
+      download_verb
+    </a>
+  </p>
+</div>
+`;
+
+exports[`Shoud renders for "mac" correctly 1`] = `
+<div
+  className="spacer-bottom"
+>
+  <h4
+    className="spacer-bottom"
+  >
+    onboarding.analysis.build_wrapper.header.mac
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.build_wrapper.text"
+      id="onboarding.analysis.build_wrapper.text"
+      values={
+        Object {
+          "env_var": <code>
+            PATH
+          </code>,
+        }
+      }
+    />
+  </p>
+  <p>
+    <a
+      className="button"
+      download="build-wrapper-macosx-x86.zip"
+      href="/static/cpp/build-wrapper-macosx-x86.zip"
+      rel="noopener noreferrer"
+      target="_blank"
+    >
+      download_verb
+    </a>
+  </p>
+</div>
+`;
+
+exports[`Shoud renders for "win" correctly 1`] = `
+<div
+  className="spacer-bottom"
+>
+  <h4
+    className="spacer-bottom"
+  >
+    onboarding.analysis.build_wrapper.header.win
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.build_wrapper.text"
+      id="onboarding.analysis.build_wrapper.text"
+      values={
+        Object {
+          "env_var": <code>
+            %PATH%
+          </code>,
+        }
+      }
+    />
+  </p>
+  <p>
+    <a
+      className="button"
+      download="build-wrapper-win-x86.zip"
+      href="/static/cpp/build-wrapper-win-x86.zip"
+      rel="noopener noreferrer"
+      target="_blank"
+    >
+      download_verb
+    </a>
+  </p>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/DownloadScanner-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/DownloadScanner-test.tsx.snap
new file mode 100644 (file)
index 0000000..5437c93
--- /dev/null
@@ -0,0 +1,118 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Shoud renders for "linux" correctly 1`] = `
+<div>
+  <h4
+    className="spacer-bottom"
+  >
+    onboarding.analysis.sq_scanner.header.linux
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.sq_scanner.text"
+      id="onboarding.analysis.sq_scanner.text"
+      values={
+        Object {
+          "dir": <code>
+            bin
+          </code>,
+          "env_var": <code>
+            PATH
+          </code>,
+        }
+      }
+    />
+  </p>
+  <p>
+    <Link
+      className="button"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      target="_blank"
+      to="/documentation/analysis/scan/sonarscanner/"
+    >
+      download_verb
+    </Link>
+  </p>
+</div>
+`;
+
+exports[`Shoud renders for "mac" correctly 1`] = `
+<div>
+  <h4
+    className="spacer-bottom"
+  >
+    onboarding.analysis.sq_scanner.header.mac
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.sq_scanner.text"
+      id="onboarding.analysis.sq_scanner.text"
+      values={
+        Object {
+          "dir": <code>
+            bin
+          </code>,
+          "env_var": <code>
+            PATH
+          </code>,
+        }
+      }
+    />
+  </p>
+  <p>
+    <Link
+      className="button"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      target="_blank"
+      to="/documentation/analysis/scan/sonarscanner/"
+    >
+      download_verb
+    </Link>
+  </p>
+</div>
+`;
+
+exports[`Shoud renders for "win" correctly 1`] = `
+<div>
+  <h4
+    className="spacer-bottom"
+  >
+    onboarding.analysis.sq_scanner.header.win
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.sq_scanner.text"
+      id="onboarding.analysis.sq_scanner.text"
+      values={
+        Object {
+          "dir": <code>
+            bin
+          </code>,
+          "env_var": <code>
+            %PATH%
+          </code>,
+        }
+      }
+    />
+  </p>
+  <p>
+    <Link
+      className="button"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      target="_blank"
+      to="/documentation/analysis/scan/sonarscanner/"
+    >
+      download_verb
+    </Link>
+  </p>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/ExecBuildWrapper-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/ExecBuildWrapper-test.tsx.snap
new file mode 100644 (file)
index 0000000..7e7f188
--- /dev/null
@@ -0,0 +1,115 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Shoud renders for "linux" correctly 1`] = `
+<Fragment>
+  <h4
+    className="huge-spacer-top spacer-bottom"
+  >
+    onboarding.analysis.build_wrapper.execute
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    onboarding.analysis.build_wrapper.execute_text
+  </p>
+  <CodeSnippet
+    snippet="build-wrapper-linux-x86-64 --out-dir bw-output onboarding.analysis.build_wrapper.execute_build_command"
+  />
+  <p
+    className="big-spacer-top markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.build_wrapper.docs"
+      id="onboarding.analysis.build_wrapper.docs"
+      values={
+        Object {
+          "link": <Link
+            onlyActiveOnIndex={false}
+            style={Object {}}
+            target="_blank"
+            to="/documentation/analysis/languages/cfamily/"
+          >
+            onboarding.analysis.build_wrapper.docs_link
+          </Link>,
+        }
+      }
+    />
+  </p>
+</Fragment>
+`;
+
+exports[`Shoud renders for "mac" correctly 1`] = `
+<Fragment>
+  <h4
+    className="huge-spacer-top spacer-bottom"
+  >
+    onboarding.analysis.build_wrapper.execute
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    onboarding.analysis.build_wrapper.execute_text
+  </p>
+  <CodeSnippet
+    snippet="build-wrapper-macosx-x86 --out-dir bw-output onboarding.analysis.build_wrapper.execute_build_command"
+  />
+  <p
+    className="big-spacer-top markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.build_wrapper.docs"
+      id="onboarding.analysis.build_wrapper.docs"
+      values={
+        Object {
+          "link": <Link
+            onlyActiveOnIndex={false}
+            style={Object {}}
+            target="_blank"
+            to="/documentation/analysis/languages/cfamily/"
+          >
+            onboarding.analysis.build_wrapper.docs_link
+          </Link>,
+        }
+      }
+    />
+  </p>
+</Fragment>
+`;
+
+exports[`Shoud renders for "win" correctly 1`] = `
+<Fragment>
+  <h4
+    className="huge-spacer-top spacer-bottom"
+  >
+    onboarding.analysis.build_wrapper.execute
+  </h4>
+  <p
+    className="spacer-bottom markdown"
+  >
+    onboarding.analysis.build_wrapper.execute_text
+  </p>
+  <CodeSnippet
+    snippet="build-wrapper-win-x86-64.exe --out-dir bw-output onboarding.analysis.build_wrapper.execute_build_command"
+  />
+  <p
+    className="big-spacer-top markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.build_wrapper.docs"
+      id="onboarding.analysis.build_wrapper.docs"
+      values={
+        Object {
+          "link": <Link
+            onlyActiveOnIndex={false}
+            style={Object {}}
+            target="_blank"
+            to="/documentation/analysis/languages/cfamily/"
+          >
+            onboarding.analysis.build_wrapper.docs_link
+          </Link>,
+        }
+      }
+    />
+  </p>
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/ExecScanner-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/ExecScanner-test.tsx.snap
new file mode 100644 (file)
index 0000000..140fe68
--- /dev/null
@@ -0,0 +1,213 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Shoud renders for "linux" correctly 1`] = `
+<div>
+  <h4
+    className="huge-spacer-top spacer-bottom"
+  >
+    onboarding.analysis.sq_scanner.execute
+  </h4>
+  <InstanceMessage
+    message="onboarding.analysis.sq_scanner.execute.text"
+  >
+    <Component />
+  </InstanceMessage>
+  <CodeSnippet
+    isOneLine={false}
+    snippet={
+      Array [
+        "sonar-scanner",
+        "-Dsonar.projectKey=projectKey",
+        "-Dsonar.sources=.",
+        undefined,
+        "-Dsonar.host.url=host",
+        "-Dsonar.login=token",
+      ]
+    }
+  />
+  <p
+    className="big-spacer-top markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.sq_scanner.docs"
+      id="onboarding.analysis.sq_scanner.docs"
+      values={
+        Object {
+          "link": <Link
+            onlyActiveOnIndex={false}
+            style={Object {}}
+            target="_blank"
+            to="/documentation/analysis/scan/sonarscanner/"
+          >
+            onboarding.analysis.sq_scanner.docs_link
+          </Link>,
+        }
+      }
+    />
+  </p>
+  <p
+    className="big-spacer-top markdown"
+  >
+    onboarding.analysis.auto_refresh_after_analysis
+  </p>
+</div>
+`;
+
+exports[`Shoud renders for "mac" correctly 1`] = `
+<div>
+  <h4
+    className="huge-spacer-top spacer-bottom"
+  >
+    onboarding.analysis.sq_scanner.execute
+  </h4>
+  <InstanceMessage
+    message="onboarding.analysis.sq_scanner.execute.text"
+  >
+    <Component />
+  </InstanceMessage>
+  <CodeSnippet
+    isOneLine={false}
+    snippet={
+      Array [
+        "sonar-scanner",
+        "-Dsonar.projectKey=projectKey",
+        "-Dsonar.sources=.",
+        undefined,
+        "-Dsonar.host.url=host",
+        "-Dsonar.login=token",
+      ]
+    }
+  />
+  <p
+    className="big-spacer-top markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.sq_scanner.docs"
+      id="onboarding.analysis.sq_scanner.docs"
+      values={
+        Object {
+          "link": <Link
+            onlyActiveOnIndex={false}
+            style={Object {}}
+            target="_blank"
+            to="/documentation/analysis/scan/sonarscanner/"
+          >
+            onboarding.analysis.sq_scanner.docs_link
+          </Link>,
+        }
+      }
+    />
+  </p>
+  <p
+    className="big-spacer-top markdown"
+  >
+    onboarding.analysis.auto_refresh_after_analysis
+  </p>
+</div>
+`;
+
+exports[`Shoud renders for "win" correctly 1`] = `
+<div>
+  <h4
+    className="huge-spacer-top spacer-bottom"
+  >
+    onboarding.analysis.sq_scanner.execute
+  </h4>
+  <InstanceMessage
+    message="onboarding.analysis.sq_scanner.execute.text"
+  >
+    <Component />
+  </InstanceMessage>
+  <CodeSnippet
+    isOneLine={true}
+    snippet={
+      Array [
+        "sonar-scanner.bat",
+        "-D\\"sonar.projectKey=projectKey\\"",
+        "-D\\"sonar.sources=.\\"",
+        undefined,
+        "-D\\"sonar.host.url=host\\"",
+        "-D\\"sonar.login=token\\"",
+      ]
+    }
+  />
+  <p
+    className="big-spacer-top markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.sq_scanner.docs"
+      id="onboarding.analysis.sq_scanner.docs"
+      values={
+        Object {
+          "link": <Link
+            onlyActiveOnIndex={false}
+            style={Object {}}
+            target="_blank"
+            to="/documentation/analysis/scan/sonarscanner/"
+          >
+            onboarding.analysis.sq_scanner.docs_link
+          </Link>,
+        }
+      }
+    />
+  </p>
+  <p
+    className="big-spacer-top markdown"
+  >
+    onboarding.analysis.auto_refresh_after_analysis
+  </p>
+</div>
+`;
+
+exports[`Should render for cfamily 1`] = `
+<div>
+  <h4
+    className="huge-spacer-top spacer-bottom"
+  >
+    onboarding.analysis.sq_scanner.execute
+  </h4>
+  <InstanceMessage
+    message="onboarding.analysis.sq_scanner.execute.text"
+  >
+    <Component />
+  </InstanceMessage>
+  <CodeSnippet
+    isOneLine={false}
+    snippet={
+      Array [
+        "sonar-scanner",
+        "-Dsonar.projectKey=projectKey",
+        "-Dsonar.sources=.",
+        "-Dsonar.cfamily.build-wrapper-output=bw-output",
+        "-Dsonar.host.url=host",
+        "-Dsonar.login=token",
+      ]
+    }
+  />
+  <p
+    className="big-spacer-top markdown"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.analysis.sq_scanner.docs"
+      id="onboarding.analysis.sq_scanner.docs"
+      values={
+        Object {
+          "link": <Link
+            onlyActiveOnIndex={false}
+            style={Object {}}
+            target="_blank"
+            to="/documentation/analysis/scan/sonarscanner/"
+          >
+            onboarding.analysis.sq_scanner.docs_link
+          </Link>,
+        }
+      }
+    />
+  </p>
+  <p
+    className="big-spacer-top markdown"
+  >
+    onboarding.analysis.auto_refresh_after_analysis
+  </p>
+</div>
+`;
index 5b11bd567dbc1e2fc2011f2c4b77571d7fc6dd41..15cc7f9866973f4ce4c54c267ab9a153e4640ba8 100644 (file)
 
 exports[`renders correctly: linux 1`] = `
 <div>
-  <div>
-    <h4
-      className="spacer-bottom"
-    >
-      onboarding.analysis.sq_scanner.header.linux
-    </h4>
-    <p
-      className="spacer-bottom markdown"
-    >
-      <FormattedMessage
-        defaultMessage="onboarding.analysis.sq_scanner.text"
-        id="onboarding.analysis.sq_scanner.text"
-        values={
-          Object {
-            "dir": <code>
-              bin
-            </code>,
-            "env_var": <code>
-              PATH
-            </code>,
-          }
-        }
-      />
-    </p>
-    <p>
-      <Link
-        className="button"
-        onlyActiveOnIndex={false}
-        style={Object {}}
-        target="_blank"
-        to="/documentation/analysis/scan/sonarscanner/"
-      >
-        download_verb
-      </Link>
-    </p>
-  </div>
-  <h4
-    className="huge-spacer-top spacer-bottom"
-  >
-    onboarding.analysis.sq_scanner.execute
-  </h4>
-  <InstanceMessage
-    message="onboarding.analysis.sq_scanner.execute.text"
-  >
-    <Component />
-  </InstanceMessage>
-  <CodeSnippet
-    isOneLine={false}
-    snippet={
-      Array [
-        "sonar-scanner",
-        "-Dsonar.projectKey=projectKey",
-        "-Dsonar.sources=.",
-        "-Dsonar.host.url=host",
-        "-Dsonar.login=token",
-      ]
-    }
+  <SQScanner
+    os="linux"
+  />
+  <ExecScanner
+    host="host"
+    os="linux"
+    projectKey="projectKey"
+    token="token"
   />
-  <p
-    className="big-spacer-top markdown"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.analysis.sq_scanner.docs"
-      id="onboarding.analysis.sq_scanner.docs"
-      values={
-        Object {
-          "link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/scan/sonarscanner/"
-          >
-            onboarding.analysis.sq_scanner.docs_link
-          </Link>,
-        }
-      }
-    />
-  </p>
 </div>
 `;
 
 exports[`renders correctly: macos 1`] = `
 <div>
-  <div>
-    <h4
-      className="spacer-bottom"
-    >
-      onboarding.analysis.sq_scanner.header.mac
-    </h4>
-    <p
-      className="spacer-bottom markdown"
-    >
-      <FormattedMessage
-        defaultMessage="onboarding.analysis.sq_scanner.text"
-        id="onboarding.analysis.sq_scanner.text"
-        values={
-          Object {
-            "dir": <code>
-              bin
-            </code>,
-            "env_var": <code>
-              PATH
-            </code>,
-          }
-        }
-      />
-    </p>
-    <p>
-      <Link
-        className="button"
-        onlyActiveOnIndex={false}
-        style={Object {}}
-        target="_blank"
-        to="/documentation/analysis/scan/sonarscanner/"
-      >
-        download_verb
-      </Link>
-    </p>
-  </div>
-  <h4
-    className="huge-spacer-top spacer-bottom"
-  >
-    onboarding.analysis.sq_scanner.execute
-  </h4>
-  <InstanceMessage
-    message="onboarding.analysis.sq_scanner.execute.text"
-  >
-    <Component />
-  </InstanceMessage>
-  <CodeSnippet
-    isOneLine={false}
-    snippet={
-      Array [
-        "sonar-scanner",
-        "-Dsonar.projectKey=projectKey",
-        "-Dsonar.sources=.",
-        "-Dsonar.host.url=host",
-        "-Dsonar.login=token",
-      ]
-    }
+  <SQScanner
+    os="mac"
+  />
+  <ExecScanner
+    host="host"
+    os="mac"
+    projectKey="projectKey"
+    token="token"
   />
-  <p
-    className="big-spacer-top markdown"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.analysis.sq_scanner.docs"
-      id="onboarding.analysis.sq_scanner.docs"
-      values={
-        Object {
-          "link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/scan/sonarscanner/"
-          >
-            onboarding.analysis.sq_scanner.docs_link
-          </Link>,
-        }
-      }
-    />
-  </p>
 </div>
 `;
 
 exports[`renders correctly: windows 1`] = `
 <div>
-  <div>
-    <h4
-      className="spacer-bottom"
-    >
-      onboarding.analysis.sq_scanner.header.win
-    </h4>
-    <p
-      className="spacer-bottom markdown"
-    >
-      <FormattedMessage
-        defaultMessage="onboarding.analysis.sq_scanner.text"
-        id="onboarding.analysis.sq_scanner.text"
-        values={
-          Object {
-            "dir": <code>
-              bin
-            </code>,
-            "env_var": <code>
-              %PATH%
-            </code>,
-          }
-        }
-      />
-    </p>
-    <p>
-      <Link
-        className="button"
-        onlyActiveOnIndex={false}
-        style={Object {}}
-        target="_blank"
-        to="/documentation/analysis/scan/sonarscanner/"
-      >
-        download_verb
-      </Link>
-    </p>
-  </div>
-  <h4
-    className="huge-spacer-top spacer-bottom"
-  >
-    onboarding.analysis.sq_scanner.execute
-  </h4>
-  <InstanceMessage
-    message="onboarding.analysis.sq_scanner.execute.text"
-  >
-    <Component />
-  </InstanceMessage>
-  <CodeSnippet
-    isOneLine={true}
-    snippet={
-      Array [
-        "sonar-scanner.bat",
-        "-D\\"sonar.projectKey=projectKey\\"",
-        "-D\\"sonar.sources=.\\"",
-        "-D\\"sonar.host.url=host\\"",
-        "-D\\"sonar.login=token\\"",
-      ]
-    }
+  <SQScanner
+    os="win"
+  />
+  <ExecScanner
+    host="host"
+    os="win"
+    projectKey="projectKey"
+    token="token"
   />
-  <p
-    className="big-spacer-top markdown"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.analysis.sq_scanner.docs"
-      id="onboarding.analysis.sq_scanner.docs"
-      values={
-        Object {
-          "link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/scan/sonarscanner/"
-          >
-            onboarding.analysis.sq_scanner.docs_link
-          </Link>,
-        }
-      }
-    />
-  </p>
 </div>
 `;
index 9a20efa47f022bafec434bbb69f3560854795af7..5f9ba566b6191b1fe83873723a9b68210e7d6465 100644 (file)
@@ -27,6 +27,7 @@ export enum TutorialModes {
 export enum BuildTools {
   Maven = 'maven',
   Gradle = 'gradle',
+  CFamily = 'cfamily',
   DotNet = 'dotnet',
   Other = 'other'
 }
@@ -39,4 +40,4 @@ export enum OSs {
 
 export type ManualTutorialConfig =
   | { buildTool?: BuildTools.Maven | BuildTools.Gradle | BuildTools.DotNet }
-  | { buildTool: BuildTools.Other; os?: OSs };
+  | { buildTool: BuildTools.Other | BuildTools.CFamily; os?: OSs };
index c9c6710aa715837aa842017b91e8b2e70c8d558c..93ca2e332071b072a8115d206ab60807966542bd 100644 (file)
@@ -3288,6 +3288,7 @@ onboarding.build.maven=Maven
 onboarding.build.gradle=Gradle
 onboarding.build.make=Make
 onboarding.build.dotnet=.NET
+onboarding.build.cfamily=C,C++ or ObjC
 onboarding.build.other=Other (for JS, TS, Go, Python, PHP, ...)
 
 onboarding.build.other.os=What is your OS?
@@ -3296,6 +3297,16 @@ onboarding.build.other.os.win=Windows
 onboarding.build.other.os.mac=macOS
 
 onboarding.analysis.docs=Please visit the {link} for more details.
+onboarding.analysis.build_wrapper.header.linux=Download and unzip the Build Wrapper for Linux
+onboarding.analysis.build_wrapper.header.win=Download and unzip the Build Wrapper for Windows
+onboarding.analysis.build_wrapper.header.mac=Download and unzip the Build Wrapper for macOS
+onboarding.analysis.build_wrapper.text=And add the executable's directory to the {env_var} environment variable
+onboarding.analysis.build_wrapper.execute=Execute the Build Wrapper as a prefix to your build command
+onboarding.analysis.build_wrapper.execute_text=Run the following command in your project's folder.
+onboarding.analysis.build_wrapper.execute_build_command=<your clean build command>
+onboarding.analysis.build_wrapper.docs=Please visit the {link}  of the Build Wrapper for more details.
+onboarding.analysis.build_wrapper.docs_link=official documentation
+
 
 onboarding.analysis.java.maven.header=Execute the Scanner for Maven from your computer
 onboarding.analysis.java.maven.header.ci=Execute the Scanner for Maven from your CI