aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@gmail.com>2013-11-03 22:35:21 +0100
committerJulien Lancelot <julien.lancelot@gmail.com>2013-11-03 22:35:21 +0100
commit4d5a0b1c1cd8e787cedffe2cc8d1f4772b74c2b0 (patch)
treede343cafa0a9d91b30208c6324bb9d84b48e6100
parent2eb5e77ee6ff9f74f70a294e19c3ad23411367d1 (diff)
downloadsonarqube-4d5a0b1c1cd8e787cedffe2cc8d1f4772b74c2b0.tar.gz
sonarqube-4d5a0b1c1cd8e787cedffe2cc8d1f4772b74c2b0.zip
SONAR-4834 Add technical debt in issues changelog
-rw-r--r--sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java14
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java6
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogDiffFormat.java44
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java35
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java4
-rw-r--r--sonar-server/src/main/java/org/sonar/server/technicalDebt/InternalRubyTechnicalDebtService.java43
-rw-r--r--sonar-server/src/main/java/org/sonar/server/technicalDebt/TechnicalDebtFormatter.java57
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb3
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb9
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb12
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java8
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java55
-rw-r--r--sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java60
-rw-r--r--sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtFormatterTest.java67
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java20
-rw-r--r--sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/changelog-with-technical-debt.json25
17 files changed, 434 insertions, 30 deletions
diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
index 1c521975f32..68ea3739d3b 100644
--- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/technicaldebt/TechnicalDebtConverterTest.java
@@ -55,16 +55,16 @@ public class TechnicalDebtConverterTest {
@Test
public void convert_simple_values() {
- checkValues(converter.fromMinutes(15L), 15L, 0L, 0L);
- checkValues(converter.fromMinutes(120L), 0L, 2L, 0L);
- checkValues(converter.fromMinutes(720L), 0L, 0L, 1L);
+ checkValues(converter.fromMinutes(15L), 15, 0, 0);
+ checkValues(converter.fromMinutes(120L), 0, 2, 0);
+ checkValues(converter.fromMinutes(720L), 0, 0, 1);
}
@Test
public void convert_complex_values() {
- checkValues(converter.fromMinutes(70L), 10L, 1L, 0L);
- checkValues(converter.fromMinutes(730L), 10L, 0L, 1L);
- checkValues(converter.fromMinutes(790L), 10L, 1L, 1L);
+ checkValues(converter.fromMinutes(70L), 10, 1, 0);
+ checkValues(converter.fromMinutes(730L), 10, 0, 1);
+ checkValues(converter.fromMinutes(790L), 10, 1, 1);
}
@Test
@@ -77,7 +77,7 @@ public class TechnicalDebtConverterTest {
assertThat(converter.toDays(TechnicalDebt.of(45, 6, 1))).isEqualTo(1.5625);
}
- private void checkValues(TechnicalDebt technicalDebt, Long expectedMinutes, Long expectedHours, Long expectedDays) {
+ private void checkValues(TechnicalDebt technicalDebt, int expectedMinutes, int expectedHours, int expectedDays) {
assertThat(technicalDebt.minutes()).isEqualTo(expectedMinutes);
assertThat(technicalDebt.hours()).isEqualTo(expectedHours);
assertThat(technicalDebt.days()).isEqualTo(expectedDays);
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java
index 386de94e09e..2be7b500f59 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java
@@ -141,10 +141,12 @@ public class FieldDiffs implements Serializable {
this.newValue = newValue;
}
+ @CheckForNull
public T oldValue() {
return oldValue;
}
+ @CheckForNull
public T newValue() {
return newValue;
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java
index 5fdc21e3d79..6c0509294e2 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/TechnicalDebt.java
@@ -69,15 +69,15 @@ public class TechnicalDebt implements Serializable {
return days * DAY + hours * HOUR + minutes * MINUTE;
}
- public long days() {
+ public int days() {
return days;
}
- public long hours() {
+ public int hours() {
return hours;
}
- public long minutes() {
+ public int minutes() {
return minutes;
}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogDiffFormat.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogDiffFormat.java
new file mode 100644
index 00000000000..214f85e5e1f
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogDiffFormat.java
@@ -0,0 +1,44 @@
+/*
+ * 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 javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class IssueChangelogDiffFormat {
+
+ private String oldValue, newValue;
+
+ public IssueChangelogDiffFormat(@Nullable String oldValue, @Nullable String newValue) {
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ }
+
+ @CheckForNull
+ public String oldValue() {
+ return oldValue;
+ }
+
+ @CheckForNull
+ public String newValue() {
+ return newValue;
+ }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java
index 1923c026ac4..ac9586fd14b 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java
@@ -21,8 +21,12 @@ package org.sonar.server.issue;
import org.sonar.api.ServerComponent;
import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.technicaldebt.TechnicalDebt;
import org.sonar.core.i18n.I18nManager;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.server.technicaldebt.TechnicalDebtFormatter;
+import java.io.Serializable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -32,9 +36,11 @@ import static com.google.common.collect.Lists.newArrayList;
public class IssueChangelogFormatter implements ServerComponent {
private final I18nManager i18nManager;
+ private final TechnicalDebtFormatter technicalDebtFormatter;
- public IssueChangelogFormatter(I18nManager i18nManager) {
+ public IssueChangelogFormatter(I18nManager i18nManager, TechnicalDebtFormatter technicalDebtFormatter) {
this.i18nManager = i18nManager;
+ this.technicalDebtFormatter = technicalDebtFormatter;
}
public List<String> format(Locale locale, FieldDiffs diffs) {
@@ -42,15 +48,15 @@ public class IssueChangelogFormatter implements ServerComponent {
for (Map.Entry<String, FieldDiffs.Diff> entry : diffs.diffs().entrySet()) {
StringBuilder message = new StringBuilder();
String key = entry.getKey();
- FieldDiffs.Diff diff = entry.getValue();
- if (diff.newValue() != null && !diff.newValue().equals("")) {
- message.append(i18nManager.message(locale, "issue.changelog.changed_to", null, i18nManager.message(locale, "issue.changelog.field." + key, null), diff.newValue()));
+ IssueChangelogDiffFormat diffFormat = format(locale, key, entry.getValue());
+ if (diffFormat.newValue() != null) {
+ message.append(i18nManager.message(locale, "issue.changelog.changed_to", null, i18nManager.message(locale, "issue.changelog.field." + key, null), diffFormat.newValue()));
} else {
message.append(i18nManager.message(locale, "issue.changelog.removed", null, i18nManager.message(locale, "issue.changelog.field." + key, null)));
}
- if (diff.oldValue() != null && !diff.oldValue().equals("")) {
+ if (diffFormat.oldValue() != null) {
message.append(" (");
- message.append(i18nManager.message(locale, "issue.changelog.was", null, diff.oldValue()));
+ message.append(i18nManager.message(locale, "issue.changelog.was", null, diffFormat.oldValue()));
message.append(")");
}
result.add(message.toString());
@@ -58,4 +64,21 @@ public class IssueChangelogFormatter implements ServerComponent {
return result;
}
+ private IssueChangelogDiffFormat format(Locale locale, String key, FieldDiffs.Diff diff) {
+ Serializable newValue = diff.newValue();
+ Serializable oldValue = diff.oldValue();
+
+ String newValueString = newValue != null && !newValue.equals("") ? diff.newValue().toString() : null;
+ String oldValueString = oldValue != null && !oldValue.equals("") ? diff.oldValue().toString() : null;
+ if (IssueUpdater.TECHNICAL_DEBT.equals(key)) {
+ if (newValueString != null) {
+ newValueString = technicalDebtFormatter.format(locale, TechnicalDebt.fromLong(Long.parseLong(newValueString)));
+ }
+ if (oldValueString != null) {
+ oldValueString = technicalDebtFormatter.format(locale, TechnicalDebt.fromLong(Long.parseLong(oldValueString)));
+ }
+ }
+ return new IssueChangelogDiffFormat(oldValueString, newValueString);
+ }
+
}
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index 9bd3b2071ad..5af173d2839 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -94,6 +94,8 @@ import org.sonar.server.rule.RubyRuleService;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
import org.sonar.server.startup.*;
+import org.sonar.server.technicaldebt.InternalRubyTechnicalDebtService;
+import org.sonar.server.technicaldebt.TechnicalDebtFormatter;
import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.text.RubyTextService;
import org.sonar.server.ui.*;
@@ -300,10 +302,12 @@ public final class Platform {
servicesContainer.addSingleton(RubyRuleService.class);
// technical debt
+ servicesContainer.addSingleton(InternalRubyTechnicalDebtService.class);
servicesContainer.addSingleton(TechnicalDebtManager.class);
servicesContainer.addSingleton(TechnicalDebtModelRepository.class);
servicesContainer.addSingleton(TechnicalDebtXMLImporter.class);
servicesContainer.addSingleton(TechnicalDebtConverter.class);
+ servicesContainer.addSingleton(TechnicalDebtFormatter.class);
// text
servicesContainer.addSingleton(MacroInterpreter.class);
diff --git a/sonar-server/src/main/java/org/sonar/server/technicalDebt/InternalRubyTechnicalDebtService.java b/sonar-server/src/main/java/org/sonar/server/technicalDebt/InternalRubyTechnicalDebtService.java
new file mode 100644
index 00000000000..60a9f143870
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/technicalDebt/InternalRubyTechnicalDebtService.java
@@ -0,0 +1,43 @@
+/*
+ * 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.technicaldebt;
+
+import org.sonar.api.ServerComponent;
+import org.sonar.api.technicaldebt.TechnicalDebt;
+import org.sonar.server.user.UserSession;
+
+public class InternalRubyTechnicalDebtService implements ServerComponent {
+
+ private final TechnicalDebtFormatter technicalDebtFormatter;
+
+ public InternalRubyTechnicalDebtService(TechnicalDebtFormatter technicalDebtFormatter) {
+ this.technicalDebtFormatter = technicalDebtFormatter;
+ }
+
+ public String format(TechnicalDebt technicalDebt){
+ return technicalDebtFormatter.format(UserSession.get().locale(), technicalDebt);
+ }
+
+ public TechnicalDebt toTechnicalDebt(String technicalDebtInLong){
+ return TechnicalDebt.fromLong(Long.parseLong(technicalDebtInLong));
+ }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/technicalDebt/TechnicalDebtFormatter.java b/sonar-server/src/main/java/org/sonar/server/technicalDebt/TechnicalDebtFormatter.java
new file mode 100644
index 00000000000..7e7f4672500
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/technicalDebt/TechnicalDebtFormatter.java
@@ -0,0 +1,57 @@
+/*
+ * 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.technicaldebt;
+
+import org.sonar.api.ServerComponent;
+import org.sonar.api.technicaldebt.TechnicalDebt;
+import org.sonar.core.i18n.I18nManager;
+
+import java.util.Locale;
+
+public class TechnicalDebtFormatter implements ServerComponent {
+
+ private final I18nManager i18nManager;
+
+ public TechnicalDebtFormatter(I18nManager i18nManager) {
+ this.i18nManager = i18nManager;
+ }
+
+ public String format(Locale locale, TechnicalDebt technicalDebt) {
+ StringBuilder message = new StringBuilder();
+ if (technicalDebt.days() > 0) {
+ message.append(i18nManager.message(locale, "issue.technical_debt.x_days", null, technicalDebt.days()));
+ }
+ if (technicalDebt.hours() > 0) {
+ if (message.length() > 0) {
+ message.append(" ");
+ }
+ message.append(i18nManager.message(locale, "issue.technical_debt.x_hours", null, technicalDebt.hours()));
+ }
+ // Do not display minutes if days is not null to not have too much information
+ if (technicalDebt.minutes() > 0 && technicalDebt.days() == 0) {
+ if (message.length() > 0) {
+ message.append(" ");
+ }
+ message.append(i18nManager.message(locale, "issue.technical_debt.x_minutes", null, technicalDebt.minutes()));
+ }
+ return message.toString();
+ }
+}
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb
index 7070f829c6e..c43de64b4d7 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb
@@ -54,6 +54,9 @@ class Internal
component(Java::OrgSonarServerPermission::InternalPermissionTemplateService.java_class)
end
+ def self.technical_debt
+ component(Java::OrgSonarServerTechnicaldebt::InternalRubyTechnicalDebtService.java_class)
+ end
private
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb
index 095321ac3d4..3c5d561803d 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb
@@ -73,8 +73,13 @@ class Issue
diff = entry.getValue()
hash_diff = {}
hash_diff[:key] = key
- hash_diff[:newValue] = diff.newValue() if diff.newValue.present?
- hash_diff[:oldValue] = diff.oldValue() if diff.oldValue.present?
+ if key == 'technicalDebt'
+ hash_diff[:newValue] = technical_debt_to_hash(Internal.technical_debt.toTechnicalDebt(diff.newValue())) if diff.newValue.present?
+ hash_diff[:oldValue] = technical_debt_to_hash(Internal.technical_debt.toTechnicalDebt(diff.oldValue())) if diff.oldValue.present?
+ else
+ hash_diff[:newValue] = diff.newValue() if diff.newValue.present?
+ hash_diff[:oldValue] = diff.oldValue() if diff.oldValue.present?
+ end
hash_change[:diffs] << hash_diff
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
index 77bbe090616..d73587fc55e 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb
@@ -39,18 +39,8 @@
<% if issue.technicalDebt %>
<img src="<%= ApplicationController.root_context -%>/images/sep12.png"/>
&nbsp;
- <% technical_debt = issue.technicalDebt
- days = technical_debt.days
- hours = technical_debt.hours
- minutes = technical_debt.minutes
- message = ''
- message += message('issue.technical_debt.x_days', :params => days) + ' ' if days > 0
- message += message('issue.technical_debt.x_hours', :params => hours) + ' ' if hours > 0
- # Do not display minutes if days is not null to not have too much information
- message += message('issue.technical_debt.x_minutes', :params => minutes) if minutes > 0 && days == 0
- %>
<%= message('issue.technical_debt') -%>&nbsp;<a href="#" onclick="return toggleTechnicalDebt(this)" class="gray issue-technicaldebt-link"
- id="toggle-issue-technicaldebt"><%= message -%></a>
+ id="toggle-issue-technicaldebt"><%= Internal.technical_debt.format(issue.technicalDebt) -%></a>
&nbsp;
<% end %>
</div>
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java
index 9a8865a5dcc..850d665e4b3 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java
@@ -39,6 +39,7 @@ import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.user.UserSession;
import java.util.Collections;
+import java.util.Locale;
import java.util.Map;
import static com.google.common.collect.Lists.newArrayList;
@@ -573,6 +574,13 @@ public class InternalRubyIssueServiceTest {
verify(issueBulkChangeService).execute(any(IssueBulkChangeQuery.class), any(UserSession.class));
}
+ @Test
+ public void format_changelog() {
+ FieldDiffs fieldDiffs = new FieldDiffs();
+ service.formatChangelog(fieldDiffs);
+ verify(issueChangelogFormatter).format(any(Locale.class), eq(fieldDiffs));
+ }
+
private void checkBadRequestException(Exception e, String key, Object... params) {
BadRequestException exception = (BadRequestException) e;
assertThat(exception.l10nKey()).isEqualTo(key);
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java
index 6de106c78b8..c1e65a0af78 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java
@@ -25,7 +25,9 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.technicaldebt.TechnicalDebt;
import org.sonar.core.i18n.I18nManager;
+import org.sonar.server.technicaldebt.TechnicalDebtFormatter;
import java.util.List;
import java.util.Locale;
@@ -41,11 +43,14 @@ public class IssueChangelogFormatterTest {
@Mock
private I18nManager i18nManager;
+ @Mock
+ private TechnicalDebtFormatter technicalDebtFormatter;
+
private IssueChangelogFormatter formatter;
@Before
public void before(){
- formatter = new IssueChangelogFormatter(i18nManager);
+ formatter = new IssueChangelogFormatter(i18nManager, technicalDebtFormatter);
}
@Test
@@ -120,4 +125,52 @@ public class IssueChangelogFormatterTest {
assertThat(message).isEqualTo("Severity removed");
}
+ @Test
+ public void format_technical_debt_with_old_and_new_value(){
+ FieldDiffs diffs = new FieldDiffs();
+ diffs.setDiff("technicalDebt", "500", "10000");
+
+ when(technicalDebtFormatter.format(DEFAULT_LOCALE, TechnicalDebt.of(0, 5, 0))).thenReturn("5 hours");
+ when(technicalDebtFormatter.format(DEFAULT_LOCALE, TechnicalDebt.of(0, 0, 1))).thenReturn("1 days");
+
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.technicalDebt", null)).thenReturn("Technical Debt");
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.changed_to", null, "Technical Debt", "1 days")).thenReturn("Technical Debt changed to 1 days");
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.was", null, "5 hours")).thenReturn("was 5 hours");
+
+ List<String> result = formatter.format(DEFAULT_LOCALE, diffs);
+ assertThat(result).hasSize(1);
+ String message = result.get(0);
+ assertThat(message).isEqualTo("Technical Debt changed to 1 days (was 5 hours)");
+ }
+
+ @Test
+ public void format_technical_debt_with_new_value_only(){
+ FieldDiffs diffs = new FieldDiffs();
+ diffs.setDiff("technicalDebt", null, "10000");
+
+ when(technicalDebtFormatter.format(DEFAULT_LOCALE, TechnicalDebt.of(0, 0, 1))).thenReturn("1 days");
+
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.technicalDebt", null)).thenReturn("Technical Debt");
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.changed_to", null, "Technical Debt", "1 days")).thenReturn("Technical Debt changed to 1 days");
+
+ List<String> result = formatter.format(DEFAULT_LOCALE, diffs);
+ assertThat(result).hasSize(1);
+ String message = result.get(0);
+ assertThat(message).isEqualTo("Technical Debt changed to 1 days");
+ }
+
+ @Test
+ public void format_technical_debt_without_value(){
+ FieldDiffs diffs = new FieldDiffs();
+ diffs.setDiff("technicalDebt", null, null);
+
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.technicalDebt", null)).thenReturn("Technical Debt");
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.removed", null, "Technical Debt")).thenReturn("Technical Debt removed");
+
+ List<String> result = formatter.format(DEFAULT_LOCALE, diffs);
+ assertThat(result).hasSize(1);
+ String message = result.get(0);
+ assertThat(message).isEqualTo("Technical Debt removed");
+ }
+
}
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java
new file mode 100644
index 00000000000..5cfa4b34de3
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/technicaldebt/InternalRubyTechnicalDebtServiceTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.technicaldebt;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.technicaldebt.TechnicalDebt;
+
+import java.util.Locale;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+
+@RunWith(MockitoJUnitRunner.class)
+public class InternalRubyTechnicalDebtServiceTest {
+
+ @Mock
+ private TechnicalDebtFormatter technicalDebtFormatter;
+
+ private InternalRubyTechnicalDebtService service;
+
+ @Before
+ public void before() {
+ service = new InternalRubyTechnicalDebtService(technicalDebtFormatter);
+ }
+
+ @Test
+ public void format() {
+ TechnicalDebt technicalDebt = TechnicalDebt.of(5, 0, 0);
+ service.format(technicalDebt);
+ verify(technicalDebtFormatter).format(any(Locale.class), eq(technicalDebt));
+ }
+
+ @Test
+ public void to_technical_debt() {
+ assertThat(service.toTechnicalDebt("500")).isEqualTo(TechnicalDebt.of(0, 5, 0));
+ }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtFormatterTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtFormatterTest.java
new file mode 100644
index 00000000000..a9d2c4a1cfe
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/technicaldebt/TechnicalDebtFormatterTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.technicaldebt;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.technicaldebt.TechnicalDebt;
+import org.sonar.core.i18n.I18nManager;
+
+import java.util.Locale;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TechnicalDebtFormatterTest {
+
+ private static final Locale DEFAULT_LOCALE = Locale.getDefault();
+
+ @Mock
+ private I18nManager i18nManager;
+
+ private TechnicalDebtFormatter formatter;
+
+ @Before
+ public void before() {
+ formatter = new TechnicalDebtFormatter(i18nManager);
+ }
+
+ @Test
+ public void format() {
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.technical_debt.x_days", null, 5)).thenReturn("5 days");
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.technical_debt.x_hours", null, 2)).thenReturn("2 hours");
+ when(i18nManager.message(DEFAULT_LOCALE, "issue.technical_debt.x_minutes", null, 1)).thenReturn("1 minutes");
+
+ assertThat(formatter.format(DEFAULT_LOCALE, TechnicalDebt.of(0, 0, 5))).isEqualTo("5 days");
+ assertThat(formatter.format(DEFAULT_LOCALE, TechnicalDebt.of(0, 2, 0))).isEqualTo("2 hours");
+ assertThat(formatter.format(DEFAULT_LOCALE, TechnicalDebt.of(1, 0, 0))).isEqualTo("1 minutes");
+
+ assertThat(formatter.format(DEFAULT_LOCALE, TechnicalDebt.of(0, 2, 5))).isEqualTo("5 days 2 hours");
+ assertThat(formatter.format(DEFAULT_LOCALE, TechnicalDebt.of(1, 2, 0))).isEqualTo("2 hours 1 minutes");
+ assertThat(formatter.format(DEFAULT_LOCALE, TechnicalDebt.of(1, 2, 5))).isEqualTo("5 days 2 hours");
+ }
+
+
+}
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java
index d7c5e22a07b..87f86d26c4e 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/internal/IssueJsonParserTest.java
@@ -20,6 +20,7 @@
package org.sonar.wsclient.issue.internal;
import org.apache.commons.io.IOUtils;
+import org.junit.Ignore;
import org.junit.Test;
import org.sonar.wsclient.base.Paging;
import org.sonar.wsclient.component.Component;
@@ -241,6 +242,25 @@ public class IssueJsonParserTest {
}
@Test
+ @Ignore
+ public void should_parse_changelog_with_technical_debt() throws Exception {
+ String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/changelog-with-technical-debt.json"));
+ List<IssueChange> changes = new IssueJsonParser().parseChangelog(json);
+
+ assertThat(changes).hasSize(1);
+ IssueChange change = changes.get(0);
+ assertThat(change.user()).isEqualTo("julien");
+ assertThat(change.createdAt().getTime()).isEqualTo(1383202235000l);
+ assertThat(change.updatedAt().getTime()).isEqualTo(1383202235000l);
+
+ assertThat(change.diffs()).hasSize(1);
+ IssueChangeDiff diffChange1 = change.diffs().get(0);
+ assertThat(diffChange1.key()).isEqualTo("technicalDebt");
+ assertThat(diffChange1.newValue()).isEqualTo("1.0");
+ assertThat(diffChange1.oldValue()).isNull();
+ }
+
+ @Test
public void should_parse_bulk_change() throws Exception {
String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/internal/IssueJsonParserTest/bulk-change.json"));
BulkChange bulkChange = new IssueJsonParser().parseBulkChange(json);
diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/changelog-with-technical-debt.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/changelog-with-technical-debt.json
new file mode 100644
index 00000000000..cb1acd79fbe
--- /dev/null
+++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/internal/IssueJsonParserTest/changelog-with-technical-debt.json
@@ -0,0 +1,25 @@
+{
+ "changelog": [
+ {
+ "user": "julien",
+ "createdAt": "2013-10-31T07:50:35+0100",
+ "updatedAt": "2013-10-31T07:50:35+0100",
+ "diffs": [
+ {
+ "key": "technicalDebt",
+ "oldValue": {
+ "days": 3,
+ "hours": 0,
+ "minutes": 10
+ },
+ "newValue": {
+ "days": 2,
+ "hours": 1,
+ "minutes": 0
+ }
+ }
+ ]
+ }
+ ]
+}
+