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