]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5179 Project administrator cannot create action plans
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 7 Apr 2014 13:14:51 +0000 (15:14 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 7 Apr 2014 13:20:08 +0000 (15:20 +0200)
sonar-server/src/main/java/org/sonar/server/issue/ActionPlanService.java
sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
sonar-server/src/main/webapp/WEB-INF/app/views/action_plans/index.html.erb
sonar-server/src/test/java/org/sonar/server/issue/ActionPlanServiceTest.java
sonar-server/src/test/java/org/sonar/server/issue/ActionServiceTest.java
sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java

index 4d0f6eeca1478c615ed19d4e9da94da1d5bfb51a..4ddaec8baf3f1515800feca94774306e13fabbae 100644 (file)
@@ -36,10 +36,11 @@ import org.sonar.core.issue.db.*;
 import org.sonar.core.resource.ResourceDao;
 import org.sonar.core.resource.ResourceDto;
 import org.sonar.core.resource.ResourceQuery;
-import org.sonar.core.user.AuthorizationDao;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UserSession;
 
 import javax.annotation.CheckForNull;
+
 import java.util.*;
 
 import static com.google.common.collect.Lists.newArrayList;
@@ -52,17 +53,15 @@ public class ActionPlanService implements ServerComponent {
   private final ActionPlanDao actionPlanDao;
   private final ActionPlanStatsDao actionPlanStatsDao;
   private final ResourceDao resourceDao;
-  private final AuthorizationDao authorizationDao;
   private final IssueDao issueDao;
   private final IssueUpdater issueUpdater;
   private final IssueStorage issueStorage;
 
-  public ActionPlanService(ActionPlanDao actionPlanDao, ActionPlanStatsDao actionPlanStatsDao, ResourceDao resourceDao, AuthorizationDao authorizationDao,
+  public ActionPlanService(ActionPlanDao actionPlanDao, ActionPlanStatsDao actionPlanStatsDao, ResourceDao resourceDao,
                            IssueDao issueDao, IssueUpdater issueUpdater, IssueStorage issueStorage) {
     this.actionPlanDao = actionPlanDao;
     this.actionPlanStatsDao = actionPlanStatsDao;
     this.resourceDao = resourceDao;
-    this.authorizationDao = authorizationDao;
     this.issueDao = issueDao;
     this.issueUpdater = issueUpdater;
     this.issueStorage = issueStorage;
@@ -70,21 +69,21 @@ public class ActionPlanService implements ServerComponent {
 
   public ActionPlan create(ActionPlan actionPlan, UserSession userSession) {
     ResourceDto project = findProject(actionPlan.projectKey());
-    checkAuthorization(userSession, project, UserRole.ADMIN);
+    checkUserIsProjectAdministrator(project.getKey(), userSession);
     actionPlanDao.save(ActionPlanDto.toActionDto(actionPlan, project.getId()));
     return actionPlan;
   }
 
   public ActionPlan update(ActionPlan actionPlan, UserSession userSession) {
     ResourceDto project = findProject(actionPlan.projectKey());
-    checkAuthorization(userSession, project, UserRole.ADMIN);
+    checkUserIsProjectAdministrator(project.getKey(), userSession);
     actionPlanDao.update(ActionPlanDto.toActionDto(actionPlan, project.getId()));
     return actionPlan;
   }
 
   public void delete(String actionPlanKey, UserSession userSession) {
     ActionPlanDto dto = findActionPlanDto(actionPlanKey);
-    checkAuthorization(userSession, dto.getProjectKey(), UserRole.ADMIN);
+    checkUserIsProjectAdministrator(dto.getProjectKey(), userSession);
     unplanIssues(dto.toActionPlan(), userSession);
     actionPlanDao.delete(actionPlanKey);
   }
@@ -111,7 +110,7 @@ public class ActionPlanService implements ServerComponent {
 
   public ActionPlan setStatus(String actionPlanKey, String status, UserSession userSession) {
     ActionPlanDto actionPlanDto = findActionPlanDto(actionPlanKey);
-    checkAuthorization(userSession, actionPlanDto.getProjectKey(), UserRole.ADMIN);
+    checkUserIsProjectAdministrator(actionPlanDto.getProjectKey(), userSession);
 
     actionPlanDto.setStatus(status);
     actionPlanDto.setCreatedAt(new Date());
@@ -125,7 +124,7 @@ public class ActionPlanService implements ServerComponent {
     if (actionPlanDto == null) {
       return null;
     }
-    checkAuthorization(userSession, actionPlanDto.getProjectKey(), UserRole.USER);
+    checkUserCanAccessProject(actionPlanDto.getProjectKey(), userSession);
     return actionPlanDto.toActionPlan();
   }
 
@@ -136,7 +135,7 @@ public class ActionPlanService implements ServerComponent {
 
   public Collection<ActionPlan> findOpenByProjectKey(String projectKey, UserSession userSession) {
     ResourceDto project = findProject(projectKey);
-    checkAuthorization(userSession, project, UserRole.USER);
+    checkUserCanAccessProject(project.getKey(), userSession);
 
     List<ActionPlanDto> dtos = actionPlanDao.findOpenByProjectId(project.getId());
     List<ActionPlan> plans = toActionPlans(dtos);
@@ -146,7 +145,7 @@ public class ActionPlanService implements ServerComponent {
 
   public List<ActionPlanStats> findActionPlanStats(String projectKey, UserSession userSession) {
     ResourceDto project = findProject(projectKey);
-    checkAuthorization(userSession, project, UserRole.USER);
+    checkUserCanAccessProject(project.getKey(), userSession);
 
     List<ActionPlanStatsDto> actionPlanStatsDtos = actionPlanStatsDao.findByProjectId(project.getId());
     List<ActionPlanStats> actionPlanStats = newArrayList(Iterables.transform(actionPlanStatsDtos, new Function<ActionPlanStatsDto, ActionPlanStats>() {
@@ -175,8 +174,7 @@ public class ActionPlanService implements ServerComponent {
   private ActionPlanDto findActionPlanDto(String actionPlanKey) {
     ActionPlanDto actionPlanDto = actionPlanDao.findByKey(actionPlanKey);
     if (actionPlanDto == null) {
-      // TODO throw 404
-      throw new IllegalArgumentException("Action plan " + actionPlanKey + " has not been found.");
+      throw new NotFoundException("Action plan " + actionPlanKey + " has not been found.");
     }
     return actionPlanDto;
   }
@@ -184,21 +182,17 @@ public class ActionPlanService implements ServerComponent {
   private ResourceDto findProject(String projectKey) {
     ResourceDto resourceDto = resourceDao.getResource(ResourceQuery.create().setKey(projectKey));
     if (resourceDto == null) {
-      // TODO throw 404
-      throw new IllegalArgumentException("Project " + projectKey + " does not exists.");
+      throw new NotFoundException("Project " + projectKey + " does not exists.");
     }
     return resourceDto;
   }
 
-  private void checkAuthorization(UserSession userSession, String projectKey, String requiredRole) {
-    checkAuthorization(userSession, findProject(projectKey), requiredRole);
+  private void checkUserCanAccessProject(String projectKey, UserSession userSession) {
+    userSession.checkProjectPermission(UserRole.USER, projectKey);
   }
 
-  private void checkAuthorization(UserSession userSession, ResourceDto project, String requiredRole) {
-    if (!authorizationDao.isAuthorizedComponentKey(project.getKey(), userSession.userId(), requiredRole)) {
-      // TODO throw unauthorized
-      throw new IllegalStateException("User does not have the required role on the project: " + project.getKey());
-    }
+  private void checkUserIsProjectAdministrator(String projectKey, UserSession userSession) {
+    userSession.checkProjectPermission(UserRole.ADMIN, projectKey);
   }
 
 }
index 2ec80be5110ad4bf7a46df658e36e94434018565..bef324ee95fc35f17b3869b158cb7fe5a5d54ca7 100644 (file)
@@ -65,6 +65,8 @@ import java.util.Map;
 import static com.google.common.collect.Lists.newArrayList;
 
 /**
+ * Used through ruby code <pre>Internal.issues</pre>
+ *
  * All the issue features that are not published to public API.
  *
  * @since 3.6
index 9e7d5e512df0bc43be701edb6b147027bd710ebf..882fd3bc3dd74938d114c7561546dae0a3d16d3c 100644 (file)
@@ -1,5 +1,5 @@
 <div>
-  <% if profiles_administrator? %>
+  <% if is_admin?(@resource.id) %>
   <ul style="float: right" class="horizontal">
     <li class="marginleft10 add">
       <a id="create-link-action_plans"
index d986ff3da92619fd4793a9418c3131329d7cc03d..4ceb7c0560eac5ef0dd278edfc813e0a0925b7dd 100644 (file)
@@ -22,7 +22,10 @@ package org.sonar.server.issue;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
 import org.sonar.api.issue.ActionPlan;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.issue.IssueQuery;
@@ -36,7 +39,9 @@ import org.sonar.core.issue.db.*;
 import org.sonar.core.resource.ResourceDao;
 import org.sonar.core.resource.ResourceDto;
 import org.sonar.core.resource.ResourceQuery;
-import org.sonar.core.user.AuthorizationDao;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.MockUserSession;
 import org.sonar.server.user.UserSession;
 
 import java.util.Collection;
@@ -45,127 +50,129 @@ import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.assertions.Fail.fail;
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.*;
 
+@RunWith(MockitoJUnitRunner.class)
 public class ActionPlanServiceTest {
 
-  private ActionPlanDao actionPlanDao = mock(ActionPlanDao.class);
-  private ActionPlanStatsDao actionPlanStatsDao = mock(ActionPlanStatsDao.class);
-  private ResourceDao resourceDao = mock(ResourceDao.class);
-  private AuthorizationDao authorizationDao = mock(AuthorizationDao.class);
-  private UserSession userSession = mock(UserSession.class);
-  private IssueDao issueDao = mock(IssueDao.class);
-  private IssueUpdater issueUpdater = mock(IssueUpdater.class);
-  private IssueStorage issueStorage = mock(IssueStorage.class);
+  @Mock
+  ActionPlanDao actionPlanDao;
+
+  @Mock
+  ActionPlanStatsDao actionPlanStatsDao;
+
+  @Mock
+  ResourceDao resourceDao;
+
+  @Mock
+  IssueDao issueDao;
+
+  @Mock
+  IssueUpdater issueUpdater;
+
+  @Mock
+  IssueStorage issueStorage;
+
+  String projectKey = "org.sonar.Sample";
+
+  UserSession projectAdministratorUserSession = MockUserSession.create().setLogin("nicolas").setName("Nicolas").addProjectPermissions(UserRole.ADMIN, projectKey);
+  UserSession projectUserSession = MockUserSession.create().setLogin("nicolas").setName("Nicolas").addProjectPermissions(UserRole.USER, projectKey);
+  UserSession unauthorizedUserSession = MockUserSession.create().setLogin("nicolas").setName("Nicolas");
 
   private ActionPlanService actionPlanService;
 
   @Before
   public void before() {
-    when(userSession.isLoggedIn()).thenReturn(true);
-    when(userSession.userId()).thenReturn(10);
-    when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(true);
-
-    actionPlanService = new ActionPlanService(actionPlanDao, actionPlanStatsDao, resourceDao, authorizationDao, issueDao, issueUpdater, issueStorage);
+    actionPlanService = new ActionPlanService(actionPlanDao, actionPlanStatsDao, resourceDao, issueDao, issueUpdater, issueStorage);
   }
 
   @Test
-  public void should_create() {
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void create() {
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
     ActionPlan actionPlan = DefaultActionPlan.create("Long term");
 
-    actionPlanService.create(actionPlan, userSession);
+    actionPlanService.create(actionPlan, projectAdministratorUserSession);
     verify(actionPlanDao).save(any(ActionPlanDto.class));
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.ADMIN));
   }
 
   @Test
-  public void should_create_required_admin_role() {
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void create_required_admin_role() {
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
     ActionPlan actionPlan = DefaultActionPlan.create("Long term");
-    when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(false);
 
     try {
-      actionPlanService.create(actionPlan, userSession);
+      actionPlanService.create(actionPlan, unauthorizedUserSession);
       fail();
     } catch (Exception e) {
-      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("User does not have the required role on the project: org.sonar.Sample");
+      assertThat(e).isInstanceOf(ForbiddenException.class);
     }
-    verify(authorizationDao).isAuthorizedComponentKey(eq("org.sonar.Sample"), eq(10), eq(UserRole.ADMIN));
     verifyZeroInteractions(actionPlanDao);
   }
 
   @Test
-  public void should_set_status() {
-    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD"));
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void set_status() {
+    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD").setProjectKey_unit_test_only(projectKey));
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
 
-    ActionPlan result = actionPlanService.setStatus("ABCD", "CLOSED", userSession);
+    ActionPlan result = actionPlanService.setStatus("ABCD", "CLOSED", projectAdministratorUserSession);
     verify(actionPlanDao).update(any(ActionPlanDto.class));
 
     assertThat(result).isNotNull();
     assertThat(result.status()).isEqualTo("CLOSED");
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.ADMIN));
   }
 
   @Test
-  public void should_update() {
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void update() {
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
     ActionPlan actionPlan = DefaultActionPlan.create("Long term");
 
-    actionPlanService.update(actionPlan, userSession);
+    actionPlanService.update(actionPlan, projectAdministratorUserSession);
     verify(actionPlanDao).update(any(ActionPlanDto.class));
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.ADMIN));
   }
 
   @Test
-  public void should_delete() {
-    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD"));
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
-    actionPlanService.delete("ABCD", userSession);
+  public void delete() {
+    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD").setProjectKey_unit_test_only(projectKey));
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
+    actionPlanService.delete("ABCD", projectAdministratorUserSession);
     verify(actionPlanDao).delete("ABCD");
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.ADMIN));
   }
 
   @Test
-  public void should_unplan_all_linked_issues_when_deleting_an_action_plan() {
-    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD"));
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void unplan_all_linked_issues_when_deleting_an_action_plan() {
+    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD").setProjectKey_unit_test_only(projectKey));
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
 
     IssueDto issueDto = new IssueDto().setId(100L).setStatus(Issue.STATUS_OPEN).setRuleKey_unit_test_only("squid", "s100");
     when(issueDao.selectIssues(any(IssueQuery.class))).thenReturn(newArrayList(issueDto));
     when(issueUpdater.plan(any(DefaultIssue.class), eq((ActionPlan) null), any(IssueChangeContext.class))).thenReturn(true);
 
     ArgumentCaptor<DefaultIssue> captor = ArgumentCaptor.forClass(DefaultIssue.class);
-    actionPlanService.delete("ABCD", userSession);
+    actionPlanService.delete("ABCD", projectAdministratorUserSession);
     verify(actionPlanDao).delete("ABCD");
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.ADMIN));
     verify(issueUpdater).plan(captor.capture(), eq((ActionPlan) null), any(IssueChangeContext.class));
     verify(issueStorage).save(newArrayList(captor.getAllValues()));
   }
 
   @Test
-  public void should_find_by_key() {
-    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD"));
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void find_by_key() {
+    when(actionPlanDao.findByKey("ABCD")).thenReturn(new ActionPlanDto().setKey("ABCD").setProjectKey_unit_test_only(projectKey));
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
 
-    ActionPlan result = actionPlanService.findByKey("ABCD", userSession);
+    ActionPlan result = actionPlanService.findByKey("ABCD", projectUserSession);
     assertThat(result).isNotNull();
     assertThat(result.key()).isEqualTo("ABCD");
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.USER));
   }
 
   @Test
-  public void should_return_null_if_no_action_plan_when_find_by_key() {
+  public void return_null_if_no_action_plan_when_find_by_key() {
     when(actionPlanDao.findByKey("ABCD")).thenReturn(null);
-    assertThat(actionPlanService.findByKey("ABCD", userSession)).isNull();
+    assertThat(actionPlanService.findByKey("ABCD", projectUserSession)).isNull();
   }
 
   @Test
-  public void should_find_by_keys() {
+  public void find_by_keys() {
     when(actionPlanDao.findByKeys(newArrayList("ABCD"))).thenReturn(newArrayList(new ActionPlanDto().setKey("ABCD")));
     Collection<ActionPlan> results = actionPlanService.findByKeys(newArrayList("ABCD"));
     assertThat(results).hasSize(1);
@@ -173,52 +180,48 @@ public class ActionPlanServiceTest {
   }
 
   @Test
-  public void should_find_open_by_project_key() {
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void find_open_by_project_key() {
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
     when(actionPlanDao.findOpenByProjectId(1l)).thenReturn(newArrayList(new ActionPlanDto().setKey("ABCD")));
-    Collection<ActionPlan> results = actionPlanService.findOpenByProjectKey("org.sonar.Sample", userSession);
+    Collection<ActionPlan> results = actionPlanService.findOpenByProjectKey(projectKey, projectUserSession);
     assertThat(results).hasSize(1);
     assertThat(results.iterator().next().key()).isEqualTo("ABCD");
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.USER));
   }
 
   @Test
-  public void should_find_open_by_project_key_required_user_role() {
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey("org.sonar.Sample").setId(1l));
+  public void find_open_by_project_key_required_user_role() {
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setKey(projectKey).setId(1l));
     when(actionPlanDao.findOpenByProjectId(1l)).thenReturn(newArrayList(new ActionPlanDto().setKey("ABCD")));
-    when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(false);
 
     try {
-      actionPlanService.findOpenByProjectKey("org.sonar.Sample", userSession);
+      actionPlanService.findOpenByProjectKey(projectKey, unauthorizedUserSession);
       fail();
     } catch (Exception e) {
-      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("User does not have the required role on the project: org.sonar.Sample");
+      assertThat(e).isInstanceOf(ForbiddenException.class);
     }
-    verify(authorizationDao).isAuthorizedComponentKey(eq("org.sonar.Sample"), eq(10), eq(UserRole.USER));
     verifyZeroInteractions(actionPlanDao);
   }
 
-  @Test(expected = IllegalArgumentException.class)
-  public void should_throw_exception_if_project_not_found_when_find_open_by_project_key() {
+  @Test(expected = NotFoundException.class)
+  public void throw_exception_if_project_not_found_when_find_open_by_project_key() {
     when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null);
-    actionPlanService.findOpenByProjectKey("<Unkown>", userSession);
+    actionPlanService.findOpenByProjectKey("<Unkown>", projectUserSession);
   }
 
   @Test
-  public void should_find_action_plan_stats() {
-    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setId(1L).setKey("org.sonar.Sample"));
+  public void find_action_plan_stats() {
+    when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setId(1L).setKey(projectKey));
     when(actionPlanStatsDao.findByProjectId(1L)).thenReturn(newArrayList(new ActionPlanStatsDto()));
 
-    Collection<ActionPlanStats> results = actionPlanService.findActionPlanStats("org.sonar.Sample", userSession);
+    Collection<ActionPlanStats> results = actionPlanService.findActionPlanStats(projectKey, projectUserSession);
     assertThat(results).hasSize(1);
-    verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.USER));
   }
 
-  @Test(expected = IllegalArgumentException.class)
-  public void should_throw_exception_if_project_not_found_when_find_open_action_plan_stats() {
+  @Test(expected = NotFoundException.class)
+  public void throw_exception_if_project_not_found_when_find_open_action_plan_stats() {
     when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null);
 
-    actionPlanService.findActionPlanStats("org.sonar.Sample", userSession);
+    actionPlanService.findActionPlanStats(projectKey, projectUserSession);
   }
 
 }
index 1e6996d94ee5a32a88c849af4ce6647af2c4ae6d..85190eebe4e9bff89f41732f59a9dcfa8ee4a61f 100644 (file)
@@ -71,7 +71,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_execute_functions() {
+  public void execute_functions() {
     Function function1 = mock(Function.class);
     Function function2 = mock(Function.class);
 
@@ -92,7 +92,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_modify_issue_when_executing_a_function() {
+  public void modify_issue_when_executing_a_function() {
     Function function = new TweetFunction();
 
     UserSession userSession = mock(UserSession.class);
@@ -113,7 +113,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_inject_project_settings_when_executing_a_function() {
+  public void inject_project_settings_when_executing_a_function() {
     Function function = new TweetFunction();
 
     UserSession userSession = mock(UserSession.class);
@@ -135,7 +135,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_not_execute_function_if_issue_not_found() {
+  public void not_execute_function_if_issue_not_found() {
     Function function = mock(Function.class);
 
     IssueQueryResult issueQueryResult = new DefaultIssueQueryResult(Collections.<Issue>emptyList());
@@ -152,7 +152,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_not_execute_function_if_action_not_found() {
+  public void not_execute_function_if_action_not_found() {
     Function function = mock(Function.class);
 
     Issue issue = new DefaultIssue().setKey("ABCD");
@@ -170,7 +170,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_not_execute_function_if_action_is_not_supported() {
+  public void not_execute_function_if_action_is_not_supported() {
     Function function = mock(Function.class);
 
     Issue issue = new DefaultIssue().setKey("ABCD");
@@ -188,7 +188,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_list_available_supported_actions() {
+  public void list_available_supported_actions() {
     Issue issue = new DefaultIssue().setKey("ABCD");
     IssueQueryResult issueQueryResult = new DefaultIssueQueryResult(newArrayList(issue));
     when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
@@ -199,7 +199,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_list_available_actions_throw_exception_if_issue_not_found() {
+  public void list_available_actions_throw_exception_if_issue_not_found() {
     IssueQueryResult issueQueryResult = new DefaultIssueQueryResult(Collections.<Issue>emptyList());
     when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
 
@@ -214,7 +214,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_return_no_action() {
+  public void return_no_action() {
     Issue issue = new DefaultIssue().setKey("ABCD");
     IssueQueryResult issueQueryResult = new DefaultIssueQueryResult(newArrayList(issue));
     when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
@@ -223,7 +223,7 @@ public class ActionServiceTest {
   }
 
   @Test
-  public void should_get_project_settings(){
+  public void get_project_settings(){
     Component project = mock(Component.class);
     when(project.key()).thenReturn("struts");
 
index b079f6ed98445acf0fa8406250b151f230d9f4a1..44b5cc3df88ba0c4c7a7f7cee8eaa119a7aa3ea9 100644 (file)
 
 package org.sonar.server.issue;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
 import org.sonar.api.issue.ActionPlan;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.issue.action.Action;
 import org.sonar.api.issue.internal.DefaultIssue;
 import org.sonar.api.issue.internal.FieldDiffs;
 import org.sonar.api.user.User;
@@ -51,19 +56,38 @@ import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.*;
 
+@RunWith(MockitoJUnitRunner.class)
 public class InternalRubyIssueServiceTest {
 
-  InternalRubyIssueService service;
-  IssueService issueService = mock(IssueService.class);
+  @Mock
+  IssueService issueService;
+
+  @Mock
   IssueCommentService commentService = mock(IssueCommentService.class);
+
+  @Mock
   IssueChangelogService changelogService = mock(IssueChangelogService.class);
+
+  @Mock
   ActionPlanService actionPlanService = mock(ActionPlanService.class);
+
+  @Mock
   ResourceDao resourceDao = mock(ResourceDao.class);
+
+  @Mock
   IssueStatsFinder issueStatsFinder = mock(IssueStatsFinder.class);
+
+  @Mock
   ActionService actionService = mock(ActionService.class);
+
+  @Mock
   IssueFilterService issueFilterService = mock(IssueFilterService.class);
+
+  @Mock
   IssueBulkChangeService issueBulkChangeService = mock(IssueBulkChangeService.class);
 
+  InternalRubyIssueService service;
+
   @Before
   public void setUp() {
     ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
@@ -72,14 +96,54 @@ public class InternalRubyIssueServiceTest {
       issueFilterService, issueBulkChangeService);
   }
 
+  @Test
+  public void find_issue_assignees() throws Exception {
+    service.findIssueAssignees(ImmutableMap.<String, Object>of("issues", "ABCD"));
+    verify(issueStatsFinder).findIssueAssignees(any(IssueQuery.class));
+  }
+
+  @Test
+  public void list_transitions_by_issue_key() throws Exception {
+    service.listTransitions("ABCD");
+    verify(issueService).listTransitions(eq("ABCD"), any(UserSession.class));
+  }
+
+  @Test
+  public void list_transitions_by_issue() throws Exception {
+    Issue issue = new DefaultIssue().setKey("ABCD");
+    service.listTransitions(issue);
+    verify(issueService).listTransitions(eq(issue), any(UserSession.class));
+  }
+
+  @Test
+  public void list_status() throws Exception {
+    service.listStatus();
+    verify(issueService).listStatus();
+  }
+
+  @Test
+  public void list_resolutions() throws Exception {
+    assertThat(service.listResolutions()).isEqualTo(Issue.RESOLUTIONS);
+  }
+
   @Test
   public void list_plugin_actions() {
-    service.listPluginActions();
-    verify(actionService).listAllActions();
+    Action action = mock(Action.class);
+    when(action.key()).thenReturn("link-to-jira");
+
+    when(actionService.listAllActions()).thenReturn(newArrayList(action));
+
+    assertThat(service.listPluginActions()).containsOnly("link-to-jira");
   }
 
-    @Test
-  public void should_create_action_plan() {
+  @Test
+  public void do_transition() throws Exception {
+    service.doTransition("ABCD", Issue.STATUS_RESOLVED);
+    verify(issueService).doTransition(eq("ABCD"), eq(Issue.STATUS_RESOLVED), any(UserSession.class));
+  }
+
+  @Test
+  public void create_action_plan() {
     Map<String, String> parameters = newHashMap();
     parameters.put("name", "Long term");
     parameters.put("description", "Long term issues");
@@ -101,7 +165,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_update_action_plan() {
+  public void update_action_plan() {
     when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
 
     Map<String, String> parameters = newHashMap();
@@ -125,7 +189,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_update_action_plan_with_new_project() {
+  public void update_action_plan_with_new_project() {
     when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term").setProjectKey("org.sonar.MultiSample"));
 
     Map<String, String> parameters = newHashMap();
@@ -149,7 +213,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_not_update_action_plan_when_action_plan_is_not_found() {
+  public void not_update_action_plan_when_action_plan_is_not_found() {
     when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
 
     Result result = service.updateActionPlan("ABCD", null);
@@ -158,7 +222,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_delete_action_plan() {
+  public void delete_action_plan() {
     when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
 
     Result result = service.deleteActionPlan("ABCD");
@@ -167,7 +231,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_not_delete_action_plan_if_action_plan_not_found() {
+  public void not_delete_action_plan_if_action_plan_not_found() {
     when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
 
     Result result = service.deleteActionPlan("ABCD");
@@ -177,7 +241,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_close_action_plan() {
+  public void close_action_plan() {
     when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
 
     Result result = service.closeActionPlan("ABCD");
@@ -186,7 +250,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_open_action_plan() {
+  public void open_action_plan() {
     when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
 
     Result result = service.openActionPlan("ABCD");
@@ -195,7 +259,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_no_project() {
+  public void 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");
@@ -206,7 +270,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_no_name() {
+  public void get_error_on_action_plan_result_when_no_name() {
     Map<String, String> parameters = newHashMap();
     parameters.put("name", null);
     parameters.put("description", "Long term issues");
@@ -218,7 +282,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_name_is_too_long() {
+  public void 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");
@@ -230,7 +294,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_description_is_too_long() {
+  public void 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));
@@ -242,7 +306,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_dead_line_use_wrong_format() {
+  public void 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");
@@ -255,7 +319,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_dead_line_is_in_the_past() {
+  public void 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");
@@ -268,7 +332,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_name_is_already_used_for_project() {
+  public void 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");
@@ -282,7 +346,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_action_plan_result_when_project_not_found() {
+  public void 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");
@@ -297,7 +361,7 @@ public class InternalRubyIssueServiceTest {
 
   @Test
   public void test_changelog_from_issue_key() throws Exception {
-    IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs> emptyList(), Collections.<User> emptyList());
+    IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
     when(changelogService.changelog(eq("ABCDE"))).thenReturn(changelog);
 
     IssueChangelog result = service.changelog("ABCDE");
@@ -309,7 +373,7 @@ public class InternalRubyIssueServiceTest {
   public void test_changelog_from_issue() throws Exception {
     Issue issue = new DefaultIssue().setKey("ABCDE");
 
-    IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs> emptyList(), Collections.<User> emptyList());
+    IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
     when(changelogService.changelog(eq(issue))).thenReturn(changelog);
 
     IssueChangelog result = service.changelog(issue);
@@ -318,7 +382,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_create_issue_filter() {
+  public void create_issue_filter() {
     Map<String, String> parameters = newHashMap();
     parameters.put("name", "Long term");
     parameters.put("description", "Long term issues");
@@ -333,7 +397,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_update_issue_filter() {
+  public void update_issue_filter() {
     Map<String, String> parameters = newHashMap();
     parameters.put("id", "10");
     parameters.put("name", "Long term");
@@ -351,20 +415,20 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_update_data() {
+  public void update_data() {
     Map<String, Object> data = newHashMap();
     service.updateIssueFilterQuery(10L, data);
     verify(issueFilterService).updateFilterQuery(eq(10L), eq(data), any(UserSession.class));
   }
 
   @Test
-  public void should_delete_issue_filter() {
+  public void delete_issue_filter() {
     service.deleteIssueFilter(1L);
     verify(issueFilterService).delete(eq(1L), any(UserSession.class));
   }
 
   @Test
-  public void should_copy_issue_filter() {
+  public void copy_issue_filter() {
     Map<String, String> parameters = newHashMap();
     parameters.put("name", "Copy of Long term");
     parameters.put("description", "Copy of Long term issues");
@@ -379,7 +443,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_create_issue_filter_result_when_no_name() {
+  public void get_error_on_create_issue_filter_result_when_no_name() {
     Map<String, String> parameters = newHashMap();
     parameters.put("name", "");
     parameters.put("description", "Long term issues");
@@ -395,7 +459,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_create_issue_filter_result_when_name_is_too_long() {
+  public void get_error_on_create_issue_filter_result_when_name_is_too_long() {
     Map<String, String> parameters = newHashMap();
     parameters.put("name", createLongString(101));
     parameters.put("description", "Long term issues");
@@ -411,7 +475,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_create_issue_filter_result_when_description_is_too_long() {
+  public void get_error_on_create_issue_filter_result_when_description_is_too_long() {
     Map<String, String> parameters = newHashMap();
     parameters.put("name", "Long term");
     parameters.put("description", createLongString(4001));
@@ -427,7 +491,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_create_issue_filter_result_when_id_is_null_on_update() {
+  public void get_error_on_create_issue_filter_result_when_id_is_null_on_update() {
     Map<String, String> parameters = newHashMap();
     parameters.put("id", null);
     parameters.put("name", "Long term");
@@ -444,7 +508,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_error_on_create_issue_filter_result_when_user_is_null_on_update() {
+  public void get_error_on_create_issue_filter_result_when_user_is_null_on_update() {
     Map<String, String> parameters = newHashMap();
     parameters.put("id", "10");
     parameters.put("name", "All Open Issues");
@@ -461,7 +525,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_get_no_error_on_issue_filter_result_when_id_and_user_are_null_on_copy() {
+  public void get_no_error_on_issue_filter_result_when_id_and_user_are_null_on_copy() {
     Map<String, String> parameters = newHashMap();
     parameters.put("id", null);
     parameters.put("name", "Long term");
@@ -473,13 +537,13 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_execute_issue_filter_from_issue_query() {
-    service.execute(Maps.<String, Object> newHashMap());
+  public void execute_issue_filter_from_issue_query() {
+    service.execute(Maps.<String, Object>newHashMap());
     verify(issueFilterService).execute(any(IssueQuery.class));
   }
 
   @Test
-  public void should_execute_issue_filter_from_existing_filter() {
+  public void execute_issue_filter_from_existing_filter() {
     Map<String, Object> props = newHashMap();
     props.put("componentRoots", "struts");
     props.put("statuses", "OPEN");
@@ -504,7 +568,7 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_serialize_filter_query() {
+  public void serialize_filter_query() {
     Map<String, Object> props = newHashMap();
     props.put("componentRoots", "struts");
     service.serializeFilterQuery(props);
@@ -512,14 +576,14 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_deserialize_filter_query() {
+  public void deserialize_filter_query() {
     DefaultIssueFilter issueFilter = new DefaultIssueFilter();
     service.deserializeFilterQuery(issueFilter);
     verify(issueFilterService).deserializeIssueFilterQuery(issueFilter);
   }
 
   @Test
-  public void should_sanitize_filter_query() {
+  public void sanitize_filter_query() {
     Map<String, Object> query = newHashMap();
     query.put("statuses", "CLOSED");
     query.put("resolved", true);
@@ -529,31 +593,31 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_find_user_issue_filters() {
+  public void find_user_issue_filters() {
     service.findIssueFiltersForCurrentUser();
     verify(issueFilterService).findByUser(any(UserSession.class));
   }
 
   @Test
-  public void should_find_shared_issue_filters() {
+  public void find_shared_issue_filters() {
     service.findSharedFiltersForCurrentUser();
     verify(issueFilterService).findSharedFiltersWithoutUserFilters(any(UserSession.class));
   }
 
   @Test
-  public void should_find_favourite_issue_filters() {
+  public void find_favourite_issue_filters() {
     service.findFavouriteIssueFiltersForCurrentUser();
     verify(issueFilterService).findFavoriteFilters(any(UserSession.class));
   }
 
   @Test
-  public void should_toggle_favourite_issue_filter() {
+  public void toggle_favourite_issue_filter() {
     service.toggleFavouriteIssueFilter(10L);
     verify(issueFilterService).toggleFavouriteIssueFilter(eq(10L), any(UserSession.class));
   }
 
   @Test
-  public void should_check_if_user_is_authorized_to_see_issue_filter() {
+  public void check_if_user_is_authorized_to_see_issue_filter() {
     DefaultIssueFilter issueFilter = new DefaultIssueFilter();
     service.isUserAuthorized(issueFilter);
     verify(issueFilterService).getLoggedLogin(any(UserSession.class));
@@ -561,13 +625,13 @@ public class InternalRubyIssueServiceTest {
   }
 
   @Test
-  public void should_check_if_user_can_share_issue_filter() {
+  public void check_if_user_can_share_issue_filter() {
     service.canUserShareIssueFilter();
     verify(issueFilterService).canShareFilter(any(UserSession.class));
   }
 
   @Test
-  public void should_execute_bulk_change() {
+  public void execute_bulk_change() {
     Map<String, Object> params = newHashMap();
     params.put("issues", newArrayList("ABCD", "EFGH"));
     params.put("actions", newArrayList("do_transition", "assign", "set_severity", "plan"));