aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2022-03-15 17:45:43 +0100
committersonartech <sonartech@sonarsource.com>2022-03-23 20:02:45 +0000
commit9a35b0e3e65302ee4f6c1b4cc2c5db71df5b0a5d (patch)
tree3c7dfb98f45b43a7165b3de25d1463903f16b29f /server
parent71f680aa1c432ea8bb18e1f5fd4e2d2d40a3ab8d (diff)
downloadsonarqube-9a35b0e3e65302ee4f6c1b4cc2c5db71df5b0a5d.tar.gz
sonarqube-9a35b0e3e65302ee4f6c1b4cc2c5db71df5b0a5d.zip
SONAR-15914 Clean up redux
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/api/auth.ts4
-rw-r--r--server/sonar-web/src/main/js/app/components/ComponentContainer.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/App.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx31
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx27
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx15
-rw-r--r--server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx30
-rw-r--r--server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx2
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/branch-like-test.ts (renamed from server/sonar-web/src/main/js/helpers/__tests__/branches-test.ts)0
-rw-r--r--server/sonar-web/src/main/js/store/__tests__/branches-test.ts65
-rw-r--r--server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx82
-rw-r--r--server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx13
-rw-r--r--server/sonar-web/src/main/js/store/branches.ts33
-rw-r--r--server/sonar-web/src/main/js/store/globalMessages.ts19
-rw-r--r--server/sonar-web/src/main/js/store/rootActions.ts77
-rw-r--r--server/sonar-web/src/main/js/types/actions.ts (renamed from server/sonar-web/src/main/js/store/utils/actions.ts)0
21 files changed, 171 insertions, 241 deletions
diff --git a/server/sonar-web/src/main/js/api/auth.ts b/server/sonar-web/src/main/js/api/auth.ts
index d556401ff8d..958dc9f4175 100644
--- a/server/sonar-web/src/main/js/api/auth.ts
+++ b/server/sonar-web/src/main/js/api/auth.ts
@@ -19,7 +19,7 @@
*/
import { request } from '../helpers/request';
-export function login(login: string, password: string): Promise<Response> {
+export function logIn(login: string, password: string): Promise<Response> {
return request('/api/authentication/login')
.setMethod('POST')
.setData({ login, password })
@@ -27,7 +27,7 @@ export function login(login: string, password: string): Promise<Response> {
.then(basicCheckStatus);
}
-export function logout(): Promise<Response> {
+export function logOut(): Promise<Response> {
return request('/api/authentication/logout')
.setMethod('POST')
.submit()
diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
index e663080820a..fc98bc60e17 100644
--- a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
@@ -34,7 +34,7 @@ import {
} from '../../helpers/branch-like';
import { HttpStatus } from '../../helpers/request';
import { getPortfolioUrl } from '../../helpers/urls';
-import { registerBranchStatus } from '../../store/rootActions';
+import { registerBranchStatus } from '../../store/branches';
import {
ProjectAlmBindingConfigurationErrors,
ProjectAlmBindingResponse
diff --git a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx
index 34f37f04af9..57bb881e842 100644
--- a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx
+++ b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx
@@ -35,7 +35,7 @@ import { Alert } from '../../../components/ui/Alert';
import { isPullRequest, isSameBranchLike } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
import { getCodeUrl, getProjectUrl } from '../../../helpers/urls';
-import { fetchBranchStatus } from '../../../store/rootActions';
+import { fetchBranchStatus } from '../../../store/branches';
import { BranchLike } from '../../../types/branch-like';
import { isPortfolioLike } from '../../../types/component';
import { Breadcrumb, Component, ComponentMeasure, Dict, Issue, Metric } from '../../../types/types';
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx
index 4078382e7f9..ce61093edf2 100644
--- a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx
@@ -44,7 +44,7 @@ import {
removeSideBarClass,
removeWhitePageClass
} from '../../../helpers/pages';
-import { fetchBranchStatus } from '../../../store/rootActions';
+import { fetchBranchStatus } from '../../../store/branches';
import { BranchLike } from '../../../types/branch-like';
import { ComponentQualifier, isPortfolioLike } from '../../../types/component';
import {
diff --git a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx
index 1e3578afcb1..49e326575cb 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.tsx
@@ -23,7 +23,7 @@ import withCurrentUserContext from '../../../app/components/current-user/withCur
import { withRouter } from '../../../components/hoc/withRouter';
import { lazyLoadComponent } from '../../../components/lazyLoadComponent';
import { parseIssueFromResponse } from '../../../helpers/issues';
-import { fetchBranchStatus } from '../../../store/rootActions';
+import { fetchBranchStatus } from '../../../store/branches';
import { Store } from '../../../store/rootReducer';
import { FetchIssuesPromise } from '../../../types/issues';
import { RawQuery } from '../../../types/types';
diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx
index b1543639017..bc78aeab32e 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/AppContainer-test.tsx
@@ -19,7 +19,7 @@
*/
import { connect } from 'react-redux';
import { searchIssues } from '../../../../api/issues';
-import { fetchBranchStatus } from '../../../../store/rootActions';
+import { fetchBranchStatus } from '../../../../store/branches';
import '../AppContainer';
jest.mock('react-redux', () => ({
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx
index a2866c937e1..bfb4c232ec3 100644
--- a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx
+++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx
@@ -28,7 +28,7 @@ import { getBranchLikeQuery } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
import { enhanceConditionWithMeasure, enhanceMeasuresWithMetrics } from '../../../helpers/measures';
import { isDefined } from '../../../helpers/types';
-import { fetchBranchStatus } from '../../../store/rootActions';
+import { fetchBranchStatus } from '../../../store/branches';
import { getBranchStatusByBranchLike, Store } from '../../../store/rootReducer';
import { BranchLike, PullRequest } from '../../../types/branch-like';
import { IssueType } from '../../../types/issues';
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
index e774afc2b45..2eaf52d2950 100644
--- a/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
+++ b/server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
@@ -31,7 +31,7 @@ import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../helpe
import { KeyboardCodes, KeyboardKeys } from '../../helpers/keycodes';
import { scrollToElement } from '../../helpers/scrolling';
import { getStandards } from '../../helpers/security-standard';
-import { fetchBranchStatus } from '../../store/rootActions';
+import { fetchBranchStatus } from '../../store/branches';
import { BranchLike } from '../../types/branch-like';
import { SecurityStandard, Standards } from '../../types/security';
import {
diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx b/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx
index 197caadbd43..294c57e47e8 100644
--- a/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx
+++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginContainer.tsx
@@ -19,25 +19,18 @@
*/
import { Location } from 'history';
import * as React from 'react';
-import { connect } from 'react-redux';
+import { logIn } from '../../../api/auth';
import { getIdentityProviders } from '../../../api/users';
+import addGlobalErrorMessage from '../../../app/utils/addGlobalErrorMessage';
import { getReturnUrl } from '../../../helpers/urls';
-import { doLogin } from '../../../store/rootActions';
import { IdentityProvider } from '../../../types/types';
import Login from './Login';
-interface OwnProps {
+interface Props {
location: Pick<Location, 'hash' | 'pathname' | 'query'> & {
query: { advanced?: string; return_to?: string };
};
}
-
-interface DispatchToProps {
- doLogin: (login: string, password: string) => Promise<void>;
-}
-
-type Props = OwnProps & DispatchToProps;
-
interface State {
identityProviders?: IdentityProvider[];
}
@@ -55,7 +48,9 @@ export class LoginContainer extends React.PureComponent<Props, State> {
this.setState({ identityProviders });
}
},
- () => {}
+ () => {
+ /* already handled */
+ }
);
}
@@ -67,8 +62,13 @@ export class LoginContainer extends React.PureComponent<Props, State> {
window.location.href = getReturnUrl(this.props.location);
};
- handleSubmit = (login: string, password: string) => {
- return this.props.doLogin(login, password).then(this.handleSuccessfulLogin, () => {});
+ handleSubmit = (id: string, password: string) => {
+ return logIn(id, password)
+ .then(this.handleSuccessfulLogin)
+ .catch(() => {
+ addGlobalErrorMessage('Authentication failed');
+ return Promise.reject();
+ });
};
render() {
@@ -89,7 +89,4 @@ export class LoginContainer extends React.PureComponent<Props, State> {
}
}
-const mapStateToProps = null;
-const mapDispatchToProps = { doLogin: doLogin as any };
-
-export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer);
+export default LoginContainer;
diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx
index 3d5d250ec47..4e4cae3b245 100644
--- a/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx
+++ b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx
@@ -18,26 +18,23 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { connect } from 'react-redux';
+import { logOut } from '../../../api/auth';
import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer';
import RecentHistory from '../../../app/components/RecentHistory';
+import addGlobalErrorMessage from '../../../app/utils/addGlobalErrorMessage';
import { translate } from '../../../helpers/l10n';
import { getBaseUrl } from '../../../helpers/system';
-import { doLogout } from '../../../store/rootActions';
-interface Props {
- doLogout: () => Promise<void>;
-}
-
-export class Logout extends React.PureComponent<Props> {
+export class Logout extends React.PureComponent<{}> {
componentDidMount() {
- this.props.doLogout().then(
- () => {
+ logOut()
+ .then(() => {
RecentHistory.clear();
window.location.replace(getBaseUrl() + '/');
- },
- () => {}
- );
+ })
+ .catch(() => {
+ addGlobalErrorMessage('Logout failed');
+ });
}
render() {
@@ -50,8 +47,4 @@ export class Logout extends React.PureComponent<Props> {
}
}
-const mapStateToProps = () => ({});
-
-const mapDispatchToProps = { doLogout };
-
-export default connect(mapStateToProps, mapDispatchToProps)(Logout as any);
+export default Logout;
diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx
index f09d24aba35..510f7c4074f 100644
--- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginContainer-test.tsx
@@ -19,6 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { logIn } from '../../../../api/auth';
import { getIdentityProviders } from '../../../../api/users';
import { mockLocation } from '../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../helpers/testUtils';
@@ -33,6 +34,10 @@ jest.mock('../../../../api/users', () => {
};
});
+jest.mock('../../../../api/auth', () => ({
+ logIn: jest.fn().mockResolvedValue({})
+}));
+
beforeEach(jest.clearAllMocks);
it('should render correctly', async () => {
@@ -53,14 +58,12 @@ it('should not provide any options if no IdPs are present', async () => {
});
it('should handle submission', () => {
- const doLogin = jest.fn().mockResolvedValue(null);
- const wrapper = shallowRender({ doLogin });
+ (logIn as jest.Mock).mockResolvedValue(null);
+ const wrapper = shallowRender();
wrapper.instance().handleSubmit('user', 'pass');
- expect(doLogin).toBeCalledWith('user', 'pass');
+ expect(logIn).toBeCalledWith('user', 'pass');
});
function shallowRender(props: Partial<LoginContainer['props']> = {}) {
- return shallow<LoginContainer>(
- <LoginContainer doLogin={jest.fn()} location={mockLocation()} {...props} />
- );
+ return shallow<LoginContainer>(<LoginContainer location={mockLocation()} {...props} />);
}
diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx
index dcb44bf2ed9..5b0d0012913 100644
--- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx
+++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/Logout-test.tsx
@@ -19,11 +19,21 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { logOut } from '../../../../api/auth';
+import addGlobalErrorMessage from '../../../../app/utils/addGlobalErrorMessage';
import { waitAndUpdate } from '../../../../helpers/testUtils';
import { Logout } from '../Logout';
-const originalLocation = window.location;
+jest.mock('../../../../api/auth', () => ({
+ logOut: jest.fn().mockResolvedValue(true)
+}));
+
+jest.mock('../../../../app/utils/addGlobalErrorMessage', () => ({
+ __esModule: true,
+ default: jest.fn()
+}));
+const originalLocation = window.location;
beforeAll(() => {
const location = {
...window.location,
@@ -47,26 +57,28 @@ afterAll(() => {
});
it('should logout correctly', async () => {
- const doLogout = jest.fn().mockResolvedValue(true);
+ (logOut as jest.Mock).mockResolvedValue(true);
- const wrapper = shallowRender({ doLogout });
+ const wrapper = shallowRender();
await waitAndUpdate(wrapper);
- expect(doLogout).toHaveBeenCalled();
+ expect(logOut).toHaveBeenCalled();
expect(window.location.replace).toHaveBeenCalledWith('/');
+ expect(addGlobalErrorMessage).not.toHaveBeenCalled();
});
it('should not redirect if logout fails', async () => {
- const doLogout = jest.fn().mockRejectedValue(false);
+ (logOut as jest.Mock).mockRejectedValue(false);
- const wrapper = shallowRender({ doLogout });
+ const wrapper = shallowRender();
await waitAndUpdate(wrapper);
- expect(doLogout).toHaveBeenCalled();
+ expect(logOut).toHaveBeenCalled();
expect(window.location.replace).not.toHaveBeenCalled();
+ expect(addGlobalErrorMessage).toHaveBeenCalled();
expect(wrapper).toMatchSnapshot();
});
-function shallowRender(props: Partial<Logout['props']> = {}) {
- return shallow(<Logout doLogout={jest.fn()} {...props} />);
+function shallowRender() {
+ return shallow(<Logout />);
}
diff --git a/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx b/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx
index ae5700e8cc9..23cf4dfcd3c 100644
--- a/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx
+++ b/server/sonar-web/src/main/js/components/workspace/WorkspaceComponentViewer.tsx
@@ -23,7 +23,7 @@ import { connect } from 'react-redux';
import { getParents } from '../../api/components';
import { isPullRequest } from '../../helpers/branch-like';
import { scrollToElement } from '../../helpers/scrolling';
-import { fetchBranchStatus } from '../../store/rootActions';
+import { fetchBranchStatus } from '../../store/branches';
import { BranchLike } from '../../types/branch-like';
import { Issue, SourceViewerFile } from '../../types/types';
import SourceViewer from '../SourceViewer/SourceViewer';
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/branches-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/branch-like-test.ts
index 639a3ea96b6..639a3ea96b6 100644
--- a/server/sonar-web/src/main/js/helpers/__tests__/branches-test.ts
+++ b/server/sonar-web/src/main/js/helpers/__tests__/branch-like-test.ts
diff --git a/server/sonar-web/src/main/js/store/__tests__/branches-test.ts b/server/sonar-web/src/main/js/store/__tests__/branches-test.ts
index 9ef4f9d1ae6..eb52257e42a 100644
--- a/server/sonar-web/src/main/js/store/__tests__/branches-test.ts
+++ b/server/sonar-web/src/main/js/store/__tests__/branches-test.ts
@@ -24,7 +24,9 @@ import { BranchLike } from '../../types/branch-like';
import { QualityGateStatusCondition } from '../../types/quality-gates';
import { Status } from '../../types/types';
import reducer, {
+ fetchBranchStatus,
getBranchStatusByBranchLike,
+ registerBranchStatus,
registerBranchStatusAction,
State
} from '../branches';
@@ -82,3 +84,66 @@ function convertToState(items: TestArgs[] = []) {
return state;
}
+
+jest.mock('../../app/utils/addGlobalErrorMessage', () => ({
+ __esModule: true,
+ default: jest.fn()
+}));
+
+jest.mock('../../api/quality-gates', () => {
+ const { mockQualityGateProjectStatus } = jest.requireActual('../../helpers/mocks/quality-gates');
+ return {
+ getQualityGateProjectStatus: jest.fn().mockResolvedValue(
+ mockQualityGateProjectStatus({
+ conditions: [
+ {
+ actualValue: '10',
+ comparator: 'GT',
+ errorThreshold: '0',
+ metricKey: 'foo',
+ periodIndex: 1,
+ status: 'ERROR'
+ }
+ ]
+ })
+ )
+ };
+});
+
+describe('branch store actions', () => {
+ const branchLike = mockBranch();
+ const component = 'foo';
+ const status = 'OK';
+
+ it('correctly registers a new branch status', () => {
+ const dispatch = jest.fn();
+
+ registerBranchStatus(branchLike, component, status)(dispatch);
+ expect(dispatch).toBeCalledWith({
+ branchLike,
+ component,
+ status,
+ type: 'REGISTER_BRANCH_STATUS'
+ });
+ });
+
+ it('correctly fetches a branch status', async () => {
+ const dispatch = jest.fn();
+
+ fetchBranchStatus(branchLike, component)(dispatch);
+ await new Promise(setImmediate);
+
+ expect(dispatch).toBeCalledWith({
+ branchLike,
+ component,
+ status,
+ conditions: [
+ mockQualityGateStatusCondition({
+ period: 1
+ })
+ ],
+ ignoredConditions: false,
+ type: 'REGISTER_BRANCH_STATUS'
+ });
+ });
+});
diff --git a/server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx b/server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx
deleted file mode 100644
index f53d45a86ed..00000000000
--- a/server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx
+++ /dev/null
@@ -1,82 +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 { mockBranch } from '../../helpers/mocks/branch-like';
-import { mockQualityGateStatusCondition } from '../../helpers/mocks/quality-gates';
-import { registerBranchStatusAction } from '../branches';
-import { fetchBranchStatus, registerBranchStatus } from '../rootActions';
-
-jest.mock('../branches', () => ({
- ...jest.requireActual('../branches'),
- registerBranchStatusAction: jest.fn()
-}));
-
-jest.mock('../../api/quality-gates', () => {
- const { mockQualityGateProjectStatus } = jest.requireActual('../../helpers/mocks/quality-gates');
- return {
- getQualityGateProjectStatus: jest.fn().mockResolvedValue(
- mockQualityGateProjectStatus({
- conditions: [
- {
- actualValue: '10',
- comparator: 'GT',
- errorThreshold: '0',
- metricKey: 'foo',
- periodIndex: 1,
- status: 'ERROR'
- }
- ]
- })
- )
- };
-});
-
-describe('branch store actions', () => {
- const branchLike = mockBranch();
- const component = 'foo';
- const status = 'OK';
-
- it('correctly registers a new branch status', () => {
- const dispatch = jest.fn();
-
- registerBranchStatus(branchLike, component, status)(dispatch);
- expect(registerBranchStatusAction).toBeCalledWith(branchLike, component, status);
- expect(dispatch).toBeCalled();
- });
-
- it('correctly fetches a branch status', async () => {
- const dispatch = jest.fn();
-
- fetchBranchStatus(branchLike, component)(dispatch);
- await new Promise(setImmediate);
-
- expect(registerBranchStatusAction).toBeCalledWith(
- branchLike,
- component,
- status,
- [
- mockQualityGateStatusCondition({
- period: 1
- })
- ],
- false
- );
- expect(dispatch).toBeCalled();
- });
-});
diff --git a/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx b/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx
index 0f97725f12a..c6cffde06bd 100644
--- a/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx
+++ b/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx
@@ -21,17 +21,12 @@ import { mockPullRequest } from '../../helpers/mocks/branch-like';
import * as fromBranches from '../branches';
import { getBranchStatusByBranchLike, Store } from '../rootReducer';
-jest.mock('../branches', () => {
- return {
- ...jest.requireActual('../branches'),
- getBranchStatusByBranchLike: jest.fn()
- };
-});
-
it('correctly reduce state for branches', () => {
- const branches = {};
+ const spiedOn = jest.spyOn(fromBranches, 'getBranchStatusByBranchLike').mockReturnValueOnce({});
+
+ const branches = { byComponent: {} };
const component = 'foo';
const branchLike = mockPullRequest();
getBranchStatusByBranchLike({ branches } as Store, component, branchLike);
- expect(fromBranches.getBranchStatusByBranchLike).toBeCalledWith(branches, component, branchLike);
+ expect(spiedOn).toBeCalledWith(branches, component, branchLike);
});
diff --git a/server/sonar-web/src/main/js/store/branches.ts b/server/sonar-web/src/main/js/store/branches.ts
index c24b94bceb7..e6e4dada333 100644
--- a/server/sonar-web/src/main/js/store/branches.ts
+++ b/server/sonar-web/src/main/js/store/branches.ts
@@ -17,11 +17,15 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { getBranchLikeKey } from '../helpers/branch-like';
+import { Dispatch } from 'redux';
+import { getQualityGateProjectStatus } from '../api/quality-gates';
+import addGlobalErrorMessage from '../app/utils/addGlobalErrorMessage';
+import { getBranchLikeKey, getBranchLikeQuery } from '../helpers/branch-like';
+import { extractStatusConditionsFromProjectStatus } from '../helpers/qualityGates';
+import { ActionType } from '../types/actions';
import { BranchLike } from '../types/branch-like';
import { QualityGateStatusCondition } from '../types/quality-gates';
import { Dict, Status } from '../types/types';
-import { ActionType } from './utils/actions';
export interface BranchStatusData {
conditions?: QualityGateStatusCondition[];
@@ -56,7 +60,7 @@ export function registerBranchStatusAction(
};
}
-export default function(state: State = { byComponent: {} }, action: Action): State {
+export default function branchesReducer(state: State = { byComponent: {} }, action: Action): State {
if (action.type === Actions.RegisterBranchStatus) {
const { component, conditions, branchLike, ignoredConditions, status } = action;
const branchLikeKey = getBranchLikeKey(branchLike);
@@ -86,3 +90,26 @@ export function getBranchStatusByBranchLike(
const branchLikeKey = getBranchLikeKey(branchLike);
return state.byComponent[component] && state.byComponent[component][branchLikeKey];
}
+
+export function fetchBranchStatus(branchLike: BranchLike, projectKey: string) {
+ return (dispatch: Dispatch) => {
+ getQualityGateProjectStatus({ projectKey, ...getBranchLikeQuery(branchLike) }).then(
+ projectStatus => {
+ const { ignoredConditions, status } = projectStatus;
+ const conditions = extractStatusConditionsFromProjectStatus(projectStatus);
+ dispatch(
+ registerBranchStatusAction(branchLike, projectKey, status, conditions, ignoredConditions)
+ );
+ },
+ () => {
+ addGlobalErrorMessage('Fetching Quality Gate status failed');
+ }
+ );
+ };
+}
+
+export function registerBranchStatus(branchLike: BranchLike, component: string, status: Status) {
+ return (dispatch: Dispatch) => {
+ dispatch(registerBranchStatusAction(branchLike, component, status));
+ };
+}
diff --git a/server/sonar-web/src/main/js/store/globalMessages.ts b/server/sonar-web/src/main/js/store/globalMessages.ts
index a220d15cb47..c64ac9dafdb 100644
--- a/server/sonar-web/src/main/js/store/globalMessages.ts
+++ b/server/sonar-web/src/main/js/store/globalMessages.ts
@@ -19,7 +19,7 @@
*/
import { uniqueId } from 'lodash';
import { Dispatch } from 'redux';
-import { ActionType } from './utils/actions';
+import { ActionType } from '../types/actions';
enum MessageLevel {
Error = 'ERROR',
@@ -32,6 +32,10 @@ interface Message {
level: MessageLevel;
}
+const MESSAGE_DISPLAY_TIME = 5000;
+
+/* Action creators */
+
function addGlobalMessageActionCreator(id: string, message: string, level: MessageLevel) {
return { type: 'ADD_GLOBAL_MESSAGE', message, level, id };
}
@@ -40,20 +44,15 @@ export function closeGlobalMessage(id: string) {
return { type: 'CLOSE_GLOBAL_MESSAGE', id };
}
-export function closeAllGlobalMessages() {
- return { type: 'CLOSE_ALL_GLOBAL_MESSAGES' };
-}
-
type Action =
| ActionType<typeof addGlobalMessageActionCreator, 'ADD_GLOBAL_MESSAGE'>
- | ActionType<typeof closeGlobalMessage, 'CLOSE_GLOBAL_MESSAGE'>
- | ActionType<typeof closeAllGlobalMessages, 'CLOSE_ALL_GLOBAL_MESSAGES'>;
+ | ActionType<typeof closeGlobalMessage, 'CLOSE_GLOBAL_MESSAGE'>;
function addGlobalMessage(message: string, level: MessageLevel) {
return (dispatch: Dispatch) => {
const id = uniqueId('global-message-');
dispatch(addGlobalMessageActionCreator(id, message, level));
- setTimeout(() => dispatch(closeGlobalMessage(id)), 5000);
+ setTimeout(() => dispatch(closeGlobalMessage(id)), MESSAGE_DISPLAY_TIME);
};
}
@@ -67,7 +66,7 @@ export function addGlobalSuccessMessage(message: string) {
export type State = Message[];
-export default function(state: State = [], action: Action): State {
+export default function globalMessagesReducer(state: State = [], action: Action): State {
switch (action.type) {
case 'ADD_GLOBAL_MESSAGE':
return [{ id: action.id, message: action.message, level: action.level }];
@@ -75,8 +74,6 @@ export default function(state: State = [], action: Action): State {
case 'CLOSE_GLOBAL_MESSAGE':
return state.filter(message => message.id !== action.id);
- case 'CLOSE_ALL_GLOBAL_MESSAGES':
- return [];
default:
return state;
}
diff --git a/server/sonar-web/src/main/js/store/rootActions.ts b/server/sonar-web/src/main/js/store/rootActions.ts
deleted file mode 100644
index fd2d12cc351..00000000000
--- a/server/sonar-web/src/main/js/store/rootActions.ts
+++ /dev/null
@@ -1,77 +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 { Dispatch } from 'redux';
-import * as auth from '../api/auth';
-import { getQualityGateProjectStatus } from '../api/quality-gates';
-import { getBranchLikeQuery } from '../helpers/branch-like';
-import { extractStatusConditionsFromProjectStatus } from '../helpers/qualityGates';
-import { BranchLike } from '../types/branch-like';
-import { Status } from '../types/types';
-import { registerBranchStatusAction } from './branches';
-import { addGlobalErrorMessage } from './globalMessages';
-
-export function fetchBranchStatus(branchLike: BranchLike, projectKey: string) {
- return (dispatch: Dispatch<any>) => {
- getQualityGateProjectStatus({ projectKey, ...getBranchLikeQuery(branchLike) }).then(
- projectStatus => {
- const { ignoredConditions, status } = projectStatus;
- const conditions = extractStatusConditionsFromProjectStatus(projectStatus);
- dispatch(
- registerBranchStatusAction(branchLike, projectKey, status, conditions, ignoredConditions)
- );
- },
- () => {
- dispatch(addGlobalErrorMessage('Fetching Quality Gate status failed'));
- }
- );
- };
-}
-
-export function doLogin(login: string, password: string) {
- return (dispatch: Dispatch<any>) =>
- auth.login(login, password).then(
- () => {
- /* everything is fine */
- },
- () => {
- dispatch(addGlobalErrorMessage('Authentication failed'));
- return Promise.reject();
- }
- );
-}
-
-export function doLogout() {
- return (dispatch: Dispatch<any>) =>
- auth.logout().then(
- () => {
- /* everything is fine */
- },
- () => {
- dispatch(addGlobalErrorMessage('Logout failed'));
- return Promise.reject();
- }
- );
-}
-
-export function registerBranchStatus(branchLike: BranchLike, component: string, status: Status) {
- return (dispatch: Dispatch) => {
- dispatch(registerBranchStatusAction(branchLike, component, status));
- };
-}
diff --git a/server/sonar-web/src/main/js/store/utils/actions.ts b/server/sonar-web/src/main/js/types/actions.ts
index 1e340e07cf0..1e340e07cf0 100644
--- a/server/sonar-web/src/main/js/store/utils/actions.ts
+++ b/server/sonar-web/src/main/js/types/actions.ts