From 7c59be8a74c0a068c2584d6f43a09330bd5cdc16 Mon Sep 17 00:00:00 2001 From: Revanshu Paliwal Date: Tue, 12 Apr 2022 14:42:07 +0200 Subject: [PATCH] SONAR-16247 RTL migration for quality gates app --- .../js/api/mocks/QualityGatesServiceMock.ts | 103 ++++- .../components/PermissionItem.tsx | 5 +- .../quality-gates/components/Projects.tsx | 9 +- ...QualityGatePermissionsAddModalRenderer.tsx | 2 +- .../components/__tests__/App-it.tsx | 210 ++++++++- .../components/__tests__/App.tsx | 91 ---- .../components/__tests__/Details-test.tsx | 124 ------ .../__tests__/DetailsContent-test.tsx | 49 --- .../__tests__/DetailsHeader-test.tsx | 97 ----- .../__tests__/PermissionItem-test.tsx | 32 -- .../components/__tests__/Projects-test.tsx | 119 ----- .../__tests__/QualityGatePermissions-test.tsx | 247 ----------- .../QualityGatePermissionsAddModal-test.tsx | 93 ---- ...tyGatePermissionsAddModalRenderer-test.tsx | 53 --- .../QualityGatePermissionsRenderer-test.tsx | 62 --- .../__tests__/__snapshots__/App.tsx.snap | 147 ------- .../__snapshots__/Details-test.tsx.snap | 53 --- .../DetailsContent-test.tsx.snap | 275 ------------ .../__snapshots__/DetailsHeader-test.tsx.snap | 163 ------- .../PermissionItem-test.tsx.snap | 49 --- .../__snapshots__/Projects-test.tsx.snap | 59 --- .../QualityGatePermissions-test.tsx.snap | 23 - ...alityGatePermissionsAddModal-test.tsx.snap | 11 - ...ePermissionsAddModalRenderer-test.tsx.snap | 165 ------- ...alityGatePermissionsRenderer-test.tsx.snap | 409 ------------------ 25 files changed, 315 insertions(+), 2335 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Details-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsContent-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsHeader-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/PermissionItem-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Projects-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissions-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModal-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsRenderer-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/App.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Details-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsContent-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsHeader-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/PermissionItem-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Projects-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissions-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModal-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsRenderer-test.tsx.snap diff --git a/server/sonar-web/src/main/js/api/mocks/QualityGatesServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/QualityGatesServiceMock.ts index 0ca29ed0d63..e087d046dc1 100644 --- a/server/sonar-web/src/main/js/api/mocks/QualityGatesServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/QualityGatesServiceMock.ts @@ -18,20 +18,28 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { cloneDeep, flatten, omit, remove } from 'lodash'; +import { Project } from '../../apps/quality-gates/components/Projects'; import { mockQualityGate } from '../../helpers/mocks/quality-gates'; +import { mockUserBase } from '../../helpers/mocks/users'; +import { mockGroup } from '../../helpers/testMocks'; import { Condition, QualityGate } from '../../types/types'; import { + addGroup, + addUser, + associateGateWithProject, copyQualityGate, createCondition, createQualityGate, deleteCondition, deleteQualityGate, + dissociateGateWithProject, fetchQualityGate, fetchQualityGates, renameQualityGate, searchGroups, searchProjects, searchUsers, + setQualityGateAsDefault, updateCondition } from '../quality-gates'; @@ -39,6 +47,7 @@ export class QualityGatesServiceMock { isAdmin = false; readOnlyList: QualityGate[]; list: QualityGate[]; + projects: Project[]; constructor(list?: QualityGate[], defaultId = 'AWBWEMe2qGAMGEYPjJlm') { this.readOnlyList = list || [ @@ -117,6 +126,13 @@ export class QualityGatesServiceMock { this.list = cloneDeep(this.readOnlyList); + this.projects = [ + { key: 'test1', name: 'test1', selected: false }, + { key: 'test2', name: 'test2', selected: false }, + { key: 'test3', name: 'test3', selected: true }, + { key: 'test4', name: 'test4', selected: true } + ]; + (fetchQualityGate as jest.Mock).mockImplementation(this.showHandler); (fetchQualityGates as jest.Mock).mockImplementation(this.listHandler); (createQualityGate as jest.Mock).mockImplementation(this.createHandler); @@ -126,18 +142,16 @@ export class QualityGatesServiceMock { (createCondition as jest.Mock).mockImplementation(this.createConditionHandler); (updateCondition as jest.Mock).mockImplementation(this.updateConditionHandler); (deleteCondition as jest.Mock).mockImplementation(this.deleteConditionHandler); + (searchProjects as jest.Mock).mockImplementation(this.searchProjectsHandler); + (searchUsers as jest.Mock).mockImplementation(this.searchUsersHandler); + (searchGroups as jest.Mock).mockImplementation(this.searchGroupsHandler); + (associateGateWithProject as jest.Mock).mockImplementation(this.selectHandler); + (dissociateGateWithProject as jest.Mock).mockImplementation(this.deSelectHandler); + (setQualityGateAsDefault as jest.Mock).mockImplementation(this.setDefaultHandler); // To be implemented. - (searchUsers as jest.Mock).mockResolvedValue({ users: [] }); - (searchGroups as jest.Mock).mockResolvedValue({ groups: [] }); - (searchProjects as jest.Mock).mockResolvedValue({ - paging: { - pageIndex: 1, - pageSize: 100, - total: 0 - }, - results: [] - }); + (addUser as jest.Mock).mockResolvedValue({}); + (addGroup as jest.Mock).mockResolvedValue({}); } getCorruptedQualityGateName() { @@ -247,6 +261,18 @@ export class QualityGatesServiceMock { }); }; + setDefaultHandler = ({ id }: { id: string }) => { + this.list.forEach(q => { + q.isDefault = false; + }); + const selectedQG = this.list.find(q => q.id === id); + if (selectedQG === undefined) { + return Promise.reject({ errors: [{ msg: `No quality gate has been found for id ${id}` }] }); + } + selectedQG.isDefault = true; + return Promise.resolve(); + }; + createConditionHandler = ( data: { gateId: string; @@ -288,6 +314,63 @@ export class QualityGatesServiceMock { return Promise.resolve(); }; + searchProjectsHandler = ({ + selected, + query + }: { + selected: string; + query: string | undefined; + }) => { + let filteredProjects = this.projects; + if (selected === 'selected') { + filteredProjects = this.projects.filter(p => p.selected); + } else if (selected === 'deselected') { + filteredProjects = this.projects.filter(p => !p.selected); + } + + if (query !== '' && query !== undefined) { + filteredProjects = filteredProjects.filter(p => p.name.includes(query)); + } + + const response = { + paging: { pageIndex: 1, pageSize: 3, total: 55 }, + results: filteredProjects + }; + return this.reply(response); + }; + + searchUsersHandler = ({ selected }: { selected: string }) => { + if (selected === 'selected') { + return this.reply({ users: [] }); + } + + return this.reply({ users: [mockUserBase()] }); + }; + + searchGroupsHandler = ({ selected }: { selected: string }) => { + if (selected === 'selected') { + return this.reply({ groups: [] }); + } + + return this.reply({ groups: [mockGroup()] }); + }; + + selectHandler = ({ projectKey }: { projectKey: string }) => { + const changedProject = this.projects.find(p => p.key === projectKey); + if (changedProject) { + changedProject.selected = true; + } + return Promise.resolve(); + }; + + deSelectHandler = ({ projectKey }: { projectKey: string }) => { + const changedProject = this.projects.find(p => p.key === projectKey); + if (changedProject) { + changedProject.selected = false; + } + return Promise.resolve(); + }; + reply(response: T): Promise { return Promise.resolve(cloneDeep(response)); } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/PermissionItem.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/PermissionItem.tsx index 3acb730163f..8f34e433203 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/PermissionItem.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/PermissionItem.tsx @@ -45,7 +45,10 @@ export default function PermissionItem(props: PermissionItemProps) { {isUser(item) &&
{item.login}
} - props.onClickDelete(item)} /> + props.onClickDelete(item)} + data-testid="permission-delete-button" + /> ); } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx index 8f14671da7c..62e8171d9d7 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Projects.tsx @@ -39,11 +39,18 @@ interface Props { interface State { needToReload: boolean; lastSearchParams?: SelectListSearchParams; - projects: Array<{ key: string; name: string; selected: boolean }>; + projects: Project[]; projectsTotalCount?: number; selectedProjects: string[]; } +// exported for testing +export interface Project { + key: string; + name: string; + selected: boolean; +} + export default class Projects extends React.PureComponent { mounted = false; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx index b06affa7a2a..c230b7aac19 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatePermissionsAddModalRenderer.tsx @@ -87,7 +87,7 @@ export default function QualityGatePermissionsAddModalRenderer( export function customOptions(option: OptionWithValue) { return ( - + {isUser(option) ? ( ) : ( diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx index 612607f9c19..3f02e085989 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx @@ -20,6 +20,7 @@ import { screen, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import selectEvent from 'react-select-event'; +import { searchProjects, searchUsers } from '../../../../api/quality-gates'; import { QualityGatesServiceMock } from '../../../../api/mocks/QualityGatesServiceMock'; import { mockAppState } from '../../../../helpers/testMocks'; import { renderApp } from '../../../../helpers/testReactTestingUtils'; @@ -66,7 +67,6 @@ it('should be able to create a quality gate then delete it', async () => { const user = userEvent.setup(); handler.setIsAdmin(true); renderQualityGateApp(); - let createButton = await screen.findByRole('button', { name: 'create' }); // Using keyboard @@ -136,6 +136,18 @@ it('should be able to rename a quality gate', async () => { expect(await screen.findByRole('menuitem', { name: /New Name.*/ })).toBeInTheDocument(); }); +it('should be able to set as default a quality gate', async () => { + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily'); + await user.click(notDefaultQualityGate); + const setAsDefaultButton = screen.getByRole('button', { name: 'set_as_default' }); + await user.click(setAsDefaultButton); + expect(screen.getAllByRole('menuitem')[1]).toHaveTextContent('default'); +}); + it('should be able to add a condition', async () => { const user = userEvent.setup(); handler.setIsAdmin(true); @@ -266,6 +278,202 @@ it('should explain condition on branch', async () => { ).toBeInTheDocument(); }); +describe('The Project section', () => { + it('should render list of projects correctly in different tabs', async () => { + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily'); + + await user.click(notDefaultQualityGate); + // by default it shows "selected" values + expect(screen.getAllByRole('radio')).toHaveLength(3); + expect(screen.getAllByRole('checkbox')).toHaveLength(2); + + // change tabs to show deselected projects + await user.click(screen.getByRole('radio', { name: 'quality_gates.projects.without' })); + expect(screen.getAllByRole('checkbox')).toHaveLength(2); + + // change tabs to show all projects + await user.click(screen.getByRole('radio', { name: 'quality_gates.projects.all' })); + expect(screen.getAllByRole('checkbox')).toHaveLength(4); + }); + + it('should handle select and deselect correctly', async () => { + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily'); + await user.click(notDefaultQualityGate); + + const checkedProjects = screen.getAllByRole('checkbox')[0]; + expect(screen.getAllByRole('checkbox')).toHaveLength(2); + await user.click(checkedProjects); + const reloadButton = screen.getByRole('button', { name: 'reload' }); + expect(reloadButton).toBeInTheDocument(); + await user.click(reloadButton); + expect(screen.getAllByRole('checkbox')).toHaveLength(1); + + // change tabs to show deselected projects + await user.click(screen.getAllByRole('radio')[1]); + + const uncheckedProjects = screen.getAllByRole('checkbox')[0]; + expect(screen.getAllByRole('checkbox')).toHaveLength(3); + await user.click(uncheckedProjects); + expect(reloadButton).toBeInTheDocument(); + await user.click(reloadButton); + expect(screen.getAllByRole('checkbox')).toHaveLength(2); + }); + + it('should handle the search of projects', async () => { + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily'); + + await user.click(notDefaultQualityGate); + + const searchInput = screen.getByRole('searchbox', { name: 'search_verb' }); + expect(searchInput).toBeInTheDocument(); + await user.click(searchInput); + await user.keyboard('test2{Enter}'); + expect(screen.getAllByRole('checkbox')).toHaveLength(1); + }); + + it('should display show more button if there are multiple pages of data', async () => { + (searchProjects as jest.Mock).mockResolvedValueOnce({ + paging: { pageIndex: 2, pageSize: 3, total: 55 }, + results: [] + }); + + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily'); + await user.click(notDefaultQualityGate); + + expect(screen.getByRole('button', { name: 'show_more' })).toBeInTheDocument(); + }); +}); + +describe('The Permissions section', () => { + it('should not show button to grant permission when user is not admin', () => { + renderQualityGateApp(); + + expect(screen.queryByText('quality_gates.permissions')).not.toBeInTheDocument(); + }); + it('should show button to grant permission when user is admin', async () => { + handler.setIsAdmin(true); + renderQualityGateApp(); + + const grantPermissionButton = await screen.findByRole('button', { + name: 'quality_gates.permissions.grant' + }); + expect(screen.getByText('quality_gates.permissions')).toBeInTheDocument(); + expect(grantPermissionButton).toBeInTheDocument(); + }); + + it('should assign permission to a user and delete it later', async () => { + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + expect(screen.queryByText('userlogin')).not.toBeInTheDocument(); + + // Granting permission to a user + const grantPermissionButton = await screen.findByRole('button', { + name: 'quality_gates.permissions.grant' + }); + await user.click(grantPermissionButton); + const popup = screen.getByRole('dialog'); + const searchUserInput = within(popup).getByRole('textbox'); + expect(searchUserInput).toBeInTheDocument(); + const addUserButton = screen.getByRole('button', { + name: 'add_verb' + }); + expect(addUserButton).toBeDisabled(); + await user.click(searchUserInput); + expect(screen.getAllByTestId('qg-add-permission-option')).toHaveLength(2); + await user.click(screen.getByText('userlogin')); + expect(addUserButton).toBeEnabled(); + await user.click(addUserButton); + expect(screen.getByText('userlogin')).toBeInTheDocument(); + + // Cancel granting permission + await user.click(grantPermissionButton); + await user.click(searchUserInput); + await user.keyboard('test{Enter}'); + + const cancelButton = screen.getByRole('button', { + name: 'cancel' + }); + await user.click(cancelButton); + expect(screen.getAllByRole('listitem')).toHaveLength(1); + + // Delete the user permission + const deleteButton = screen.getByTestId('permission-delete-button'); + await user.click(deleteButton); + const deletePopup = screen.getByRole('dialog'); + const dialogDeleteButton = within(deletePopup).getByRole('button', { name: 'remove' }); + await user.click(dialogDeleteButton); + expect(screen.queryByRole('listitem')).not.toBeInTheDocument(); + }); + + it('should assign permission to a group and delete it later', async () => { + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + expect(screen.queryByText('userlogin')).not.toBeInTheDocument(); + + // Granting permission to a group + const grantPermissionButton = await screen.findByRole('button', { + name: 'quality_gates.permissions.grant' + }); + await user.click(grantPermissionButton); + const popup = screen.getByRole('dialog'); + const searchUserInput = within(popup).getByRole('textbox'); + const addUserButton = screen.getByRole('button', { + name: 'add_verb' + }); + await user.click(searchUserInput); + expect(screen.getAllByTestId('qg-add-permission-option')).toHaveLength(2); + await user.click(screen.getAllByTestId('qg-add-permission-option')[1]); + await user.click(addUserButton); + expect(screen.getByText('Foo')).toBeInTheDocument(); + + // Delete the group permission + const deleteButton = screen.getByTestId('permission-delete-button'); + await user.click(deleteButton); + const deletePopup = screen.getByRole('dialog'); + const dialogDeleteButton = within(deletePopup).getByRole('button', { name: 'remove' }); + await user.click(dialogDeleteButton); + expect(screen.queryByRole('listitem')).not.toBeInTheDocument(); + }); + + it('should handle searchUser service failure', async () => { + (searchUsers as jest.Mock).mockRejectedValue('error'); + + const user = userEvent.setup(); + handler.setIsAdmin(true); + renderQualityGateApp(); + + const grantPermissionButton = await screen.findByRole('button', { + name: 'quality_gates.permissions.grant' + }); + await user.click(grantPermissionButton); + const popup = screen.getByRole('dialog'); + const searchUserInput = within(popup).getByRole('textbox'); + await user.click(searchUserInput); + + expect(screen.getByText('no_results')).toBeInTheDocument(); + }); +}); + function renderQualityGateApp(appState?: AppState) { renderApp('quality_gates', routes, { appState }); } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App.tsx deleted file mode 100644 index 445678ce3a4..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App.tsx +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 ScreenPositionHelper from '../../../../components/common/ScreenPositionHelper'; -import { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { - addSideBarClass, - addWhitePageClass, - removeSideBarClass, - removeWhitePageClass -} from '../../../../helpers/pages'; -import { mockRouter } from '../../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import App from '../App'; - -jest.mock('../../../../helpers/pages', () => ({ - addSideBarClass: jest.fn(), - addWhitePageClass: jest.fn(), - removeSideBarClass: jest.fn(), - removeWhitePageClass: jest.fn() -})); - -jest.mock('../../../../api/quality-gates', () => { - const { mockQualityGate } = jest.requireActual('../../../../helpers/mocks/quality-gates'); - return { - fetchQualityGates: jest.fn().mockResolvedValue({ - actions: { create: true }, - qualitygates: [ - mockQualityGate(), - mockQualityGate({ id: '2', name: 'qualitygate 2', isDefault: true }) - ] - }) - }; -}); - -it('should render correctly', async () => { - const wrapper = shallowRender(); - const replace = jest.fn(() => wrapper.setProps({ params: { id: '2' } })); - wrapper.setProps({ router: mockRouter({ replace }) }); - - expect(wrapper).toMatchSnapshot('default'); - expect(wrapper.find(ScreenPositionHelper).dive()).toMatchSnapshot('ScreenPositionHelper'); - - await waitAndUpdate(wrapper); - - // No ID parameter passed, it should redirect to the default gate. - expect(replace).toBeCalledWith({ pathname: '/quality_gates/show/2' }); - expect(wrapper).toMatchSnapshot('default gate'); - - // Pass an ID, show a specific gate. - wrapper.setProps({ params: { id: '1' } }); - expect(wrapper).toMatchSnapshot('specific gate'); - - expect(addSideBarClass).toBeCalled(); - expect(addWhitePageClass).toBeCalled(); - - wrapper.unmount(); - expect(removeSideBarClass).toBeCalled(); - expect(removeWhitePageClass).toBeCalled(); -}); - -it('should handle set default correctly', async () => { - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - expect(wrapper.state().qualityGates?.find(gate => gate.isDefault)?.id).toBe('2'); - wrapper.instance().handleSetDefault(mockQualityGate({ id: '1' })); - expect(wrapper.state().qualityGates?.find(gate => gate.isDefault)?.id).toBe('1'); -}); - -function shallowRender(props: Partial = {}) { - return shallow(); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Details-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Details-test.tsx deleted file mode 100644 index 3f634504205..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Details-test.tsx +++ /dev/null @@ -1,124 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { fetchQualityGate } from '../../../../api/quality-gates'; -import { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { mockCondition } from '../../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import { addCondition, deleteCondition, replaceCondition } from '../../utils'; -import Details from '../Details'; - -jest.mock('../../../../api/quality-gates', () => { - const { mockQualityGate } = jest.requireActual('../../../../helpers/mocks/quality-gates'); - return { - fetchQualityGate: jest.fn().mockResolvedValue(mockQualityGate()) - }; -}); - -jest.mock('../../utils', () => ({ - checkIfDefault: jest.fn(() => false), - addCondition: jest.fn(qg => qg), - deleteCondition: jest.fn(qg => qg), - replaceCondition: jest.fn(qg => qg) -})); - -beforeEach(jest.clearAllMocks); - -it('should render correctly', async () => { - const wrapper = shallowRender(); - expect(wrapper).toMatchSnapshot('loading'); - - await waitAndUpdate(wrapper); - expect(fetchQualityGate).toBeCalledWith({ id: '1' }); - expect(wrapper).toMatchSnapshot('loaded'); -}); - -it('should refresh if the QG id changes', async () => { - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - jest.clearAllMocks(); - - wrapper.setProps({ id: '2' }); - expect(fetchQualityGate).toBeCalledWith({ id: '2' }); -}); - -it('should correctly add/replace/remove conditions', async () => { - const qualityGate = mockQualityGate(); - (fetchQualityGate as jest.Mock).mockResolvedValue(qualityGate); - - const wrapper = shallowRender(); - const instance = wrapper.instance(); - - instance.handleAddCondition(mockCondition()); - expect(wrapper.state().qualityGate).toBeUndefined(); - - instance.handleSaveCondition(mockCondition(), mockCondition()); - expect(wrapper.state().qualityGate).toBeUndefined(); - - instance.handleRemoveCondition(mockCondition()); - expect(wrapper.state().qualityGate).toBeUndefined(); - - await waitAndUpdate(wrapper); - - const newCondition = mockCondition({ metric: 'bugs', id: '2' }); - instance.handleAddCondition(newCondition); - expect(addCondition).toBeCalledWith(qualityGate, newCondition); - - const updatedCondition = mockCondition({ metric: 'new_bugs' }); - instance.handleSaveCondition(newCondition, updatedCondition); - expect(replaceCondition).toBeCalledWith(qualityGate, newCondition, updatedCondition); - - instance.handleRemoveCondition(newCondition); - expect(deleteCondition).toBeCalledWith(qualityGate, newCondition); -}); - -it('should correctly handle setting default', async () => { - const qualityGate = mockQualityGate(); - (fetchQualityGate as jest.Mock).mockResolvedValue(qualityGate); - - const onSetDefault = jest.fn(); - const wrapper = shallowRender({ onSetDefault }); - - wrapper.instance().handleSetDefault(); - expect(wrapper.state().qualityGate).toBeUndefined(); - - await waitAndUpdate(wrapper); - - wrapper.instance().handleSetDefault(); - expect(wrapper.state().qualityGate).toEqual( - expect.objectContaining({ - id: qualityGate.id, - actions: { delete: false, setAsDefault: false } - }) - ); -}); - -function shallowRender(props: Partial = {}) { - return shallow
( -
- ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsContent-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsContent-test.tsx deleted file mode 100644 index 9846a8f2b40..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsContent-test.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { mockCondition } from '../../../../helpers/testMocks'; -import { DetailsContent, DetailsContentProps } from '../DetailsContent'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('is not default'); - expect(shallowRender({ isDefault: true })).toMatchSnapshot('is default'); - expect( - shallowRender({ isDefault: true, qualityGate: mockQualityGate({ conditions: [] }) }) - ).toMatchSnapshot('is default, no conditions'); - expect( - shallowRender({ - qualityGate: mockQualityGate({ actions: { delegate: true } }) - }) - ).toMatchSnapshot('Admin'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsHeader-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsHeader-test.tsx deleted file mode 100644 index f268cc9f539..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/DetailsHeader-test.tsx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { setQualityGateAsDefault } from '../../../../api/quality-gates'; -import { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { mockCondition } from '../../../../helpers/testMocks'; -import { click, waitAndUpdate } from '../../../../helpers/testUtils'; -import DetailsHeader from '../DetailsHeader'; - -jest.mock('../../../../api/quality-gates', () => ({ - setQualityGateAsDefault: jest.fn().mockResolvedValue(null) -})); - -beforeEach(jest.clearAllMocks); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect( - shallowRender({ - qualityGate: mockQualityGate({ isBuiltIn: true, conditions: [mockCondition()] }) - }) - ).toMatchSnapshot('built-in'); - expect( - shallowRender({ - qualityGate: mockQualityGate({ - conditions: [mockCondition()], - actions: { - copy: true, - delete: true, - rename: true, - setAsDefault: true - } - }) - }) - ).toMatchSnapshot('admin actions'); - expect( - shallowRender({ - qualityGate: mockQualityGate({ actions: { setAsDefault: true }, conditions: [] }) - }) - ).toMatchSnapshot('no conditions, cannot set as default'); -}); - -it('should allow the QG to be set as the default', async () => { - const onSetDefault = jest.fn(); - const refreshItem = jest.fn(); - const refreshList = jest.fn(); - - const qualityGate = mockQualityGate({ id: 'one', actions: { setAsDefault: true } }); - const wrapper = shallowRender({ onSetDefault, qualityGate, refreshItem, refreshList }); - - click(wrapper.find('Button#quality-gate-toggle-default')); - expect(setQualityGateAsDefault).toBeCalledWith({ id: 'one' }); - expect(onSetDefault).toBeCalled(); - await waitAndUpdate(wrapper); - expect(refreshItem).toBeCalled(); - expect(refreshList).toBeCalled(); - - jest.clearAllMocks(); - - wrapper.setProps({ qualityGate: mockQualityGate({ ...qualityGate, isDefault: true }) }); - click(wrapper.find('Button#quality-gate-toggle-default')); - expect(setQualityGateAsDefault).not.toBeCalled(); - expect(onSetDefault).not.toBeCalled(); - await waitAndUpdate(wrapper); - expect(refreshItem).not.toBeCalled(); - expect(refreshList).not.toBeCalled(); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/PermissionItem-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/PermissionItem-test.tsx deleted file mode 100644 index ee34922c847..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/PermissionItem-test.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { mockUser } from '../../../../helpers/testMocks'; -import PermissionItem, { PermissionItemProps } from '../PermissionItem'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('user'); - expect(shallowRender({ item: { name: 'groupname' } })).toMatchSnapshot('group'); -}); - -function shallowRender(overrides: Partial = {}) { - return shallow(); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Projects-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Projects-test.tsx deleted file mode 100644 index 6e3b69093c9..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Projects-test.tsx +++ /dev/null @@ -1,119 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { - associateGateWithProject, - dissociateGateWithProject, - searchProjects -} from '../../../../api/quality-gates'; -import SelectList, { SelectListFilter } from '../../../../components/controls/SelectList'; -import { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { mockCondition } from '../../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import Projects from '../Projects'; - -jest.mock('../../../../api/quality-gates', () => ({ - searchProjects: jest.fn().mockResolvedValue({ - paging: { pageIndex: 1, pageSize: 3, total: 55 }, - results: [ - { id: 'test1', key: 'test1', name: 'test1', selected: false }, - { id: 'test2', key: 'test2', name: 'test2', selected: false }, - { id: 'test3', key: 'test3', name: 'test3', selected: true } - ] - }), - associateGateWithProject: jest.fn().mockResolvedValue({}), - dissociateGateWithProject: jest.fn().mockResolvedValue({}) -})); - -beforeEach(() => { - jest.clearAllMocks(); -}); - -it('should render correctly', async () => { - const wrapper = shallowRender(); - wrapper - .find(SelectList) - .props() - .onSearch({ - query: '', - filter: SelectListFilter.Selected, - page: 1, - pageSize: 100 - }); - await waitAndUpdate(wrapper); - - expect(wrapper.instance().mounted).toBe(true); - expect(wrapper).toMatchSnapshot('default'); - expect(wrapper.instance().renderElement('test1')).toMatchSnapshot('known project'); - expect(wrapper.instance().renderElement('test_foo')).toMatchSnapshot('unknown project'); - expect(shallowRender({ qualityGate: mockQualityGate({ conditions: [] }) })).toMatchSnapshot( - 'quality gate without conditions' - ); - - expect(searchProjects).toHaveBeenCalledWith( - expect.objectContaining({ - gateName: 'Foo', - page: 1, - pageSize: 100, - query: undefined, - selected: SelectListFilter.Selected - }) - ); - expect(wrapper.state().needToReload).toBe(false); - - wrapper.instance().componentWillUnmount(); - expect(wrapper.instance().mounted).toBe(false); -}); - -it('should handle selection properly', async () => { - const wrapper = shallowRender(); - wrapper.instance().handleSelect('toto'); - await waitAndUpdate(wrapper); - - expect(associateGateWithProject).toHaveBeenCalledWith( - expect.objectContaining({ - projectKey: 'toto' - }) - ); - expect(wrapper.state().needToReload).toBe(true); -}); - -it('should handle deselection properly', async () => { - const wrapper = shallowRender(); - wrapper.instance().handleUnselect('tata'); - await waitAndUpdate(wrapper); - - expect(dissociateGateWithProject).toHaveBeenCalledWith( - expect.objectContaining({ - projectKey: 'tata' - }) - ); - expect(wrapper.state().needToReload).toBe(true); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissions-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissions-test.tsx deleted file mode 100644 index 03664fcceaf..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissions-test.tsx +++ /dev/null @@ -1,247 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { - addGroup, - addUser, - removeGroup, - removeUser, - searchGroups, - searchUsers -} from '../../../../api/quality-gates'; -import { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { mockUserBase } from '../../../../helpers/mocks/users'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import QualityGatePermissions from '../QualityGatePermissions'; - -jest.mock('../../../../api/quality-gates', () => ({ - addUser: jest.fn().mockResolvedValue(undefined), - removeUser: jest.fn().mockResolvedValue(undefined), - searchUsers: jest.fn().mockResolvedValue({ users: [] }), - addGroup: jest.fn().mockResolvedValue(undefined), - removeGroup: jest.fn().mockResolvedValue(undefined), - searchGroups: jest.fn().mockResolvedValue({ groups: [] }) -})); - -beforeEach(() => { - jest.clearAllMocks(); -}); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -it('should fetch users and groups', async () => { - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - expect(searchUsers).toBeCalledWith({ gateName: 'qualitygate', selected: 'selected' }); - expect(searchGroups).toBeCalledWith({ gateName: 'qualitygate', selected: 'selected' }); -}); - -it('should handle errors when fetching users and groups', async () => { - (searchUsers as jest.Mock).mockRejectedValueOnce('nope'); - (searchGroups as jest.Mock).mockRejectedValueOnce('nope'); - - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - expect(wrapper.state().groups).toHaveLength(0); - expect(wrapper.state().users).toHaveLength(0); -}); - -it('should fetch users and groups on update', async () => { - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - (searchUsers as jest.Mock).mockClear(); - - wrapper.setProps({ qualityGate: mockQualityGate({ id: '2', name: 'qg2' }) }); - expect(searchUsers).toBeCalledWith({ gateName: 'qg2', selected: 'selected' }); -}); - -it('should handleCloseAddPermission', () => { - const wrapper = shallowRender(); - wrapper.setState({ showAddModal: true }); - wrapper.instance().handleCloseAddPermission(); - expect(wrapper.state().showAddModal).toBe(false); -}); - -it('should handleClickAddPermission', () => { - const wrapper = shallowRender(); - wrapper.setState({ showAddModal: false }); - wrapper.instance().handleClickAddPermission(); - expect(wrapper.state().showAddModal).toBe(true); -}); - -it('should handleSubmitAddPermission for a user', async () => { - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().users).toHaveLength(0); - expect(wrapper.state().groups).toHaveLength(0); - - wrapper.instance().handleSubmitAddPermission(mockUserBase({ login: 'user1', name: 'User One' })); - expect(wrapper.state().submitting).toBe(true); - - expect(addUser).toBeCalledWith({ gateName: 'qualitygate', login: 'user1' }); - expect(addGroup).not.toBeCalled(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().submitting).toBe(false); - expect(wrapper.state().showAddModal).toBe(false); - expect(wrapper.state().users).toHaveLength(1); - expect(wrapper.state().groups).toHaveLength(0); -}); - -it('should handleSubmitAddPermission for a group', async () => { - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().users).toHaveLength(0); - expect(wrapper.state().groups).toHaveLength(0); - - wrapper.instance().handleSubmitAddPermission({ name: 'group' }); - expect(wrapper.state().submitting).toBe(true); - - expect(addUser).not.toBeCalled(); - expect(addGroup).toBeCalledWith({ gateName: 'qualitygate', groupName: 'group' }); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().submitting).toBe(false); - expect(wrapper.state().showAddModal).toBe(false); - expect(wrapper.state().users).toHaveLength(0); - expect(wrapper.state().groups).toHaveLength(1); -}); - -it('should handleSubmitAddPermission if it returns an error', async () => { - (addUser as jest.Mock).mockRejectedValueOnce(undefined); - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().users).toHaveLength(0); - - wrapper.setState({ showAddModal: true }); - wrapper.instance().handleSubmitAddPermission(mockUserBase({ login: 'user1', name: 'User One' })); - expect(wrapper.state().submitting).toBe(true); - - expect(addUser).toBeCalledWith({ gateName: 'qualitygate', login: 'user1' }); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().submitting).toBe(false); - expect(wrapper.state().showAddModal).toBe(true); - expect(wrapper.state().users).toHaveLength(0); -}); - -it('should handleCloseDeletePermission', () => { - const wrapper = shallowRender(); - wrapper.setState({ permissionToDelete: mockUserBase() }); - wrapper.instance().handleCloseDeletePermission(); - expect(wrapper.state().permissionToDelete).toBeUndefined(); -}); - -it('should handleClickDeletePermission', () => { - const user = mockUserBase(); - - const wrapper = shallowRender(); - wrapper.setState({ permissionToDelete: undefined }); - wrapper.instance().handleClickDeletePermission(user); - expect(wrapper.state().permissionToDelete).toBe(user); -}); - -it('should handleConfirmDeletePermission for a user', async () => { - const deleteThisUser = mockUserBase(); - const deleteThisGroup = { name: 'deletableGroup' }; - (searchUsers as jest.Mock).mockResolvedValueOnce({ users: [deleteThisUser] }); - (searchGroups as jest.Mock).mockResolvedValueOnce({ groups: [deleteThisGroup] }); - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().users).toHaveLength(1); - expect(wrapper.state().groups).toHaveLength(1); - - wrapper.instance().handleConfirmDeletePermission(deleteThisUser); - - expect(removeUser).toBeCalledWith({ gateName: 'qualitygate', login: deleteThisUser.login }); - expect(removeGroup).not.toBeCalled(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().permissionToDelete).toBeUndefined(); - expect(wrapper.state().users).toHaveLength(0); - expect(wrapper.state().groups).toHaveLength(1); -}); - -it('should handleConfirmDeletePermission for a group', async () => { - const deleteThisUser = mockUserBase(); - const deleteThisGroup = { name: 'deletableGroup' }; - (searchUsers as jest.Mock).mockResolvedValueOnce({ users: [deleteThisUser] }); - (searchGroups as jest.Mock).mockResolvedValueOnce({ groups: [deleteThisGroup] }); - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().users).toHaveLength(1); - expect(wrapper.state().groups).toHaveLength(1); - - wrapper.instance().handleConfirmDeletePermission(deleteThisGroup); - - expect(removeUser).not.toBeCalled(); - expect(removeGroup).toBeCalledWith({ gateName: 'qualitygate', groupName: deleteThisGroup.name }); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().permissionToDelete).toBeUndefined(); - expect(wrapper.state().users).toHaveLength(1); - expect(wrapper.state().groups).toHaveLength(0); -}); - -it('should handleConfirmDeletePermission if it returns an error', async () => { - const deleteThisUser = mockUserBase(); - (searchUsers as jest.Mock).mockResolvedValueOnce({ users: [deleteThisUser] }); - (removeUser as jest.Mock).mockRejectedValueOnce(undefined); - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().users).toHaveLength(1); - - wrapper.instance().handleConfirmDeletePermission(deleteThisUser); - - expect(removeUser).toBeCalledWith({ gateName: 'qualitygate', login: deleteThisUser.login }); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().permissionToDelete).toBeUndefined(); - expect(wrapper.state().users).toHaveLength(1); -}); - -function shallowRender(overrides: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModal-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModal-test.tsx deleted file mode 100644 index e331472a167..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModal-test.tsx +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { searchGroups, searchUsers } from '../../../../api/quality-gates'; -import { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { mockUserBase } from '../../../../helpers/mocks/users'; -import { mockEvent } from '../../../../helpers/testUtils'; -import QualityGatePermissionsAddModal from '../QualityGatePermissionsAddModal'; -import QualityGatePermissionsAddModalRenderer from '../QualityGatePermissionsAddModalRenderer'; - -jest.mock('../../../../api/quality-gates', () => ({ - searchUsers: jest.fn().mockResolvedValue({ users: [] }), - searchGroups: jest.fn().mockResolvedValue({ groups: [] }) -})); - -beforeEach(() => { - jest.clearAllMocks(); -}); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -it('should fetch users and groups on mount', async () => { - (searchUsers as jest.Mock).mockResolvedValue({ users: [mockUserBase()] }); - (searchGroups as jest.Mock).mockResolvedValue({ groups: [{ name: 'group' }] }); - - const wrapper = shallowRender(); - - const query = 'Waldo'; - const results = await new Promise(resolve => { - wrapper.instance().handleSearch(query, resolve); - }); - - expect(searchUsers).toBeCalledWith(expect.objectContaining({ q: query })); - expect(searchGroups).toBeCalledWith(expect.objectContaining({ q: query })); - - expect(results).toHaveLength(2); -}); - -it('should handleSelection', () => { - const wrapper = shallowRender(); - const selection = { ...mockUserBase(), value: 'value' }; - wrapper - .find(QualityGatePermissionsAddModalRenderer) - .props() - .onSelection(selection); - expect(wrapper.state().selection).toBe(selection); -}); - -it('should handleSubmit', () => { - const onSubmit = jest.fn(); - const wrapper = shallowRender({ onSubmit }); - - wrapper.instance().handleSubmit(mockEvent()); - - expect(onSubmit).not.toBeCalled(); - - const selection = mockUserBase(); - wrapper.setState({ selection }); - wrapper.instance().handleSubmit(mockEvent()); - expect(onSubmit).toBeCalledWith(selection); -}); - -function shallowRender(overrides: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx deleted file mode 100644 index 5ddc17b7cef..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsAddModalRenderer-test.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { mockUserBase } from '../../../../helpers/mocks/users'; -import QualityGatePermissionsAddModalRenderer, { - customOptions, - QualityGatePermissionsAddModalRendererProps -} from '../QualityGatePermissionsAddModalRenderer'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ selection: mockUserBase(), submitting: true })).toMatchSnapshot( - 'with selection and submitting' - ); -}); - -it('should render options correctly', () => { - expect( - customOptions({ avatar: 'A', name: 'name', login: 'login', value: 'login' }) - ).toMatchSnapshot('user'); - expect(customOptions({ name: 'group name', value: 'group name' })).toMatchSnapshot('group'); -}); - -function shallowRender(overrides: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsRenderer-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsRenderer-test.tsx deleted file mode 100644 index 72d457f3a2a..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGatePermissionsRenderer-test.tsx +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { mockQualityGate } from '../../../../helpers/mocks/quality-gates'; -import { mockUserBase } from '../../../../helpers/mocks/users'; -import { mockUser } from '../../../../helpers/testMocks'; -import QualityGatePermissionsRenderer, { - QualityGatePermissionsRendererProps -} from '../QualityGatePermissionsRenderer'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('with users and groups'); - expect(shallowRender({ users: [] })).toMatchSnapshot('with no users'); - expect(shallowRender({ groups: [] })).toMatchSnapshot('with no groups'); - expect(shallowRender({ groups: [], users: [] })).toMatchSnapshot('with no users or groups'); - expect(shallowRender({ showAddModal: true })).toMatchSnapshot('show add modal'); - expect(shallowRender({ permissionToDelete: mockUserBase() })).toMatchSnapshot( - 'show remove modal for user' - ); - - expect(shallowRender({ permissionToDelete: { name: 'deletable group' } })).toMatchSnapshot( - 'show remove modal for group' - ); -}); - -function shallowRender(overrides: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/App.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/App.tsx.snap deleted file mode 100644 index e8d08c79dd6..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/App.tsx.snap +++ /dev/null @@ -1,147 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: ScreenPositionHelper 1`] = ` -
-
-
-
- - - - -
-
-
-
-`; - -exports[`should render correctly: default 1`] = ` - - -
- - - - -
-
-`; - -exports[`should render correctly: default gate 1`] = ` - - -
- - - - -
-
-
-`; - -exports[`should render correctly: specific gate 1`] = ` - - -
- - - - -
-
-
-`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Details-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Details-test.tsx.snap deleted file mode 100644 index 90b42c35d66..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Details-test.tsx.snap +++ /dev/null @@ -1,53 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: loaded 1`] = ` -
- - - - - -
-`; - -exports[`should render correctly: loading 1`] = ` -
- -
-`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsContent-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsContent-test.tsx.snap deleted file mode 100644 index 74843ff5fe9..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsContent-test.tsx.snap +++ /dev/null @@ -1,275 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: Admin 1`] = ` -
- -
-
-
-

- quality_gates.projects -

- - quality_gates.projects.help -
- } - /> - - -
-
- -
-
- -`; - -exports[`should render correctly: is default 1`] = ` -
- -
-
-
-

- quality_gates.projects -

- - quality_gates.projects.help -
- } - /> - - quality_gates.projects_for_default -
-
- -`; - -exports[`should render correctly: is default, no conditions 1`] = ` -
- - quality_gates.is_default_no_conditions - - -
-
-
-

- quality_gates.projects -

- - quality_gates.projects.help -
- } - /> - - quality_gates.projects_for_default -
-
- -`; - -exports[`should render correctly: is not default 1`] = ` -
- -
-
-
-

- quality_gates.projects -

- - quality_gates.projects.help -
- } - /> - - -
-
- -`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsHeader-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsHeader-test.tsx.snap deleted file mode 100644 index a1106a333c9..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/DetailsHeader-test.tsx.snap +++ /dev/null @@ -1,163 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: admin actions 1`] = ` -
-
-
-
-

- qualitygate -

-
-
- - - - - - - - - - -
-
-
-
-`; - -exports[`should render correctly: built-in 1`] = ` -
-
-
-
-

- qualitygate -

- -
-
-
-
-
-`; - -exports[`should render correctly: default 1`] = ` -
-
-
-
-

- qualitygate -

-
-
-
-
-
-`; - -exports[`should render correctly: no conditions, cannot set as default 1`] = ` -
-
-
-
-

- qualitygate -

-
-
- - - -
-
-
-
-`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/PermissionItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/PermissionItem-test.tsx.snap deleted file mode 100644 index 096ddf281a6..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/PermissionItem-test.tsx.snap +++ /dev/null @@ -1,49 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: group 1`] = ` -
- -
- - groupname - -
- -
-`; - -exports[`should render correctly: user 1`] = ` -
- -
- - John Doe - -
- john.doe -
-
- -
-`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Projects-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Projects-test.tsx.snap deleted file mode 100644 index 417137c72cc..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Projects-test.tsx.snap +++ /dev/null @@ -1,59 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` - -`; - -exports[`should render correctly: known project 1`] = ` -
- - test1 -
- - test1 - -
-
-`; - -exports[`should render correctly: quality gate without conditions 1`] = ` -
- quality_gates.projects.cannot_associate_projects_no_conditions -
-`; - -exports[`should render correctly: unknown project 1`] = ` -
- test_foo -
-`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissions-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissions-test.tsx.snap deleted file mode 100644 index 703b2a5babf..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissions-test.tsx.snap +++ /dev/null @@ -1,23 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModal-test.tsx.snap deleted file mode 100644 index 9535f6713e9..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModal-test.tsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap deleted file mode 100644 index 8abba358be6..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsAddModalRenderer-test.tsx.snap +++ /dev/null @@ -1,165 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` - -
-

- quality_gates.permissions.grant -

-
-
-
-
- - -
-
-
- - add_verb - - - cancel - -
-
-
-`; - -exports[`should render correctly: with selection and submitting 1`] = ` - -
-

- quality_gates.permissions.grant -

-
-
-
-
- - -
-
-
- - - add_verb - - - cancel - -
- -
-`; - -exports[`should render options correctly: group 1`] = ` - - - - group name - - -`; - -exports[`should render options correctly: user 1`] = ` - - - - name - - - login - - -`; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsRenderer-test.tsx.snap deleted file mode 100644 index 66d0aa60ef3..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/QualityGatePermissionsRenderer-test.tsx.snap +++ /dev/null @@ -1,409 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: show add modal 1`] = ` -
-

- quality_gates.permissions -

-

- quality_gates.permissions.help -

-
- -
    -
  • - -
  • -
  • - -
  • -
-
-
- - -
-`; - -exports[`should render correctly: show remove modal for group 1`] = ` -
-

- quality_gates.permissions -

-

- quality_gates.permissions.help -

-
- -
    -
  • - -
  • -
  • - -
  • -
-
-
- - - - deletable group - , - } - } - /> - -
-`; - -exports[`should render correctly: show remove modal for user 1`] = ` -
-

- quality_gates.permissions -

-

- quality_gates.permissions.help -

-
- -
    -
  • - -
  • -
  • - -
  • -
-
-
- - - , - } - } - /> - -
-`; - -exports[`should render correctly: with no groups 1`] = ` -
-

- quality_gates.permissions -

-

- quality_gates.permissions.help -

-
- -
    -
  • - -
  • -
-
-
- -
-`; - -exports[`should render correctly: with no users 1`] = ` -
-

- quality_gates.permissions -

-

- quality_gates.permissions.help -

-
- -
    -
  • - -
  • -
-
-
- -
-`; - -exports[`should render correctly: with no users or groups 1`] = ` -
-

- quality_gates.permissions -

-

- quality_gates.permissions.help -

-
- -
    - -
- -
-`; - -exports[`should render correctly: with users and groups 1`] = ` -
-

- quality_gates.permissions -

-

- quality_gates.permissions.help -

-
- -
    -
  • - -
  • -
  • - -
  • -
-
-
- -
-`; -- 2.39.5