return Promise.resolve(this.branchLikes);
};
+ emptyBranches = () => {
+ this.branchLikes = [];
+ };
+
+ addBranch = (branch: BranchLike) => {
+ this.branchLikes.push(branch);
+ };
+
resetBranches = () => {
this.branchLikes = cloneDeep(this.defaultBranchLikes);
};
import { getBranches } from '../../../../../../api/branches';
import { getRegulatoryReportUrl } from '../../../../../../api/regulatory-report';
import DocLink from '../../../../../../components/common/DocLink';
-import { ButtonLink } from '../../../../../../components/controls/buttons';
import Select, { LabelValueSelectOption } from '../../../../../../components/controls/Select';
+import { ButtonLink } from '../../../../../../components/controls/buttons';
import { Alert } from '../../../../../../components/ui/Alert';
import {
getBranchLikeDisplayName,
- isBranch,
+ getBranchLikeKey,
isMainBranch,
} from '../../../../../../helpers/branch-like';
import { translate } from '../../../../../../helpers/l10n';
interface State {
downloadStarted: boolean;
selectedBranch: string;
- branchLikesOptions: LabelValueSelectOption[];
+ branchOptions: LabelValueSelectOption[];
}
export default class RegulatoryReport extends React.PureComponent<Props, State> {
this.state = {
downloadStarted: false,
selectedBranch: '',
- branchLikesOptions: [],
+ branchOptions: [],
};
}
const { component, branchLike } = this.props;
getBranches(component.key)
.then((data) => {
- const mainBranch = data.find(isMainBranch);
+ const availableBranches = data.filter(
+ (br) => br.analysisDate && (isMainBranch(br) || br.excludedFromPurge)
+ );
+ const mainBranch = availableBranches.find(isMainBranch);
const otherBranchSorted = orderBy(
- data.filter(isBranch).filter((b) => !isMainBranch(b)),
+ availableBranches.filter((b) => !isMainBranch(b)),
(b) => b.name
);
const sortedBranch = mainBranch ? [mainBranch, ...otherBranchSorted] : otherBranchSorted;
- const options = sortedBranch
- .filter((br) => br.excludedFromPurge)
- .map((br) => {
- return {
- value: getBranchLikeDisplayName(br),
- label: getBranchLikeDisplayName(br),
- };
- });
+ const options = sortedBranch.map((br) => {
+ return {
+ value: getBranchLikeDisplayName(br),
+ label: getBranchLikeDisplayName(br),
+ };
+ });
let selectedBranch = '';
- if (branchLike && isBranch(branchLike) && branchLike.excludedFromPurge) {
+ if (
+ branchLike &&
+ availableBranches.find((br) => getBranchLikeKey(br) === getBranchLikeKey(branchLike))
+ ) {
selectedBranch = getBranchLikeDisplayName(branchLike);
} else if (mainBranch) {
selectedBranch = getBranchLikeDisplayName(mainBranch);
}
- this.setState({ selectedBranch, branchLikesOptions: options });
+ this.setState({ selectedBranch, branchOptions: options });
})
.catch(() => {
- this.setState({ branchLikesOptions: [] });
+ this.setState({ branchOptions: [] });
});
}
render() {
const { component, onClose } = this.props;
- const { downloadStarted, selectedBranch, branchLikesOptions } = this.state;
+ const { downloadStarted, selectedBranch, branchOptions } = this.state;
+ const isDownloadButtonDisabled = downloadStarted || !selectedBranch;
return (
<>
</ul>
</div>
<p>{translate('regulatory_report.description2')}</p>
- <div className="modal-field big-spacer-top">
- <label htmlFor="regulatory-report-branch-select">
- {translate('regulatory_page.select_branch')}
- </label>
- <Select
- className="width-100"
- inputId="regulatory-report-branch-select"
- id="regulatory-report-branch-select-input"
- onChange={this.onBranchSelect}
- options={branchLikesOptions}
- value={branchLikesOptions.find((o) => o.value === selectedBranch)}
- />
- </div>
- <Alert variant="info">
- <div>
- {translate('regulatory_page.available_branches_info.only_keep_when_inactive')}
- </div>
- <div>
- <FormattedMessage
- id="regulatory_page.available_branches_info.more_info"
- defaultMessage={translate('regulatory_page.available_branches_info.more_info')}
- values={{
- doc_link: (
- <DocLink to="/analyzing-source-code/branches/branch-analysis/#inactive-branches">
- {translate('regulatory_page.available_branches_info.more_info.doc_link')}
- </DocLink>
- ),
- }}
- />
+ {branchOptions.length > 0 ? (
+ <>
+ <div className="modal-field big-spacer-top">
+ <label htmlFor="regulatory-report-branch-select">
+ {translate('regulatory_page.select_branch')}
+ </label>
+ <Select
+ className="width-100"
+ inputId="regulatory-report-branch-select"
+ id="regulatory-report-branch-select-input"
+ onChange={this.onBranchSelect}
+ options={branchOptions}
+ value={branchOptions.find((o) => o.value === selectedBranch)}
+ />
+ </div>
+ <Alert variant="info">
+ <div>
+ {translate('regulatory_page.available_branches_info.only_keep_when_inactive')}
+ </div>
+ <div>
+ <FormattedMessage
+ id="regulatory_page.available_branches_info.more_info"
+ defaultMessage={translate('regulatory_page.available_branches_info.more_info')}
+ values={{
+ doc_link: (
+ <DocLink to="/analyzing-source-code/branches/branch-analysis/#inactive-branches">
+ {translate('regulatory_page.available_branches_info.more_info.doc_link')}
+ </DocLink>
+ ),
+ }}
+ />
+ </div>
+ </Alert>
+ </>
+ ) : (
+ <div className="big-spacer-top">
+ <Alert variant="warning">
+ <div>{translate('regulatory_page.no_available_branch')}</div>
+ </Alert>
</div>
- </Alert>
+ )}
<div className="modal-field big-spacer-top">
{downloadStarted && (
<div>
<div className="modal-foot">
<a
className={classNames('button button-primary big-spacer-right', {
- disabled: downloadStarted,
+ disabled: isDownloadButtonDisabled,
})}
download={[component.name, selectedBranch, 'regulatory report.zip']
.filter((s) => !!s)
href={getRegulatoryReportUrl(component.key, selectedBranch)}
target="_blank"
rel="noopener noreferrer"
+ aria-disabled={isDownloadButtonDisabled}
>
{translate('download_verb')}
</a>
import userEvent from '@testing-library/user-event';
import * as React from 'react';
import BranchesServiceMock from '../../../../../../../api/mocks/BranchesServiceMock';
+import { mockBranch, mockMainBranch } from '../../../../../../../helpers/mocks/branch-like';
import { renderComponent } from '../../../../../../../helpers/testReactTestingUtils';
+import { BranchLike } from '../../../../../../../types/branch-like';
import RegulatoryReport from '../RegulatoryReport';
jest.mock('../../../../../../../api/branches');
afterEach(() => handler.resetBranches());
-it('should open the regulatory report page', async () => {
- const user = userEvent.setup();
- renderRegulatoryReportApp();
- expect(await screen.findByText('regulatory_report.page')).toBeInTheDocument();
- expect(screen.getByText('regulatory_report.description1')).toBeInTheDocument();
- expect(screen.getByText('regulatory_report.description2')).toBeInTheDocument();
- expect(
- screen.getByText('regulatory_page.available_branches_info.only_keep_when_inactive')
- ).toBeInTheDocument();
- expect(screen.getByText('regulatory_page.available_branches_info.more_info')).toBeInTheDocument();
-
- const branchSelect = screen.getByRole('combobox', { name: 'regulatory_page.select_branch' });
- expect(branchSelect).toBeInTheDocument();
-
- await user.click(branchSelect);
- await user.keyboard('[ArrowDown][Enter]');
-
- const downloadButton = screen.getByText('download_verb');
- expect(downloadButton).toBeInTheDocument();
-
- expect(screen.queryByText('regulatory_page.download_start.sentence')).not.toBeInTheDocument();
- await user.click(downloadButton);
- expect(screen.getByText('regulatory_page.download_start.sentence')).toBeInTheDocument();
+describe('RegulatoryReport tests', () => {
+ it('should open the regulatory report page', async () => {
+ const user = userEvent.setup();
+ renderRegulatoryReportApp();
+ expect(await screen.findByText('regulatory_report.page')).toBeInTheDocument();
+ expect(screen.getByText('regulatory_report.description1')).toBeInTheDocument();
+ expect(screen.getByText('regulatory_report.description2')).toBeInTheDocument();
+ expect(
+ screen.getByText('regulatory_page.available_branches_info.only_keep_when_inactive')
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText('regulatory_page.available_branches_info.more_info')
+ ).toBeInTheDocument();
+
+ const branchSelect = screen.getByRole('combobox', { name: 'regulatory_page.select_branch' });
+ expect(branchSelect).toBeInTheDocument();
+
+ await user.click(branchSelect);
+ await user.keyboard('[ArrowDown][Enter]');
+
+ const downloadButton = screen.getByRole('link', { name: 'download_verb' });
+ expect(downloadButton).toBeInTheDocument();
+
+ expect(screen.queryByText('regulatory_page.download_start.sentence')).not.toBeInTheDocument();
+ await user.click(downloadButton);
+ expect(screen.getByText('regulatory_page.download_start.sentence')).toBeInTheDocument();
+ });
+
+ it('should display warning message if there is no available branch', async () => {
+ handler.emptyBranches();
+ renderRegulatoryReportApp();
+
+ expect(await screen.findByText('regulatory_report.page')).toBeInTheDocument();
+
+ expect(screen.getByText('regulatory_page.no_available_branch')).toBeInTheDocument();
+
+ const downloadButton = screen.getByRole('link', { name: 'download_verb' });
+ expect(downloadButton).toBeInTheDocument();
+ expect(downloadButton).toHaveClass('disabled');
+ });
+
+ it('should automatically select passed branch if compatible', async () => {
+ const compatibleBranch = mockBranch({ name: 'compatible-branch' });
+ handler.addBranch(compatibleBranch);
+ renderRegulatoryReportApp(compatibleBranch);
+
+ expect(await screen.findByText('regulatory_report.page')).toBeInTheDocument();
+
+ const downloadButton = screen.getByRole<HTMLAnchorElement>('link', { name: 'download_verb' });
+ expect(downloadButton).toBeInTheDocument();
+ expect(downloadButton).not.toHaveClass('disabled');
+ expect(downloadButton.href).toContain(compatibleBranch.name);
+ });
+
+ it('should automatically select main branch if present and passed branch is not compatible', async () => {
+ handler.emptyBranches();
+ const mainBranch = mockMainBranch({ name: 'main' });
+ const notCompatibleBranch = mockBranch({
+ name: 'not-compatible-branch',
+ excludedFromPurge: false,
+ });
+ handler.addBranch(mainBranch);
+ handler.addBranch(notCompatibleBranch);
+ renderRegulatoryReportApp(notCompatibleBranch);
+
+ expect(await screen.findByText('regulatory_report.page')).toBeInTheDocument();
+
+ const downloadButton = screen.getByRole<HTMLAnchorElement>('link', { name: 'download_verb' });
+ expect(downloadButton).toBeInTheDocument();
+ expect(downloadButton).not.toHaveClass('disabled');
+ expect(downloadButton.href).toContain(mainBranch.name);
+ });
});
-function renderRegulatoryReportApp() {
- renderComponent(<RegulatoryReport component={{ key: '', name: '' }} onClose={() => {}} />);
+function renderRegulatoryReportApp(branchLike?: BranchLike) {
+ renderComponent(
+ <RegulatoryReport
+ component={{ key: '', name: '' }}
+ branchLike={branchLike}
+ onClose={() => {}}
+ />
+ );
}
regulatory_report.description2=The generation and download of the report may take a few minutes.
regulatory_page.download_start.sentence=Your download should start shortly. This may take some time.
regulatory_page.select_branch=Select Branch
+regulatory_page.no_available_branch=No branch has been analyzed yet, no report can be generated.
regulatory_page.available_branches_info.only_keep_when_inactive=Only branches marked as "Keep when inactive" are available.
regulatory_page.available_branches_info.more_info=For further details, please check the {doc_link}.
regulatory_page.available_branches_info.more_info.doc_link=related documentation