* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { cloneDeep } from 'lodash';
-import { mockNewCodePeriod, mockNewCodePeriodBranch } from '../../helpers/mocks/new-code-period';
-import { NewCodePeriod, NewCodePeriodBranch, NewCodePeriodSettingType } from '../../types/types';
+import {
+ mockNewCodePeriod,
+ mockNewCodePeriodBranch,
+} from '../../helpers/mocks/new-code-definition';
+import {
+ NewCodeDefinition,
+ NewCodeDefinitionBranch,
+ NewCodeDefinitionType,
+} from '../../types/new-code-definition';
import {
getNewCodePeriod,
listBranchesNewCodePeriod,
mockNewCodePeriodBranch({ inherited: true, branchKey: 'main' }),
mockNewCodePeriodBranch({
branchKey: 'feature',
- type: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ type: NewCodeDefinitionType.NumberOfDays,
value: '1',
}),
];
- #newCodePeriod: NewCodePeriod;
- #listBranchesNewCode: NewCodePeriodBranch[];
+ #newCodePeriod: NewCodeDefinition;
+ #listBranchesNewCode: NewCodeDefinitionBranch[];
constructor() {
this.#newCodePeriod = cloneDeep(this.#defaultNewCodePeriod);
handleSetNewCodePeriod = (data: {
project?: string;
branch?: string;
- type: NewCodePeriodSettingType;
+ type: NewCodeDefinitionType;
value?: string;
}) => {
const { type, value, branch } = data;
if (branch) {
const branchNewCode = this.#listBranchesNewCode.find(
(bNew) => bNew.branchKey === branch
- ) as NewCodePeriodBranch;
+ ) as NewCodeDefinitionBranch;
branchNewCode.type = type;
branchNewCode.value = value;
} else {
return this.reply({ newCodePeriods: this.#listBranchesNewCode });
};
- setNewCodePeriod = (newCodePeriod: NewCodePeriod) => {
+ setNewCodePeriod = (newCodePeriod: NewCodeDefinition) => {
this.#newCodePeriod = newCodePeriod;
};
- setListBranchesNewCode = (listBranchesNewCode: NewCodePeriodBranch[]) => {
+ setListBranchesNewCode = (listBranchesNewCode: NewCodeDefinitionBranch[]) => {
this.#listBranchesNewCode = listBranchesNewCode;
};
*/
import { throwGlobalError } from '../helpers/error';
import { getJSON, post } from '../helpers/request';
-import { NewCodePeriod, NewCodePeriodBranch, NewCodePeriodSettingType } from '../types/types';
+import {
+ NewCodeDefinition,
+ NewCodeDefinitionBranch,
+ NewCodeDefinitionType,
+} from '../types/new-code-definition';
export function getNewCodePeriod(data?: {
project?: string;
branch?: string;
-}): Promise<Omit<NewCodePeriod, 'effectiveValue'>> {
+}): Promise<Omit<NewCodeDefinition, 'effectiveValue'>> {
return getJSON('/api/new_code_periods/show', data).catch(throwGlobalError);
}
export function setNewCodePeriod(data: {
project?: string;
branch?: string;
- type: NewCodePeriodSettingType;
+ type: NewCodeDefinitionType;
value?: string;
}): Promise<void> {
return post('/api/new_code_periods/set', data).catch(throwGlobalError);
export function listBranchesNewCodePeriod(data: {
project: string;
-}): Promise<{ newCodePeriods: NewCodePeriodBranch[] }> {
+}): Promise<{ newCodePeriods: NewCodeDefinitionBranch[] }> {
return getJSON('/api/new_code_periods/list', data).catch(throwGlobalError);
}
import DateFromNow from '../../../components/intl/DateFromNow';
import DateTimeFormatter, { formatterOption } from '../../../components/intl/DateTimeFormatter';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { getPeriodDate, getPeriodLabel } from '../../../helpers/periods';
+import { getNewCodePeriodDate, getNewCodePeriodLabel } from '../../../helpers/new-code-period';
import { ComponentQualifier } from '../../../types/component';
-import { ComponentMeasure, NewCodePeriodSettingType, Period } from '../../../types/types';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
+import { ComponentMeasure, Period } from '../../../types/types';
export interface LeakPeriodLegendProps {
component: ComponentMeasure;
);
}
- const leakPeriodLabel = getPeriodLabel(
+ const leakPeriodLabel = getNewCodePeriodLabel(
period,
period.mode === 'manual_baseline' ? this.formatDateTime : this.formatDate
);
</LeakPeriodLabel>
);
- if (period.mode === 'days' || period.mode === NewCodePeriodSettingType.NUMBER_OF_DAYS) {
+ if (period.mode === 'days' || period.mode === NewCodeDefinitionType.NumberOfDays) {
return label;
}
- const date = getPeriodDate(period);
+ const date = getNewCodePeriodDate(period);
const tooltip = date && (
<div>
<DateFromNow date={date} />
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import classNames from 'classnames';
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
import { FormattedMessage } from 'react-intl';
import { Location, Router, withRouter } from '../../../components/hoc/withRouter';
import NewCodeDefinitionSelector from '../../../components/new-code-definition/NewCodeDefinitionSelector';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
+import { addGlobalSuccessMessage } from '../../../helpers/globalMessages';
import { translate } from '../../../helpers/l10n';
import { getProjectUrl } from '../../../helpers/urls';
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings';
import { AppState } from '../../../types/appstate';
import { Feature } from '../../../types/features';
-import { NewCodePeriodWithCompliance } from '../../../types/types';
+import { NewCodeDefinitiondWithCompliance } from '../../../types/new-code-definition';
import AlmBindingDefinitionForm from '../../settings/components/almIntegration/AlmBindingDefinitionForm';
import AzureProjectCreate from './Azure/AzureProjectCreate';
import BitbucketCloudProjectCreate from './BitbucketCloud/BitbucketCloudProjectCreate';
import ManualProjectCreate from './manual/ManualProjectCreate';
import './style.css';
import { CreateProjectApiCallback, CreateProjectModes } from './types';
-import { addGlobalSuccessMessage } from '../../../helpers/globalMessages';
-import classNames from 'classnames';
export interface CreateProjectPageProps extends WithAvailableFeaturesProps {
appState: AppState;
loading: boolean;
isProjectSetupDone: boolean;
creatingAlmDefinition?: AlmKeys;
- selectedNcd: NewCodePeriodWithCompliance | null;
+ selectedNcd: NewCodeDefinitiondWithCompliance | null;
submitting: boolean;
}
}
};
- handleNcdChanged = (ncd: NewCodePeriodWithCompliance) => {
+ handleNcdChanged = (ncd: NewCodeDefinitiondWithCompliance) => {
this.setState({
selectedNcd: ncd,
});
import { mockAppState } from '../../../../helpers/testMocks';
import { renderApp } from '../../../../helpers/testReactTestingUtils';
import { byRole, byText } from '../../../../helpers/testSelector';
-import { NewCodePeriodSettingType } from '../../../../types/types';
+import { NewCodeDefinitionType } from '../../../../types/new-code-definition';
import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage';
jest.mock('../../../../api/alm-settings');
it('should select the global NCD when it is compliant', async () => {
jest
.mocked(getNewCodePeriod)
- .mockResolvedValue({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '30' });
+ .mockResolvedValue({ type: NewCodeDefinitionType.NumberOfDays, value: '30' });
const user = userEvent.setup();
renderCreateProject();
await fillFormAndNext('test', user);
it('global NCD option should be disabled if not compliant', async () => {
jest
.mocked(getNewCodePeriod)
- .mockResolvedValue({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '96' });
+ .mockResolvedValue({ type: NewCodeDefinitionType.NumberOfDays, value: '96' });
const user = userEvent.setup();
renderCreateProject();
await fillFormAndNext('test', user);
async ({ canAdmin, message }) => {
jest
.mocked(getNewCodePeriod)
- .mockResolvedValue({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '96' });
+ .mockResolvedValue({ type: NewCodeDefinitionType.NumberOfDays, value: '96' });
const user = userEvent.setup();
renderCreateProject({ appState: mockAppState({ canAdmin }) });
await fillFormAndNext('test', user);
async (option) => {
jest
.mocked(getNewCodePeriod)
- .mockResolvedValue({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '96' });
+ .mockResolvedValue({ type: NewCodeDefinitionType.NumberOfDays, value: '96' });
const user = userEvent.setup();
renderCreateProject();
await fillFormAndNext('test', user);
it('number of days should show error message if value is not a number', async () => {
jest
.mocked(getNewCodePeriod)
- .mockResolvedValue({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '60' });
+ .mockResolvedValue({ type: NewCodeDefinitionType.NumberOfDays, value: '60' });
const user = userEvent.setup();
renderCreateProject();
await fillFormAndNext('test', user);
await user.click(ui.ncdOptionDaysRadio.get());
expect(ui.ncdOptionDaysInput.get()).toBeInTheDocument();
- expect(ui.ncdOptionDaysInput.get()).toHaveValue('30');
+ expect(ui.ncdOptionDaysInput.get()).toHaveValue('60');
expect(ui.projectCreateButton.get()).toBeEnabled();
await user.click(ui.ncdOptionDaysInput.get());
});
it('the project onboarding page should be displayed when the project is created', async () => {
- newCodePeriodHandler.setNewCodePeriod({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS });
+ newCodePeriodHandler.setNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays });
const user = userEvent.setup();
renderCreateProject();
await fillFormAndNext('testing', user);
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { ProjectBase } from '../../../api/components';
-import { NewCodePeriodSettingType } from '../../../types/types';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
export enum CreateProjectModes {
Manual = 'manual',
}
export type CreateProjectApiCallback = (
- newCodeDefinitionType?: NewCodePeriodSettingType,
+ newCodeDefinitionType?: NewCodeDefinitionType,
newCodeDefinitionValue?: string
) => Promise<{ project: ProjectBase }>;
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { isApplicationPeriod } from '../../../helpers/periods';
+import { isApplicationNewCodePeriod } from '../../../helpers/new-code-period';
import { ApplicationPeriod } from '../../../types/application';
import { Period } from '../../../types/types';
import ApplicationLeakPeriodInfo from './ApplicationLeakPeriodInfo';
}
export function LeakPeriodInfo({ leakPeriod }: LeakPeriodInfoProps) {
- if (isApplicationPeriod(leakPeriod)) {
+ if (isApplicationNewCodePeriod(leakPeriod)) {
return <ApplicationLeakPeriodInfo leakPeriod={leakPeriod} />;
}
return <ProjectLeakPeriodInfo leakPeriod={leakPeriod} />;
import { queryToSearch } from '../../../helpers/urls';
import { Branch } from '../../../types/branch-like';
import { ComponentQualifier } from '../../../types/component';
-import { Component, NewCodePeriodSettingType, Period } from '../../../types/types';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
+import { Component, Period } from '../../../types/types';
export interface MeasuresPanelNoNewCodeProps {
branch?: Branch;
const isApp = component.qualifier === ComponentQualifier.Application;
const hasBadReferenceBranch =
- !isApp && !!period && !period.date && period.mode === NewCodePeriodSettingType.REFERENCE_BRANCH;
+ !isApp && !!period && !period.date && period.mode === NewCodeDefinitionType.ReferenceBranch;
/*
* If the period is "reference branch"-based, and if there's no date, it means
* that we're not lacking a second analysis, but that we'll never have new code because the
import DateFromNow from '../../../components/intl/DateFromNow';
import { formatterOption } from '../../../components/intl/DateTimeFormatter';
import { translateWithParameters } from '../../../helpers/l10n';
-import { getPeriodDate, getPeriodLabel } from '../../../helpers/periods';
-import { NewCodePeriodSettingType, Period } from '../../../types/types';
+import { getNewCodePeriodDate, getNewCodePeriodLabel } from '../../../helpers/new-code-period';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
+import { Period } from '../../../types/types';
export interface ProjectLeakPeriodInfoProps extends WrappedComponentProps {
leakPeriod: Period;
leakPeriod,
} = props;
- const leakPeriodLabel = getPeriodLabel(
+ const leakPeriodLabel = getNewCodePeriodLabel(
leakPeriod,
- ['manual_baseline', NewCodePeriodSettingType.SPECIFIC_ANALYSIS].includes(leakPeriod.mode)
+ ['manual_baseline', NewCodeDefinitionType.SpecificAnalysis].includes(leakPeriod.mode)
? (date: string) => formatTime(date, formatterOption)
: (date: string) => formatDate(date, longFormatterOption)
);
if (
leakPeriod.mode === 'days' ||
- leakPeriod.mode === NewCodePeriodSettingType.NUMBER_OF_DAYS ||
- leakPeriod.mode === NewCodePeriodSettingType.REFERENCE_BRANCH
+ leakPeriod.mode === NewCodeDefinitionType.NumberOfDays ||
+ leakPeriod.mode === NewCodeDefinitionType.ReferenceBranch
) {
return <div>{leakPeriodLabel} </div>;
}
- const leakPeriodDate = getPeriodDate(leakPeriod);
+ const leakPeriodDate = getNewCodePeriodDate(leakPeriod);
if (!leakPeriodDate) {
return null;
import { IntlShape } from 'react-intl';
import { mockPeriod } from '../../../../helpers/testMocks';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
-import { NewCodePeriodSettingType, Period } from '../../../../types/types';
+import { NewCodeDefinitionType } from '../../../../types/new-code-definition';
+import { Period } from '../../../../types/types';
import { ProjectLeakPeriodInfo } from '../ProjectLeakPeriodInfo';
jest.mock('date-fns', () => {
it('should render correctly for "REFERENCE_BRANCH"', async () => {
renderProjectLeakPeriodInfo({
- mode: NewCodePeriodSettingType.REFERENCE_BRANCH,
+ mode: NewCodeDefinitionType.ReferenceBranch,
parameter: 'master',
});
expect(await screen.findByText('overview.period.reference_branch.master')).toBeInTheDocument();
import DateFromNow from '../../../components/intl/DateFromNow';
import DateTimeFormatter, { formatterOption } from '../../../components/intl/DateTimeFormatter';
import { translateWithParameters } from '../../../helpers/l10n';
-import { getPeriodDate, getPeriodLabel } from '../../../helpers/periods';
-import { Dict, NewCodePeriodSettingType, Period } from '../../../types/types';
+import { getNewCodePeriodDate, getNewCodePeriodLabel } from '../../../helpers/new-code-period';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
+import { Dict, Period } from '../../../types/types';
interface Props {
period: Period;
render() {
const { period } = this.props;
- const leakPeriodLabel = getPeriodLabel(
+ const leakPeriodLabel = getNewCodePeriodLabel(
period,
MODE_INCLUDES_TIME[period.mode] ? this.formatDateTime : this.formatDate
);
return null;
}
- if (period.mode === 'days' || period.mode === NewCodePeriodSettingType.NUMBER_OF_DAYS) {
+ if (period.mode === 'days' || period.mode === NewCodeDefinitionType.NumberOfDays) {
return (
<div className="overview-legend overview-legend-spaced-line">
{translateWithParameters('overview.new_code_period_x', leakPeriodLabel)}
);
}
- const leakPeriodDate = getPeriodDate(period);
+ const leakPeriodDate = getNewCodePeriodDate(period);
if (!leakPeriodDate) {
return null;
}
import * as React from 'react';
import RadioCard from '../../../components/controls/RadioCard';
import { translate } from '../../../helpers/l10n';
-import { NewCodePeriodSettingType } from '../../../types/types';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
export interface Props {
- onSelect: (selection: NewCodePeriodSettingType) => void;
+ onSelect: (selection: NewCodeDefinitionType) => void;
selected: boolean;
}
<RadioCard
noRadio
disabled
- onClick={() => onSelect(NewCodePeriodSettingType.SPECIFIC_ANALYSIS)}
+ onClick={() => onSelect(NewCodeDefinitionType.SpecificAnalysis)}
selected={selected}
title={translate('baseline.specific_analysis')}
>
import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { NewCodePeriodSettingType } from '../../../types/types';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
export interface BaselineSettingReferenceBranchProps {
branchList: BranchOption[];
className?: string;
disabled?: boolean;
onChangeReferenceBranch: (value: string) => void;
- onSelect: (selection: NewCodePeriodSettingType) => void;
+ onSelect: (selection: NewCodeDefinitionType) => void;
referenceBranch: string;
selected: boolean;
settingLevel: 'project' | 'branch';
noRadio
className={className}
disabled={disabled}
- onClick={() => props.onSelect(NewCodePeriodSettingType.REFERENCE_BRANCH)}
+ onClick={() => props.onSelect(NewCodeDefinitionType.ReferenceBranch)}
selected={selected}
title={translate('baseline.reference_branch')}
>
*/
import * as React from 'react';
import { setNewCodePeriod } from '../../../api/newCodePeriod';
-import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import Modal from '../../../components/controls/Modal';
+import { ResetButtonLink, SubmitButton } from '../../../components/controls/buttons';
import NewCodeDefinitionDaysOption from '../../../components/new-code-definition/NewCodeDefinitionDaysOption';
import NewCodeDefinitionPreviousVersionOption from '../../../components/new-code-definition/NewCodeDefinitionPreviousVersionOption';
import NewCodeDefinitionWarning from '../../../components/new-code-definition/NewCodeDefinitionWarning';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { toISO8601WithOffsetString } from '../../../helpers/dates';
import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { getNumberOfDaysDefaultValue } from '../../../helpers/new-code-definition';
import { Branch, BranchWithNewCodePeriod } from '../../../types/branch-like';
+import { NewCodeDefinition, NewCodeDefinitionType } from '../../../types/new-code-definition';
import { ParsedAnalysis } from '../../../types/project-activity';
-import { NewCodePeriod, NewCodePeriodSettingType } from '../../../types/types';
import { getSettingValue, validateSetting } from '../utils';
import BaselineSettingAnalysis from './BaselineSettingAnalysis';
import BaselineSettingReferenceBranch from './BaselineSettingReferenceBranch';
branch: BranchWithNewCodePeriod;
branchList: Branch[];
component: string;
- onClose: (branch?: string, newSetting?: NewCodePeriod) => void;
+ onClose: (branch?: string, newSetting?: NewCodeDefinition) => void;
+ inheritedSetting: NewCodeDefinition;
+ generalSetting: NewCodeDefinition;
}
interface State {
days: string;
referenceBranch: string;
saving: boolean;
- selected?: NewCodePeriodSettingType;
+ selected?: NewCodeDefinitionType;
}
export default class BranchBaselineSettingModal extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
- const otherBranches = props.branchList.filter((b) => b.name !== props.branch.name);
+ const { branch, branchList, inheritedSetting, generalSetting } = props;
+ const otherBranches = branchList.filter((b) => b.name !== branch.name);
const defaultBranch = otherBranches.length > 0 ? otherBranches[0].name : '';
this.state = {
- analysis: this.getValueFromProps(NewCodePeriodSettingType.SPECIFIC_ANALYSIS) || '',
- days: this.getValueFromProps(NewCodePeriodSettingType.NUMBER_OF_DAYS) || '30',
+ analysis: this.getValueFromProps(NewCodeDefinitionType.SpecificAnalysis) || '',
+ days:
+ this.getValueFromProps(NewCodeDefinitionType.NumberOfDays) ||
+ getNumberOfDaysDefaultValue(generalSetting, inheritedSetting),
referenceBranch:
- this.getValueFromProps(NewCodePeriodSettingType.REFERENCE_BRANCH) || defaultBranch,
+ this.getValueFromProps(NewCodeDefinitionType.ReferenceBranch) || defaultBranch,
saving: false,
- selected: this.props.branch.newCodePeriod && this.props.branch.newCodePeriod.type,
+ selected: branch.newCodePeriod?.type,
};
}
this.mounted = false;
}
- getValueFromProps(type: NewCodePeriodSettingType) {
+ getValueFromProps(type: NewCodeDefinitionType) {
return this.props.branch.newCodePeriod && this.props.branch.newCodePeriod.type === type
? this.props.branch.newCodePeriod.value
: null;
branch: branch.name,
}).then(
() => {
- this.setState({
- saving: false,
- });
- this.props.onClose(branch.name, {
- type,
- value,
- effectiveValue: analysisDate && toISO8601WithOffsetString(analysisDate),
- });
+ if (this.mounted) {
+ this.setState({
+ saving: false,
+ });
+ this.props.onClose(branch.name, {
+ type,
+ value,
+ effectiveValue: analysisDate && toISO8601WithOffsetString(analysisDate),
+ });
+ }
},
() => {
- this.setState({
- saving: false,
- });
+ if (this.mounted) {
+ this.setState({
+ saving: false,
+ });
+ }
}
);
}
handleSelectReferenceBranch = (referenceBranch: string) => this.setState({ referenceBranch });
- handleSelectSetting = (selected: NewCodePeriodSettingType) => this.setState({ selected });
+ handleSelectSetting = (selected: NewCodeDefinitionType) => this.setState({ selected });
render() {
const { branch, branchList } = this.props;
const header = translateWithParameters('baseline.new_code_period_for_branch_x', branch.name);
- const currentSetting = branch.newCodePeriod && branch.newCodePeriod.type;
- const currentSettingValue = branch.newCodePeriod && branch.newCodePeriod.value;
+ const currentSetting = branch.newCodePeriod?.type;
+ const currentSettingValue = branch.newCodePeriod?.value;
const { isChanged, isValid } = validateSetting({
analysis,
<NewCodeDefinitionPreviousVersionOption
isDefault={false}
onSelect={this.handleSelectSetting}
- selected={selected === NewCodePeriodSettingType.PREVIOUS_VERSION}
+ selected={selected === NewCodeDefinitionType.PreviousVersion}
/>
<NewCodeDefinitionDaysOption
days={days}
isValid={isValid}
onChangeDays={this.handleSelectDays}
onSelect={this.handleSelectSetting}
- selected={selected === NewCodePeriodSettingType.NUMBER_OF_DAYS}
+ selected={selected === NewCodeDefinitionType.NumberOfDays}
/>
<BaselineSettingReferenceBranch
branchList={branchList.map(this.branchToOption)}
onChangeReferenceBranch={this.handleSelectReferenceBranch}
onSelect={this.handleSelectSetting}
referenceBranch={referenceBranch}
- selected={selected === NewCodePeriodSettingType.REFERENCE_BRANCH}
+ selected={selected === NewCodeDefinitionType.ReferenceBranch}
settingLevel="branch"
/>
- {currentSetting === NewCodePeriodSettingType.SPECIFIC_ANALYSIS && (
+ {currentSetting === NewCodeDefinitionType.SpecificAnalysis && (
<BaselineSettingAnalysis
onSelect={() => {}}
- selected={selected === NewCodePeriodSettingType.SPECIFIC_ANALYSIS}
+ selected={selected === NewCodeDefinitionType.SpecificAnalysis}
/>
)}
</div>
- {selected === NewCodePeriodSettingType.SPECIFIC_ANALYSIS && (
+ {selected === NewCodeDefinitionType.SpecificAnalysis && (
<BranchAnalysisList
analysis={analysis}
branch={branch.name}
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { isBranch, sortBranches } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
+import { DEFAULT_NEW_CODE_DEFINITION_TYPE } from '../../../helpers/new-code-definition';
import { Branch, BranchLike, BranchWithNewCodePeriod } from '../../../types/branch-like';
-import { Component, NewCodePeriod } from '../../../types/types';
-import { DEFAULT_GENERAL_SETTING_TYPE } from '../constants';
+import { NewCodeDefinition } from '../../../types/new-code-definition';
+import { Component } from '../../../types/types';
import BranchBaselineSettingModal from './BranchBaselineSettingModal';
import BranchListRow from './BranchListRow';
interface Props {
branchList: Branch[];
component: Component;
- inheritedSetting: NewCodePeriod;
+ inheritedSetting: NewCodeDefinition;
+ generalSetting: NewCodeDefinition;
}
interface State {
if (!newCodePeriod) {
return b;
}
- const { type = DEFAULT_GENERAL_SETTING_TYPE, value, effectiveValue } = newCodePeriod;
+ const { type = DEFAULT_NEW_CODE_DEFINITION_TYPE, value, effectiveValue } = newCodePeriod;
return {
...b,
newCodePeriod: { type, value, effectiveValue },
);
}
- updateBranchNewCodePeriod = (branch: string, newSetting: NewCodePeriod | undefined) => {
+ updateBranchNewCodePeriod = (branch: string, newSetting: NewCodeDefinition | undefined) => {
const { branches } = this.state;
const updated = branches.find((b) => b.name === branch);
this.setState({ editedBranch: branch });
};
- closeEditModal = (branch?: string, newSetting?: NewCodePeriod) => {
+ closeEditModal = (branch?: string, newSetting?: NewCodeDefinition) => {
if (branch) {
this.setState({
branches: this.updateBranchNewCodePeriod(branch, newSetting),
};
render() {
- const { branchList, inheritedSetting } = this.props;
+ const { branchList, inheritedSetting, generalSetting } = this.props;
const { branches, editedBranch, loading } = this.state;
if (branches.length < 1) {
branchList={branchList}
component={this.props.component.key}
onClose={this.closeEditModal}
+ inheritedSetting={inheritedSetting}
+ generalSetting={generalSetting}
/>
)}
</>
import WarningIcon from '../../../components/icons/WarningIcon';
import DateTimeFormatter from '../../../components/intl/DateTimeFormatter';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { isNewCodeDefinitionCompliant } from '../../../helpers/periods';
+import { isNewCodeDefinitionCompliant } from '../../../helpers/new-code-definition';
import { BranchWithNewCodePeriod } from '../../../types/branch-like';
-import { NewCodePeriod, NewCodePeriodSettingType } from '../../../types/types';
+import { NewCodeDefinition, NewCodeDefinitionType } from '../../../types/new-code-definition';
export interface BranchListRowProps {
branch: BranchWithNewCodePeriod;
existingBranches: Array<string>;
- inheritedSetting: NewCodePeriod;
+ inheritedSetting: NewCodeDefinition;
onOpenEditModal: (branch: BranchWithNewCodePeriod) => void;
onResetToDefault: (branchName: string) => void;
}
-function renderNewCodePeriodSetting(newCodePeriod: NewCodePeriod) {
+function renderNewCodePeriodSetting(newCodePeriod: NewCodeDefinition) {
switch (newCodePeriod.type) {
- case NewCodePeriodSettingType.SPECIFIC_ANALYSIS:
+ case NewCodeDefinitionType.SpecificAnalysis:
return (
<>
{`${translate('baseline.specific_analysis')}: `}
)}
</>
);
- case NewCodePeriodSettingType.NUMBER_OF_DAYS:
+ case NewCodeDefinitionType.NumberOfDays:
return `${translate('new_code_definition.number_days')}: ${newCodePeriod.value}`;
- case NewCodePeriodSettingType.PREVIOUS_VERSION:
+ case NewCodeDefinitionType.PreviousVersion:
return translate('new_code_definition.previous_version');
- case NewCodePeriodSettingType.REFERENCE_BRANCH:
+ case NewCodeDefinitionType.ReferenceBranch:
return `${translate('baseline.reference_branch')}: ${newCodePeriod.value}`;
default:
return newCodePeriod.type;
function branchInheritsItselfAsReference(
branch: BranchWithNewCodePeriod,
- inheritedSetting: NewCodePeriod
+ inheritedSetting: NewCodeDefinition
) {
return (
!branch.newCodePeriod &&
- inheritedSetting.type === NewCodePeriodSettingType.REFERENCE_BRANCH &&
+ inheritedSetting.type === NewCodeDefinitionType.ReferenceBranch &&
branch.name === inheritedSetting.value
);
}
return (
branch.newCodePeriod &&
branch.newCodePeriod.value &&
- branch.newCodePeriod.type === NewCodePeriodSettingType.REFERENCE_BRANCH &&
+ branch.newCodePeriod.type === NewCodeDefinitionType.ReferenceBranch &&
!existingBranches.includes(branch.newCodePeriod.value)
);
}
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { isBranch, sortBranches } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
+import {
+ DEFAULT_NEW_CODE_DEFINITION_TYPE,
+ getNumberOfDaysDefaultValue,
+} from '../../../helpers/new-code-definition';
import { AppState } from '../../../types/appstate';
import { Branch, BranchLike } from '../../../types/branch-like';
import { Feature } from '../../../types/features';
+import { NewCodeDefinition, NewCodeDefinitionType } from '../../../types/new-code-definition';
import { ParsedAnalysis } from '../../../types/project-activity';
-import { Component, NewCodePeriod, NewCodePeriodSettingType } from '../../../types/types';
-import { DEFAULT_GENERAL_SETTING_TYPE } from '../constants';
+import { Component } from '../../../types/types';
import '../styles.css';
import { getSettingValue } from '../utils';
import AppHeader from './AppHeader';
interface State {
analysis?: string;
branchList: Branch[];
- currentSetting?: NewCodePeriodSettingType;
+ currentSetting?: NewCodeDefinitionType;
currentSettingValue?: string;
days: string;
- generalSetting?: NewCodePeriod;
+ generalSetting?: NewCodeDefinition;
loading: boolean;
overrideGeneralSetting?: boolean;
referenceBranch?: string;
saving: boolean;
- selected?: NewCodePeriodSettingType;
+ selected?: NewCodeDefinitionType;
success?: boolean;
}
-const DEFAULT_NUMBER_OF_DAYS = '30';
-
class ProjectBaselineApp extends React.PureComponent<Props, State> {
mounted = false;
state: State = {
branchList: [],
- days: DEFAULT_NUMBER_OF_DAYS,
+ days: getNumberOfDaysDefaultValue(),
loading: true,
saving: false,
};
}
getUpdatedState(params: {
- currentSetting?: NewCodePeriodSettingType;
+ currentSetting?: NewCodeDefinitionType;
currentSettingValue?: string;
- generalSetting: NewCodePeriod;
+ generalSetting: NewCodeDefinition;
}) {
const { currentSetting, currentSettingValue, generalSetting } = params;
const { referenceBranch } = this.state;
- const defaultDays =
- (generalSetting.type === NewCodePeriodSettingType.NUMBER_OF_DAYS && generalSetting.value) ||
- DEFAULT_NUMBER_OF_DAYS;
+ const defaultDays = getNumberOfDaysDefaultValue(generalSetting);
return {
loading: false,
selected: currentSetting || generalSetting.type,
overrideGeneralSetting: Boolean(currentSetting),
days:
- (currentSetting === NewCodePeriodSettingType.NUMBER_OF_DAYS && currentSettingValue) ||
+ (currentSetting === NewCodeDefinitionType.NumberOfDays && currentSettingValue) ||
defaultDays,
analysis:
- (currentSetting === NewCodePeriodSettingType.SPECIFIC_ANALYSIS && currentSettingValue) ||
- '',
+ (currentSetting === NewCodeDefinitionType.SpecificAnalysis && currentSettingValue) || '',
referenceBranch:
- (currentSetting === NewCodePeriodSettingType.REFERENCE_BRANCH && currentSettingValue) ||
+ (currentSetting === NewCodeDefinitionType.ReferenceBranch && currentSettingValue) ||
referenceBranch,
};
}
([generalSetting, setting]) => {
if (this.mounted) {
if (!generalSetting.type) {
- generalSetting = { type: DEFAULT_GENERAL_SETTING_TYPE };
+ generalSetting = { type: DEFAULT_NEW_CODE_DEFINITION_TYPE };
}
const currentSettingValue = setting.value;
const currentSetting = setting.inherited
? undefined
- : setting.type || DEFAULT_GENERAL_SETTING_TYPE;
+ : setting.type || DEFAULT_NEW_CODE_DEFINITION_TYPE;
this.setState(
this.getUpdatedState({
handleCancel = () =>
this.setState(
({
- generalSetting = { type: DEFAULT_GENERAL_SETTING_TYPE },
+ generalSetting = { type: DEFAULT_NEW_CODE_DEFINITION_TYPE },
currentSetting,
currentSettingValue,
}) => this.getUpdatedState({ generalSetting, currentSetting, currentSettingValue })
);
- handleSelectSetting = (selected?: NewCodePeriodSettingType) => this.setState({ selected });
+ handleSelectSetting = (selected?: NewCodeDefinitionType) => this.setState({ selected });
handleToggleSpecificSetting = (overrideGeneralSetting: boolean) =>
this.setState({ overrideGeneralSetting });
}
: generalSetting
}
+ generalSetting={generalSetting}
/>
</div>
)}
import { Alert } from '../../../components/ui/Alert';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { translate } from '../../../helpers/l10n';
-import { isNewCodeDefinitionCompliant } from '../../../helpers/periods';
+import { isNewCodeDefinitionCompliant } from '../../../helpers/new-code-definition';
import { Branch } from '../../../types/branch-like';
+import { NewCodeDefinition, NewCodeDefinitionType } from '../../../types/new-code-definition';
import { ParsedAnalysis } from '../../../types/project-activity';
-import { NewCodePeriod, NewCodePeriodSettingType } from '../../../types/types';
import { validateSetting } from '../utils';
import BaselineSettingAnalysis from './BaselineSettingAnalysis';
import BaselineSettingReferenceBranch from './BaselineSettingReferenceBranch';
branchesEnabled?: boolean;
canAdmin: boolean | undefined;
component: string;
- currentSetting?: NewCodePeriodSettingType;
+ currentSetting?: NewCodeDefinitionType;
currentSettingValue?: string;
days: string;
- generalSetting: NewCodePeriod;
+ generalSetting: NewCodeDefinition;
onCancel: () => void;
onSelectAnalysis: (analysis: ParsedAnalysis) => void;
onSelectDays: (value: string) => void;
onSelectReferenceBranch: (value: string) => void;
- onSelectSetting: (value?: NewCodePeriodSettingType) => void;
+ onSelectSetting: (value?: NewCodeDefinitionType) => void;
onSubmit: (e: React.SyntheticEvent<HTMLFormElement>) => void;
onToggleSpecificSetting: (selection: boolean) => void;
referenceBranch?: string;
saving: boolean;
- selected?: NewCodePeriodSettingType;
+ selected?: NewCodeDefinitionType;
overrideGeneralSetting: boolean;
}
<NewCodeDefinitionPreviousVersionOption
disabled={!overrideGeneralSetting}
onSelect={props.onSelectSetting}
- selected={
- overrideGeneralSetting && selected === NewCodePeriodSettingType.PREVIOUS_VERSION
- }
+ selected={overrideGeneralSetting && selected === NewCodeDefinitionType.PreviousVersion}
/>
<NewCodeDefinitionDaysOption
days={days}
isValid={isValid}
onChangeDays={props.onSelectDays}
onSelect={props.onSelectSetting}
- selected={
- overrideGeneralSetting && selected === NewCodePeriodSettingType.NUMBER_OF_DAYS
- }
+ selected={overrideGeneralSetting && selected === NewCodeDefinitionType.NumberOfDays}
/>
{branchesEnabled && (
<BaselineSettingReferenceBranch
onSelect={props.onSelectSetting}
referenceBranch={referenceBranch || ''}
selected={
- overrideGeneralSetting && selected === NewCodePeriodSettingType.REFERENCE_BRANCH
+ overrideGeneralSetting && selected === NewCodeDefinitionType.ReferenceBranch
}
settingLevel="project"
/>
)}
- {!branchesEnabled && currentSetting === NewCodePeriodSettingType.SPECIFIC_ANALYSIS && (
+ {!branchesEnabled && currentSetting === NewCodeDefinitionType.SpecificAnalysis && (
<BaselineSettingAnalysis
onSelect={() => {}}
selected={
- overrideGeneralSetting && selected === NewCodePeriodSettingType.SPECIFIC_ANALYSIS
+ overrideGeneralSetting && selected === NewCodeDefinitionType.SpecificAnalysis
}
/>
)}
</div>
{!branchesEnabled &&
overrideGeneralSetting &&
- selected === NewCodePeriodSettingType.SPECIFIC_ANALYSIS && (
+ selected === NewCodeDefinitionType.SpecificAnalysis && (
<BranchAnalysisList
analysis={analysis || ''}
branch={branch.name}
import { ProjectActivityServiceMock } from '../../../../api/mocks/ProjectActivityServiceMock';
import { mockBranch } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
-import { mockNewCodePeriodBranch } from '../../../../helpers/mocks/new-code-period';
+import { mockNewCodePeriodBranch } from '../../../../helpers/mocks/new-code-definition';
import { mockAppState } from '../../../../helpers/testMocks';
import {
RenderContext,
} from '../../../../helpers/testReactTestingUtils';
import { byRole, byText } from '../../../../helpers/testSelector';
import { Feature } from '../../../../types/features';
-import { NewCodePeriodSettingType } from '../../../../types/types';
+import { NewCodeDefinitionType } from '../../../../types/new-code-definition';
import routes from '../../routes';
jest.mock('../../../../api/newCodePeriod');
it('prevents selection of global setting if it is not compliant and warns non-admin about it', async () => {
codePeriodsMock.setNewCodePeriod({
- type: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ type: NewCodeDefinitionType.NumberOfDays,
value: '99',
inherited: true,
});
it('prevents selection of global setting if it is not compliant and warns admin about it', async () => {
codePeriodsMock.setNewCodePeriod({
- type: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ type: NewCodeDefinitionType.NumberOfDays,
value: '99',
inherited: true,
});
it('cannot set specific analysis setting', async () => {
const { ui } = getPageObjects();
codePeriodsMock.setNewCodePeriod({
- type: NewCodePeriodSettingType.SPECIFIC_ANALYSIS,
+ type: NewCodeDefinitionType.SpecificAnalysis,
value: 'analysis_id',
});
renderProjectBaselineApp();
codePeriodsMock.setListBranchesNewCode([
mockNewCodePeriodBranch({
branchKey: 'main',
- type: NewCodePeriodSettingType.SPECIFIC_ANALYSIS,
+ type: NewCodeDefinitionType.SpecificAnalysis,
value: 'analysis_id',
}),
]);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { NewCodePeriodSettingType } from '../../../../types/types';
+import { NewCodeDefinitionType } from '../../../../types/new-code-definition';
import { getSettingValue, validateSetting } from '../../utils';
describe('getSettingValue', () => {
};
it('should work for Days', () => {
- expect(getSettingValue({ ...state, type: NewCodePeriodSettingType.NUMBER_OF_DAYS })).toBe(
+ expect(getSettingValue({ ...state, type: NewCodeDefinitionType.NumberOfDays })).toBe(
state.days
);
});
it('should work for Analysis', () => {
- expect(getSettingValue({ ...state, type: NewCodePeriodSettingType.SPECIFIC_ANALYSIS })).toBe(
+ expect(getSettingValue({ ...state, type: NewCodeDefinitionType.SpecificAnalysis })).toBe(
state.analysis
);
});
it('should work for Previous version', () => {
expect(
- getSettingValue({ ...state, type: NewCodePeriodSettingType.PREVIOUS_VERSION })
+ getSettingValue({ ...state, type: NewCodeDefinitionType.PreviousVersion })
).toBeUndefined();
});
it('should work for Reference branch', () => {
- expect(getSettingValue({ ...state, type: NewCodePeriodSettingType.REFERENCE_BRANCH })).toBe(
+ expect(getSettingValue({ ...state, type: NewCodeDefinitionType.ReferenceBranch })).toBe(
state.referenceBranch
);
});
expect(validateSetting({ days: '' })).toEqual({ isChanged: false, isValid: false });
expect(
validateSetting({
- currentSetting: NewCodePeriodSettingType.PREVIOUS_VERSION,
+ currentSetting: NewCodeDefinitionType.PreviousVersion,
days: '12',
- selected: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ selected: NewCodeDefinitionType.NumberOfDays,
})
).toEqual({ isChanged: true, isValid: true });
expect(
validateSetting({
- currentSetting: NewCodePeriodSettingType.PREVIOUS_VERSION,
+ currentSetting: NewCodeDefinitionType.PreviousVersion,
days: 'nope',
- selected: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ selected: NewCodeDefinitionType.NumberOfDays,
})
).toEqual({ isChanged: true, isValid: false });
expect(
validateSetting({
- currentSetting: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ currentSetting: NewCodeDefinitionType.NumberOfDays,
currentSettingValue: '15',
days: '15',
- selected: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ selected: NewCodeDefinitionType.NumberOfDays,
})
).toEqual({ isChanged: false, isValid: true });
expect(
validateSetting({
- currentSetting: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ currentSetting: NewCodeDefinitionType.NumberOfDays,
currentSettingValue: '15',
days: '13',
- selected: NewCodePeriodSettingType.NUMBER_OF_DAYS,
+ selected: NewCodeDefinitionType.NumberOfDays,
})
).toEqual({ isChanged: true, isValid: true });
expect(
validateSetting({
analysis: 'analysis1',
- currentSetting: NewCodePeriodSettingType.SPECIFIC_ANALYSIS,
+ currentSetting: NewCodeDefinitionType.SpecificAnalysis,
currentSettingValue: 'analysis1',
days: '',
- selected: NewCodePeriodSettingType.SPECIFIC_ANALYSIS,
+ selected: NewCodeDefinitionType.SpecificAnalysis,
})
).toEqual({ isChanged: false, isValid: false });
expect(
validateSetting({
analysis: 'analysis2',
- currentSetting: NewCodePeriodSettingType.SPECIFIC_ANALYSIS,
+ currentSetting: NewCodeDefinitionType.SpecificAnalysis,
currentSettingValue: 'analysis1',
days: '',
- selected: NewCodePeriodSettingType.SPECIFIC_ANALYSIS,
+ selected: NewCodeDefinitionType.SpecificAnalysis,
})
).toEqual({ isChanged: true, isValid: false });
expect(
validateSetting({
- currentSetting: NewCodePeriodSettingType.REFERENCE_BRANCH,
+ currentSetting: NewCodeDefinitionType.ReferenceBranch,
currentSettingValue: 'master',
days: '',
referenceBranch: 'master',
- selected: NewCodePeriodSettingType.REFERENCE_BRANCH,
+ selected: NewCodeDefinitionType.ReferenceBranch,
})
).toEqual({ isChanged: false, isValid: true });
expect(
validateSetting({
- currentSetting: NewCodePeriodSettingType.REFERENCE_BRANCH,
+ currentSetting: NewCodeDefinitionType.ReferenceBranch,
currentSettingValue: 'master',
days: '',
referenceBranch: '',
- selected: NewCodePeriodSettingType.REFERENCE_BRANCH,
+ selected: NewCodeDefinitionType.ReferenceBranch,
})
).toEqual({ isChanged: true, isValid: false });
});
});
expect(
validateSetting({
- currentSetting: NewCodePeriodSettingType.PREVIOUS_VERSION,
+ currentSetting: NewCodeDefinitionType.PreviousVersion,
days: '',
overrideGeneralSetting: false,
})
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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 { NewCodePeriodSettingType } from '../../types/types';
-
-export const DEFAULT_GENERAL_SETTING_TYPE: NewCodePeriodSettingType =
- NewCodePeriodSettingType.PREVIOUS_VERSION;
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { isNewCodeDefinitionCompliant } from '../../helpers/periods';
-import { NewCodePeriodSettingType } from '../../types/types';
+import { isNewCodeDefinitionCompliant } from '../../helpers/new-code-definition';
+import { NewCodeDefinitionType } from '../../types/new-code-definition';
export function getSettingValue({
analysis,
analysis?: string;
days?: string;
referenceBranch?: string;
- type?: NewCodePeriodSettingType;
+ type?: NewCodeDefinitionType;
}) {
switch (type) {
- case NewCodePeriodSettingType.NUMBER_OF_DAYS:
+ case NewCodeDefinitionType.NumberOfDays:
return days;
- case NewCodePeriodSettingType.REFERENCE_BRANCH:
+ case NewCodeDefinitionType.ReferenceBranch:
return referenceBranch;
- case NewCodePeriodSettingType.SPECIFIC_ANALYSIS:
+ case NewCodeDefinitionType.SpecificAnalysis:
return analysis;
default:
return undefined;
export function validateSetting(state: {
analysis?: string;
- currentSetting?: NewCodePeriodSettingType;
+ currentSetting?: NewCodeDefinitionType;
currentSettingValue?: string;
days: string;
overrideGeneralSetting?: boolean;
referenceBranch?: string;
- selected?: NewCodePeriodSettingType;
+ selected?: NewCodeDefinitionType;
}) {
const {
analysis = '',
isChanged =
overrideGeneralSetting === false ||
selected !== currentSetting ||
- (selected === NewCodePeriodSettingType.NUMBER_OF_DAYS && days !== currentSettingValue) ||
- (selected === NewCodePeriodSettingType.SPECIFIC_ANALYSIS &&
- analysis !== currentSettingValue) ||
- (selected === NewCodePeriodSettingType.REFERENCE_BRANCH &&
+ (selected === NewCodeDefinitionType.NumberOfDays && days !== currentSettingValue) ||
+ (selected === NewCodeDefinitionType.SpecificAnalysis && analysis !== currentSettingValue) ||
+ (selected === NewCodeDefinitionType.ReferenceBranch &&
referenceBranch !== currentSettingValue);
}
type: selected,
value: days,
}) &&
- (selected !== NewCodePeriodSettingType.SPECIFIC_ANALYSIS || analysis.length > 0) &&
- (selected !== NewCodePeriodSettingType.REFERENCE_BRANCH || referenceBranch.length > 0));
+ (selected !== NewCodeDefinitionType.SpecificAnalysis || analysis.length > 0) &&
+ (selected !== NewCodeDefinitionType.ReferenceBranch || referenceBranch.length > 0));
return { isChanged, isValid };
}
import NewCodeDefinitionWarning from '../../../components/new-code-definition/NewCodeDefinitionWarning';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { translate } from '../../../helpers/l10n';
-import { isNewCodeDefinitionCompliant } from '../../../helpers/periods';
-import { NewCodePeriodSettingType } from '../../../types/types';
+import {
+ getNumberOfDaysDefaultValue,
+ isNewCodeDefinitionCompliant,
+} from '../../../helpers/new-code-definition';
+import { NewCodeDefinitionType } from '../../../types/new-code-definition';
interface State {
- currentSetting?: NewCodePeriodSettingType;
+ currentSetting?: NewCodeDefinitionType;
days: string;
loading: boolean;
currentSettingValue?: string;
saving: boolean;
- selected?: NewCodePeriodSettingType;
+ selected?: NewCodeDefinitionType;
success: boolean;
}
mounted = false;
state: State = {
loading: true,
- days: '30',
+ days: getNumberOfDaysDefaultValue(),
saving: false,
success: false,
};
.then(({ type, value }) => {
this.setState(({ days }) => ({
currentSetting: type,
- days: type === NewCodePeriodSettingType.NUMBER_OF_DAYS ? String(value) : days,
+ days: type === NewCodeDefinitionType.NumberOfDays ? String(value) : days,
loading: false,
currentSettingValue: value,
selected: type,
this.setState({ days, success: false });
};
- onSelectSetting = (selected: NewCodePeriodSettingType) => {
+ onSelectSetting = (selected: NewCodeDefinitionType) => {
this.setState({ selected, success: false });
};
this.setState(({ currentSetting, currentSettingValue, days }) => ({
selected: currentSetting,
days:
- currentSetting === NewCodePeriodSettingType.NUMBER_OF_DAYS
- ? String(currentSettingValue)
- : days,
+ currentSetting === NewCodeDefinitionType.NumberOfDays ? String(currentSettingValue) : days,
}));
};
const { days, selected } = this.state;
const type = selected;
- const value = type === NewCodePeriodSettingType.NUMBER_OF_DAYS ? days : undefined;
+ const value = type === NewCodeDefinitionType.NumberOfDays ? days : undefined;
this.setState({ saving: true, success: false });
setNewCodePeriod({
- type: type as NewCodePeriodSettingType,
+ type: type as NewCodeDefinitionType,
value,
}).then(
() => {
- this.setState({
- saving: false,
- currentSetting: type,
- currentSettingValue: value || undefined,
- success: true,
- });
+ if (this.mounted) {
+ this.setState({
+ saving: false,
+ currentSetting: type,
+ currentSettingValue: value || undefined,
+ success: true,
+ });
+ }
},
() => {
- this.setState({
- saving: false,
- });
+ if (this.mounted) {
+ this.setState({
+ saving: false,
+ });
+ }
}
);
};
const isChanged =
selected !== currentSetting ||
- (selected === NewCodePeriodSettingType.NUMBER_OF_DAYS &&
- String(days) !== currentSettingValue);
+ (selected === NewCodeDefinitionType.NumberOfDays && String(days) !== currentSettingValue);
const isValid =
- selected !== NewCodePeriodSettingType.NUMBER_OF_DAYS ||
- isNewCodeDefinitionCompliant({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: days });
+ selected !== NewCodeDefinitionType.NumberOfDays ||
+ isNewCodeDefinitionCompliant({ type: NewCodeDefinitionType.NumberOfDays, value: days });
return (
<>
<NewCodeDefinitionPreviousVersionOption
isDefault
onSelect={this.onSelectSetting}
- selected={selected === NewCodePeriodSettingType.PREVIOUS_VERSION}
+ selected={selected === NewCodeDefinitionType.PreviousVersion}
/>
<NewCodeDefinitionDaysOption
className="spacer-top sw-mb-4"
isValid={isValid}
onChangeDays={this.onSelectDays}
onSelect={this.onSelectSetting}
- selected={selected === NewCodePeriodSettingType.NUMBER_OF_DAYS}
+ selected={selected === NewCodeDefinitionType.NumberOfDays}
/>
<NewCodeDefinitionWarning
newCodeDefinitionType={currentSetting}
import NewCodePeriodsServiceMock from '../../../../api/mocks/NewCodePeriodsServiceMock';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import { byRole, byText } from '../../../../helpers/testSelector';
-import { NewCodePeriodSettingType } from '../../../../types/types';
+import { NewCodeDefinitionType } from '../../../../types/new-code-definition';
import NewCodePeriod from '../NewCodePeriod';
let newCodeMock: NewCodePeriodsServiceMock;
it('renders and behaves properly when the current value is not compliant', async () => {
const user = userEvent.setup();
- newCodeMock.setNewCodePeriod({ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '91' });
+ newCodeMock.setNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '91' });
renderNewCodePeriod();
expect(await ui.newCodeTitle.find()).toBeInTheDocument();
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { translate, translateWithParameters } from '../../helpers/l10n';
-import { NewCodePeriod, NewCodePeriodSettingType } from '../../types/types';
+import { NewCodeDefinition, NewCodeDefinitionType } from '../../types/new-code-definition';
import Link from '../common/Link';
import { Alert } from '../ui/Alert';
interface Props {
- globalNcd: NewCodePeriod;
+ globalNcd: NewCodeDefinition;
isGlobalNcdCompliant: boolean;
canAdmin?: boolean;
}
let setting: string;
let description: string;
let useCase: string;
- if (globalNcd.type === NewCodePeriodSettingType.NUMBER_OF_DAYS) {
+ if (globalNcd.type === NewCodeDefinitionType.NumberOfDays) {
setting = `${translate('new_code_definition.number_days')} (${translateWithParameters(
'duration.days',
globalNcd.value ?? '?'
*/
import * as React from 'react';
import { translate, translateWithParameters } from '../../helpers/l10n';
-import { MAX_NUMBER_OF_DAYS, MIN_NUMBER_OF_DAYS } from '../../helpers/periods';
-import { NewCodePeriodSettingType } from '../../types/types';
+import {
+ NUMBER_OF_DAYS_MAX_VALUE,
+ NUMBER_OF_DAYS_MIN_VALUE,
+} from '../../helpers/new-code-definition';
+import { NewCodeDefinitionType } from '../../types/new-code-definition';
import RadioCard from '../controls/RadioCard';
import ValidationInput, { ValidationInputErrorPlacement } from '../controls/ValidationInput';
import MandatoryFieldsExplanation from '../ui/MandatoryFieldsExplanation';
isChanged: boolean;
isValid: boolean;
onChangeDays: (value: string) => void;
- onSelect: (selection: NewCodePeriodSettingType) => void;
+ onSelect: (selection: NewCodeDefinitionType) => void;
selected: boolean;
}
noRadio
className={className}
disabled={disabled}
- onClick={() => onSelect(NewCodePeriodSettingType.NUMBER_OF_DAYS)}
+ onClick={() => onSelect(NewCodeDefinitionType.NumberOfDays)}
selected={selected}
title={translate('new_code_definition.number_days')}
>
errorPlacement={ValidationInputErrorPlacement.Bottom}
error={translateWithParameters(
'new_code_definition.number_days.invalid',
- MIN_NUMBER_OF_DAYS,
- MAX_NUMBER_OF_DAYS
+ NUMBER_OF_DAYS_MIN_VALUE,
+ NUMBER_OF_DAYS_MAX_VALUE
)}
label={translate('new_code_definition.number_days.specify_days')}
required
*/
import * as React from 'react';
import { translate } from '../../helpers/l10n';
-import { NewCodePeriodSettingType } from '../../types/types';
+import { NewCodeDefinitionType } from '../../types/new-code-definition';
import RadioCard from '../controls/RadioCard';
interface Props {
disabled?: boolean;
isDefault?: boolean;
- onSelect: (selection: NewCodePeriodSettingType) => void;
+ onSelect: (selection: NewCodeDefinitionType) => void;
selected: boolean;
}
<RadioCard
noRadio
disabled={disabled}
- onClick={() => onSelect(NewCodePeriodSettingType.PREVIOUS_VERSION)}
+ onClick={() => onSelect(NewCodeDefinitionType.PreviousVersion)}
selected={selected}
title={
translate('new_code_definition.previous_version') +
import { RadioButton } from 'design-system/lib';
import { noop } from 'lodash';
import * as React from 'react';
-import { useEffect } from 'react';
import { getNewCodePeriod } from '../../api/newCodePeriod';
import { translate } from '../../helpers/l10n';
-import { isNewCodeDefinitionCompliant } from '../../helpers/periods';
import {
- NewCodePeriod,
- NewCodePeriodSettingType,
- NewCodePeriodWithCompliance,
-} from '../../types/types';
+ getNumberOfDaysDefaultValue,
+ isNewCodeDefinitionCompliant,
+} from '../../helpers/new-code-definition';
+import {
+ NewCodeDefinition,
+ NewCodeDefinitionType,
+ NewCodeDefinitiondWithCompliance,
+} from '../../types/new-code-definition';
import RadioCard from '../controls/RadioCard';
import Tooltip from '../controls/Tooltip';
import { Alert } from '../ui/Alert';
interface Props {
canAdmin: boolean | undefined;
- onNcdChanged: (ncd: NewCodePeriodWithCompliance) => void;
+ onNcdChanged: (ncd: NewCodeDefinitiondWithCompliance) => void;
}
-const INITIAL_DAYS = '30';
-
export default function NewCodeDefinitionSelector(props: Props) {
const { canAdmin, onNcdChanged } = props;
- const [globalNcd, setGlobalNcd] = React.useState<NewCodePeriod | null>(null);
- const [selectedNcdType, setSelectedNcdType] = React.useState<NewCodePeriodSettingType | null>(
- null
- );
- const [days, setDays] = React.useState<string>(INITIAL_DAYS);
+ const [globalNcd, setGlobalNcd] = React.useState<NewCodeDefinition | null>(null);
+ const [selectedNcdType, setSelectedNcdType] = React.useState<NewCodeDefinitionType | null>(null);
+ const [days, setDays] = React.useState<string>('');
- const iGlobalNcdCompliant = React.useMemo(
+ const isGlobalNcdCompliant = React.useMemo(
() => Boolean(globalNcd && isNewCodeDefinitionCompliant(globalNcd)),
[globalNcd]
);
+ const initialNumberOfDays = React.useMemo(() => {
+ const numberOfDays = getNumberOfDaysDefaultValue(globalNcd);
+ setDays(numberOfDays);
+
+ return numberOfDays;
+ }, [globalNcd]);
+
const isChanged = React.useMemo(
- () => selectedNcdType === NewCodePeriodSettingType.NUMBER_OF_DAYS && days !== INITIAL_DAYS,
- [selectedNcdType, days]
+ () => selectedNcdType === NewCodeDefinitionType.NumberOfDays && days !== initialNumberOfDays,
+ [selectedNcdType, days, initialNumberOfDays]
);
const isCompliant = React.useMemo(
[selectedNcdType, days]
);
- useEffect(() => {
+ React.useEffect(() => {
function fetchGlobalNcd() {
getNewCodePeriod().then(setGlobalNcd, noop);
}
fetchGlobalNcd();
}, []);
- useEffect(() => {
+ React.useEffect(() => {
if (selectedNcdType) {
const type =
- selectedNcdType === NewCodePeriodSettingType.INHERITED ? undefined : selectedNcdType;
- const value = selectedNcdType === NewCodePeriodSettingType.NUMBER_OF_DAYS ? days : undefined;
+ selectedNcdType === NewCodeDefinitionType.Inherited ? undefined : selectedNcdType;
+ const value = selectedNcdType === NewCodeDefinitionType.NumberOfDays ? days : undefined;
onNcdChanged({ isCompliant, type, value });
}
}, [selectedNcdType, days, isCompliant, onNcdChanged]);
<div className="big-spacer-top spacer-bottom" role="radiogroup">
<RadioButton
aria-label={translate('new_code_definition.global_setting')}
- checked={selectedNcdType === NewCodePeriodSettingType.INHERITED}
+ checked={selectedNcdType === NewCodeDefinitionType.Inherited}
className="big-spacer-bottom"
- disabled={!iGlobalNcdCompliant}
- onCheck={() => setSelectedNcdType(NewCodePeriodSettingType.INHERITED)}
+ disabled={!isGlobalNcdCompliant}
+ onCheck={() => setSelectedNcdType(NewCodeDefinitionType.Inherited)}
value="general"
>
<Tooltip
overlay={
- iGlobalNcdCompliant
+ isGlobalNcdCompliant
? null
: translate('new_code_definition.compliance.warning.title.global')
}
{globalNcd && (
<GlobalNewCodeDefinitionDescription
globalNcd={globalNcd}
- isGlobalNcdCompliant={iGlobalNcdCompliant}
+ isGlobalNcdCompliant={isGlobalNcdCompliant}
canAdmin={canAdmin}
/>
)}
<RadioButton
aria-label={translate('new_code_definition.specific_setting')}
- checked={Boolean(
- selectedNcdType && selectedNcdType !== NewCodePeriodSettingType.INHERITED
- )}
+ checked={Boolean(selectedNcdType && selectedNcdType !== NewCodeDefinitionType.Inherited)}
className="huge-spacer-top"
- onCheck={() => setSelectedNcdType(NewCodePeriodSettingType.PREVIOUS_VERSION)}
+ onCheck={() => setSelectedNcdType(NewCodeDefinitionType.PreviousVersion)}
value="specific"
>
{translate('new_code_definition.specific_setting')}
<div className="display-flex-row big-spacer-bottom" role="radiogroup">
<NewCodeDefinitionPreviousVersionOption
disabled={Boolean(
- !selectedNcdType || selectedNcdType === NewCodePeriodSettingType.INHERITED
+ !selectedNcdType || selectedNcdType === NewCodeDefinitionType.Inherited
)}
onSelect={setSelectedNcdType}
- selected={selectedNcdType === NewCodePeriodSettingType.PREVIOUS_VERSION}
+ selected={selectedNcdType === NewCodeDefinitionType.PreviousVersion}
/>
<NewCodeDefinitionDaysOption
days={days}
disabled={Boolean(
- !selectedNcdType || selectedNcdType === NewCodePeriodSettingType.INHERITED
+ !selectedNcdType || selectedNcdType === NewCodeDefinitionType.Inherited
)}
isChanged={isChanged}
isValid={isCompliant}
onChangeDays={setDays}
onSelect={setSelectedNcdType}
- selected={selectedNcdType === NewCodePeriodSettingType.NUMBER_OF_DAYS}
+ selected={selectedNcdType === NewCodeDefinitionType.NumberOfDays}
/>
<RadioCard
noRadio
disabled={Boolean(
- !selectedNcdType || selectedNcdType === NewCodePeriodSettingType.INHERITED
+ !selectedNcdType || selectedNcdType === NewCodeDefinitionType.Inherited
)}
- onClick={() => setSelectedNcdType(NewCodePeriodSettingType.REFERENCE_BRANCH)}
- selected={selectedNcdType === NewCodePeriodSettingType.REFERENCE_BRANCH}
+ onClick={() => setSelectedNcdType(NewCodeDefinitionType.ReferenceBranch)}
+ selected={selectedNcdType === NewCodeDefinitionType.ReferenceBranch}
title={translate('new_code_definition.reference_branch')}
>
<div>
{translate('new_code_definition.reference_branch.description')}
</p>
<p className="sw-mb-4">{translate('new_code_definition.reference_branch.usecase')}</p>
- {selectedNcdType === NewCodePeriodSettingType.REFERENCE_BRANCH && (
+ {selectedNcdType === NewCodeDefinitionType.ReferenceBranch && (
<Alert variant="info">
{translate('new_code_definition.reference_branch.notice')}
</Alert>
import * as React from 'react';
import { translate } from '../../helpers/l10n';
-import { isNewCodeDefinitionCompliant } from '../../helpers/periods';
-import { NewCodePeriodSettingType } from '../../types/types';
+import { isNewCodeDefinitionCompliant } from '../../helpers/new-code-definition';
+import { NewCodeDefinitionType } from '../../types/new-code-definition';
import DocLink from '../common/DocLink';
import { Alert } from '../ui/Alert';
export interface NewCodeDefinitionWarningProps {
- newCodeDefinitionType: NewCodePeriodSettingType | undefined;
+ newCodeDefinitionType: NewCodeDefinitionType | undefined;
newCodeDefinitionValue: string | undefined;
isBranchSupportEnabled: boolean | undefined;
level: 'branch' | 'project' | 'global';
return null;
}
- if (newCodeDefinitionType === NewCodePeriodSettingType.SPECIFIC_ANALYSIS) {
+ if (newCodeDefinitionType === NewCodeDefinitionType.SpecificAnalysis) {
return (
<Alert variant="warning" className="sw-mb-4 sw-max-w-[800px]">
<p className="sw-mb-2 sw-font-bold">
);
}
- if (newCodeDefinitionType === NewCodePeriodSettingType.NUMBER_OF_DAYS) {
+ if (newCodeDefinitionType === NewCodeDefinitionType.NumberOfDays) {
return (
<Alert variant="warning" className="sw-mb-4 sw-max-w-[800px]">
<p className="sw-mb-2 sw-font-bold">
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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 { NewCodeDefinition, NewCodeDefinitionType } from '../../types/new-code-definition';
+import { mockNewCodePeriod } from '../mocks/new-code-definition';
+import {
+ NUMBER_OF_DAYS_DEFAULT_VALUE,
+ getNumberOfDaysDefaultValue,
+ isNewCodeDefinitionCompliant,
+} from '../new-code-definition';
+
+describe('isNewCodeDefinitionCompliant', () => {
+ it.each([
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '0' }), false],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '15' }), true],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '15.' }), false],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '15.0' }), false],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '15.3' }), false],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '91' }), false],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.PreviousVersion }), true],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.ReferenceBranch }), true],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.SpecificAnalysis }), false],
+ ])(
+ 'should test for new code definition compliance properly %s',
+ (newCodePeriod: NewCodeDefinition, result: boolean) => {
+ expect(isNewCodeDefinitionCompliant(newCodePeriod)).toEqual(result);
+ }
+ );
+});
+
+describe('getNumberOfDaysDefaultValue', () => {
+ it.each([
+ [null, null, NUMBER_OF_DAYS_DEFAULT_VALUE.toString()],
+ [
+ mockNewCodePeriod({ type: NewCodeDefinitionType.PreviousVersion }),
+ null,
+ NUMBER_OF_DAYS_DEFAULT_VALUE.toString(),
+ ],
+ [
+ null,
+ mockNewCodePeriod({ type: NewCodeDefinitionType.PreviousVersion }),
+ NUMBER_OF_DAYS_DEFAULT_VALUE.toString(),
+ ],
+ [
+ mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '91' }),
+ null,
+ NUMBER_OF_DAYS_DEFAULT_VALUE.toString(),
+ ],
+ [
+ null,
+ mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '91' }),
+ NUMBER_OF_DAYS_DEFAULT_VALUE.toString(),
+ ],
+ [mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '90' }), null, '90'],
+ [null, mockNewCodePeriod({ type: NewCodeDefinitionType.NumberOfDays, value: '90' }), '90'],
+ ])(
+ 'should return the defaut number of days vale properly %s',
+ (
+ globalNewCodeDefinition: NewCodeDefinition | null,
+ inheritedNewCodeDefinition: NewCodeDefinition | null,
+ result: string
+ ) => {
+ expect(
+ getNumberOfDaysDefaultValue(globalNewCodeDefinition, inheritedNewCodeDefinition)
+ ).toEqual(result);
+ }
+ );
+});
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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 { NewCodeDefinitionType } from '../../types/new-code-definition';
+import { getNewCodePeriodLabel } from '../new-code-period';
+import { mockPeriod } from '../testMocks';
+
+const formatter = jest.fn((v) => v);
+
+beforeEach(() => {
+ formatter.mockClear();
+});
+
+describe('getPeriodLabel', () => {
+ it('should handle missing value', () => {
+ expect(getNewCodePeriodLabel(undefined, formatter)).toBeUndefined();
+ });
+
+ it('should handle date', () => {
+ expect(getNewCodePeriodLabel(mockPeriod({ mode: 'date' }), formatter)).toBe(
+ 'overview.period.date.'
+ );
+ expect(
+ getNewCodePeriodLabel(
+ mockPeriod({ mode: 'date', parameter: '2019-02-21T01:11:21+0100' }),
+ formatter
+ )
+ ).toBe('overview.period.date.2019-02-21T01:11:21+0100');
+ expect(formatter).toHaveBeenCalledTimes(1);
+ });
+
+ it('should handle days', () => {
+ expect(getNewCodePeriodLabel(mockPeriod({ mode: 'days', modeParam: '12' }), formatter)).toBe(
+ 'overview.period.days.12'
+ );
+ expect(formatter).not.toHaveBeenCalled();
+ });
+
+ it('should handle previous analysis', () => {
+ expect(
+ getNewCodePeriodLabel(
+ mockPeriod({ mode: 'previous_analysis', parameter: 'param' }),
+ formatter
+ )
+ ).toBe('overview.period.previous_analysis.param');
+ expect(formatter).not.toHaveBeenCalled();
+ });
+
+ it('should handle previous version', () => {
+ expect(getNewCodePeriodLabel(mockPeriod({ mode: 'previous_version' }), formatter)).toBe(
+ 'overview.period.previous_version_only_date'
+ );
+ expect(
+ getNewCodePeriodLabel(mockPeriod({ mode: 'previous_version', parameter: '7.9' }), formatter)
+ ).toBe('overview.period.previous_version.7.9');
+ expect(formatter).not.toHaveBeenCalled();
+ });
+
+ it('should handle version', () => {
+ expect(
+ getNewCodePeriodLabel(mockPeriod({ mode: 'version', modeParam: '7.2' }), formatter)
+ ).toBe('overview.period.version.7.2');
+ expect(
+ getNewCodePeriodLabel(mockPeriod({ mode: 'previous_version', parameter: '7.9' }), formatter)
+ ).toBe('overview.period.previous_version.7.9');
+ expect(formatter).not.toHaveBeenCalled();
+ });
+
+ it('should handle manual baseline', () => {
+ expect(
+ getNewCodePeriodLabel(
+ mockPeriod({ mode: 'manual_baseline', modeParam: 'A658678DE' }),
+ formatter
+ )
+ ).toBe('overview.period.manual_baseline.A658678DE');
+ expect(getNewCodePeriodLabel(mockPeriod({ mode: 'manual_baseline' }), formatter)).toBe(
+ 'overview.period.manual_baseline.2019-04-23T02:12:32+0100'
+ );
+ expect(formatter).toHaveBeenCalledTimes(1);
+ });
+
+ it('should handle SPECIFIC_ANALYSIS', () => {
+ expect(
+ getNewCodePeriodLabel(
+ mockPeriod({ mode: NewCodeDefinitionType.SpecificAnalysis, parameter: '7.1' }),
+ formatter
+ )
+ ).toBe('overview.period.specific_analysis.2019-04-23T02:12:32+0100');
+ expect(
+ getNewCodePeriodLabel(mockPeriod({ mode: NewCodeDefinitionType.SpecificAnalysis }), formatter)
+ ).toBe('overview.period.specific_analysis.2019-04-23T02:12:32+0100');
+ expect(formatter).toHaveBeenCalledTimes(2);
+ });
+
+ it('should handle PREVIOUS_VERSION', () => {
+ expect(
+ getNewCodePeriodLabel(
+ mockPeriod({ mode: NewCodeDefinitionType.PreviousVersion, modeParam: 'A658678DE' }),
+ formatter
+ )
+ ).toBe('overview.period.previous_version.A658678DE');
+ expect(
+ getNewCodePeriodLabel(mockPeriod({ mode: NewCodeDefinitionType.PreviousVersion }), formatter)
+ ).toBe('overview.period.previous_version.2019-04-23T02:12:32+0100');
+ expect(formatter).toHaveBeenCalledTimes(1);
+ });
+});
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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 { NewCodePeriod, NewCodePeriodSettingType } from '../../types/types';
-import { getPeriodLabel, isNewCodeDefinitionCompliant } from '../periods';
-import { mockPeriod } from '../testMocks';
-
-const formatter = jest.fn((v) => v);
-
-beforeEach(() => {
- formatter.mockClear();
-});
-
-describe('getPeriodLabel', () => {
- it('should handle missing value', () => {
- expect(getPeriodLabel(undefined, formatter)).toBeUndefined();
- });
-
- it('should handle date', () => {
- expect(getPeriodLabel(mockPeriod({ mode: 'date' }), formatter)).toBe('overview.period.date.');
- expect(
- getPeriodLabel(mockPeriod({ mode: 'date', parameter: '2019-02-21T01:11:21+0100' }), formatter)
- ).toBe('overview.period.date.2019-02-21T01:11:21+0100');
- expect(formatter).toHaveBeenCalledTimes(1);
- });
-
- it('should handle days', () => {
- expect(getPeriodLabel(mockPeriod({ mode: 'days', modeParam: '12' }), formatter)).toBe(
- 'overview.period.days.12'
- );
- expect(formatter).not.toHaveBeenCalled();
- });
-
- it('should handle previous analysis', () => {
- expect(
- getPeriodLabel(mockPeriod({ mode: 'previous_analysis', parameter: 'param' }), formatter)
- ).toBe('overview.period.previous_analysis.param');
- expect(formatter).not.toHaveBeenCalled();
- });
-
- it('should handle previous version', () => {
- expect(getPeriodLabel(mockPeriod({ mode: 'previous_version' }), formatter)).toBe(
- 'overview.period.previous_version_only_date'
- );
- expect(
- getPeriodLabel(mockPeriod({ mode: 'previous_version', parameter: '7.9' }), formatter)
- ).toBe('overview.period.previous_version.7.9');
- expect(formatter).not.toHaveBeenCalled();
- });
-
- it('should handle version', () => {
- expect(getPeriodLabel(mockPeriod({ mode: 'version', modeParam: '7.2' }), formatter)).toBe(
- 'overview.period.version.7.2'
- );
- expect(
- getPeriodLabel(mockPeriod({ mode: 'previous_version', parameter: '7.9' }), formatter)
- ).toBe('overview.period.previous_version.7.9');
- expect(formatter).not.toHaveBeenCalled();
- });
-
- it('should handle manual baseline', () => {
- expect(
- getPeriodLabel(mockPeriod({ mode: 'manual_baseline', modeParam: 'A658678DE' }), formatter)
- ).toBe('overview.period.manual_baseline.A658678DE');
- expect(getPeriodLabel(mockPeriod({ mode: 'manual_baseline' }), formatter)).toBe(
- 'overview.period.manual_baseline.2019-04-23T02:12:32+0100'
- );
- expect(formatter).toHaveBeenCalledTimes(1);
- });
-
- it('should handle SPECIFIC_ANALYSIS', () => {
- expect(
- getPeriodLabel(
- mockPeriod({ mode: NewCodePeriodSettingType.SPECIFIC_ANALYSIS, parameter: '7.1' }),
- formatter
- )
- ).toBe('overview.period.specific_analysis.2019-04-23T02:12:32+0100');
- expect(
- getPeriodLabel(mockPeriod({ mode: NewCodePeriodSettingType.SPECIFIC_ANALYSIS }), formatter)
- ).toBe('overview.period.specific_analysis.2019-04-23T02:12:32+0100');
- expect(formatter).toHaveBeenCalledTimes(2);
- });
-
- it('should handle PREVIOUS_VERSION', () => {
- expect(
- getPeriodLabel(
- mockPeriod({ mode: NewCodePeriodSettingType.PREVIOUS_VERSION, modeParam: 'A658678DE' }),
- formatter
- )
- ).toBe('overview.period.previous_version.A658678DE');
- expect(
- getPeriodLabel(mockPeriod({ mode: NewCodePeriodSettingType.PREVIOUS_VERSION }), formatter)
- ).toBe('overview.period.previous_version.2019-04-23T02:12:32+0100');
- expect(formatter).toHaveBeenCalledTimes(1);
- });
-});
-
-describe('isNewCodeDefinitionCompliant', () => {
- it.each([
- [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '0' }, false],
- [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '15' }, true],
- [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '15.' }, false],
- [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '15.0' }, false],
- [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '15.3' }, false],
- [{ type: NewCodePeriodSettingType.NUMBER_OF_DAYS, value: '91' }, false],
- [{ type: NewCodePeriodSettingType.PREVIOUS_VERSION }, true],
- [{ type: NewCodePeriodSettingType.REFERENCE_BRANCH }, true],
- [{ type: NewCodePeriodSettingType.SPECIFIC_ANALYSIS }, false],
- ])(
- 'should test for new code definition compliance properly %s',
- (newCodePeriod: NewCodePeriod, result: boolean) => {
- expect(isNewCodeDefinitionCompliant(newCodePeriod)).toEqual(result);
- }
- );
-});
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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 {
+ NewCodeDefinition,
+ NewCodeDefinitionBranch,
+ NewCodeDefinitionType,
+} from '../../types/new-code-definition';
+
+export function mockNewCodePeriod(overrides: Partial<NewCodeDefinition> = {}): NewCodeDefinition {
+ return {
+ type: NewCodeDefinitionType.PreviousVersion,
+ ...overrides,
+ };
+}
+
+export function mockNewCodePeriodBranch(
+ overrides: Partial<NewCodeDefinitionBranch> = {}
+): NewCodeDefinitionBranch {
+ return {
+ projectKey: 'pkey',
+ branchKey: 'bKey',
+ ...mockNewCodePeriod(),
+ ...overrides,
+ };
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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 { NewCodePeriod, NewCodePeriodBranch, NewCodePeriodSettingType } from '../../types/types';
-
-export function mockNewCodePeriod(overrides: Partial<NewCodePeriod> = {}) {
- return {
- type: NewCodePeriodSettingType.PREVIOUS_VERSION,
- ...overrides,
- };
-}
-
-export function mockNewCodePeriodBranch(overrides: Partial<NewCodePeriodBranch> = {}) {
- return {
- projectKey: 'pkey',
- branchKey: 'bKey',
- ...mockNewCodePeriod(),
- ...overrides,
- };
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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 { NewCodeDefinition, NewCodeDefinitionType } from '../types/new-code-definition';
+
+export const DEFAULT_NEW_CODE_DEFINITION_TYPE: NewCodeDefinitionType =
+ NewCodeDefinitionType.PreviousVersion;
+export const NUMBER_OF_DAYS_MIN_VALUE = 1;
+export const NUMBER_OF_DAYS_MAX_VALUE = 90;
+export const NUMBER_OF_DAYS_DEFAULT_VALUE = 30;
+
+export function isNewCodeDefinitionCompliant(newCodePeriod: NewCodeDefinition) {
+ switch (newCodePeriod.type) {
+ case NewCodeDefinitionType.NumberOfDays:
+ if (!newCodePeriod.value) {
+ return false;
+ }
+ return (
+ !/\D/.test(newCodePeriod.value) &&
+ Number.isInteger(+newCodePeriod.value) &&
+ NUMBER_OF_DAYS_MIN_VALUE <= +newCodePeriod.value &&
+ +newCodePeriod.value <= NUMBER_OF_DAYS_MAX_VALUE
+ );
+ case NewCodeDefinitionType.SpecificAnalysis:
+ return false;
+ default:
+ return true;
+ }
+}
+
+export function getNumberOfDaysDefaultValue(
+ globalNewCodeDefinition?: NewCodeDefinition | null,
+ inheritedNewCodeDefinition?: NewCodeDefinition | null
+) {
+ if (
+ inheritedNewCodeDefinition &&
+ isNewCodeDefinitionCompliant(inheritedNewCodeDefinition) &&
+ inheritedNewCodeDefinition.type === NewCodeDefinitionType.NumberOfDays &&
+ inheritedNewCodeDefinition.value
+ ) {
+ return inheritedNewCodeDefinition.value;
+ }
+
+ if (
+ globalNewCodeDefinition &&
+ isNewCodeDefinitionCompliant(globalNewCodeDefinition) &&
+ globalNewCodeDefinition.type === NewCodeDefinitionType.NumberOfDays &&
+ globalNewCodeDefinition.value
+ ) {
+ return globalNewCodeDefinition.value;
+ }
+
+ return NUMBER_OF_DAYS_DEFAULT_VALUE.toString();
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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 { ApplicationPeriod } from '../types/application';
+import { NewCodeDefinitionType } from '../types/new-code-definition';
+import { Period } from '../types/types';
+import { parseDate } from './dates';
+import { translate, translateWithParameters } from './l10n';
+
+export function getNewCodePeriodDate(period?: { date?: string }): Date | undefined {
+ return period?.date ? parseDate(period.date) : undefined;
+}
+
+export function getNewCodePeriodLabel(
+ period: Period | undefined,
+ dateFormatter: (date: string) => string
+) {
+ if (!period) {
+ return undefined;
+ }
+
+ let parameter = period.modeParam || period.parameter || '';
+
+ switch (period.mode) {
+ case NewCodeDefinitionType.SpecificAnalysis:
+ parameter = dateFormatter(period.date);
+ break;
+ case NewCodeDefinitionType.PreviousVersion:
+ parameter = parameter || dateFormatter(period.date);
+ break;
+ /*
+ * Handle legacy period modes, that predate MMF-1579
+ */
+ case 'previous_version':
+ if (!parameter) {
+ return translate('overview.period.previous_version_only_date');
+ }
+ break;
+ case 'date':
+ parameter = parameter && dateFormatter(parameter);
+ break;
+ case 'manual_baseline':
+ parameter = parameter || dateFormatter(period.date);
+ break;
+ default: // No change in the parameter
+ }
+
+ return translateWithParameters(`overview.period.${period.mode.toLowerCase()}`, parameter);
+}
+
+export function isApplicationNewCodePeriod(
+ period: Period | ApplicationPeriod
+): period is ApplicationPeriod {
+ return (period as ApplicationPeriod).project !== undefined;
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 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 { parseDate } from '../helpers/dates';
-import { translate, translateWithParameters } from '../helpers/l10n';
-import { ApplicationPeriod } from '../types/application';
-import { NewCodePeriod, NewCodePeriodSettingType, Period } from '../types/types';
-
-export function getPeriodLabel(
- period: Period | undefined,
- dateFormatter: (date: string) => string
-) {
- if (!period) {
- return undefined;
- }
-
- let parameter = period.modeParam || period.parameter || '';
-
- switch (period.mode) {
- case NewCodePeriodSettingType.SPECIFIC_ANALYSIS:
- parameter = dateFormatter(period.date);
- break;
- case NewCodePeriodSettingType.PREVIOUS_VERSION:
- parameter = parameter || dateFormatter(period.date);
- break;
- /*
- * Handle legacy period modes, that predate MMF-1579
- */
- case 'previous_version':
- if (!parameter) {
- return translate('overview.period.previous_version_only_date');
- }
- break;
- case 'date':
- parameter = parameter && dateFormatter(parameter);
- break;
- case 'manual_baseline':
- parameter = parameter || dateFormatter(period.date);
- break;
- default: // No change in the parameter
- }
-
- return translateWithParameters(`overview.period.${period.mode.toLowerCase()}`, parameter);
-}
-
-export function getPeriodDate(period?: { date?: string }): Date | undefined {
- return period && period.date ? parseDate(period.date) : undefined;
-}
-
-export function isApplicationPeriod(
- period: Period | ApplicationPeriod
-): period is ApplicationPeriod {
- return (period as ApplicationPeriod).project !== undefined;
-}
-
-export const MIN_NUMBER_OF_DAYS = 1;
-export const MAX_NUMBER_OF_DAYS = 90;
-
-export function isNewCodeDefinitionCompliant(newCodePeriod: NewCodePeriod) {
- switch (newCodePeriod.type) {
- case NewCodePeriodSettingType.NUMBER_OF_DAYS:
- if (!newCodePeriod.value) {
- return false;
- }
- return (
- !/\D/.test(newCodePeriod.value) &&
- Number.isInteger(+newCodePeriod.value) &&
- MIN_NUMBER_OF_DAYS <= +newCodePeriod.value &&
- +newCodePeriod.value <= MAX_NUMBER_OF_DAYS
- );
- case NewCodePeriodSettingType.SPECIFIC_ANALYSIS:
- return false;
- default:
- return true;
- }
-}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { NewCodeDefinition } from './new-code-definition';
import { QualityGateStatusCondition } from './quality-gates';
-import { NewCodePeriod, Status } from './types';
+import { Status } from './types';
export interface Branch {
analysisDate?: string;
export type BranchParameters = { branch?: string } | { pullRequest?: string };
export interface BranchWithNewCodePeriod extends Branch {
- newCodePeriod?: NewCodePeriod;
+ newCodePeriod?: NewCodeDefinition;
}
export interface BranchStatusData {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.
+ */
+
+export enum NewCodeDefinitionType {
+ PreviousVersion = 'PREVIOUS_VERSION',
+ NumberOfDays = 'NUMBER_OF_DAYS',
+ SpecificAnalysis = 'SPECIFIC_ANALYSIS',
+ ReferenceBranch = 'REFERENCE_BRANCH',
+ Inherited = 'INHERITED',
+}
+
+export interface NewCodeDefinition {
+ type: NewCodeDefinitionType;
+ value?: string;
+ effectiveValue?: string;
+ inherited?: boolean;
+}
+
+export interface NewCodeDefinitiondWithCompliance {
+ type?: NewCodeDefinitionType;
+ value?: string;
+ isCompliant: boolean;
+}
+
+export interface NewCodeDefinitionBranch extends NewCodeDefinition {
+ projectKey: string;
+ branchKey: string;
+}
import { RuleDescriptionSection } from '../apps/coding-rules/rule';
import { ComponentQualifier, Visibility } from './component';
import { MessageFormatting } from './issues';
+import { NewCodeDefinitionType } from './new-code-definition';
import { UserActive, UserBase } from './users';
export type Dict<T> = { [key: string]: T };
qualityGate?: string;
}
-export interface NewCodePeriod {
- type: NewCodePeriodSettingType;
- value?: string;
- effectiveValue?: string;
- inherited?: boolean;
-}
-
-export interface NewCodePeriodWithCompliance {
- type?: NewCodePeriodSettingType;
- value?: string;
- isCompliant: boolean;
-}
-
-export interface NewCodePeriodBranch extends NewCodePeriod {
- projectKey: string;
- branchKey: string;
-}
-
-export enum NewCodePeriodSettingType {
- PREVIOUS_VERSION = 'PREVIOUS_VERSION',
- NUMBER_OF_DAYS = 'NUMBER_OF_DAYS',
- SPECIFIC_ANALYSIS = 'SPECIFIC_ANALYSIS',
- REFERENCE_BRANCH = 'REFERENCE_BRANCH',
- INHERITED = 'INHERITED',
-}
-
export interface Paging {
pageIndex: number;
pageSize: number;
export interface Period {
date: string;
index?: number;
- mode: PeriodMode | NewCodePeriodSettingType;
+ mode: PeriodMode | NewCodeDefinitionType;
modeParam?: string;
parameter?: string;
}