You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EventInner-it.tsx 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 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 } from '@testing-library/react';
  21. import userEvent from '@testing-library/user-event';
  22. import * as React from 'react';
  23. import { Route } from 'react-router-dom';
  24. import BranchesServiceMock from '../../../api/mocks/BranchesServiceMock';
  25. import { isMainBranch } from '../../../helpers/branch-like';
  26. import { mockBranch, mockMainBranch } from '../../../helpers/mocks/branch-like';
  27. import { mockAnalysisEvent } from '../../../helpers/mocks/project-activity';
  28. import { renderAppWithComponentContext } from '../../../helpers/testReactTestingUtils';
  29. import { byRole, byText } from '../../../helpers/testSelector';
  30. import { Branch, BranchLike } from '../../../types/branch-like';
  31. import {
  32. ApplicationAnalysisEventCategory,
  33. DefinitionChangeType,
  34. ProjectAnalysisEventCategory,
  35. } from '../../../types/project-activity';
  36. import EventInner, { EventInnerProps } from '../EventInner';
  37. const ui = {
  38. showMoreBtn: byRole('button', { name: 'more' }),
  39. showLessBtn: byRole('button', { name: 'hide' }),
  40. projectLink: (name: string) => byRole('link', { name }),
  41. definitionChangeLabel: byText('event.category.DEFINITION_CHANGE', { exact: false }),
  42. projectAddedTxt: (branch: BranchLike) =>
  43. isMainBranch(branch)
  44. ? byText(/event\.definition_change\.added/)
  45. : byText(/event\.definition_change\.branch_added/),
  46. projectRemovedTxt: (branch: BranchLike) =>
  47. isMainBranch(branch)
  48. ? byText('event.definition_change.removed')
  49. : byText('event.definition_change.branch_removed'),
  50. branchReplacedTxt: byText('event.definition_change.branch_replaced'),
  51. qualityGateLabel: byText('event.category.QUALITY_GATE', { exact: false }),
  52. stillFailingTxt: byText('event.quality_gate.still_x'),
  53. versionLabel: byText('event.category.VERSION', { exact: false }),
  54. sqUpgradeLabel: (sqVersion: string) => byText(`event.sqUpgrade${sqVersion}`),
  55. };
  56. const handler = new BranchesServiceMock();
  57. beforeEach(() => {
  58. handler.reset();
  59. });
  60. describe('DEFINITION_CHANGE events', () => {
  61. it.each([mockMainBranch(), mockBranch()])(
  62. 'should render correctly for "ADDED" events',
  63. async (branchLike: Branch) => {
  64. handler.addBranch(branchLike);
  65. const user = userEvent.setup();
  66. renderEventInner(
  67. {
  68. event: mockAnalysisEvent({
  69. category: ApplicationAnalysisEventCategory.DefinitionChange,
  70. definitionChange: {
  71. projects: [
  72. {
  73. changeType: DefinitionChangeType.Added,
  74. key: 'foo',
  75. name: 'Foo',
  76. branch: 'master-foo',
  77. },
  78. ],
  79. },
  80. }),
  81. },
  82. `branch=${branchLike.name}&id=my-project`,
  83. );
  84. expect(await ui.definitionChangeLabel.find()).toBeInTheDocument();
  85. await user.click(ui.showMoreBtn.get());
  86. expect(await ui.projectAddedTxt(branchLike).find()).toBeInTheDocument();
  87. expect(ui.projectLink('Foo').get()).toBeInTheDocument();
  88. expect(screen.getByText('master-foo')).toBeInTheDocument();
  89. },
  90. );
  91. it.each([mockMainBranch(), mockBranch()])(
  92. 'should render correctly for "REMOVED" events',
  93. async (branchLike: Branch) => {
  94. const user = userEvent.setup();
  95. handler.addBranch(branchLike);
  96. renderEventInner(
  97. {
  98. event: mockAnalysisEvent({
  99. category: ApplicationAnalysisEventCategory.DefinitionChange,
  100. definitionChange: {
  101. projects: [
  102. {
  103. changeType: DefinitionChangeType.Removed,
  104. key: 'bar',
  105. name: 'Bar',
  106. branch: 'master-bar',
  107. },
  108. ],
  109. },
  110. }),
  111. },
  112. `branch=${branchLike.name}&id=my-project`,
  113. );
  114. expect(ui.definitionChangeLabel.get()).toBeInTheDocument();
  115. await user.click(ui.showMoreBtn.get());
  116. expect(await ui.projectRemovedTxt(branchLike).find()).toBeInTheDocument();
  117. expect(ui.projectLink('Bar').get()).toBeInTheDocument();
  118. expect(screen.getByText('master-bar')).toBeInTheDocument();
  119. },
  120. );
  121. it('should render correctly for "BRANCH_CHANGED" events', async () => {
  122. const user = userEvent.setup();
  123. renderEventInner({
  124. event: mockAnalysisEvent({
  125. category: ApplicationAnalysisEventCategory.DefinitionChange,
  126. definitionChange: {
  127. projects: [
  128. {
  129. changeType: DefinitionChangeType.BranchChanged,
  130. key: 'baz',
  131. name: 'Baz',
  132. oldBranch: 'old-branch',
  133. newBranch: 'new-branch',
  134. },
  135. ],
  136. },
  137. }),
  138. });
  139. expect(ui.definitionChangeLabel.get()).toBeInTheDocument();
  140. await user.click(ui.showMoreBtn.get());
  141. expect(ui.branchReplacedTxt.get()).toBeInTheDocument();
  142. expect(ui.projectLink('Baz').get()).toBeInTheDocument();
  143. expect(screen.getByText('old-branch')).toBeInTheDocument();
  144. expect(screen.getByText('new-branch')).toBeInTheDocument();
  145. });
  146. });
  147. describe('QUALITY_GATE events', () => {
  148. it('should render correctly for simple "QUALITY_GATE" events', () => {
  149. renderEventInner({
  150. event: mockAnalysisEvent({
  151. category: ProjectAnalysisEventCategory.QualityGate,
  152. qualityGate: { status: 'ERROR', stillFailing: false, failing: [] },
  153. }),
  154. });
  155. expect(ui.qualityGateLabel.get()).toBeInTheDocument();
  156. });
  157. it('should render correctly for "still failing" "QUALITY_GATE" events', () => {
  158. renderEventInner({
  159. event: mockAnalysisEvent({
  160. category: ProjectAnalysisEventCategory.QualityGate,
  161. qualityGate: { status: 'ERROR', stillFailing: true, failing: [] },
  162. }),
  163. });
  164. expect(ui.qualityGateLabel.get()).toBeInTheDocument();
  165. expect(ui.stillFailingTxt.get()).toBeInTheDocument();
  166. });
  167. it('should render correctly for application "QUALITY_GATE" events', async () => {
  168. const user = userEvent.setup();
  169. renderEventInner({
  170. event: mockAnalysisEvent({
  171. category: ProjectAnalysisEventCategory.QualityGate,
  172. qualityGate: {
  173. status: 'ERROR',
  174. stillFailing: true,
  175. failing: [
  176. {
  177. key: 'foo',
  178. name: 'Foo',
  179. branch: 'master',
  180. },
  181. {
  182. key: 'bar',
  183. name: 'Bar',
  184. branch: 'feature/bar',
  185. },
  186. ],
  187. },
  188. }),
  189. });
  190. expect(ui.qualityGateLabel.get()).toBeInTheDocument();
  191. await user.click(ui.showMoreBtn.get());
  192. expect(ui.projectLink('Foo').get()).toBeInTheDocument();
  193. expect(ui.projectLink('Bar').get()).toBeInTheDocument();
  194. await user.click(ui.showLessBtn.get());
  195. expect(ui.projectLink('Foo').query()).not.toBeInTheDocument();
  196. expect(ui.projectLink('Bar').query()).not.toBeInTheDocument();
  197. });
  198. });
  199. describe('VERSION events', () => {
  200. it('should render correctly', () => {
  201. renderEventInner({
  202. event: mockAnalysisEvent({
  203. category: ProjectAnalysisEventCategory.Version,
  204. name: '1.0',
  205. }),
  206. });
  207. expect(ui.versionLabel.get()).toBeInTheDocument();
  208. expect(screen.getByText('1.0')).toBeInTheDocument();
  209. });
  210. });
  211. describe('SQ_UPGRADE events', () => {
  212. it('should render correctly', () => {
  213. renderEventInner({
  214. event: mockAnalysisEvent({
  215. category: ProjectAnalysisEventCategory.SqUpgrade,
  216. name: '10.0',
  217. }),
  218. });
  219. expect(ui.sqUpgradeLabel('10.0').get()).toBeInTheDocument();
  220. });
  221. });
  222. function renderEventInner(props: Partial<EventInnerProps> = {}, params?: string) {
  223. return renderAppWithComponentContext(
  224. '/',
  225. () => <Route path="*" element={<EventInner event={mockAnalysisEvent()} {...props} />} />,
  226. { navigateTo: params ? `/?id=my-project&${params}` : '/?id=my-project' },
  227. );
  228. }