*/
package org.sonar.plugins.core.dashboards;
+import com.google.common.base.Preconditions;
import org.sonar.api.web.Dashboard;
import org.sonar.api.web.DashboardLayout;
import org.sonar.api.web.DashboardTemplate;
+import org.sonar.core.issue.db.IssueFilterDao;
+import org.sonar.core.issue.db.IssueFilterDto;
/**
* Issues dashboard for Sonar
*/
public final class ProjectIssuesDashboard extends DashboardTemplate {
+ private final IssueFilterDao issueFilterDao;
+
+ public ProjectIssuesDashboard(IssueFilterDao issueFilterDao) {
+ this.issueFilterDao = issueFilterDao;
+ }
+
@Override
public String getName() {
return "Issues";
public Dashboard createDashboard() {
Dashboard dashboard = Dashboard.create();
dashboard.setLayout(DashboardLayout.TWO_COLUMNS);
- addFirstColumn(dashboard);
- addSecondColumn();
+
+ IssueFilterDto unresolvedIssues = getIssueFilterByName("Unresolved Issues");
+ IssueFilterDto hiddenDebt = getIssueFilterByName("False Positive and Won't Fix Issues");
+ IssueFilterDto myUnresolvedIssues = getIssueFilterByName("My Unresolved Issues");
+
+ addFirstColumn(dashboard, unresolvedIssues);
+ addSecondColumn(dashboard, unresolvedIssues, hiddenDebt, myUnresolvedIssues);
return dashboard;
}
- private void addFirstColumn(Dashboard dashboard) {
- // TODO: + unresolved issues by status
+ private IssueFilterDto getIssueFilterByName(String name) {
+ IssueFilterDto filter = issueFilterDao.selectProvidedFilterByName(name);
+ Preconditions.checkState(filter != null, String.format("Could not find a provided issue filter with name '%s'", name));
+ return filter;
+ }
+
+ private void addFirstColumn(Dashboard dashboard, IssueFilterDto unresolvedIssues) {
+ // Unresolved issues by status
+ dashboard.addWidget("project_issue_filter", 1)
+ .setProperty("filter", Long.toString(unresolvedIssues.getId()))
+ .setProperty("distributionAxis", "statuses");
+ // Action plans
dashboard.addWidget("action_plans", 1);
}
- private void addSecondColumn() {
- // TODO: + unresolved issues by assignee
- // TODO: + my unresolved issues
- // TODO: + false positive and won't fix issues
+ private void addSecondColumn(Dashboard dashboard, IssueFilterDto unresolvedIssues, IssueFilterDto hiddenDebt, IssueFilterDto myUnresolvedIssues) {
+ // Unresolved issues by assignee
+ dashboard.addWidget("project_issue_filter", 2)
+ .setProperty("filter", Long.toString(unresolvedIssues.getId()))
+ .setProperty("distributionAxis", "assignees");
+ // My unresolved issues
+ dashboard.addWidget("project_issue_filter", 2)
+ .setProperty("filter", Long.toString(myUnresolvedIssues.getId()));
+ // False positive and won't fix issues by resolution
+ dashboard.addWidget("project_issue_filter", 2)
+ .setProperty("filter", Long.toString(hiddenDebt.getId()))
+ .setProperty("distributionAxis", "resolutions");
}
}
package org.sonar.plugins.core.dashboards;
+import org.junit.Before;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.experimental.categories.Category;
import org.sonar.api.web.Dashboard;
import org.sonar.api.web.DashboardLayout;
+import org.sonar.core.issue.db.IssueFilterDao;
+import org.sonar.core.persistence.DbTester;
import org.sonar.plugins.core.CorePlugin;
+import org.sonar.test.DbTests;
import static org.assertj.core.api.Assertions.assertThat;
+@Category(DbTests.class)
public class ProjectIssuesDashboardTest {
- ProjectIssuesDashboard template = new ProjectIssuesDashboard();
+ @ClassRule
+ public static final DbTester dbTester = new DbTester();
+
+ ProjectIssuesDashboard template;
+
+ @Before
+ public void setUp() throws Exception {
+ IssueFilterDao issueFilterDao = new IssueFilterDao(dbTester.myBatis());
+ template = new ProjectIssuesDashboard(issueFilterDao);
+ }
@Test
public void should_have_a_name() {
@Test
public void should_create_dashboard() {
+ dbTester.prepareDbUnit(getClass(), "filters.xml");
Dashboard dashboard = template.createDashboard();
assertThat(dashboard.getLayout()).isEqualTo(DashboardLayout.TWO_COLUMNS);
- assertThat(dashboard.getWidgets()).hasSize(1);
+ assertThat(dashboard.getWidgets()).hasSize(5);
}
+ @Test
+ public void should_provide_clean_error_message_on_failure() {
+ try {
+ template.createDashboard();
+ } catch (IllegalStateException illegalState) {
+ assertThat(illegalState).hasMessage("Could not find a provided issue filter with name 'Unresolved Issues'");
+ }
+ }
}
--- /dev/null
+<dataset>
+
+ <issue_filters
+ id="1"
+ name="Unresolved Issues"
+ user_login="[null]"
+ shared="[true]"
+ description="[null]"
+ data="resolved=false"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+ <issue_filters
+ id="2"
+ name="False Positive and Won't Fix Issues"
+ user_login="[null]"
+ shared="[true]"
+ description="[null]"
+ data="resolutions=FALSE-POSITIVE,WONTFIX"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+ <issue_filters
+ id="3"
+ name="My Unresolved Issues"
+ user_login="[null]"
+ shared="[true]"
+ description="[null]"
+ data="resolved=false|assignees=__me__"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+</dataset>
}
}
+ public IssueFilterDto selectProvidedFilterByName(String name) {
+ SqlSession session = mybatis.openSession(false);
+ try {
+ return getMapper(session).selectProvidedFilterByName(name);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
public List<IssueFilterDto> selectSharedFilters() {
SqlSession session = mybatis.openSession(false);
try {
List<IssueFilterDto> selectSharedFilters();
+ IssueFilterDto selectProvidedFilterByName(String name);
+
void insert(IssueFilterDto filter);
void update(IssueFilterDto filter);
void delete(long id);
+
}
where filters.shared=${_true}
</select>
+ <select id="selectProvidedFilterByName" parameterType="String" resultType="IssueFilter">
+ select <include refid="issueFilterColumns"/>
+ from issue_filters filters
+ where filters.user_login is null
+ and filters.shared=${_true}
+ and filters.name=#{name}
+ </select>
+
<insert id="insert" parameterType="IssueFilter" keyColumn="id" useGeneratedKeys="true" keyProperty="id" >
INSERT INTO issue_filters (name, user_login, shared, description, data, created_at, updated_at)
VALUES (#{name}, #{userLogin}, #{shared}, #{description}, #{data}, #{createdAt}, #{updatedAt})
assertThat(dao.selectSharedFilters()).hasSize(1);
}
+ @Test
+ public void should_select_provided_by_name() {
+ setupData("should_select_provided_by_name");
+
+ assertThat(dao.selectProvidedFilterByName("Unresolved Issues").getName()).isEqualTo("Unresolved Issues");
+ assertThat(dao.selectProvidedFilterByName("My Unresolved Issues").getName()).isEqualTo("My Unresolved Issues");
+ assertThat(dao.selectProvidedFilterByName("Unknown Filter")).isNull();
+ }
+
@Test
public void should_insert() {
setupData("shared");
--- /dev/null
+<dataset>
+
+ <!-- This one must be found -->
+ <issue_filters
+ id="1"
+ name="Unresolved Issues"
+ user_login="[null]"
+ shared="[true]"
+ description="[null]"
+ data="resolved=false"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+ <!-- This one must NOT be found: belongs to admin -->
+ <issue_filters
+ id="2"
+ name="Unresolved Issues"
+ user_login="admin"
+ shared="[true]"
+ description="[null]"
+ data="resolved=false"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+ <!-- This one must NOT be found: not shared -->
+ <issue_filters
+ id="3"
+ name="Unresolved Issues"
+ user_login="[null]"
+ shared="[false]"
+ description="[null]"
+ data="resolved=false"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+ <!-- This one must be found -->
+ <issue_filters
+ id="4"
+ name="My Unresolved Issues"
+ user_login="[null]"
+ shared="[true]"
+ description="[null]"
+ data="resolved=false|assignees=__me__"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+ <!-- This one must NOT be found: not shared -->
+ <issue_filters
+ id="5"
+ name="Unknown Filter"
+ user_login="[null]"
+ shared="[false]"
+ description="[null]"
+ data="resolved=false"
+ created_at="2011-04-25 01:15:00"
+ updated_at="2011-04-25 01:15:00" />
+
+</dataset>