aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server
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 /sonar-server
parent2eb5e77ee6ff9f74f70a294e19c3ad23411367d1 (diff)
downloadsonarqube-4d5a0b1c1cd8e787cedffe2cc8d1f4772b74c2b0.tar.gz
sonarqube-4d5a0b1c1cd8e787cedffe2cc8d1f4772b74c2b0.zip
SONAR-4834 Add technical debt in issues changelog
Diffstat (limited to 'sonar-server')
-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
12 files changed, 377 insertions, 20 deletions
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");
+ }
+
+
+}