3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 import { screen, within } from '@testing-library/react';
21 import userEvent from '@testing-library/user-event';
22 import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup';
23 import * as React from 'react';
24 import UserTokensMock from '../../../../api/mocks/UserTokensMock';
25 import { mockComponent } from '../../../../helpers/mocks/component';
26 import { mockLanguage, mockLoggedInUser } from '../../../../helpers/testMocks';
27 import { RenderContext, renderApp } from '../../../../helpers/testReactTestingUtils';
28 import { Permissions } from '../../../../types/permissions';
29 import { TokenType } from '../../../../types/token';
30 import { getCopyToClipboardValue, getTutorialBuildButtons } from '../../test-utils';
31 import { OSs } from '../../types';
32 import AzurePipelinesTutorial, { AzurePipelinesTutorialProps } from '../AzurePipelinesTutorial';
34 jest.mock('../../../../api/settings', () => ({
35 getAllValues: jest.fn().mockResolvedValue([]),
38 let tokenMock: UserTokensMock;
41 tokenMock = new UserTokensMock();
48 it('should render correctly and allow token generation', async () => {
49 renderAzurePipelinesTutorial();
50 const user = userEvent.setup();
53 screen.getByRole('heading', { name: 'onboarding.tutorial.with.azure_pipelines.title' }),
54 ).toBeInTheDocument();
57 assertDefaultStepIsCorrectlyRendered();
60 assertServiceEndpointStepIsCorrectlyRendered();
63 await clickButton(user, 'onboarding.token.generate.long');
64 const modal = screen.getByRole('dialog');
65 await clickButton(user, 'onboarding.token.generate', modal);
66 const lastToken = tokenMock.getLastToken();
68 expect(lastToken).toBeDefined();
70 expect(lastToken!.type).toBe(TokenType.Global);
72 within(modal).getByText(`users.tokens.new_token_created.${lastToken!.token}`),
73 ).toBeInTheDocument();
74 await clickButton(user, 'continue', modal);
76 // Analysis step: .NET
77 await user.click(getTutorialBuildButtons().dotnetBuildButton.get());
78 assertDotNetStepIsCorrectlyRendered();
80 // Analysis step: Maven
81 await user.click(getTutorialBuildButtons().mavenBuildButton.get());
82 assertMavenStepIsCorrectlyRendered();
84 // Analysis step: Gradle
85 await user.click(getTutorialBuildButtons().gradleBuildButton.get());
86 assertGradleStepIsCorrectlyRendered();
88 // Analysis step: C Family
89 await user.click(getTutorialBuildButtons().cppBuildButton.get());
90 // Default: Automatic configuration
91 // expect linux/win/macos buttons not to be present
92 expect(getTutorialBuildButtons().linuxButton.query()).not.toBeInTheDocument();
93 expect(getTutorialBuildButtons().windowsButton.query()).not.toBeInTheDocument();
94 expect(getTutorialBuildButtons().macosButton.query()).not.toBeInTheDocument();
95 assertAutomaticCppStepIsCorrectlyRendered();
97 // Switch to manual configuration
98 await user.click(getTutorialBuildButtons().autoConfigManual.get());
99 await user.click(getTutorialBuildButtons().linuxButton.get());
100 assertManualCppStepIsCorrectlyRendered(OSs.Linux);
101 await user.click(getTutorialBuildButtons().arm64Button.get());
102 assertManualCppStepIsCorrectlyRendered(OSs.Linux, 'arm64');
103 await user.click(getTutorialBuildButtons().windowsButton.get());
104 assertObjCStepIsCorrectlyRendered(OSs.Windows);
105 await user.click(getTutorialBuildButtons().macosButton.get());
106 assertObjCStepIsCorrectlyRendered(OSs.MacOS);
108 // Analysis step: C Family
109 await user.click(getTutorialBuildButtons().objCBuildButton.get());
110 await user.click(getTutorialBuildButtons().linuxButton.get());
111 await user.click(getTutorialBuildButtons().x86_64Button.get());
112 assertObjCStepIsCorrectlyRendered(OSs.Linux);
113 await user.click(getTutorialBuildButtons().arm64Button.get());
114 assertObjCStepIsCorrectlyRendered(OSs.Linux, 'arm64');
115 await user.click(getTutorialBuildButtons().windowsButton.get());
116 assertObjCStepIsCorrectlyRendered(OSs.Windows);
117 await user.click(getTutorialBuildButtons().macosButton.get());
118 assertObjCStepIsCorrectlyRendered(OSs.MacOS);
120 // Analysis step: Dart
121 await user.click(getTutorialBuildButtons().dartBuildButton.get());
122 assertOtherStepIsCorrectlyRendered();
124 // Analysis step: Other
125 await user.click(getTutorialBuildButtons().otherBuildButton.get());
126 assertOtherStepIsCorrectlyRendered();
129 assertFinishStepIsCorrectlyRendered();
132 it('should not offer CFamily analysis if the language is not available', () => {
133 renderAzurePipelinesTutorial(undefined, { languages: {} });
135 expect(getTutorialBuildButtons().dotnetBuildButton.get()).toBeInTheDocument();
136 expect(getTutorialBuildButtons().cppBuildButton.query()).not.toBeInTheDocument();
139 function assertDefaultStepIsCorrectlyRendered() {
141 screen.getByRole('heading', {
142 name: 'onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title',
144 ).toBeInTheDocument();
147 function assertServiceEndpointStepIsCorrectlyRendered() {
149 screen.getByRole('heading', {
150 name: 'onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title',
152 ).toBeInTheDocument();
153 expect(getCopyToClipboardValue(0, 'Copy to clipboard')).toBe('https://sonarqube.example.com/');
155 screen.getByRole('button', { name: 'onboarding.token.generate.long' }),
156 ).toBeInTheDocument();
159 function assertDotNetStepIsCorrectlyRendered() {
161 screen.getByRole('heading', {
162 name: 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.title',
164 ).toBeInTheDocument();
166 expect(getCopyToClipboardValue(1, 'Copy to clipboard')).toBe('foo');
169 function assertMavenStepIsCorrectlyRendered() {
170 expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('maven, copy additional properties');
173 function assertGradleStepIsCorrectlyRendered() {
174 expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('gradle, copy additional properties');
177 function assertObjCStepIsCorrectlyRendered(os: string, arch: string = 'x86_64') {
178 expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot(
179 `objectivec ${os} ${arch}, copy shell script`,
181 expect(getCopyToClipboardValue(1, 'Copy to clipboard')).toBe('foo');
182 expect(getCopyToClipboardValue(2, 'Copy to clipboard')).toMatchSnapshot(
183 `objectivec ${os} ${arch}, copy additional properties`,
185 expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot(
186 `objectivec ${os} ${arch}, copy build-wrapper command`,
190 function assertAutomaticCppStepIsCorrectlyRendered() {
191 assertOtherStepIsCorrectlyRendered();
194 function assertManualCppStepIsCorrectlyRendered(os: string, arch: string = 'x86_64') {
195 expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot(
196 `manual-cpp ${os} ${arch}, copy shell script`,
198 expect(getCopyToClipboardValue(1, 'Copy to clipboard')).toBe('foo');
199 expect(getCopyToClipboardValue(2, 'Copy to clipboard')).toMatchSnapshot(
200 `manual-cpp ${os} ${arch}, copy additional properties`,
202 expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot(
203 `manual-cpp ${os} ${arch}, copy build-wrapper command`,
207 function assertOtherStepIsCorrectlyRendered() {
208 expect(getCopyToClipboardValue(1, 'Copy to clipboard')).toBe('foo');
211 function assertFinishStepIsCorrectlyRendered() {
213 screen.getByRole('heading', {
214 name: 'onboarding.tutorial.ci_outro.done',
216 ).toBeInTheDocument();
219 function renderAzurePipelinesTutorial(
220 props: Partial<AzurePipelinesTutorialProps> = {},
221 { languages = { c: mockLanguage({ key: 'c' }) } }: RenderContext = {},
225 <AzurePipelinesTutorial
226 baseUrl="https://sonarqube.example.com/"
227 component={mockComponent({ key: 'foo' })}
228 currentUser={mockLoggedInUser({ permissions: { global: [Permissions.Scan] } })}
229 willRefreshAutomatically
236 async function clickButton(user: UserEvent, name: string, context?: HTMLElement) {
238 await user.click(within(context).getByRole('button', { name }));
240 await user.click(screen.getByRole('button', { name }));