remove=Remove
rename=Rename
reset_verb=Reset
+resolution=Resolution
result=Result
results=Results
x_results={0} results
issue.manual.missing_rule=Missing rule
issue.manual.no_rules=No rules.
issue.reported_by=Reported by
-issue.component_deleted=Removed
#------------------------------------------------------------------------------
widget.my_reviews.property.numberOfLines.name=Number of lines
widget.my_reviews.property.numberOfLines.desc=Maximum number of issues displayed at the same time.
-widget.false_positive_reviews.name=False Positives
+widget.false_positive_reviews.name=False Positives Issues
widget.false_positive_reviews.description=Shows all the false positives found on the project.
widget.false_positive_reviews.property.numberOfLines.name=Number of lines
widget.false_positive_reviews.property.numberOfLines.desc=Maximum number of issues displayed at the same time.
widget.action_plans.name=Action Plans
widget.action_plans.description=Shows all the open action plans of the project.
widget.action_plans.property.showResolvedIssues.name=Show Resolved Issues
-widget.action_plans.title=Open Action Plans
+widget.action_plans.title=Open action plans
widget.action_plans.no_action_plan=No action plan
widget.action_plans.x_unresolved_issues={0} unresolved issues
global_role.profileadmin.desc=Ability to perform any action on the quality profiles.
-#------------------------------------------------------------------------------
-#
-# PROJECTS ROLES
-#
-#------------------------------------------------------------------------------
-projects_role.role=Role Membership For New {0}
-projects_role.users=Users
-projects_role.groups=Groups
-
-
#------------------------------------------------------------------------------
#
# ERRORS HANDLING
Rule rule = new Rule("squid", "AvoidCycles");
DefaultIssue issue = new DefaultIssue()
.setChanged(true)
- .setFieldDiff(mock(IssueChangeContext.class), "severity", "MINOR", "BLOCKER")
+ .setFieldChange(mock(IssueChangeContext.class), "severity", "MINOR", "BLOCKER")
.setRuleKey(ruleKey);
when(issueCache.all()).thenReturn(Arrays.asList(issue));
when(ruleFinder.findByKey(ruleKey)).thenReturn(rule);
RuleKey ruleKey = RuleKey.of("squid", "AvoidCycles");
DefaultIssue issue = new DefaultIssue()
.setChanged(true)
- .setFieldDiff(changeContext, "severity", "MINOR", "BLOCKER")
+ .setFieldChange(changeContext, "severity", "MINOR", "BLOCKER")
.setRuleKey(ruleKey);
when(issueCache.all()).thenReturn(Arrays.asList(issue));
when(ruleFinder.findByKey(ruleKey)).thenReturn(null);
@CheckForNull
private Notification createChangeNotification(DefaultIssue issue, IssueChangeContext context, Rule rule, Component project, @Nullable Component component, @Nullable String comment) {
- if (comment == null && (issue.diffs() == null || issue.diffs().diffs().isEmpty())) {
+ if (comment == null && (issue.currentChange() == null || issue.currentChange().diffs().isEmpty())) {
return null;
}
Notification notification = newNotification(project, "issue-changes");
notification.setFieldValue("comment", comment);
}
- FieldDiffs diffs = issue.diffs();
+ FieldDiffs diffs = issue.currentChange();
if (diffs != null) {
for (Map.Entry<String, FieldDiffs.Diff> entry : diffs.diffs().entrySet()) {
String type = entry.getKey();
throw new IllegalStateException("Severity can't be changed");
}
if (!Objects.equal(severity, issue.severity())) {
- issue.setFieldDiff(context, "severity", issue.severity(), severity);
+ issue.setFieldChange(context, "severity", issue.severity(), severity);
issue.setSeverity(severity);
issue.setUpdateDate(context.date());
issue.setChanged(true);
public boolean setManualSeverity(DefaultIssue issue, String severity, IssueChangeContext context) {
if (!issue.manualSeverity() || !Objects.equal(severity, issue.severity())) {
- issue.setFieldDiff(context, "severity", issue.severity(), severity);
+ issue.setFieldChange(context, "severity", issue.severity(), severity);
issue.setSeverity(severity);
issue.setManualSeverity(true);
issue.setUpdateDate(context.date());
public boolean assign(DefaultIssue issue, @Nullable String assignee, IssueChangeContext context) {
String sanitizedAssignee = StringUtils.defaultIfBlank(assignee, null);
if (!Objects.equal(sanitizedAssignee, issue.assignee())) {
- issue.setFieldDiff(context, "assignee", issue.assignee(), sanitizedAssignee);
+ issue.setFieldChange(context, "assignee", issue.assignee(), sanitizedAssignee);
issue.setAssignee(sanitizedAssignee);
issue.setUpdateDate(context.date());
issue.setChanged(true);
public boolean setResolution(DefaultIssue issue, @Nullable String resolution, IssueChangeContext context) {
if (!Objects.equal(resolution, issue.resolution())) {
- issue.setFieldDiff(context, "resolution", issue.resolution(), resolution);
+ issue.setFieldChange(context, "resolution", issue.resolution(), resolution);
issue.setResolution(resolution);
issue.setUpdateDate(context.date());
issue.setChanged(true);
public boolean setStatus(DefaultIssue issue, String status, IssueChangeContext context) {
if (!Objects.equal(status, issue.status())) {
- issue.setFieldDiff(context, "status", issue.status(), status);
+ issue.setFieldChange(context, "status", issue.status(), status);
issue.setStatus(status);
issue.setUpdateDate(context.date());
issue.setChanged(true);
public boolean setAuthorLogin(DefaultIssue issue, @Nullable String authorLogin, IssueChangeContext context) {
if (!Objects.equal(authorLogin, issue.authorLogin())) {
- issue.setFieldDiff(context, "author", issue.authorLogin(), authorLogin);
+ issue.setFieldChange(context, "author", issue.authorLogin(), authorLogin);
issue.setAuthorLogin(authorLogin);
issue.setUpdateDate(context.date());
issue.setChanged(true);
public boolean setAttribute(DefaultIssue issue, String key, @Nullable String value, IssueChangeContext context) {
String oldValue = issue.attribute(key);
if (!Objects.equal(oldValue, value)) {
- issue.setFieldDiff(context, key, oldValue, value);
+ issue.setFieldChange(context, key, oldValue, value);
issue.setAttribute(key, value);
issue.setUpdateDate(context.date());
issue.setChanged(true);
public boolean plan(DefaultIssue issue, @Nullable String actionPlanKey, IssueChangeContext context) {
String sanitizedActionPlanKey = StringUtils.defaultIfBlank(actionPlanKey, null);
if (!Objects.equal(sanitizedActionPlanKey, issue.actionPlanKey())) {
- issue.setFieldDiff(context, "actionPlanKey", issue.actionPlanKey(), sanitizedActionPlanKey);
+ issue.setFieldChange(context, "actionPlanKey", issue.actionPlanKey(), sanitizedActionPlanKey);
issue.setActionPlanKey(sanitizedActionPlanKey);
issue.setUpdateDate(context.date());
issue.setChanged(true);
import org.sonar.api.BatchComponent;
import org.sonar.api.ServerComponent;
import org.sonar.api.issue.internal.DefaultIssueComment;
+import org.sonar.api.issue.internal.FieldDiffs;
import org.sonar.core.persistence.MyBatis;
import javax.annotation.CheckForNull;
-
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
}
public List<DefaultIssueComment> selectCommentsByIssues(SqlSession session, Collection<String> issueKeys) {
- return selectByIssuesAndType(session, issueKeys, IssueChangeDto.TYPE_COMMENT);
+ List<DefaultIssueComment> comments = Lists.newArrayList();
+ for (IssueChangeDto dto : selectByIssuesAndType(session, issueKeys, IssueChangeDto.TYPE_COMMENT)) {
+ comments.add(dto.toComment());
+ }
+ return comments;
}
- public List<IssueChangeDto> selectIssueChangelog(String issueKey) {
+ public List<FieldDiffs> selectChangelogByIssue(String issueKey) {
SqlSession session = mybatis.openSession();
try {
- IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class);
- return mapper.selectByIssue(issueKey);
-
+ List<FieldDiffs> result = Lists.newArrayList();
+ for (IssueChangeDto dto : selectByIssuesAndType(session, Arrays.asList(issueKey), IssueChangeDto.TYPE_FIELD_CHANGE)) {
+ result.add(dto.toFieldDiffs());
+ }
+ return result;
} finally {
MyBatis.closeQuietly(session);
}
}
}
- List<DefaultIssueComment> selectByIssuesAndType(SqlSession session, Collection<String> issueKeys, String changeType) {
+ List<IssueChangeDto> selectByIssuesAndType(SqlSession session, Collection<String> issueKeys, String changeType) {
Preconditions.checkArgument(issueKeys.size() < 1000, "Number of issue keys is greater than or equal 1000");
- List<DefaultIssueComment> result = Lists.newArrayList();
- if (!issueKeys.isEmpty()) {
- IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class);
- List<IssueChangeDto> dtos = mapper.selectByIssuesAndType(issueKeys, changeType);
- for (IssueChangeDto dto : dtos) {
- result.add(dto.toComment());
- }
+ if (issueKeys.isEmpty()) {
+ return Collections.emptyList();
}
- return result;
+ IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class);
+ return mapper.selectByIssuesAndType(issueKeys, changeType);
}
public boolean delete(String key) {
mapper.insert(changeDto);
}
}
- FieldDiffs diffs = issue.diffs();
+ FieldDiffs diffs = issue.currentChange();
if (diffs != null) {
IssueChangeDto changeDto = IssueChangeDto.of(issue.key(), diffs);
mapper.insert(changeDto);
import org.sonar.api.user.UserQuery;
import javax.annotation.CheckForNull;
+import java.util.Collection;
import java.util.List;
/**
return toUsers(dtos);
}
- private List<User> toUsers(List<UserDto> dtos) {
+ private List<User> toUsers(Collection<UserDto> dtos) {
List<User> users = Lists.newArrayList();
for (UserDto dto : dtos) {
users.add(dto.toUser());
import org.sonar.core.persistence.MyBatis;
import javax.annotation.CheckForNull;
+import java.util.Collection;
import java.util.List;
/**
.setMessage("the message")
.setKey("ABCDE")
.setAssignee("freddy")
- .setFieldDiff(context, "resolution", null, "FIXED")
- .setFieldDiff(context, "status", "OPEN", "RESOLVED")
+ .setFieldChange(context, "resolution", null, "FIXED")
+ .setFieldChange(context, "status", "OPEN", "RESOLVED")
.setComponentKey("struts:Action")
.setProjectKey("struts");
DefaultIssueQueryResult queryResult = new DefaultIssueQueryResult(Arrays.<Issue>asList(issue));
boolean updated = updater.assign(issue, "emmerik", context);
assertThat(updated).isTrue();
assertThat(issue.assignee()).isEqualTo("emmerik");
- FieldDiffs.Diff diff = issue.diffs().get("assignee");
+ FieldDiffs.Diff diff = issue.currentChange().get("assignee");
assertThat(diff.oldValue()).isNull();
assertThat(diff.newValue()).isEqualTo("emmerik");
}
boolean updated = updater.assign(issue, null, context);
assertThat(updated).isTrue();
assertThat(issue.assignee()).isNull();
- FieldDiffs.Diff diff = issue.diffs().get("assignee");
+ FieldDiffs.Diff diff = issue.currentChange().get("assignee");
assertThat(diff.oldValue()).isEqualTo("morgan");
assertThat(diff.newValue()).isNull();
}
boolean updated = updater.assign(issue, "emmerik", context);
assertThat(updated).isTrue();
assertThat(issue.assignee()).isEqualTo("emmerik");
- FieldDiffs.Diff diff = issue.diffs().get("assignee");
+ FieldDiffs.Diff diff = issue.currentChange().get("assignee");
assertThat(diff.oldValue()).isEqualTo("morgan");
assertThat(diff.newValue()).isEqualTo("emmerik");
}
issue.setAssignee("morgan");
boolean updated = updater.assign(issue, "morgan", context);
assertThat(updated).isFalse();
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
assertThat(issue.severity()).isEqualTo("BLOCKER");
assertThat(issue.manualSeverity()).isFalse();
- FieldDiffs.Diff diff = issue.diffs().get("severity");
+ FieldDiffs.Diff diff = issue.currentChange().get("severity");
assertThat(diff.oldValue()).isNull();
assertThat(diff.newValue()).isEqualTo("BLOCKER");
}
assertThat(updated).isTrue();
assertThat(issue.severity()).isEqualTo("BLOCKER");
- FieldDiffs.Diff diff = issue.diffs().get("severity");
+ FieldDiffs.Diff diff = issue.currentChange().get("severity");
assertThat(diff.oldValue()).isEqualTo("INFO");
assertThat(diff.newValue()).isEqualTo("BLOCKER");
}
assertThat(updated).isTrue();
assertThat(issue.severity()).isEqualTo("MINOR");
- FieldDiffs.Diff diff = issue.diffs().get("severity");
+ FieldDiffs.Diff diff = issue.currentChange().get("severity");
assertThat(diff.oldValue()).isEqualTo("BLOCKER");
assertThat(diff.newValue()).isEqualTo("MINOR");
}
issue.setSeverity("MINOR");
boolean updated = updater.setSeverity(issue, "MINOR", context);
assertThat(updated).isFalse();
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
assertThat(updated).isTrue();
assertThat(issue.severity()).isEqualTo("MINOR");
assertThat(issue.manualSeverity()).isTrue();
- FieldDiffs.Diff diff = issue.diffs().get("severity");
+ FieldDiffs.Diff diff = issue.currentChange().get("severity");
assertThat(diff.oldValue()).isEqualTo("BLOCKER");
assertThat(diff.newValue()).isEqualTo("MINOR");
}
issue.setSeverity("MINOR").setManualSeverity(true);
boolean updated = updater.setManualSeverity(issue, "MINOR", context);
assertThat(updated).isFalse();
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
assertThat(issue.line()).isEqualTo(123);
// do not save change
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
assertThat(issue.line()).isEqualTo(42);
// do not save change
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
boolean updated = updater.setLine(issue, 123);
assertThat(updated).isFalse();
assertThat(issue.line()).isEqualTo(123);
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
assertThat(updated).isTrue();
assertThat(issue.resolution()).isEqualTo("OPEN");
- FieldDiffs.Diff diff = issue.diffs().get("resolution");
+ FieldDiffs.Diff diff = issue.currentChange().get("resolution");
assertThat(diff.oldValue()).isNull();
assertThat(diff.newValue()).isEqualTo("OPEN");
}
boolean updated = updater.setResolution(issue, "FIXED", context);
assertThat(updated).isFalse();
assertThat(issue.resolution()).isEqualTo("FIXED");
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
assertThat(updated).isTrue();
assertThat(issue.status()).isEqualTo("OPEN");
- FieldDiffs.Diff diff = issue.diffs().get("status");
+ FieldDiffs.Diff diff = issue.currentChange().get("status");
assertThat(diff.oldValue()).isNull();
assertThat(diff.newValue()).isEqualTo("OPEN");
}
boolean updated = updater.setStatus(issue, "CLOSED", context);
assertThat(updated).isFalse();
assertThat(issue.status()).isEqualTo("CLOSED");
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
boolean updated = updater.setAttribute(issue, "JIRA", "FOO-123", context);
assertThat(updated).isTrue();
assertThat(issue.attribute("JIRA")).isEqualTo("FOO-123");
- assertThat(issue.diffs().diffs()).hasSize(1);
- assertThat(issue.diffs().get("JIRA").oldValue()).isNull();
- assertThat(issue.diffs().get("JIRA").newValue()).isEqualTo("FOO-123");
+ assertThat(issue.currentChange().diffs()).hasSize(1);
+ assertThat(issue.currentChange().get("JIRA").oldValue()).isNull();
+ assertThat(issue.currentChange().get("JIRA").newValue()).isEqualTo("FOO-123");
}
@Test
boolean updated = updater.setAttribute(issue, "JIRA", null, context);
assertThat(updated).isTrue();
assertThat(issue.attribute("JIRA")).isNull();
- assertThat(issue.diffs().diffs()).hasSize(1);
- assertThat(issue.diffs().get("JIRA").oldValue()).isEqualTo("FOO-123");
- assertThat(issue.diffs().get("JIRA").newValue()).isNull();
+ assertThat(issue.currentChange().diffs()).hasSize(1);
+ assertThat(issue.currentChange().get("JIRA").oldValue()).isEqualTo("FOO-123");
+ assertThat(issue.currentChange().get("JIRA").newValue()).isNull();
}
@Test
assertThat(updated).isTrue();
assertThat(issue.actionPlanKey()).isEqualTo("ABCD");
- FieldDiffs.Diff diff = issue.diffs().get("actionPlanKey");
+ FieldDiffs.Diff diff = issue.currentChange().get("actionPlanKey");
assertThat(diff.oldValue()).isNull();
assertThat(diff.newValue()).isEqualTo("ABCD");
}
assertThat(issue.effortToFix()).isEqualTo(3.14);
// do not save change
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
assertThat(issue.message()).isEqualTo("new message");
// do not save change
- assertThat(issue.diffs()).isNull();
+ assertThat(issue.currentChange()).isNull();
}
@Test
assertThat(updated).isTrue();
assertThat(issue.authorLogin()).isEqualTo("eric");
- FieldDiffs.Diff diff = issue.diffs().get("author");
+ FieldDiffs.Diff diff = issue.currentChange().get("author");
assertThat(diff.oldValue()).isNull();
assertThat(diff.newValue()).isEqualTo("eric");
}
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.issue.internal.DefaultIssueComment;
+import org.sonar.api.issue.internal.FieldDiffs;
import org.sonar.api.utils.DateUtils;
import org.sonar.core.persistence.AbstractDaoTestCase;
}
@Test
- public void selectIssueChangelog() {
+ public void selectCommentByKey() {
setupData("shared");
- List<IssueChangeDto> changes = dao.selectIssueChangelog("1000");
- assertThat(changes).hasSize(3);
+ DefaultIssueComment comment = dao.selectCommentByKey("FGHIJ");
+ assertThat(comment).isNotNull();
+ assertThat(comment.key()).isEqualTo("FGHIJ");
+ assertThat(comment.key()).isEqualTo("FGHIJ");
+ assertThat(comment.userLogin()).isEqualTo("arthur");
- // chronological order
- assertThat(changes.get(0).getId()).isEqualTo(100);
- assertThat(changes.get(1).getId()).isEqualTo(101);
- assertThat(changes.get(2).getId()).isEqualTo(102);
+ assertThat(dao.selectCommentByKey("UNKNOWN")).isNull();
+ }
+
+
+ @Test
+ public void selectIssueChangelog() {
+ setupData("shared");
+
+ List<FieldDiffs> changelog = dao.selectChangelogByIssue("1000");
+ assertThat(changelog).hasSize(1);
+ assertThat(changelog.get(0).diffs()).hasSize(1);
+ assertThat(changelog.get(0).diffs().get("severity").newValue()).isEqualTo("BLOCKER");
+ assertThat(changelog.get(0).diffs().get("severity").oldValue()).isEqualTo("MAJOR");
}
@Test
.setChecksum("FFFFF")
.setAuthorLogin("simon")
.setAssignee("loic")
- .setFieldDiff(context, "severity", "INFO", "BLOCKER")
+ .setFieldChange(context, "severity", "INFO", "BLOCKER")
.setReporter("emmerik")
.setResolution("FIXED")
.setStatus("RESOLVED")
import org.sonar.core.persistence.AbstractDaoTestCase;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
public void selectUsersByLogins() throws Exception {
setupData("selectUsersByLogins");
- List<UserDto> users = dao.selectUsersByLogins(Arrays.asList("marius", "inactive_user", "other"));
+ Collection<UserDto> users = dao.selectUsersByLogins(Arrays.asList("marius", "inactive_user", "other"));
assertThat(users).hasSize(2);
assertThat(users).onProperty("login").containsOnly("marius", "inactive_user");
}
@Test
public void selectUsersByLogins_empty_logins() throws Exception {
// no need to access db
- List<UserDto> users = dao.selectUsersByLogins(Collections.<String>emptyList());
+ Collection<UserDto> users = dao.selectUsersByLogins(Collections.<String>emptyList());
assertThat(users).isEmpty();
}
private String checksum;
private Map<String, String> attributes = null;
private String authorLogin = null;
- private FieldDiffs diffs = null;
private String actionPlanKey;
private List<IssueComment> comments = null;
- // functional dates
+ // FUNCTIONAL DATES
private Date creationDate;
private Date updateDate;
private Date closeDate;
- // The following states are used only during scan.
+
+ // FOLLOWING FIELDS ARE AVAILABLE ONLY DURING SCAN
+
+ // Current changes
+ private FieldDiffs currentChange = null;
// true if the the issue did not exist in the previous scan.
private boolean isNew = true;
return this;
}
- public DefaultIssue setFieldDiff(IssueChangeContext context, String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) {
+ public DefaultIssue setFieldChange(IssueChangeContext context, String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) {
if (!Objects.equal(oldValue, newValue)) {
- if (diffs == null) {
- diffs = new FieldDiffs();
- diffs.setUserLogin(context.login());
+ if (currentChange == null) {
+ currentChange = new FieldDiffs();
+ currentChange.setUserLogin(context.login());
}
- diffs.setDiff(field, oldValue, newValue);
+ currentChange.setDiff(field, oldValue, newValue);
}
return this;
}
@CheckForNull
- public FieldDiffs diffs() {
- return diffs;
+ public FieldDiffs currentChange() {
+ return currentChange;
}
public DefaultIssue addComment(DefaultIssueComment comment) {
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
@SuppressWarnings("unchecked")
- public void setDiff(String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) {
+ public FieldDiffs setDiff(String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) {
Diff diff = diffs.get(field);
if (diff == null) {
diff = new Diff(oldValue, newValue);
} else {
diff.setNewValue(newValue);
}
+ return this;
}
@Override
import org.sonar.api.ServerComponent;
import javax.annotation.CheckForNull;
+import java.util.Collection;
import java.util.List;
/**
import org.sonar.core.issue.ActionPlanStats;
import org.sonar.core.issue.DefaultActionPlan;
import org.sonar.core.issue.DefaultIssueBuilder;
-import org.sonar.core.issue.db.IssueChangeDto;
import org.sonar.core.issue.workflow.Transition;
import org.sonar.core.resource.ResourceDao;
import org.sonar.core.resource.ResourceDto;
public class InternalRubyIssueService implements ServerComponent {
private final IssueService issueService;
- private final IssueChangeService changeService;
+ private final IssueCommentService commentService;
+ private final IssueChangelogService changelogService;
private final ActionPlanService actionPlanService;
private final IssueStatsFinder issueStatsFinder;
private final ResourceDao resourceDao;
private final ActionService actionService;
public InternalRubyIssueService(IssueService issueService,
- IssueChangeService changeService,
- ActionPlanService actionPlanService,
+ IssueCommentService commentService,
+ IssueChangelogService changelogService, ActionPlanService actionPlanService,
IssueStatsFinder issueStatsFinder, ResourceDao resourceDao, ActionService actionService) {
this.issueService = issueService;
- this.changeService = changeService;
+ this.commentService = commentService;
+ this.changelogService = changelogService;
this.actionPlanService = actionPlanService;
this.issueStatsFinder = issueStatsFinder;
this.resourceDao = resourceDao;
return Issue.RESOLUTIONS;
}
- public List<IssueChangeDto> changelog(String issueKey) {
+ public IssueChangelog changelog(String issueKey) {
// TODO verify security
- return changeService.changelog(issueKey);
+ return changelogService.changelog(issueKey, UserSession.get());
}
public Result<Issue> doTransition(String issueKey, String transitionKey) {
public Result<IssueComment> addComment(String issueKey, String text) {
Result<IssueComment> result = Result.of();
try {
- result.set(changeService.addComment(issueKey, text, UserSession.get()));
+ result.set(commentService.addComment(issueKey, text, UserSession.get()));
} catch (Exception e) {
result.addError(e.getMessage());
}
}
public IssueComment deleteComment(String commentKey) {
- return changeService.deleteComment(commentKey, UserSession.get());
+ return commentService.deleteComment(commentKey, UserSession.get());
}
public IssueComment editComment(String commentKey, String newText) {
- return changeService.editComment(commentKey, newText, UserSession.get());
+ return commentService.editComment(commentKey, newText, UserSession.get());
}
public IssueComment findComment(String commentKey) {
- return changeService.findComment(commentKey);
+ return commentService.findComment(commentKey);
}
/**
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.
- */
-package org.sonar.server.issue;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Strings;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.issue.IssueComment;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.issue.IssueQueryResult;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.DefaultIssueComment;
-import org.sonar.api.issue.internal.IssueChangeContext;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.issue.IssueNotifications;
-import org.sonar.core.issue.IssueUpdater;
-import org.sonar.core.issue.db.IssueChangeDao;
-import org.sonar.core.issue.db.IssueChangeDto;
-import org.sonar.core.issue.db.IssueStorage;
-import org.sonar.server.user.UserSession;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-
-public class IssueChangeService implements ServerComponent {
-
- private final IssueUpdater updater;
- private final IssueChangeDao changeDao;
- private final IssueStorage storage;
- private final DefaultIssueFinder finder;
- private final IssueNotifications issueNotifications;
-
- public IssueChangeService(IssueUpdater updater, IssueChangeDao changeDao, IssueStorage storage, DefaultIssueFinder finder, IssueNotifications issueNotifications) {
- this.updater = updater;
- this.changeDao = changeDao;
- this.storage = storage;
- this.finder = finder;
- this.issueNotifications = issueNotifications;
- }
-
- public List<IssueChangeDto> changelog(String issueKey) {
- // TODO verify security
- return changeDao.selectIssueChangelog(issueKey);
- }
-
- public IssueComment findComment(String commentKey) {
- return changeDao.selectCommentByKey(commentKey);
- }
-
- public IssueComment addComment(String issueKey, String text, UserSession userSession) {
- verifyLoggedIn(userSession);
-
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue issue = (DefaultIssue) queryResult.first();
-
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- updater.addComment(issue, text, context);
- storage.save(issue);
- issueNotifications.sendChanges(issue, context, queryResult, text);
- return issue.comments().get(issue.comments().size() - 1);
- }
-
- public IssueComment deleteComment(String commentKey, UserSession userSession) {
- DefaultIssueComment comment = changeDao.selectCommentByKey(commentKey);
- if (comment == null) {
- // TODO throw 404
- throw new IllegalStateException();
- }
- if (Strings.isNullOrEmpty(comment.userLogin()) || !Objects.equal(comment.userLogin(), userSession.login())) {
- // TODO throw unauthorized
- throw new IllegalStateException();
- }
-
- // check authorization
- finder.findByKey(comment.issueKey(), UserRole.USER);
-
- changeDao.delete(commentKey);
- return comment;
- }
-
- public IssueComment editComment(String commentKey, String text, UserSession userSession) {
- DefaultIssueComment comment = changeDao.selectCommentByKey(commentKey);
- if (comment == null) {
- // TODO throw 404
- throw new IllegalStateException();
- }
- if (Strings.isNullOrEmpty(comment.userLogin()) || !Objects.equal(comment.userLogin(), userSession.login())) {
- // TODO throw unauthorized
- throw new IllegalStateException();
- }
-
- // check authorization
- finder.findByKey(comment.issueKey(), UserRole.USER);
-
- IssueChangeDto dto = IssueChangeDto.of(comment);
- dto.setUpdatedAt(new Date());
- dto.setChangeData(text);
- changeDao.update(dto);
-
- return comment;
- }
-
- private void verifyLoggedIn(UserSession userSession) {
- if (!userSession.isLoggedIn()) {
- // must be logged
- throw new IllegalStateException("User is not logged in");
- }
- }
-
- // TODO remove this duplication from IssueService
- public IssueQueryResult loadIssue(String issueKey) {
- IssueQuery query = IssueQuery.builder().issueKeys(Arrays.asList(issueKey)).requiredRole(UserRole.USER).build();
- IssueQueryResult result = finder.find(query);
- if (result.issues().size()!=1) {
- throw new IllegalStateException("Issue not found: " + issueKey);
- }
- return result;
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.collect.Maps;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.user.User;
+
+import javax.annotation.CheckForNull;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 3.6
+ */
+public class IssueChangelog {
+
+ private final List<FieldDiffs> changes;
+ private final Map<String, User> usersByLogin;
+
+ public IssueChangelog(List<FieldDiffs> changes, Collection<User> users) {
+ this.changes = changes;
+ this.usersByLogin = Maps.newHashMap();
+ for (User user : users) {
+ usersByLogin.put(user.login(), user);
+ }
+ }
+
+ public List<FieldDiffs> changes() {
+ return changes;
+ }
+
+ @CheckForNull
+ public User user(FieldDiffs change) {
+ if (change.userLogin() == null) {
+ return null;
+ }
+ return usersByLogin.get(change.userLogin());
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.collect.Lists;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.user.User;
+import org.sonar.api.user.UserFinder;
+import org.sonar.core.issue.db.IssueChangeDao;
+import org.sonar.server.user.UserSession;
+
+import java.util.Collection;
+import java.util.List;
+
+public class IssueChangelogService implements ServerComponent {
+
+ private final IssueChangeDao changeDao;
+ private final UserFinder userFinder;
+
+ public IssueChangelogService(IssueChangeDao changeDao, UserFinder userFinder) {
+ this.changeDao = changeDao;
+ this.userFinder = userFinder;
+ }
+
+ public IssueChangelog changelog(String issueKey, UserSession userSession) {
+ // TODO verify security
+ List<FieldDiffs> changes = changeDao.selectChangelogByIssue(issueKey);
+
+ // Load users
+ List<String> logins = Lists.newArrayList();
+ for (FieldDiffs change : changes) {
+ if (change.userLogin() != null) {
+ logins.add(change.userLogin());
+ }
+ }
+ Collection<User> users = userFinder.findByLogins(logins);
+
+ return new IssueChangelog(changes, users);
+
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.issue.IssueComment;
+import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.issue.IssueQueryResult;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.issue.internal.DefaultIssueComment;
+import org.sonar.api.issue.internal.IssueChangeContext;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.issue.IssueNotifications;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.db.IssueChangeDao;
+import org.sonar.core.issue.db.IssueChangeDto;
+import org.sonar.core.issue.db.IssueStorage;
+import org.sonar.server.user.UserSession;
+
+import java.util.Arrays;
+import java.util.Date;
+
+public class IssueCommentService implements ServerComponent {
+
+ private final IssueUpdater updater;
+ private final IssueChangeDao changeDao;
+ private final IssueStorage storage;
+ private final DefaultIssueFinder finder;
+ private final IssueNotifications issueNotifications;
+
+ public IssueCommentService(IssueUpdater updater, IssueChangeDao changeDao, IssueStorage storage, DefaultIssueFinder finder, IssueNotifications issueNotifications) {
+ this.updater = updater;
+ this.changeDao = changeDao;
+ this.storage = storage;
+ this.finder = finder;
+ this.issueNotifications = issueNotifications;
+ }
+
+ public IssueComment findComment(String commentKey) {
+ return changeDao.selectCommentByKey(commentKey);
+ }
+
+ public IssueComment addComment(String issueKey, String text, UserSession userSession) {
+ verifyLoggedIn(userSession);
+
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue issue = (DefaultIssue) queryResult.first();
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
+ updater.addComment(issue, text, context);
+ storage.save(issue);
+ issueNotifications.sendChanges(issue, context, queryResult, text);
+ return issue.comments().get(issue.comments().size() - 1);
+ }
+
+ public IssueComment deleteComment(String commentKey, UserSession userSession) {
+ DefaultIssueComment comment = changeDao.selectCommentByKey(commentKey);
+ if (comment == null) {
+ // TODO throw 404
+ throw new IllegalStateException();
+ }
+ if (Strings.isNullOrEmpty(comment.userLogin()) || !Objects.equal(comment.userLogin(), userSession.login())) {
+ // TODO throw unauthorized
+ throw new IllegalStateException();
+ }
+
+ // check authorization
+ finder.findByKey(comment.issueKey(), UserRole.USER);
+
+ changeDao.delete(commentKey);
+ return comment;
+ }
+
+ public IssueComment editComment(String commentKey, String text, UserSession userSession) {
+ DefaultIssueComment comment = changeDao.selectCommentByKey(commentKey);
+ if (comment == null) {
+ // TODO throw 404
+ throw new IllegalStateException();
+ }
+ if (Strings.isNullOrEmpty(comment.userLogin()) || !Objects.equal(comment.userLogin(), userSession.login())) {
+ // TODO throw unauthorized
+ throw new IllegalStateException();
+ }
+
+ // check authorization
+ finder.findByKey(comment.issueKey(), UserRole.USER);
+
+ IssueChangeDto dto = IssueChangeDto.of(comment);
+ dto.setUpdatedAt(new Date());
+ dto.setChangeData(text);
+ changeDao.update(dto);
+
+ return comment;
+ }
+
+ private void verifyLoggedIn(UserSession userSession) {
+ if (!userSession.isLoggedIn()) {
+ // must be logged
+ throw new IllegalStateException("User is not logged in");
+ }
+ }
+
+ // TODO remove this duplication from IssueService
+ public IssueQueryResult loadIssue(String issueKey) {
+ IssueQuery query = IssueQuery.builder().issueKeys(Arrays.asList(issueKey)).requiredRole(UserRole.USER).build();
+ IssueQueryResult result = finder.find(query);
+ if (result.issues().size() != 1) {
+ throw new IllegalStateException("Issue not found: " + issueKey);
+ }
+ return result;
+ }
+}
servicesContainer.addSingleton(FunctionExecutor.class);
servicesContainer.addSingleton(IssueWorkflow.class);
servicesContainer.addSingleton(IssueService.class);
- servicesContainer.addSingleton(IssueChangeService.class);
+ servicesContainer.addSingleton(IssueCommentService.class);
servicesContainer.addSingleton(DefaultIssueFinder.class);
servicesContainer.addSingleton(IssueStatsFinder.class);
servicesContainer.addSingleton(PublicRubyIssueService.class);
servicesContainer.addSingleton(InternalRubyIssueService.class);
servicesContainer.addSingleton(ActionPlanService.class);
+ servicesContainer.addSingleton(IssueChangelogService.class);
servicesContainer.addSingleton(IssueNotifications.class);
servicesContainer.addSingleton(ActionService.class);
servicesContainer.addSingleton(Actions.class);
require_parameters :id
@issue_results = Api.issues.find(params[:id])
@issue = @issue_results.first()
- @changes = Internal.issues.changelog(params[:id])
+ @changelog = Internal.issues.changelog(params[:id])
render :partial => 'issue/changelog'
end
-<ul>
- <li>
- <%= format_datetime(@issue.creationDate()) -%>
- <% if @issue.reporter %>
- - <%= message('issue.reported_by') -%> <%= @issue_results.user(@issue.reporter).name -%>
- <% end %>
- - <%= message('created') -%>
- </li>
-
- <% @changes.each do |change| %>
- <li>
- <%= format_datetime(change.createdAt()) -%> - <%= change.userLogin -%> - <%= change.changeData -%>
- </li>
+<table class="spaced">
+ <tr>
+ <td class="thin left top" nowrap><%= format_datetime(@issue.creationDate()) -%></td>
+ <td class="thin left top"nowrap><%= @issue_results.user(@issue.reporter).name if @issue.reporter -%></td>
+ <td class="left top"><%= message('created') -%></td>
+ </tr>
+ <%
+ @changelog.changes.each do |change|
+ user = @changelog.user(change)
+ %>
+ <tr>
+ <td class="thin left top" nowrap><%= format_datetime(change.createdAt()) -%></td>
+ <td class="thin left top" nowrap><%= h(user.name()) if user -%></td>
+ <td class="left top">
+ <%
+ change.diffs.entrySet().each_with_index do |entry, index|
+ key = entry.getKey()
+ diff = entry.getValue()
+ %>
+ <% if index>0 %><br/><% end %>
+ <% if diff.newValue.present? %>
+ <%= message('issue.changelog.changed_to', :params => [message(key), diff.newValue()]) -%>
+ <% else %>
+ <%= message('issue.changelog.removed', :params => [message(key)]) -%>
+ <% end %>
+ <% if diff.oldValue.present? %>
+ (<%= message('issue.changelog.was', :params => [diff.oldValue]) -%>)
+ <% end %>
+ <% end %>
+ </td>
+ </tr>
<% end %>
-</ul>
\ No newline at end of file
+</table>
+
+
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.sonar.api.issue.ActionPlan;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.user.User;
import org.sonar.core.issue.DefaultActionPlan;
import org.sonar.core.resource.ResourceDao;
import org.sonar.core.resource.ResourceDto;
import org.sonar.core.resource.ResourceQuery;
import org.sonar.server.user.UserSession;
+import java.util.Collections;
import java.util.Map;
import static com.google.common.collect.Maps.newHashMap;
public class InternalRubyIssueServiceTest {
- private InternalRubyIssueService internalRubyIssueService;
- private IssueService issueService = mock(IssueService.class);
- private IssueChangeService commentService = mock(IssueChangeService.class);
- private ActionPlanService actionPlanService = mock(ActionPlanService.class);
- private ResourceDao resourceDao = mock(ResourceDao.class);
- private IssueStatsFinder issueStatsFinder = mock(IssueStatsFinder.class);
- private ActionService actionService = mock(ActionService.class);
+ InternalRubyIssueService service;
+ IssueService issueService = mock(IssueService.class);
+ IssueCommentService commentService = mock(IssueCommentService.class);
+ IssueChangelogService changelogService = mock(IssueChangelogService.class);
+ ActionPlanService actionPlanService = mock(ActionPlanService.class);
+ ResourceDao resourceDao = mock(ResourceDao.class);
+ IssueStatsFinder issueStatsFinder = mock(IssueStatsFinder.class);
+ ActionService actionService = mock(ActionService.class);
@Before
- public void before() {
+ public void setUp() {
ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project);
- internalRubyIssueService = new InternalRubyIssueService(issueService, commentService, actionPlanService, issueStatsFinder, resourceDao, actionService);
+ service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, issueStatsFinder, resourceDao, actionService);
}
@Test
parameters.put("deadLine", "2113-05-13");
ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
- Result result = internalRubyIssueService.createActionPlan(parameters);
+ Result result = service.createActionPlan(parameters);
assertThat(result.ok()).isTrue();
verify(actionPlanService).create(actionPlanCaptor.capture(), any(UserSession.class));
parameters.put("project", "org.sonar.MultiSample");
ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
- Result result = internalRubyIssueService.updateActionPlan("ABCD", parameters);
+ Result result = service.updateActionPlan("ABCD", parameters);
assertThat(result.ok()).isTrue();
verify(actionPlanService).update(actionPlanCaptor.capture(), any(UserSession.class));
parameters.put("deadLine", "2113-05-13");
ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
- Result result = internalRubyIssueService.updateActionPlan("ABCD", parameters);
+ Result result = service.updateActionPlan("ABCD", parameters);
assertThat(result.ok()).isTrue();
verify(actionPlanService).update(actionPlanCaptor.capture(), any(UserSession.class));
public void should_not_update_action_plan_when_action_plan_is_not_found() {
when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
- Result result = internalRubyIssueService.updateActionPlan("ABCD", null);
+ Result result = service.updateActionPlan("ABCD", null);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.action_plan_does_not_exist", "ABCD"));
}
public void should_delete_action_plan() {
when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
- Result result = internalRubyIssueService.deleteActionPlan("ABCD");
+ Result result = service.deleteActionPlan("ABCD");
verify(actionPlanService).delete(eq("ABCD"), any(UserSession.class));
assertThat(result.ok()).isTrue();
}
public void should_not_delete_action_plan_if_action_plan_not_found() {
when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
- Result result = internalRubyIssueService.deleteActionPlan("ABCD");
+ Result result = service.deleteActionPlan("ABCD");
verify(actionPlanService, never()).delete(eq("ABCD"), any(UserSession.class));
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.action_plan_does_not_exist", "ABCD"));
public void should_close_action_plan() {
when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
- Result result = internalRubyIssueService.closeActionPlan("ABCD");
+ Result result = service.closeActionPlan("ABCD");
verify(actionPlanService).setStatus(eq("ABCD"), eq("CLOSED"), any(UserSession.class));
assertThat(result.ok()).isTrue();
}
public void should_open_action_plan() {
when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
- Result result = internalRubyIssueService.openActionPlan("ABCD");
+ Result result = service.openActionPlan("ABCD");
verify(actionPlanService).setStatus(eq("ABCD"), eq("OPEN"), any(UserSession.class));
assertThat(result.ok()).isTrue();
}
parameters.put("name", "Long term");
parameters.put("description", "Long term issues");
- Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ Result result = service.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("errors.cant_be_empty", "project"));
}
parameters.put("description", "Long term issues");
parameters.put("project", "org.sonar.Sample");
- Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ Result result = service.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("errors.cant_be_empty", "name"));
}
parameters.put("description", "Long term issues");
parameters.put("project", "org.sonar.Sample");
- Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ Result result = service.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "name", 200));
}
parameters.put("description", createLongString(1001));
parameters.put("project", "org.sonar.Sample");
- Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ Result result = service.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "description", 1000));
}
parameters.put("project", "org.sonar.Sample");
parameters.put("deadLine", "18/05/2013");
- Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ Result result = service.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_not_valid", "date"));
}
parameters.put("project", "org.sonar.Sample");
parameters.put("deadLine", "2000-01-01");
- Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ Result result = service.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.date_cant_be_in_past"));
}
when(actionPlanService.isNameAlreadyUsedForProject(anyString(), anyString())).thenReturn(true);
- Result result = internalRubyIssueService.createActionPlanResult(parameters, DefaultActionPlan.create("Short term"));
+ Result result = service.createActionPlanResult(parameters, DefaultActionPlan.create("Short term"));
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.same_name_in_same_project"));
}
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null);
- Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ Result result = service.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.project_does_not_exist", "org.sonar.Sample"));
}
+
public String createLongString(int size) {
String result = "";
for (int i = 0; i < size; i++) {
}
return result;
}
+
+ @Test
+ public void test_changelog() throws Exception {
+ IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
+ when(changelogService.changelog(eq("ABCDE"), any(UserSession.class))).thenReturn(changelog);
+
+ IssueChangelog result = service.changelog("ABCDE");
+
+ assertThat(result).isSameAs(changelog);
+ }
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+package org.sonar.server.issue;
+
+import org.junit.Test;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.user.User;
+import org.sonar.api.user.UserFinder;
+import org.sonar.core.issue.db.IssueChangeDao;
+import org.sonar.core.user.DefaultUser;
+import org.sonar.server.user.UserSession;
+
+import java.util.Arrays;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class IssueChangelogServiceTest {
+
+ IssueChangeDao changeDao = mock(IssueChangeDao.class);
+ UserFinder userFinder = mock(UserFinder.class);
+ IssueChangelogService service = new IssueChangelogService(changeDao, userFinder);
+
+ @Test
+ public void should_load_changelog_and_related_users() throws Exception {
+ FieldDiffs userChange = new FieldDiffs().setUserLogin("arthur").setDiff("severity", "MAJOR", "BLOCKER");
+ FieldDiffs scanChange = new FieldDiffs().setDiff("status", "RESOLVED", "CLOSED");
+ when(changeDao.selectChangelogByIssue("ABCDE")).thenReturn(Arrays.asList(userChange, scanChange));
+ User arthur = new DefaultUser().setLogin("arthur").setName("Arthur");
+ when(userFinder.findByLogins(Arrays.asList("arthur"))).thenReturn(Arrays.asList(arthur));
+
+ IssueChangelog changelog = service.changelog("ABCDE", mock(UserSession.class));
+
+ assertThat(changelog).isNotNull();
+ assertThat(changelog.changes()).containsOnly(userChange, scanChange);
+ assertThat(changelog.user(scanChange)).isNull();
+ assertThat(changelog.user(userChange)).isSameAs(arthur);
+ }
+}