issues_action_plans.status.OPEN=Open
issues_action_plans.status.CLOSED=Closed
issues_action_plans.errors.date.cant_be_in_past=The dead-line can't be in the past
-
+issues_action_plans.errors.action_plan_does_not_exists=Action plan with key {0} does not exists
+issues_action_plans.errors.project_does_not_exists=Project with key {0} does not exists
#------------------------------------------------------------------------------
private String key;
private String name;
+ private String projectKey;
private String description;
private String userLogin;
private String status;
return this;
}
+ public String projectKey() {
+ return projectKey;
+ }
+
+ public ActionPlanStats setProjectKey(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
public String description() {
return description;
}
private String key;
private String name;
+ private String projectKey;
private String description;
private String userLogin;
private String status;
return this;
}
+ public String projectKey() {
+ return projectKey;
+ }
+
+ public DefaultActionPlan setProjectKey(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
public String description() {
return description;
}
private Date createdAt;
private Date updatedAt;
+ // joins
+ private transient String projectKey;
+
public Long getId() {
return id;
}
return this;
}
+ public String getProjectKey() {
+ return projectKey;
+ }
+
+ /**
+ * Only for unit tests
+ */
+ public ActionPlanDto setProjectKey_unit_test_only(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
public DefaultActionPlan toActionPlan() {
return DefaultActionPlan.create(name)
.setKey(kee)
+ .setProjectKey(projectKey)
.setDescription(description)
.setStatus(status)
.setDeadLine(deadLine)
private Date deadLine;
private Date createdAt;
private Date updatedAt;
-
private int totalIssues;
private int openIssues;
-
+ // joins
+ private transient String projectKey;
public Integer getId() {
return id;
return this;
}
+ public String getProjectKey() {
+ return projectKey;
+ }
+
+ /**
+ * Only for unit tests
+ */
+ public ActionPlanStatsDto setProjectKey_unit_test_only(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
- public ActionPlanStats toActionPlanStat(){
+ public ActionPlanStats toActionPlanStat() {
return ActionPlanStats.create(name)
- .setKey(kee)
- .setDescription(description)
- .setStatus(status)
- .setDeadLine(deadLine)
- .setUserLogin(userLogin)
- .setCreatedAt(createdAt)
- .setUpdatedAt(updatedAt)
- .setTotalIssues(totalIssues)
- .setOpenIssues(openIssues);
+ .setKey(kee)
+ .setProjectKey(projectKey)
+ .setDescription(description)
+ .setStatus(status)
+ .setDeadLine(deadLine)
+ .setUserLogin(userLogin)
+ .setCreatedAt(createdAt)
+ .setUpdatedAt(updatedAt)
+ .setTotalIssues(totalIssues)
+ .setOpenIssues(openIssues);
}
}
ap.status as status,
ap.deadline as deadLine,
ap.created_at as createdAt,
- ap.updated_at as updatedAt
+ ap.updated_at as updatedAt,
+ p.kee as projectKey
</sql>
<insert id="insert" parameterType="ActionPlanIssue" useGeneratedKeys="true" keyProperty="id">
<select id="findByKey" parameterType="long" resultType="ActionPlanIssue">
select <include refid="actionPlanColumns"/>
- from action_plans ap
+ from action_plans ap, projects p
<where>
- ap.kee=#{key}
+ and ap.kee=#{key}
+ and ap.project_id=p.id
</where>
</select>
<select id="findByKeys" parameterType="long" resultType="ActionPlanIssue">
select <include refid="actionPlanColumns"/>
- from action_plans ap
+ from action_plans ap, projects p
<where>
- <foreach collection="keys" open="ap.kee in (" close=")" item="list" separator=") or ap.kee in (" >
- <foreach collection="list" item="element" separator=",">
- #{element}
+ <foreach collection="keys" open="ap.kee in (" close=")" item="list" separator=") or ap.kee in (" >
+ <foreach collection="list" item="element" separator=",">
+ #{element}
+ </foreach>
</foreach>
- </foreach>
+ and ap.project_id=p.id
</where>
</select>
<select id="findOpenByProjectId" parameterType="long" resultType="ActionPlanIssue">
select <include refid="actionPlanColumns"/>
- from action_plans ap
+ from action_plans ap, projects p
<where>
and ap.project_id=#{projectId}
and ap.status='OPEN'
+ and ap.project_id=p.id
</where>
</select>
<select id="findByNameAndProjectId" parameterType="long" resultType="ActionPlanIssue">
select <include refid="actionPlanColumns"/>
- from action_plans ap
+ from action_plans ap, projects p
<where>
and ap.project_id=#{projectId}
and ap.name=#{name}
+ and ap.project_id=p.id
</where>
</select>
ap.status as status,
ap.deadline as deadLine,
ap.created_at as createdAt,
- ap.updated_at as updatedAt
+ ap.updated_at as updatedAt,
+ p.kee as projectKey
</sql>
<select id="findByProjectId" parameterType="map" resultType="ActionPlanStats">
select <include refid="actionPlanColumns"/>, count(total_issues.id) as totalIssues, count(open_issues.id) as openIssues
from action_plans ap
+ left join projects p on p.id = ap.project_id
left join issues total_issues on total_issues.action_plan_key = ap.kee
left join issues open_issues on open_issues.id = total_issues.id and open_issues.resolution is null
<where>
and ap.project_id = #{projectId}
</where>
- group by ap.id, ap.kee, ap.name, ap.description, ap.user_login, ap.project_id, ap.status, ap.deadline, ap.created_at, ap.updated_at
+ group by ap.id, ap.kee, ap.name, ap.description, ap.user_login, ap.project_id, ap.status, ap.deadline, ap.created_at, ap.updated_at, p.kee
order by ap.deadline asc
</select>
@Test
public void should_find_by_key() {
- setupData("should_find_by_key");
+ setupData("shared", "should_find_by_key");
ActionPlanDto result = dao.findByKey("ABC");
assertThat(result).isNotNull();
assertThat(result.getKey()).isEqualTo("ABC");
+ assertThat(result.getProjectKey()).isEqualTo("org.sonar.Sample");
}
@Test
public void should_find_by_keys() {
- setupData("should_find_by_keys");
+ setupData("shared", "should_find_by_keys");
Collection<ActionPlanDto> result = dao.findByKeys(newArrayList("ABC", "ABD", "ABE"));
assertThat(result).hasSize(3);
@Test
public void should_find_open_by_project_id() {
- setupData("should_find_open_by_project_id");
+ setupData("shared", "should_find_open_by_project_id");
Collection<ActionPlanDto> result = dao.findOpenByProjectId(1l);
assertThat(result).hasSize(2);
@Test
public void should_find_by_name_and_project_id() {
- setupData("should_find_by_name_and_project_id");
+ setupData("shared", "should_find_by_name_and_project_id");
Collection<ActionPlanDto> result = dao.findByNameAndProjectId("SHORT_TERM", 1l);
assertThat(result).hasSize(2);
@Test
public void should_find_by_project() {
- setupData("should_find_by_project");
+ setupData("shared", "should_find_by_project");
Collection<ActionPlanStatsDto> result = dao.findByProjectId(1l);
assertThat(result).isNotEmpty();
ActionPlanStatsDto actionPlanStatsDto = result.iterator().next();
+ assertThat(actionPlanStatsDto.getProjectKey()).isEqualTo("org.sonar.Sample");
assertThat(actionPlanStatsDto.getTotalIssues()).isEqualTo(3);
assertThat(actionPlanStatsDto.getOpenIssues()).isEqualTo(1);
}
--- /dev/null
+<dataset>
+
+ <projects id="1" kee="org.sonar.Sample" root_id="[null]" />
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <projects id="1" kee="org.sonar.Sample" root_id="[null]" />
+
+</dataset>
String name();
+ String projectKey();
+
@CheckForNull
String description();
this.resourceDao = resourceDao;
}
- public ActionPlan create(ActionPlan actionPlan, String projectKey){
- actionPlanDao.save(ActionPlanDto.toActionDto(actionPlan, findProject(projectKey).getId()));
+ public ActionPlan create(ActionPlan actionPlan){
+ actionPlanDao.save(ActionPlanDto.toActionDto(actionPlan, findProject(actionPlan.projectKey()).getId()));
return actionPlan;
}
- public ActionPlan update(ActionPlan actionPlan, String projectKey){
- actionPlanDao.update(ActionPlanDto.toActionDto(actionPlan, findProject(projectKey).getId()));
+ public ActionPlan update(ActionPlan actionPlan){
+ actionPlanDao.update(ActionPlanDto.toActionDto(actionPlan, findProject(actionPlan.projectKey()).getId()));
return actionPlan;
}
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.DefaultIssueBuilder;
import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
+import org.sonar.core.resource.ResourceQuery;
import org.sonar.server.platform.UserSession;
import java.text.SimpleDateFormat;
private final IssueService issueService;
private final IssueCommentService commentService;
private final ActionPlanService actionPlanService;
+ private final ResourceDao resourceDao;
public InternalRubyIssueService(IssueService issueService,
IssueCommentService commentService,
- ActionPlanService actionPlanService) {
+ ActionPlanService actionPlanService,
+ ResourceDao resourceDao) {
this.issueService = issueService;
this.commentService = commentService;
this.actionPlanService = actionPlanService;
+ this.resourceDao = resourceDao;
}
public List<Transition> listTransitions(String issueKey) {
public Result<ActionPlan> createActionPlan(Map<String, String> parameters) {
// TODO verify authorization
- // TODO check existence of projectKey
Result<ActionPlan> result = createActionPlanResult(parameters);
if (result.ok()) {
- result.setObject(actionPlanService.create(result.get(), parameters.get("projectKey")));
+ result.setObject(actionPlanService.create(result.get()));
}
return result;
}
public Result<ActionPlan> updateActionPlan(String key, Map<String, String> parameters) {
// TODO verify authorization
- // TODO check existence of projectKey
DefaultActionPlan existingActionPlan = (DefaultActionPlan) actionPlanService.findByKey(key);
- Result<ActionPlan> result = createActionPlanResult(parameters, existingActionPlan.name());
- if (result.ok()) {
- String projectKey = parameters.get("projectKey");
- DefaultActionPlan actionPlan = (DefaultActionPlan) result.get();
- actionPlan.setKey(existingActionPlan.key());
- actionPlan.setUserLogin(existingActionPlan.userLogin());
- result.setObject(actionPlanService.update(actionPlan, projectKey));
+ if (existingActionPlan == null) {
+ Result<ActionPlan> result = new Result<ActionPlan>();
+ result.addError("issues_action_plans.errors.action_plan_does_not_exists", key);
+ return result;
+ } else {
+ Result<ActionPlan> result = createActionPlanResult(parameters, existingActionPlan.name());
+ if (result.ok()) {
+ DefaultActionPlan actionPlan = (DefaultActionPlan) result.get();
+ actionPlan.setKey(existingActionPlan.key());
+ actionPlan.setUserLogin(existingActionPlan.userLogin());
+ result.setObject(actionPlanService.update(actionPlan));
+ }
+ return result;
}
- return result;
}
- public ActionPlan closeActionPlan(String actionPlanKey) {
+ public Result<ActionPlan> closeActionPlan(String actionPlanKey) {
// TODO verify authorization
- return actionPlanService.setStatus(actionPlanKey, ActionPlan.STATUS_CLOSED);
+ Result<ActionPlan> result = createResultForExistingActionPlan(actionPlanKey);
+ if (result.ok()) {
+ result.setObject(actionPlanService.setStatus(actionPlanKey, ActionPlan.STATUS_CLOSED));
+ }
+ return result;
}
- public ActionPlan openActionPlan(String actionPlanKey) {
+ public Result<ActionPlan> openActionPlan(String actionPlanKey) {
// TODO verify authorization
- return actionPlanService.setStatus(actionPlanKey, ActionPlan.STATUS_OPEN);
+ Result<ActionPlan> result = createResultForExistingActionPlan(actionPlanKey);
+ if (result.ok()) {
+ result.setObject(actionPlanService.setStatus(actionPlanKey, ActionPlan.STATUS_OPEN));
+ }
+ return result;
}
- public void deleteActionPlan(String actionPlanKey) {
+ public Result<ActionPlan> deleteActionPlan(String actionPlanKey) {
// TODO verify authorization
- actionPlanService.delete(actionPlanKey);
+ Result<ActionPlan> result = createResultForExistingActionPlan(actionPlanKey);
+ if (result.ok()) {
+ actionPlanService.delete(actionPlanKey);
+ }
+ return result;
}
@VisibleForTesting
String name = parameters.get("name");
String description = parameters.get("description");
String deadLineParam = parameters.get("deadLine");
- String projectParam = parameters.get("projectKey");
+ String projectParam = parameters.get("project");
Date deadLine = null;
if (Strings.isNullOrEmpty(name)) {
result.addError("errors.is_too_long", "description", 1000);
}
- if (Strings.isNullOrEmpty(projectParam)) {
+ if (Strings.isNullOrEmpty(projectParam) && oldName == null) {
result.addError("errors.cant_be_empty", "project");
+ } else {
+ ResourceDto project = resourceDao.getResource(ResourceQuery.create().setKey(projectParam));
+ if (project == null) {
+ result.addError("issues_action_plans.errors.project_does_not_exists", projectParam);
+ }
}
if (!Strings.isNullOrEmpty(deadLineParam)) {
result.addError("issues_action_plans.same_name_in_same_project");
}
- DefaultActionPlan actionPlan = DefaultActionPlan.create(name)
- .setDescription(description)
- .setUserLogin(UserSession.get().login())
- .setDeadLine(deadLine);
- result.setObject(actionPlan);
+ if (result.ok()) {
+ DefaultActionPlan actionPlan = DefaultActionPlan.create(name)
+ .setProjectKey(projectParam)
+ .setDescription(description)
+ .setUserLogin(UserSession.get().login())
+ .setDeadLine(deadLine);
+ result.setObject(actionPlan);
+ }
return result;
}
-}
+ private Result<ActionPlan> createResultForExistingActionPlan(String actionPlanKey) {
+ Result<ActionPlan> result = new Result<ActionPlan>();
+ if (findActionPlan(actionPlanKey) == null) {
+ result.addError("issues_action_plans.errors.action_plan_does_not_exists", actionPlanKey);
+ }
+ return result;
+ }
+}
\ No newline at end of file
class Api::ActionPlansController < Api::ApiController
+ before_filter :admin_required, :only => [ :create, :delete, :update, :close, :open ]
+
#
- # GET /api/issues/search?<parameters>
+ # GET /api/action_plan/show?key=<key>
#
# -- Example
- # curl -v -u admin:admin 'http://localhost:9000/api/issues/search?statuses=OPEN,RESOLVED'
+ # curl -v -u 'http://localhost:9000/api/action_plans/show?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
+ #
+ def show
+ require_parameters :key
+
+ action_plan = Internal.issues.findActionPlan(params[:key])
+ hash = {}
+ hash[:actionPlans] = action_plan_to_hash(action_plan) if action_plan
+
+ respond_to do |format|
+ format.json { render :json => jsonp(hash) }
+ format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'actionPlans') }
+ end
+ end
+
+
+ #
+ # GET /api/action_plans/search?project=<project>
+ #
+ # -- Example
+ # curl -v -u 'http://localhost:9000/api/action_plans/search?project=org.sonar.Sample'
#
def search
+ require_parameters :project
+
+ action_plans = Internal.issues.findActionPlanStats(params[:project])
+ hash = {:actionPlans => action_plans.map { |plan| action_plan_to_hash(plan)}}
+
+ respond_to do |format|
+ format.json { render :json => jsonp(hash) }
+ format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'actionPlans') }
+ end
+ end
+
+ #
+ # POST /api/action_plans/create
+ #
+ # -- Mandatory parameters
+ # 'name' is the action plan name
+ # 'project' is the project key to link the action plan to
+ #
+ # -- Optional parameters
+ # 'description' is the plain-text description
+ # 'deadLine' is the due date of the action plan. Format is 'day/month/year', for instance, '31/12/2013'.
+ #
+ # -- Example
+ # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/create?name=Current&project=org.sonar.Sample'
+ #
+ def create
+ verify_post_request
+ require_parameters :project, :name
+
+ result = Internal.issues.createActionPlan(params)
+ if result.ok()
+ action_plan = result.get()
+ render :json => jsonp({:actionPlan => action_plan_to_hash(action_plan)})
+ else
+ render_error(result)
+ end
+ end
+
+ #
+ # POST /api/action_plans/delete
+ #
+ # -- Mandatory parameters
+ # 'key' is the action plan key
+ #
+ # -- Example
+ # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/delete?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
+ #
+ def delete
+ verify_post_request
+ require_parameters :key
+
+ result = Internal.issues.deleteActionPlan(params[:key])
+ if result.ok()
+ render_success('Action plan deleted')
+ else
+ render_error(result)
+ end
+ end
+
+ #
+ # POST /api/action_plans/update
+ #
+ # -- Optional parameters
+ # 'name' is the action plan name
+ # 'project' is the project key to link the action plan to
+ # 'description' is the plain-text description
+ # 'deadLine' is the due date of the action plan. Format is 'day/month/year', for instance, '31/12/2013'.
+ #
+ # -- Example
+ # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/update?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0&name=Current'
+ #
+ def update
+ verify_post_request
+ require_parameters :key
+
+ result = Internal.issues.updateActionPlan(params[:key], params)
+ if result.ok()
+ action_plan = result.get()
+ render :json => jsonp({:actionPlan => action_plan_to_hash(action_plan)})
+ else
+ render_error(result)
+ end
+ end
+
+ #
+ # POST /api/action_plans/close
+ #
+ # -- Mandatory parameters
+ # 'key' is the action plan key
+ #
+ # -- Example
+ # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/close?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
+ #
+ def close
+ verify_post_request
+ require_parameters :key
+
+ result = Internal.issues.closeActionPlan(params[:key])
+ if result.ok()
+ action_plan = result.get()
+ render :json => jsonp({:actionPlan => action_plan_to_hash(action_plan)})
+ else
+ render_error(result)
+ end
+ end
+
+ #
+ # POST /api/action_plans/open
+ #
+ # -- Mandatory parameters
+ # 'key' is the action plan key
+ #
+ # -- Example
+ # curl -X POST -v -u admin:admin 'http://localhost:9000/api/action_plans/open?key=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
+ #
+ def open
+ verify_post_request
+ require_parameters :key
+
+ result = Internal.issues.openActionPlan(params[:key])
+ if result.ok()
+ action_plan = result.get()
+ render :json => jsonp({:actionPlan => action_plan_to_hash(action_plan)})
+ else
+ render_error(result)
+ end
+ end
+
+
+ private
+
+ def action_plan_to_hash(action_plan)
+ hash = {:key => action_plan.key(), :name => action_plan.name(), :status => action_plan.status()}
+ hash[:project] = action_plan.projectKey() if action_plan.projectKey() && !action_plan.projectKey().blank?
+ hash[:desc] = action_plan.description() if action_plan.description() && !action_plan.description().blank?
+ hash[:userLogin] = action_plan.userLogin() if action_plan.userLogin()
+ hash[:deadLine] = Api::Utils.format_datetime(action_plan.deadLine()) if action_plan.deadLine()
+ hash[:totalIssues] = action_plan.totalIssues() if action_plan.respond_to?('totalIssues')
+ hash[:openIssues] = action_plan.openIssues() if action_plan.respond_to?('openIssues')
+ hash[:createdAt] = Api::Utils.format_datetime(action_plan.createdAt()) if action_plan.createdAt()
+ hash[:updatedAt] = Api::Utils.format_datetime(action_plan.updatedAt()) if action_plan.updatedAt()
+ hash
+ end
+
+ def error_to_hash(msg)
+ {:msg => message(msg.text(), {:params => msg.params()}).capitalize}
+ end
+ def render_error(result)
+ hash = {:errors => result.errors().map { |error| error_to_hash(error) }}
+ respond_to do |format|
+ format.json { render :json => jsonp(hash), :status => 400}
+ format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'errors', :status => 400)}
+ end
end
end
\ No newline at end of file
end
def save
- options = {'projectKey' => @resource.key, 'name' => params[:name], 'description' => params[:description], 'deadLine' => params[:deadline]}
+ options = {'project' => @resource.key, 'name' => params[:name], 'description' => params[:description], 'deadLine' => params[:deadline]}
exiting_action_plan = find_by_key(params[:plan_key]) unless params[:plan_key].blank?
if exiting_action_plan
<%
@closed_action_plans.each do |plan|
deadline = Api::Utils.java_to_ruby_datetime(plan.deadLine()) if plan.deadLine()
- updated_at = Api::Utils.java_to_ruby_datetime(plan.updateDate())
+ updated_at = Api::Utils.java_to_ruby_datetime(plan.updatedAt())
%>
<tr>
<td class="thin nowrap center"><img src="<%= ApplicationController.root_context -%>/images/status/<%= plan.status() -%>.png" title="<%= message(plan.status()) -%>"/></td>
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
ActionPlan actionPlan = DefaultActionPlan.create("Long term");
- actionPlanService.create(actionPlan, "org.sonar.Sample");
+ actionPlanService.create(actionPlan);
verify(actionPlanDao).save(any(ActionPlanDto.class));
}
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.sonar.api.issue.ActionPlan;
+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 java.util.Map;
public class InternalRubyIssueServiceTest {
private InternalRubyIssueService internalRubyIssueService;
-
private IssueService issueService = mock(IssueService.class);
private IssueCommentService commentService = mock(IssueCommentService.class);
private ActionPlanService actionPlanService = mock(ActionPlanService.class);
+ private ResourceDao resourceDao = mock(ResourceDao.class);
@Before
- public void before(){
- internalRubyIssueService = new InternalRubyIssueService(issueService, commentService, actionPlanService);
+ public void before() {
+ ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
+ when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project);
+ internalRubyIssueService = new InternalRubyIssueService(issueService, commentService, actionPlanService, resourceDao);
}
@Test
- public void should_create_action_plan(){
+ public void should_create_action_plan() {
Map<String, String> parameters = newHashMap();
parameters.put("name", "Long term");
parameters.put("description", "Long term issues");
- parameters.put("projectKey", "org.sonar.Sample");
+ parameters.put("project", "org.sonar.Sample");
parameters.put("deadLine", "13/05/2113");
ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
Result result = internalRubyIssueService.createActionPlan(parameters);
assertThat(result.ok()).isTrue();
- verify(actionPlanService).create(actionPlanCaptor.capture(), eq("org.sonar.Sample"));
+ verify(actionPlanService).create(actionPlanCaptor.capture());
ActionPlan actionPlan = actionPlanCaptor.getValue();
assertThat(actionPlan).isNotNull();
}
@Test
- public void should_get_error_on_action_plan_result_when_no_project(){
+ public void should_update_action_plan() {
+ when(actionPlanService.findByKey("ABCD")).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "New Long term");
+ parameters.put("description", "New Long term issues");
+ parameters.put("deadLine", "13/05/2113");
+
+ ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
+ Result result = internalRubyIssueService.updateActionPlan("ABCD", parameters);
+ assertThat(result.ok()).isTrue();
+
+ verify(actionPlanService).update(actionPlanCaptor.capture());
+ ActionPlan actionPlan = actionPlanCaptor.getValue();
+
+ assertThat(actionPlan).isNotNull();
+ assertThat(actionPlan.key()).isNotNull();
+ assertThat(actionPlan.name()).isEqualTo("New Long term");
+ assertThat(actionPlan.description()).isEqualTo("New Long term issues");
+ assertThat(actionPlan.deadLine()).isNotNull();
+ }
+
+ @Test
+ public void should_update_action_plan_with_new_project() {
+ when(actionPlanService.findByKey("ABCD")).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "New Long term");
+ parameters.put("description", "New Long term issues");
+ parameters.put("deadLine", "13/05/2113");
+ parameters.put("project", "org.sonar.MultiSample");
+
+ ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
+ Result result = internalRubyIssueService.updateActionPlan("ABCD", parameters);
+ assertThat(result.ok()).isTrue();
+
+ verify(actionPlanService).update(actionPlanCaptor.capture());
+ ActionPlan actionPlan = actionPlanCaptor.getValue();
+
+ assertThat(actionPlan).isNotNull();
+ assertThat(actionPlan.key()).isNotNull();
+ assertThat(actionPlan.name()).isEqualTo("New Long term");
+ assertThat(actionPlan.description()).isEqualTo("New Long term issues");
+ assertThat(actionPlan.deadLine()).isNotNull();
+ assertThat(actionPlan.projectKey()).isEqualTo("org.sonar.MultiSample");
+ }
+
+ @Test
+ public void should_not_update_action_plan_when_action_plan_is_not_found() {
+ when(actionPlanService.findByKey("ABCD")).thenReturn(null);
+
+ Result result = internalRubyIssueService.updateActionPlan("ABCD", null);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(new Result.Message("issues_action_plans.errors.action_plan_does_not_exists", "ABCD"));
+ }
+
+ @Test
+ public void should_delete_action_plan() {
+ when(actionPlanService.findByKey("ABCD")).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Result result = internalRubyIssueService.deleteActionPlan("ABCD");
+ verify(actionPlanService).delete("ABCD");
+ assertThat(result.ok()).isTrue();
+ }
+
+ @Test
+ public void should_not_delete_action_plan_if_action_plan_not_found() {
+ when(actionPlanService.findByKey("ABCD")).thenReturn(null);
+
+ Result result = internalRubyIssueService.deleteActionPlan("ABCD");
+ verify(actionPlanService, never()).delete("ABCD");
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(new Result.Message("issues_action_plans.errors.action_plan_does_not_exists", "ABCD"));
+ }
+
+ @Test
+ public void should_close_action_plan() {
+ when(actionPlanService.findByKey("ABCD")).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Result result = internalRubyIssueService.closeActionPlan("ABCD");
+ verify(actionPlanService).setStatus(eq("ABCD"), eq("CLOSED"));
+ assertThat(result.ok()).isTrue();
+ }
+
+ @Test
+ public void should_open_action_plan() {
+ when(actionPlanService.findByKey("ABCD")).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Result result = internalRubyIssueService.openActionPlan("ABCD");
+ verify(actionPlanService).setStatus(eq("ABCD"), eq("OPEN"));
+ assertThat(result.ok()).isTrue();
+ }
+
+ @Test
+ public void should_get_error_on_action_plan_result_when_no_project() {
Map<String, String> parameters = newHashMap();
parameters.put("name", "Long term");
parameters.put("description", "Long term issues");
}
@Test
- public void should_get_error_on_action_plan_result_when_no_name(){
+ public void should_get_error_on_action_plan_result_when_no_name() {
Map<String, String> parameters = newHashMap();
parameters.put("name", null);
parameters.put("description", "Long term issues");
- parameters.put("projectKey", "org.sonar.Sample");
+ parameters.put("project", "org.sonar.Sample");
Result result = internalRubyIssueService.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
}
@Test
- public void should_get_error_on_action_plan_result_when_name_is_too_long(){
+ public void should_get_error_on_action_plan_result_when_name_is_too_long() {
Map<String, String> parameters = newHashMap();
parameters.put("name", createLongString(201));
parameters.put("description", "Long term issues");
- parameters.put("projectKey", "org.sonar.Sample");
+ parameters.put("project", "org.sonar.Sample");
Result result = internalRubyIssueService.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
}
@Test
- public void should_get_error_on_action_plan_result_when_description_is_too_long(){
+ public void should_get_error_on_action_plan_result_when_description_is_too_long() {
Map<String, String> parameters = newHashMap();
parameters.put("name", "Long term");
parameters.put("description", createLongString(1001));
- parameters.put("projectKey", "org.sonar.Sample");
+ parameters.put("project", "org.sonar.Sample");
Result result = internalRubyIssueService.createActionPlanResult(parameters);
assertThat(result.ok()).isFalse();
}
@Test
- public void should_get_error_on_action_plan_result_when_dead_line_use_wrong_format(){
+ public void should_get_error_on_action_plan_result_when_dead_line_use_wrong_format() {
Map<String, String> parameters = newHashMap();
parameters.put("name", "Long term");
parameters.put("description", "Long term issues");
- parameters.put("projectKey", "org.sonar.Sample");
+ parameters.put("project", "org.sonar.Sample");
parameters.put("deadLine", "2013-05-18");
Result result = internalRubyIssueService.createActionPlanResult(parameters);
}
@Test
- public void should_get_error_on_action_plan_result_when_dead_line_is_in_the_past(){
+ public void should_get_error_on_action_plan_result_when_dead_line_is_in_the_past() {
Map<String, String> parameters = newHashMap();
parameters.put("name", "Long term");
parameters.put("description", "Long term issues");
- parameters.put("projectKey", "org.sonar.Sample");
+ parameters.put("project", "org.sonar.Sample");
parameters.put("deadLine", "01/01/2000");
Result result = internalRubyIssueService.createActionPlanResult(parameters);
}
@Test
- public void should_get_error_on_action_plan_result_when_name_is_already_used_for_project(){
+ public void should_get_error_on_action_plan_result_when_name_is_already_used_for_project() {
Map<String, String> parameters = newHashMap();
parameters.put("name", "Long term");
parameters.put("description", "Long term issues");
- parameters.put("projectKey", "org.sonar.Sample");
+ parameters.put("project", "org.sonar.Sample");
when(actionPlanService.isNameAlreadyUsedForProject(anyString(), anyString())).thenReturn(true);
assertThat(result.errors()).contains(new Result.Message("issues_action_plans.same_name_in_same_project"));
}
- public String createLongString(int size){
+ @Test
+ public void should_get_error_on_action_plan_result_when_project_not_found() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+
+ when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null);
+
+ Result result = internalRubyIssueService.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(new Result.Message("issues_action_plans.errors.project_does_not_exists", "org.sonar.Sample"));
+ }
+ public String createLongString(int size) {
String result = "";
- for (int i = 0; i<size; i++) {
+ for (int i = 0; i < size; i++) {
result += "c";
}
return result;