]> source.dussan.org Git - sonarqube.git/blob
365c2e1ea0e49aeefa2e6f54624b888d13c6bfdd
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
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';
23 import * as React from 'react';
24 import UserTokensMock from '../../../../api/mocks/UserTokensMock';
25 import { mockComponent } from '../../../../helpers/mocks/component';
26 import { mockAppState, mockLanguage, mockLoggedInUser } from '../../../../helpers/testMocks';
27 import { renderApp, RenderContext } from '../../../../helpers/testReactTestingUtils';
28 import { Permissions } from '../../../../types/permissions';
29 import { TokenType } from '../../../../types/token';
30 import AzurePipelinesTutorial, { AzurePipelinesTutorialProps } from '../AzurePipelinesTutorial';
31
32 jest.mock('../../../../api/user-tokens');
33
34 jest.mock('../../../../api/settings', () => ({
35   getAllValues: jest.fn().mockResolvedValue([])
36 }));
37
38 let tokenMock: UserTokensMock;
39
40 beforeAll(() => {
41   tokenMock = new UserTokensMock();
42 });
43
44 afterEach(() => {
45   tokenMock.reset();
46 });
47
48 it('should render correctly and allow navigating between the different steps', async () => {
49   renderAzurePipelinesTutorial();
50   const user = userEvent.setup();
51
52   expect(
53     screen.getByRole('heading', { name: 'onboarding.tutorial.with.azure_pipelines.title' })
54   ).toBeInTheDocument();
55
56   //// Default step.
57   assertDefaultStepIsCorrectlyRendered();
58
59   // Continue.
60   await goToNextStep(user);
61
62   //// Token step.
63   assertServiceEndpointStepIsCorrectlyRendered();
64
65   // Generate a token.
66   await clickButton(user, 'onboarding.token.generate.long');
67   const modal = screen.getByRole('dialog');
68   await clickButton(user, 'onboarding.token.generate', modal);
69   const lastToken = tokenMock.getLastToken();
70   if (lastToken === undefined) {
71     throw new Error("Couldn't find the latest generated token.");
72   }
73   expect(lastToken.type).toBe(TokenType.Global);
74   expect(within(modal).getByRole('alert')).toHaveTextContent(
75     `users.tokens.new_token_created.${lastToken.token}`
76   );
77   await clickButton(user, 'continue', modal);
78
79   // Continue.
80   await goToNextStep(user);
81
82   //// Analysis step: .NET
83   await clickButton(user, 'onboarding.build.dotnet');
84   assertDotNetStepIsCorrectlyRendered();
85
86   //// Analysis step: Maven
87   await clickButton(user, 'onboarding.build.maven');
88   assertMavenStepIsCorrectlyRendered();
89
90   //// Analysis step: Gradle
91   await clickButton(user, 'onboarding.build.gradle');
92   assertGradleStepIsCorrectlyRendered();
93
94   //// Analysis step: Gradle
95   await clickButton(user, 'onboarding.build.gradle');
96   assertGradleStepIsCorrectlyRendered();
97
98   //// Analysis step: C Family
99   await clickButton(user, 'onboarding.build.cfamily');
100
101   // OS: Linux
102   await clickButton(user, 'onboarding.build.other.os.linux');
103   assertCFamilyLinuxStepIsCorrectlyRendered();
104
105   // OS: Windows
106   await clickButton(user, 'onboarding.build.other.os.win');
107   assertCFamilyWindowsStepIsCorrectlyRendered();
108
109   // OS: macOS
110   await clickButton(user, 'onboarding.build.other.os.mac');
111   assertCFamilyMacOSStepIsCorrectlyRendered();
112
113   //// Analysis step: Other
114   await clickButton(user, 'onboarding.build.other');
115   assertOtherStepIsCorrectlyRendered();
116
117   //// Finish tutorial
118   await clickButton(user, 'tutorials.finish');
119   assertFinishStepIsCorrectlyRendered();
120 });
121
122 it('allows to navigate back to a previous step', async () => {
123   renderAzurePipelinesTutorial();
124   const user = userEvent.setup();
125
126   // No clickable steps.
127   expect(
128     screen.queryByRole('button', {
129       name: '1 onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title'
130     })
131   ).not.toBeInTheDocument();
132
133   // Go to the next steps.
134   await goToNextStep(user);
135   await goToNextStep(user);
136
137   // The first 2 steps become clickable.
138   expect(
139     screen.getByRole('button', {
140       name: '1 onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title'
141     })
142   ).toBeInTheDocument();
143   expect(
144     screen.getByRole('button', {
145       name: '2 onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title'
146     })
147   ).toBeInTheDocument();
148
149   // Navigate back to the first step.
150   await clickButton(user, '1 onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title');
151
152   // No more clickable steps.
153   expect(
154     screen.queryByRole('button', {
155       name: '1 onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title'
156     })
157   ).not.toBeInTheDocument();
158 });
159
160 it('should not offer CFamily analysis if the language is not available', async () => {
161   renderAzurePipelinesTutorial(undefined, { languages: {} });
162   const user = userEvent.setup();
163
164   // Go to the analysis step.
165   await goToNextStep(user);
166   await goToNextStep(user);
167
168   expect(screen.getByRole('button', { name: 'onboarding.build.dotnet' })).toBeInTheDocument();
169   expect(
170     screen.queryByRole('button', { name: 'onboarding.build.cfamily' })
171   ).not.toBeInTheDocument();
172 });
173
174 function renderAzurePipelinesTutorial(
175   props: Partial<AzurePipelinesTutorialProps> = {},
176   {
177     appState = mockAppState({ branchesEnabled: true }),
178     languages = { c: mockLanguage({ key: 'c' }) }
179   }: RenderContext = {}
180 ) {
181   return renderApp(
182     '/',
183     <AzurePipelinesTutorial
184       baseUrl="http://localhost:9000"
185       component={mockComponent()}
186       currentUser={mockLoggedInUser({ permissions: { global: [Permissions.Scan] } })}
187       willRefreshAutomatically={true}
188       {...props}
189     />,
190     { appState, languages }
191   );
192 }
193
194 async function clickButton(user: UserEvent, name: string, context?: HTMLElement) {
195   if (context) {
196     await user.click(within(context).getByRole('button', { name }));
197   } else {
198     await user.click(screen.getByRole('button', { name }));
199   }
200 }
201
202 async function goToNextStep(user: UserEvent) {
203   await clickButton(user, 'continue');
204 }
205
206 function assertDefaultStepIsCorrectlyRendered() {
207   expect(
208     screen.getByRole('heading', {
209       name: 'onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title'
210     })
211   ).toBeInTheDocument();
212   expect(screen.getByTestId('azure-tutorial__extension')).toMatchSnapshot('extension step');
213 }
214
215 function assertServiceEndpointStepIsCorrectlyRendered() {
216   expect(
217     screen.getByRole('heading', {
218       name: 'onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title'
219     })
220   ).toBeInTheDocument();
221   expect(screen.getByTestId('azure-tutorial__service-endpoint')).toMatchSnapshot(
222     'service endpoint step'
223   );
224   expect(screen.getByRole('button', { name: 'copy_to_clipboard' })).toBeInTheDocument();
225   expect(
226     screen.getByRole('button', { name: 'onboarding.token.generate.long' })
227   ).toBeInTheDocument();
228 }
229
230 function assertDotNetStepIsCorrectlyRendered() {
231   expect(
232     screen.getByRole('heading', {
233       name: 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.title'
234     })
235   ).toBeInTheDocument();
236
237   expect(screen.getByTestId('azure-tutorial__analysis-command')).toMatchSnapshot('dotnet step');
238   expect(screen.getByRole('button', { name: 'copy_to_clipboard' })).toBeInTheDocument();
239 }
240
241 function assertMavenStepIsCorrectlyRendered() {
242   expect(screen.getByTestId('azure-tutorial__analysis-command')).toMatchSnapshot('maven step');
243   expect(screen.getByRole('button', { name: 'copy_to_clipboard' })).toBeInTheDocument();
244 }
245
246 function assertGradleStepIsCorrectlyRendered() {
247   expect(screen.getByTestId('azure-tutorial__analysis-command')).toMatchSnapshot('gradle step');
248   expect(screen.getByRole('button', { name: 'copy_to_clipboard' })).toBeInTheDocument();
249 }
250
251 function assertCFamilyLinuxStepIsCorrectlyRendered() {
252   expect(screen.getByTestId('azure-tutorial__analysis-command')).toMatchSnapshot(
253     'cfamily linux step'
254   );
255   expect(screen.getAllByRole('button', { name: 'copy_to_clipboard' })).toHaveLength(4);
256 }
257
258 function assertCFamilyWindowsStepIsCorrectlyRendered() {
259   expect(screen.getByTestId('azure-tutorial__analysis-command')).toMatchSnapshot(
260     'cfamily windows step'
261   );
262   expect(screen.getAllByRole('button', { name: 'copy_to_clipboard' })).toHaveLength(4);
263 }
264
265 function assertCFamilyMacOSStepIsCorrectlyRendered() {
266   expect(screen.getByTestId('azure-tutorial__analysis-command')).toMatchSnapshot(
267     'cfamily macos step'
268   );
269   expect(screen.getAllByRole('button', { name: 'copy_to_clipboard' })).toHaveLength(4);
270 }
271
272 function assertOtherStepIsCorrectlyRendered() {
273   expect(screen.getByTestId('azure-tutorial__analysis-command')).toMatchSnapshot('other step');
274   expect(screen.getByRole('button', { name: 'copy_to_clipboard' })).toBeInTheDocument();
275 }
276
277 function assertFinishStepIsCorrectlyRendered() {
278   expect(
279     screen.getByRole('heading', {
280       name: 'onboarding.tutorial.ci_outro.all_set.title'
281     })
282   ).toBeInTheDocument();
283   expect(screen.getByTestId('azure-tutorial__all-set')).toMatchSnapshot('all set step');
284 }