Browse Source

SONAR-10994 Add new branch store

tags/7.8
Wouter Admiraal 5 years ago
parent
commit
2c28c4471b

+ 6
- 4
server/sonar-web/src/main/js/app/types.d.ts View File

@@ -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 =

+ 80
- 0
server/sonar-web/src/main/js/store/__tests__/branches-test.ts View File

@@ -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;
}

+ 38
- 0
server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx View File

@@ -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();
});

+ 37
- 0
server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx View File

@@ -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);
});

+ 72
- 0
server/sonar-web/src/main/js/store/branches.ts View File

@@ -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
);
}

+ 11
- 0
server/sonar-web/src/main/js/store/rootActions.ts View File

@@ -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));
};
}

+ 11
- 0
server/sonar-web/src/main/js/store/rootReducer.ts View File

@@ -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);
}

Loading…
Cancel
Save