aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js
diff options
context:
space:
mode:
authorWouter Admiraal <wouter.admiraal@sonarsource.com>2019-03-06 15:49:52 +0100
committersonartech <sonartech@sonarsource.com>2019-03-29 09:44:57 +0100
commit2c28c4471b04811c5deb30688ad57561b2e91ae5 (patch)
treefdbfaddc4c20dfc0f703a61dfc3eb25bdf10f9bd /server/sonar-web/src/main/js
parent687ced1be70bf111c4c5617ca8d224af3f511441 (diff)
downloadsonarqube-2c28c4471b04811c5deb30688ad57561b2e91ae5.tar.gz
sonarqube-2c28c4471b04811c5deb30688ad57561b2e91ae5.zip
SONAR-10994 Add new branch store
Diffstat (limited to 'server/sonar-web/src/main/js')
-rw-r--r--server/sonar-web/src/main/js/app/types.d.ts10
-rw-r--r--server/sonar-web/src/main/js/store/__tests__/branches-test.ts80
-rw-r--r--server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx38
-rw-r--r--server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx37
-rw-r--r--server/sonar-web/src/main/js/store/branches.ts72
-rw-r--r--server/sonar-web/src/main/js/store/rootActions.ts11
-rw-r--r--server/sonar-web/src/main/js/store/rootReducer.ts11
7 files changed, 255 insertions, 4 deletions
diff --git a/server/sonar-web/src/main/js/app/types.d.ts b/server/sonar-web/src/main/js/app/types.d.ts
index 16d74f126c0..340ebfa96c6 100644
--- a/server/sonar-web/src/main/js/app/types.d.ts
+++ b/server/sonar-web/src/main/js/app/types.d.ts
@@ -108,7 +108,7 @@ declare namespace T {
analysisDate?: string;
isMain: boolean;
name: string;
- status?: { qualityGateStatus: string };
+ status?: { qualityGateStatus: Status };
}
export type BranchLike = Branch | PullRequest;
@@ -624,7 +624,7 @@ declare namespace T {
branch: string;
key: string;
isOrphan?: true;
- status?: { qualityGateStatus: string };
+ status?: { qualityGateStatus: Status };
title: string;
url?: string;
}
@@ -646,7 +646,7 @@ declare namespace T {
}
export interface QualityGateProjectStatusCondition {
- status: 'ERROR' | 'OK';
+ status: Status;
metricKey: string;
comparator: string;
periodIndex: number;
@@ -658,7 +658,7 @@ declare namespace T {
projectStatus: {
conditions?: QualityGateProjectStatusCondition[];
ignoredConditions: boolean;
- status: string;
+ status: Status;
};
}
@@ -736,6 +736,8 @@ declare namespace T {
export type RuleType = 'BUG' | 'VULNERABILITY' | 'CODE_SMELL' | 'SECURITY_HOTSPOT' | 'UNKNOWN';
+ export type Status = 'ERROR' | 'OK';
+
export type Setting = SettingValue & { definition: SettingDefinition };
export type SettingType =
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
new file mode 100644
index 00000000000..554ac0f6a7e
--- /dev/null
+++ b/server/sonar-web/src/main/js/store/__tests__/branches-test.ts
@@ -0,0 +1,80 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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 reducer, {
+ registerBranchStatusAction,
+ getBranchStatusByBranchLike,
+ State
+} from '../branches';
+import {
+ mockPullRequest,
+ mockLongLivingBranch,
+ mockShortLivingBranch
+} from '../../helpers/testMocks';
+import { getBranchLikeKey } from '../../helpers/branches';
+
+type TestArgs = [T.BranchLike, string, T.Status];
+
+const COMPONENT = 'foo';
+const BRANCH_STATUS_1: TestArgs = [mockPullRequest(), COMPONENT, 'ERROR'];
+const BRANCH_STATUS_2: TestArgs = [mockLongLivingBranch(), 'bar', 'OK'];
+const BRANCH_STATUS_3: TestArgs = [mockShortLivingBranch(), COMPONENT, 'OK'];
+
+it('should allow to register new branche statuses', () => {
+ const initialState: State = convertToState();
+
+ const newState = reducer(initialState, registerBranchStatusAction(...BRANCH_STATUS_1));
+ expect(newState).toEqual(convertToState([BRANCH_STATUS_1]));
+
+ const newerState = reducer(newState, registerBranchStatusAction(...BRANCH_STATUS_2));
+ expect(newerState).toEqual(convertToState([BRANCH_STATUS_1, BRANCH_STATUS_2]));
+ expect(newState).toEqual(convertToState([BRANCH_STATUS_1]));
+});
+
+it('should allow to update branche statuses', () => {
+ const initialState: State = convertToState([BRANCH_STATUS_1, BRANCH_STATUS_2, BRANCH_STATUS_3]);
+ const branchLike: T.BranchLike = { ...BRANCH_STATUS_1[0], status: { qualityGateStatus: 'OK' } };
+ const branchStatus: TestArgs = [branchLike, COMPONENT, 'OK'];
+
+ const newState = reducer(initialState, registerBranchStatusAction(...branchStatus));
+ expect(newState).toEqual(convertToState([branchStatus, BRANCH_STATUS_2, BRANCH_STATUS_3]));
+ expect(initialState).toEqual(convertToState([BRANCH_STATUS_1, BRANCH_STATUS_2, BRANCH_STATUS_3]));
+});
+
+it('should get the branche statuses from state', () => {
+ const initialState: State = convertToState([BRANCH_STATUS_1, BRANCH_STATUS_2]);
+
+ const [branchLike, component] = BRANCH_STATUS_1;
+ expect(getBranchStatusByBranchLike(initialState, component, branchLike)).toEqual('ERROR');
+ expect(getBranchStatusByBranchLike(initialState, component, BRANCH_STATUS_2[0])).toBeUndefined();
+});
+
+function convertToState(items: TestArgs[] = []) {
+ const state: State = { byComponent: {} };
+
+ items.forEach(item => {
+ const [branchLike, component, status] = item;
+ state.byComponent[component] = {
+ ...(state.byComponent[component] || {}),
+ [getBranchLikeKey(branchLike)]: { status }
+ };
+ });
+
+ return state;
+}
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
new file mode 100644
index 00000000000..18adff3d44e
--- /dev/null
+++ b/server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx
@@ -0,0 +1,38 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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 { registerBranchStatus } from '../rootActions';
+import { mockLongLivingBranch } from '../../helpers/testMocks';
+import { registerBranchStatusAction } from '../branches';
+
+jest.mock('../branches', () => ({
+ ...require.requireActual('../branches'),
+ registerBranchStatusAction: jest.fn()
+}));
+
+it('correctly dispatches actions for branches', () => {
+ const dispatch = jest.fn();
+ const branchLike = mockLongLivingBranch();
+ const component = 'foo';
+ const status = 'OK';
+
+ registerBranchStatus(branchLike, component, status)(dispatch);
+ expect(registerBranchStatusAction).toBeCalledWith(branchLike, component, status);
+ 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
new file mode 100644
index 00000000000..e31f34625b8
--- /dev/null
+++ b/server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx
@@ -0,0 +1,37 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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 { getBranchStatusByBranchLike, Store } from '../rootReducer';
+import * as fromBranches from '../branches';
+import { mockPullRequest } from '../../helpers/testMocks';
+
+jest.mock('../branches', () => {
+ return {
+ ...require.requireActual('../branches'),
+ getBranchStatusByBranchLike: jest.fn()
+ };
+});
+
+it('correctly reduce state for branches', () => {
+ const branches = {};
+ const component = 'foo';
+ const branchLike = mockPullRequest();
+ getBranchStatusByBranchLike({ branches } as Store, component, branchLike);
+ expect(fromBranches.getBranchStatusByBranchLike).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
new file mode 100644
index 00000000000..51593449f0d
--- /dev/null
+++ b/server/sonar-web/src/main/js/store/branches.ts
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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 { ActionType } from './utils/actions';
+import { getBranchLikeKey } from '../helpers/branches';
+
+export interface State {
+ byComponent: T.Dict<T.Dict<{ status?: T.Status }>>;
+}
+
+const enum Actions {
+ RegisterBranchStatus = 'REGISTER_BRANCH_STATUS'
+}
+
+type Action = ActionType<typeof registerBranchStatusAction, Actions.RegisterBranchStatus>;
+
+export function registerBranchStatusAction(
+ branchLike: T.BranchLike,
+ component: string,
+ status: T.Status
+) {
+ return { type: Actions.RegisterBranchStatus, branchLike, component, status };
+}
+
+export default function(state: State = { byComponent: {} }, action: Action): State {
+ if (action.type === Actions.RegisterBranchStatus) {
+ const { component, branchLike, status } = action;
+ const branchLikeKey = getBranchLikeKey(branchLike);
+ return {
+ byComponent: {
+ ...state.byComponent,
+ [component]: {
+ ...(state.byComponent[component] || {}),
+ [branchLikeKey]: {
+ status
+ }
+ }
+ }
+ };
+ }
+
+ return state;
+}
+
+export function getBranchStatusByBranchLike(
+ state: State,
+ component: string,
+ branchLike: T.BranchLike
+) {
+ const branchLikeKey = getBranchLikeKey(branchLike);
+ return (
+ state.byComponent[component] &&
+ state.byComponent[component][branchLikeKey] &&
+ state.byComponent[component][branchLikeKey].status
+ );
+}
diff --git a/server/sonar-web/src/main/js/store/rootActions.ts b/server/sonar-web/src/main/js/store/rootActions.ts
index 6bab84e7335..e9d68e0c5c2 100644
--- a/server/sonar-web/src/main/js/store/rootActions.ts
+++ b/server/sonar-web/src/main/js/store/rootActions.ts
@@ -20,6 +20,7 @@
import { Dispatch } from 'redux';
import { InjectedRouter } from 'react-router';
import { requireAuthorization as requireAuthorizationAction } from './appState';
+import { registerBranchStatusAction } from './branches';
import { addGlobalErrorMessage } from './globalMessages';
import { receiveLanguages } from './languages';
import { receiveMetrics } from './metrics';
@@ -92,3 +93,13 @@ export function requireAuthorization(router: Pick<InjectedRouter, 'replace'>) {
router.replace({ pathname: '/sessions/new', query: { return_to: returnTo } });
return requireAuthorizationAction();
}
+
+export function registerBranchStatus(
+ branchLike: T.BranchLike,
+ component: string,
+ status: T.Status
+) {
+ return (dispatch: Dispatch) => {
+ dispatch(registerBranchStatusAction(branchLike, component, status));
+ };
+}
diff --git a/server/sonar-web/src/main/js/store/rootReducer.ts b/server/sonar-web/src/main/js/store/rootReducer.ts
index e4286c79a99..c1b94e09bba 100644
--- a/server/sonar-web/src/main/js/store/rootReducer.ts
+++ b/server/sonar-web/src/main/js/store/rootReducer.ts
@@ -19,6 +19,7 @@
*/
import { combineReducers } from 'redux';
import appState from './appState';
+import branches, * as fromBranches from './branches';
import globalMessages, * as fromGlobalMessages from './globalMessages';
import languages, * as fromLanguages from './languages';
import metrics, * as fromMetrics from './metrics';
@@ -28,6 +29,7 @@ import settingsApp, * as fromSettingsApp from '../apps/settings/store/rootReduce
export type Store = {
appState: T.AppState;
+ branches: fromBranches.State;
globalMessages: fromGlobalMessages.State;
languages: T.Languages;
metrics: fromMetrics.State;
@@ -40,6 +42,7 @@ export type Store = {
export default combineReducers<Store>({
appState,
+ branches,
globalMessages,
languages,
metrics,
@@ -125,3 +128,11 @@ export function isSettingsAppLoading(state: Store, key: string) {
export function getSettingsAppValidationMessage(state: Store, key: string) {
return fromSettingsApp.getValidationMessage(state.settingsApp, key);
}
+
+export function getBranchStatusByBranchLike(
+ state: Store,
+ component: string,
+ branchLike: T.BranchLike
+) {
+ return fromBranches.getBranchStatusByBranchLike(state.branches, component, branchLike);
+}