interface Props {
hasTransitions: boolean;
isOpen: boolean;
- issue: Pick<T.Issue, 'key' | 'resolution' | 'status' | 'transitions'>;
+ issue: Pick<T.Issue, 'fromHotspot' | 'key' | 'resolution' | 'status' | 'transitions' | 'type'>;
onChange: (issue: T.Issue) => void;
togglePopup: (popup: string, show?: boolean) => void;
}
onRequestClose={this.handleClose}
open={this.props.isOpen && this.props.hasTransitions}
overlay={
- <SetTransitionPopup onSelect={this.setTransition} transitions={issue.transitions} />
+ <SetTransitionPopup
+ fromHotspot={issue.fromHotspot}
+ onSelect={this.setTransition}
+ transitions={issue.transitions}
+ type={issue.type}
+ />
}>
<ButtonLink
className="issue-action issue-action-with-options js-issue-transition"
import IssueTransition from '../IssueTransition';
import { click } from '../../../../helpers/testUtils';
-const issue = {
+const issue: IssueTransition['props']['issue'] = {
+ fromHotspot: false,
key: 'foo1234',
transitions: ['confirm', 'resolve', 'falsepositive', 'wontfix'],
- status: 'OPEN'
+ status: 'OPEN',
+ type: 'BUG'
};
it('should render without the action when there is no transitions', () => {
expect(
shallowRender({
hasTransitions: false,
- issue: { key: 'foo1234', transitions: [], status: 'CLOSED' }
+ issue: { fromHotspot: false, key: 'foo1234', transitions: [], status: 'CLOSED', type: 'BUG' }
})
).toMatchSnapshot();
});
expect(
shallowRender({
issue: {
+ fromHotspot: false,
key: 'foo1234',
transitions: ['reopen'],
status: 'RESOLVED',
- resolution: 'FIXED'
+ resolution: 'FIXED',
+ type: 'BUG'
}
})
).toMatchSnapshot();
open={true}
overlay={
<SetTransitionPopup
+ fromHotspot={false}
onSelect={[Function]}
transitions={
Array [
"wontfix",
]
}
+ type="BUG"
/>
}
>
open={false}
overlay={
<SetTransitionPopup
+ fromHotspot={false}
onSelect={[Function]}
transitions={
Array [
"reopen",
]
}
+ type="BUG"
/>
}
>
open={false}
overlay={
<SetTransitionPopup
+ fromHotspot={false}
onSelect={[Function]}
transitions={
Array [
"wontfix",
]
}
+ type="BUG"
/>
}
>
import * as React from 'react';
import SelectList from '../../common/SelectList';
import SelectListItem from '../../common/SelectListItem';
-import { translate } from '../../../helpers/l10n';
+import { translate, hasMessage } from '../../../helpers/l10n';
import { DropdownOverlay } from '../../controls/Dropdown';
-interface Props {
+export interface Props {
+ fromHotspot: boolean;
onSelect: (transition: string) => void;
transitions: string[];
+ type: T.IssueType;
}
-export default function SetTransitionPopup({ onSelect, transitions }: Props) {
+export default function SetTransitionPopup({ fromHotspot, onSelect, transitions, type }: Props) {
+ const isManualVulnerability = fromHotspot && type === 'VULNERABILITY';
return (
<DropdownOverlay>
<SelectList currentItem={transitions[0]} items={transitions} onSelect={onSelect}>
{transitions.map(transition => {
+ const [name, description] = translateTransition(transition, isManualVulnerability);
return (
- <SelectListItem
- item={transition}
- key={transition}
- title={translate('issue.transition', transition, 'description')}>
- {translate('issue.transition', transition)}
+ <SelectListItem item={transition} key={transition} title={description}>
+ {name}
</SelectListItem>
);
})}
</DropdownOverlay>
);
}
+
+function translateTransition(transition: string, isManualVulnerability: boolean) {
+ return isManualVulnerability && hasMessage('vulnerability.transition', transition)
+ ? [
+ translate('vulnerability.transition', transition),
+ translate('vulnerability.transition', transition, 'description')
+ ]
+ : [
+ translate('issue.transition', transition),
+ translate('issue.transition', transition, 'description')
+ ];
+}
*/
import * as React from 'react';
import { shallow } from 'enzyme';
-import SetTransitionPopup from '../SetTransitionPopup';
+import SetTransitionPopup, { Props } from '../SetTransitionPopup';
+import { hasMessage } from '../../../../helpers/l10n';
-it('should render tags popup correctly', () => {
- const element = shallow(
+jest.mock('../../../../helpers/l10n', () => ({
+ ...jest.requireActual('../../../../helpers/l10n'),
+ hasMessage: jest.fn().mockReturnValue(false)
+}));
+
+it('should render transition popup correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should render transition popup correctly for vulnerability', () => {
+ (hasMessage as jest.Mock).mockReturnValueOnce('true');
+ expect(
+ shallowRender({
+ fromHotspot: true,
+ transitions: ['resolveasreviewed', 'confirm']
+ })
+ ).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<Props> = {}) {
+ return shallow(
<SetTransitionPopup
+ fromHotspot={false}
onSelect={jest.fn()}
transitions={['confirm', 'resolve', 'falsepositive', 'wontfix']}
+ type="VULNERABILITY"
+ {...props}
/>
);
- expect(element).toMatchSnapshot();
-});
+}
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should render tags popup correctly 1`] = `
+exports[`should render transition popup correctly 1`] = `
<DropdownOverlay>
<SelectList
currentItem="confirm"
</SelectList>
</DropdownOverlay>
`;
+
+exports[`should render transition popup correctly for vulnerability 1`] = `
+<DropdownOverlay>
+ <SelectList
+ currentItem="resolveasreviewed"
+ items={
+ Array [
+ "resolveasreviewed",
+ "confirm",
+ ]
+ }
+ onSelect={[MockFunction]}
+ >
+ <SelectListItem
+ item="resolveasreviewed"
+ key="resolveasreviewed"
+ title="vulnerability.transition.resolveasreviewed.description"
+ >
+ vulnerability.transition.resolveasreviewed
+ </SelectListItem>
+ <SelectListItem
+ item="confirm"
+ key="confirm"
+ title="issue.transition.confirm.description"
+ >
+ issue.transition.confirm
+ </SelectListItem>
+ </SelectList>
+</DropdownOverlay>
+`;
issue.transition.close.description=
issue.transition.wontfix=Resolve as won't fix
issue.transition.wontfix.description=This issue can be ignored because the rule is irrelevant in this context. Its effort won't be counted.
-issue.transition.setinreview = Set as In Review
-issue.transition.setinreview.description = A review is required to check for a vulnerability
-issue.transition.resolveasreviewed = Resolve as Reviewed
-issue.transition.resolveasreviewed.description = There is no vulnerability in the code
-issue.transition.openasvulnerability = Open as Vulnerability
-issue.transition.openasvulnerability.description = There's a vulnerability in the code that must be fixed
-issue.transition.resetastoreview = Reset as security hotspot To Review
-issue.transition.resetastoreview.description = The security hotspot should be analyzed again
+issue.transition.setinreview=Set as In Review
+issue.transition.setinreview.description=A review is required to check for a Vulnerability
+issue.transition.openasvulnerability=Open as Vulnerability
+issue.transition.openasvulnerability.description=There's a Vulnerability in the code that must be fixed
+issue.transition.resolveasreviewed=Resolve as Reviewed
+issue.transition.resolveasreviewed.description=There is no Vulnerability in the code
+issue.transition.resetastoreview=Reset as To Review
+issue.transition.resetastoreview.description=The Security Hotspot should be analyzed again
+vulnerability.transition.resetastoreview=Reset as Security Hotspot To Review
+vulnerability.transition.resetastoreview.description=The Vulnerability can't be fixed as is and needs more details
+vulnerability.transition.resolveasreviewed=Resolve as Reviewed Security Hotspot
+vulnerability.transition.resolveasreviewed.description=The Vulnerability has been fixed
+
issue.set_severity=Change Severity
issue.set_type=Change Type