* Replace INREVIEW and TOREVIEW to IN_REVIEW and TO_REVIEW * Update transition names and descriptionstags/7.8
private static final String STATUS_REOPENED = "REOPENED"; | private static final String STATUS_REOPENED = "REOPENED"; | ||||
private static final String STATUS_RESOLVED = "RESOLVED"; | private static final String STATUS_RESOLVED = "RESOLVED"; | ||||
private static final String STATUS_TO_REVIEW = "TOREVIEW"; | |||||
private static final String STATUS_IN_REVIEW = "INREVIEW"; | |||||
private static final String STATUS_TO_REVIEW = "TO_REVIEW"; | |||||
private static final String STATUS_IN_REVIEW = "IN_REVIEW"; | |||||
private static final String STATUS_REVIEWED = "REVIEWED"; | private static final String STATUS_REVIEWED = "REVIEWED"; | ||||
private static final int RULE_TYPE_SECURITY_HOTSPOT = 4; | private static final int RULE_TYPE_SECURITY_HOTSPOT = 4; |
underTest.execute(); | underTest.execute(); | ||||
assertIssues( | assertIssues( | ||||
tuple(issue1, "TOREVIEW", null, 4, NOW), | |||||
tuple(issue2, "TOREVIEW", null, 4, NOW), | |||||
tuple(issue1, "TO_REVIEW", null, 4, NOW), | |||||
tuple(issue2, "TO_REVIEW", null, 4, NOW), | |||||
// Not updated | // Not updated | ||||
tuple(issue3, "OPEN", null, 1, PAST), | tuple(issue3, "OPEN", null, 1, PAST), | ||||
tuple(issue4, "REOPENED", null, 2, PAST), | tuple(issue4, "REOPENED", null, 2, PAST), | ||||
underTest.execute(); | underTest.execute(); | ||||
assertIssues( | assertIssues( | ||||
tuple(issue1, "INREVIEW", null, 4, NOW), | |||||
tuple(issue1, "IN_REVIEW", null, 4, NOW), | |||||
tuple(issue2, "REVIEWED", "FIXED", 4, NOW), | tuple(issue2, "REVIEWED", "FIXED", 4, NOW), | ||||
// Not updated | // Not updated | ||||
tuple(issue3, "RESOLVED", "FIXED", 1, PAST), | tuple(issue3, "RESOLVED", "FIXED", 1, PAST), | ||||
underTest.execute(); | underTest.execute(); | ||||
assertIssueChanges( | assertIssueChanges( | ||||
tuple(issue1, "diff", "status=REOPENED|TOREVIEW,resolution=", NOW, NOW, NOW), | |||||
tuple(issue3, "diff", "status=RESOLVED|INREVIEW,resolution=FIXED|", NOW, NOW, NOW), | |||||
tuple(issue1, "diff", "status=REOPENED|TO_REVIEW,resolution=", NOW, NOW, NOW), | |||||
tuple(issue3, "diff", "status=RESOLVED|IN_REVIEW,resolution=FIXED|", NOW, NOW, NOW), | |||||
tuple(issue4, "diff", "status=RESOLVED|REVIEWED,resolution=WONTFIX|FIXED", NOW, NOW, NOW)); | tuple(issue4, "diff", "status=RESOLVED|REVIEWED,resolution=WONTFIX|FIXED", NOW, NOW, NOW)); | ||||
} | } | ||||
underTest.execute(); | underTest.execute(); | ||||
assertIssues( | assertIssues( | ||||
tuple(issue1, "TOREVIEW", null, 4, NOW), | |||||
tuple(issue2, "TOREVIEW", null, 4, NOW)); | |||||
tuple(issue1, "TO_REVIEW", null, 4, NOW), | |||||
tuple(issue2, "TO_REVIEW", null, 4, NOW)); | |||||
// Set a new date for NOW in order to check that issues has not been updated again | // Set a new date for NOW in order to check that issues has not been updated again | ||||
system2.setNow(NOW + 1_000_000_000L); | system2.setNow(NOW + 1_000_000_000L); | ||||
underTest.execute(); | underTest.execute(); | ||||
assertIssues( | assertIssues( | ||||
tuple(issue1, "TOREVIEW", null, 4, NOW), | |||||
tuple(issue2, "TOREVIEW", null, 4, NOW)); | |||||
tuple(issue1, "TO_REVIEW", null, 4, NOW), | |||||
tuple(issue2, "TO_REVIEW", null, 4, NOW)); | |||||
} | } | ||||
@Test | @Test |
import java.util.Set; | import java.util.Set; | ||||
import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||
import javax.annotation.CheckForNull; | import javax.annotation.CheckForNull; | ||||
import org.apache.commons.lang.StringUtils; | |||||
import org.sonar.api.issue.Issue; | import org.sonar.api.issue.Issue; | ||||
public class State { | public class State { | ||||
public State(String key, Transition[] outTransitions) { | public State(String key, Transition[] outTransitions) { | ||||
Preconditions.checkArgument(!Strings.isNullOrEmpty(key), "State key must be set"); | Preconditions.checkArgument(!Strings.isNullOrEmpty(key), "State key must be set"); | ||||
Preconditions.checkArgument(StringUtils.isAllUpperCase(key), "State key must be upper-case"); | |||||
checkDuplications(outTransitions, key); | checkDuplications(outTransitions, key); | ||||
this.key = key; | this.key = key; |
@Rule | @Rule | ||||
public ExpectedException expectedException = ExpectedException.none(); | public ExpectedException expectedException = ExpectedException.none(); | ||||
Transition t1 = Transition.builder("close").from("OPEN").to("CLOSED").build(); | |||||
private Transition t1 = Transition.builder("close").from("OPEN").to("CLOSED").build(); | |||||
@Test | @Test | ||||
public void key_should_be_set() { | public void key_should_be_set() { | ||||
new State("", new Transition[0]); | new State("", new Transition[0]); | ||||
} | } | ||||
@Test | |||||
public void key_should_be_upper_case() { | |||||
expectedException.expect(IllegalArgumentException.class); | |||||
expectedException.expectMessage("State key must be upper-case"); | |||||
new State("close", new Transition[0]); | |||||
} | |||||
@Test | @Test | ||||
public void no_duplicated_out_transitions() { | public void no_duplicated_out_transitions() { | ||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); |
.executeProtobuf(SearchWsResponse.class); | .executeProtobuf(SearchWsResponse.class); | ||||
Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L) | Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L) | ||||
.put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("INREVIEW", 0L).put("TOREVIEW", 0L).put("REVIEWED", 0L).build(); | |||||
.put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("IN_REVIEW", 0L).put("TO_REVIEW", 0L).put("REVIEWED", 0L).build(); | |||||
assertThat(response.getFacets().getFacetsList()) | assertThat(response.getFacets().getFacetsList()) | ||||
.extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) | .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) | ||||
.executeProtobuf(SearchWsResponse.class); | .executeProtobuf(SearchWsResponse.class); | ||||
Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 10L).put("CONFIRMED", 0L) | Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 10L).put("CONFIRMED", 0L) | ||||
.put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("INREVIEW", 0L).put("TOREVIEW", 0L).put("REVIEWED", 0L).build(); | |||||
.put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("IN_REVIEW", 0L).put("TO_REVIEW", 0L).put("REVIEWED", 0L).build(); | |||||
assertThat(response.getFacets().getFacetsList()) | assertThat(response.getFacets().getFacetsList()) | ||||
.extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) | .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) | ||||
.executeProtobuf(SearchWsResponse.class); | .executeProtobuf(SearchWsResponse.class); | ||||
Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L) | Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L) | ||||
.put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("INREVIEW", 0L).put("TOREVIEW", 0L).put("REVIEWED", 0L).build(); | |||||
.put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("IN_REVIEW", 0L).put("TO_REVIEW", 0L).put("REVIEWED", 0L).build(); | |||||
assertThat(response.getFacets().getFacetsList()) | assertThat(response.getFacets().getFacetsList()) | ||||
.extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) | .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) |
} | } | ||||
const STATUSES = ['OPEN', 'CONFIRMED', 'REOPENED', 'RESOLVED']; | const STATUSES = ['OPEN', 'CONFIRMED', 'REOPENED', 'RESOLVED']; | ||||
const HOTSPOT_STATUSES = ['TOREVIEW', 'REVIEWED', 'INREVIEW']; | |||||
const HOTSPOT_STATUSES = ['TO_REVIEW', 'REVIEWED', 'IN_REVIEW']; | |||||
const COMMON_STATUSES = ['CLOSED']; | const COMMON_STATUSES = ['CLOSED']; | ||||
export default class StatusFacet extends React.PureComponent<Props> { | export default class StatusFacet extends React.PureComponent<Props> { |
it('should clear status facet', () => { | it('should clear status facet', () => { | ||||
const onChange = jest.fn(); | const onChange = jest.fn(); | ||||
const wrapper = shallowRender({ onChange, statuses: ['TOREVIEW'] }); | |||||
const wrapper = shallowRender({ onChange, statuses: ['TO_REVIEW'] }); | |||||
wrapper.children('FacetHeader').prop<Function>('onClear')(); | wrapper.children('FacetHeader').prop<Function>('onClear')(); | ||||
expect(onChange).toBeCalledWith({ statuses: [] }); | expect(onChange).toBeCalledWith({ statuses: [] }); | ||||
}); | }); | ||||
it('should select a status', () => { | it('should select a status', () => { | ||||
const onChange = jest.fn(); | const onChange = jest.fn(); | ||||
const wrapper = shallowRender({ onChange }); | const wrapper = shallowRender({ onChange }); | ||||
clickAndCheck('TOREVIEW'); | |||||
clickAndCheck('OPEN', true, ['OPEN', 'TOREVIEW']); | |||||
clickAndCheck('TO_REVIEW'); | |||||
clickAndCheck('OPEN', true, ['OPEN', 'TO_REVIEW']); | |||||
clickAndCheck('CONFIRMED'); | clickAndCheck('CONFIRMED'); | ||||
function clickAndCheck(status: string, multiple = false, expected = [status]) { | function clickAndCheck(status: string, multiple = false, expected = [status]) { | ||||
REOPENED: 0, | REOPENED: 0, | ||||
RESOLVED: 0, | RESOLVED: 0, | ||||
CLOSED: 8, | CLOSED: 8, | ||||
TOREVIEW: 150, | |||||
INREVIEW: 7, | |||||
TO_REVIEW: 150, | |||||
IN_REVIEW: 7, | |||||
REVIEWED: 1105 | REVIEWED: 1105 | ||||
}} | }} | ||||
statuses={[]} | statuses={[]} |
active={false} | active={false} | ||||
disabled={false} | disabled={false} | ||||
halfWidth={true} | halfWidth={true} | ||||
key="TOREVIEW" | |||||
key="TO_REVIEW" | |||||
loading={false} | loading={false} | ||||
name={ | name={ | ||||
<StatusHelper | <StatusHelper | ||||
status="TOREVIEW" | |||||
status="TO_REVIEW" | |||||
/> | /> | ||||
} | } | ||||
onClick={[Function]} | onClick={[Function]} | ||||
stat="150" | stat="150" | ||||
tooltip="issue.status.TOREVIEW" | |||||
value="TOREVIEW" | |||||
tooltip="issue.status.TO_REVIEW" | |||||
value="TO_REVIEW" | |||||
/> | /> | ||||
<FacetItem | <FacetItem | ||||
active={false} | active={false} | ||||
active={false} | active={false} | ||||
disabled={false} | disabled={false} | ||||
halfWidth={true} | halfWidth={true} | ||||
key="INREVIEW" | |||||
key="IN_REVIEW" | |||||
loading={false} | loading={false} | ||||
name={ | name={ | ||||
<StatusHelper | <StatusHelper | ||||
status="INREVIEW" | |||||
status="IN_REVIEW" | |||||
/> | /> | ||||
} | } | ||||
onClick={[Function]} | onClick={[Function]} | ||||
stat="7" | stat="7" | ||||
tooltip="issue.status.INREVIEW" | |||||
value="INREVIEW" | |||||
tooltip="issue.status.IN_REVIEW" | |||||
value="IN_REVIEW" | |||||
/> | /> | ||||
</FacetItemsList> | </FacetItemsList> | ||||
<FacetItemsList | <FacetItemsList |
issue.transition.wontfix=Resolve as won't fix | 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.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=Set as In Review | ||||
issue.transition.setinreview.description=A review is required to check for a Vulnerability | |||||
issue.transition.setinreview.description=A review is in progress to check for a vulnerability | |||||
issue.transition.openasvulnerability=Open as Vulnerability | issue.transition.openasvulnerability=Open as Vulnerability | ||||
issue.transition.openasvulnerability.description=There's a Vulnerability in the code that must be fixed | issue.transition.openasvulnerability.description=There's a Vulnerability in the code that must be fixed | ||||
issue.transition.resolveasreviewed=Resolve as Reviewed | issue.transition.resolveasreviewed=Resolve as Reviewed | ||||
issue.transition.resolveasreviewed.description=There is no Vulnerability in the code | issue.transition.resolveasreviewed.description=There is no Vulnerability in the code | ||||
issue.transition.resetastoreview=Reset as To Review | issue.transition.resetastoreview=Reset as To Review | ||||
issue.transition.resetastoreview.description=The Security Hotspot should be analyzed again | 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 | |||||
vulnerability.transition.resetastoreview=Reset as To Review | |||||
vulnerability.transition.resetastoreview.description=The vulnerability can't be fixed as is and needs more details. The security hotspot needs to be reviewed again | |||||
vulnerability.transition.resolveasreviewed=Resolve as Reviewed | |||||
vulnerability.transition.resolveasreviewed.description=The vulnerability has been fixed. The security hotspot is considered reviewed | |||||
issue.set_severity=Change Severity | issue.set_severity=Change Severity | ||||
issue.set_type=Change Type | issue.set_type=Change Type | ||||
issue.status.OPEN=Open | issue.status.OPEN=Open | ||||
issue.status.CONFIRMED=Confirmed | issue.status.CONFIRMED=Confirmed | ||||
issue.status.CLOSED=Closed | issue.status.CLOSED=Closed | ||||
issue.status.TOREVIEW=To Review | |||||
issue.status.INREVIEW=In Review | |||||
issue.status.TO_REVIEW=To Review | |||||
issue.status.IN_REVIEW=In Review | |||||
issue.status.REVIEWED=Reviewed | issue.status.REVIEWED=Reviewed | ||||
issue.resolution.FALSE-POSITIVE=False Positive | issue.resolution.FALSE-POSITIVE=False Positive |
/** | /** | ||||
* @since 7.8 | * @since 7.8 | ||||
*/ | */ | ||||
String STATUS_TO_REVIEW = "TOREVIEW"; | |||||
String STATUS_TO_REVIEW = "TO_REVIEW"; | |||||
/** | /** | ||||
* @since 7.8 | * @since 7.8 | ||||
*/ | */ | ||||
String STATUS_IN_REVIEW = "INREVIEW"; | |||||
String STATUS_IN_REVIEW = "IN_REVIEW"; | |||||
/** | /** | ||||
* @since 7.8 | * @since 7.8 |