diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2013-10-31 17:07:50 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2013-10-31 17:07:50 +0100 |
commit | f0f5058c481c3da9e63ff260963fb951182f5122 (patch) | |
tree | 3d9c0636f80d2f2f0669cf6ab56c527b4a6a79c5 | |
parent | f8b3f731d946a6ae06719cafd5d5ca4f0a471b0c (diff) | |
download | sonarqube-f0f5058c481c3da9e63ff260963fb951182f5122.tar.gz sonarqube-f0f5058c481c3da9e63ff260963fb951182f5122.zip |
SONAR-4834 Create a changelog formatter on java side to manage display of changelog in order to integrate more easily technical debt in changelog
11 files changed, 255 insertions, 86 deletions
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties index 022d33b2eae..e8625f2c44c 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -535,9 +535,6 @@ issue.manual.no_rules.non_admin=At least one manual rule must exist before manua issue.reported_by=Reported by issue.authorLogin=Author: issue.component_deleted=Removed -issue.changelog.changed_to={0} changed to {1} -issue.changelog.was=was {0} -issue.changelog.removed={0} removed issue.technical_debt=Technical debt: issue.technical_debt.x_days={0} days issue.technical_debt.x_hours={0} hours @@ -546,6 +543,23 @@ issue.technical_debt.x_minutes={0} minutes #------------------------------------------------------------------------------ # +# ISSUE CHANGELOG +# +#------------------------------------------------------------------------------ +issue.changelog.changed_to={0} changed to {1} +issue.changelog.was=was {0} +issue.changelog.removed={0} removed +issue.changelog.field.severity=Severity +issue.changelog.field.actionPlan=Action Plan +issue.changelog.field.assignee=Assignee +issue.changelog.field.author=Author +issue.changelog.field.resolution=Resolution +issue.changelog.field.technicalDebt=Technical Debt +issue.changelog.field.status=Status + + +#------------------------------------------------------------------------------ +# # ISSUE FILTERS # #------------------------------------------------------------------------------ diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java index 6149cb65b6c..33ffb6a94d0 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java @@ -48,6 +48,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { public static final String STATUS = "status"; public static final String AUTHOR = "author"; public static final String ACTION_PLAN = "actionPlan"; + public static final String TECHNICAL_DEBT = "technicalDebt"; public boolean setSeverity(DefaultIssue issue, String severity, IssueChangeContext context) { if (issue.manualSeverity()) { @@ -203,6 +204,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { TechnicalDebt oldValue = issue.technicalDebt(); if (!Objects.equal(value, oldValue)) { issue.setTechnicalDebt(value); + issue.setFieldChange(context, TECHNICAL_DEBT, oldValue.toLong(), value.toLong()); issue.setUpdateDate(context.date()); issue.setChanged(true); return true; diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java index 0b0f977e084..4a9415cfebc 100644 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java +++ b/sonar-core/src/main/java/org/sonar/core/technicaldebt/TechnicalDebtConverter.java @@ -65,6 +65,13 @@ public class TechnicalDebtConverter implements BatchComponent, ServerComponent { } } + public double toDays(TechnicalDebt technicalDebt) { + double resultDays = technicalDebt.days(); + resultDays += Double.valueOf(technicalDebt.hours()) / hoursInDay; + resultDays += Double.valueOf(technicalDebt.minutes()) / (hoursInDay * 60.0); + return resultDays; + } + public TechnicalDebt fromMinutes(Long inMinutes){ int oneHourInMinute = 60; int days = 0; diff --git a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java index 345b7a513ec..1a04d60d4dc 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java @@ -371,8 +371,11 @@ public class IssueUpdaterTest { boolean updated = updater.setPastTechnicalDebt(issue, previousDebt, context); assertThat(updated).isTrue(); assertThat(issue.technicalDebt()).isEqualTo(TechnicalDebt.of(15, 0, 0)); - assertThat(issue.mustSendNotifications()).isFalse(); + + FieldDiffs.Diff diff = issue.currentChange().get(TECHNICAL_DEBT); + assertThat(diff.oldValue()).isEqualTo(TechnicalDebt.of(10, 0, 0).toLong()); + assertThat(diff.newValue()).isEqualTo(TechnicalDebt.of(15, 0, 0).toLong()); } @Test 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 fe86eb80dbf..1c521975f32 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 @@ -19,14 +19,13 @@ */ package org.sonar.core.technicaldebt; -import org.fest.assertions.Assertions; import org.junit.Before; import org.junit.Test; import org.sonar.api.config.Settings; import org.sonar.api.technicaldebt.TechnicalDebt; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; + public class TechnicalDebtConverterTest { @@ -41,17 +40,17 @@ public class TechnicalDebtConverterTest { } @Test - public void convert_to_days() { - assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.DAYS)), is(6.0)); - assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.HOURS)), is(6.0 / 12.0)); - assertThat(converter.toDays(WorkUnit.create(60.0, WorkUnit.MINUTES)), is(1.0 / 12.0)); + public void convert_work_unit_to_days() { + assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.DAYS))).isEqualTo(6.0); + assertThat(converter.toDays(WorkUnit.create(6.0, WorkUnit.HOURS))).isEqualTo(6.0 / 12.0); + assertThat(converter.toDays(WorkUnit.create(60.0, WorkUnit.MINUTES))).isEqualTo(1.0 / 12.0); } @Test - public void concert_to_minutes() { - assertThat(converter.toMinutes(WorkUnit.create(2.0, WorkUnit.DAYS)), is(2 * 12 * 60L)); - assertThat(converter.toMinutes(WorkUnit.create(6.0, WorkUnit.HOURS)), is(6 * 60L)); - assertThat(converter.toMinutes(WorkUnit.create(60.0, WorkUnit.MINUTES)), is(60L)); + public void concert_work_unit_to_minutes() { + assertThat(converter.toMinutes(WorkUnit.create(2.0, WorkUnit.DAYS))).isEqualTo(2 * 12 * 60L); + assertThat(converter.toMinutes(WorkUnit.create(6.0, WorkUnit.HOURS))).isEqualTo(6 * 60L); + assertThat(converter.toMinutes(WorkUnit.create(60.0, WorkUnit.MINUTES))).isEqualTo(60L); } @Test @@ -68,10 +67,20 @@ public class TechnicalDebtConverterTest { checkValues(converter.fromMinutes(790L), 10L, 1L, 1L); } + @Test + public void convert_technical_debt_to_days() { + assertThat(converter.toDays(TechnicalDebt.of(0, 0, 6))).isEqualTo(6.0); + assertThat(converter.toDays(TechnicalDebt.of(0, 6, 0))).isEqualTo(0.5); + assertThat(converter.toDays(TechnicalDebt.of(360, 0, 0))).isEqualTo(0.5); + assertThat(converter.toDays(TechnicalDebt.of(45, 0, 0))).isEqualTo(0.0625); + + assertThat(converter.toDays(TechnicalDebt.of(45, 6, 1))).isEqualTo(1.5625); + } + private void checkValues(TechnicalDebt technicalDebt, Long expectedMinutes, Long expectedHours, Long expectedDays) { - Assertions.assertThat(technicalDebt.minutes()).isEqualTo(expectedMinutes); - Assertions.assertThat(technicalDebt.hours()).isEqualTo(expectedHours); - Assertions.assertThat(technicalDebt.days()).isEqualTo(expectedDays); + assertThat(technicalDebt.minutes()).isEqualTo(expectedMinutes); + assertThat(technicalDebt.hours()).isEqualTo(expectedHours); + assertThat(technicalDebt.days()).isEqualTo(expectedDays); } } diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java index 4bfebcd2837..ac571ba5e7d 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java @@ -32,6 +32,7 @@ import org.sonar.api.issue.IssueComment; 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.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.utils.SonarException; @@ -81,12 +82,13 @@ public class InternalRubyIssueService implements ServerComponent { private final ActionService actionService; private final IssueFilterService issueFilterService; private final IssueBulkChangeService issueBulkChangeService; + private final IssueChangelogFormatter issueChangelogFormatter; public InternalRubyIssueService(IssueService issueService, IssueCommentService commentService, IssueChangelogService changelogService, ActionPlanService actionPlanService, IssueStatsFinder issueStatsFinder, ResourceDao resourceDao, ActionService actionService, - IssueFilterService issueFilterService, IssueBulkChangeService issueBulkChangeService) { + IssueFilterService issueFilterService, IssueBulkChangeService issueBulkChangeService, IssueChangelogFormatter issueChangelogFormatter) { this.issueService = issueService; this.commentService = commentService; this.changelogService = changelogService; @@ -96,6 +98,7 @@ public class InternalRubyIssueService implements ServerComponent { this.actionService = actionService; this.issueFilterService = issueFilterService; this.issueBulkChangeService = issueBulkChangeService; + this.issueChangelogFormatter = issueChangelogFormatter; } public IssueStatsFinder.IssueStatsResult findIssueAssignees(Map<String, Object> params) { @@ -126,6 +129,10 @@ public class InternalRubyIssueService implements ServerComponent { return changelogService.changelog(issue); } + public List<String> formatChangelog(FieldDiffs diffs){ + return issueChangelogFormatter.format(UserSession.get().locale(), diffs); + } + public Result<Issue> doTransition(String issueKey, String transitionKey) { Result<Issue> result = Result.of(); try { 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 new file mode 100644 index 00000000000..1923c026ac4 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueChangelogFormatter.java @@ -0,0 +1,61 @@ +/* + * 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 org.sonar.api.ServerComponent; +import org.sonar.api.issue.internal.FieldDiffs; +import org.sonar.core.i18n.I18nManager; + +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static com.google.common.collect.Lists.newArrayList; + +public class IssueChangelogFormatter implements ServerComponent { + + private final I18nManager i18nManager; + + public IssueChangelogFormatter(I18nManager i18nManager) { + this.i18nManager = i18nManager; + } + + public List<String> format(Locale locale, FieldDiffs diffs) { + List<String> result = newArrayList(); + 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())); + } 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("")) { + message.append(" ("); + message.append(i18nManager.message(locale, "issue.changelog.was", null, diff.oldValue())); + message.append(")"); + } + result.add(message.toString()); + } + return result; + } + +} 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 08809f8c276..9bd3b2071ad 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 @@ -52,13 +52,7 @@ import org.sonar.core.measure.MeasureFilterFactory; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; -import org.sonar.core.persistence.DaoUtils; -import org.sonar.core.persistence.DatabaseVersion; -import org.sonar.core.persistence.DefaultDatabase; -import org.sonar.core.persistence.MyBatis; -import org.sonar.core.persistence.PreviewDatabaseFactory; -import org.sonar.core.persistence.SemaphoreUpdater; -import org.sonar.core.persistence.SemaphoresImpl; +import org.sonar.core.persistence.*; import org.sonar.core.preview.PreviewCache; import org.sonar.core.purge.PurgeProfiler; import org.sonar.core.qualitymodel.DefaultModelFinder; @@ -90,63 +84,19 @@ import org.sonar.server.db.EmbeddedDatabaseFactory; import org.sonar.server.db.migrations.DatabaseMigration; import org.sonar.server.db.migrations.DatabaseMigrations; import org.sonar.server.db.migrations.DatabaseMigrator; -import org.sonar.server.issue.ActionPlanService; -import org.sonar.server.issue.ActionService; -import org.sonar.server.issue.AssignAction; -import org.sonar.server.issue.CommentAction; -import org.sonar.server.issue.DefaultIssueFinder; -import org.sonar.server.issue.InternalRubyIssueService; -import org.sonar.server.issue.IssueBulkChangeService; -import org.sonar.server.issue.IssueChangelogService; -import org.sonar.server.issue.IssueCommentService; -import org.sonar.server.issue.IssueFilterService; -import org.sonar.server.issue.IssueService; -import org.sonar.server.issue.IssueStatsFinder; -import org.sonar.server.issue.PlanAction; -import org.sonar.server.issue.PublicRubyIssueService; -import org.sonar.server.issue.ServerIssueStorage; -import org.sonar.server.issue.SetSeverityAction; -import org.sonar.server.issue.TransitionAction; +import org.sonar.server.issue.*; import org.sonar.server.notifications.NotificationCenter; import org.sonar.server.notifications.NotificationService; import org.sonar.server.permission.InternalPermissionService; import org.sonar.server.permission.InternalPermissionTemplateService; -import org.sonar.server.plugins.ApplicationDeployer; -import org.sonar.server.plugins.DefaultServerPluginRepository; -import org.sonar.server.plugins.InstalledPluginReferentialFactory; -import org.sonar.server.plugins.PluginDeployer; -import org.sonar.server.plugins.PluginDownloader; -import org.sonar.server.plugins.ServerExtensionInstaller; -import org.sonar.server.plugins.UpdateCenterClient; -import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.plugins.*; import org.sonar.server.rule.RubyRuleService; import org.sonar.server.rules.ProfilesConsole; import org.sonar.server.rules.RulesConsole; -import org.sonar.server.startup.CleanDryRunCache; -import org.sonar.server.startup.DeleteDeprecatedMeasures; -import org.sonar.server.startup.GenerateBootstrapIndex; -import org.sonar.server.startup.GeneratePluginIndex; -import org.sonar.server.startup.GwtPublisher; -import org.sonar.server.startup.JdbcDriverDeployer; -import org.sonar.server.startup.LogServerId; -import org.sonar.server.startup.RegisterMetrics; -import org.sonar.server.startup.RegisterNewDashboards; -import org.sonar.server.startup.RegisterNewMeasureFilters; -import org.sonar.server.startup.RegisterNewProfiles; -import org.sonar.server.startup.RegisterPermissionTemplates; -import org.sonar.server.startup.RegisterRules; -import org.sonar.server.startup.RegisterServletFilters; -import org.sonar.server.startup.RegisterTechnicalDebtModel; -import org.sonar.server.startup.RenameDeprecatedPropertyKeys; -import org.sonar.server.startup.ServerMetadataPersister; -import org.sonar.server.startup.VerifyNoQualityModelsAreDefined; +import org.sonar.server.startup.*; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.RubyTextService; -import org.sonar.server.ui.CodeColorizers; -import org.sonar.server.ui.JRubyI18n; -import org.sonar.server.ui.PageDecorations; -import org.sonar.server.ui.SecurityRealmFactory; -import org.sonar.server.ui.Views; +import org.sonar.server.ui.*; import org.sonar.server.user.DefaultUserService; import org.sonar.server.user.NewUserNotifier; @@ -338,6 +288,7 @@ public final class Platform { servicesContainer.addSingleton(IssueFilterSerializer.class); servicesContainer.addSingleton(IssueFilterService.class); servicesContainer.addSingleton(IssueBulkChangeService.class); + servicesContainer.addSingleton(IssueChangelogFormatter.class); // issues actions servicesContainer.addSingleton(AssignAction.class); servicesContainer.addSingleton(PlanAction.class); diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb index 26c12118c09..4b95f4b330b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issue/_changelog.html.erb @@ -13,19 +13,10 @@ <td class="thin left top" nowrap><%= h(user.name()) if user -%></td> <td class="left top"> <% - change.diffs.entrySet().each_with_index do |entry, index| - key = entry.getKey() - diff = entry.getValue() + Internal.issues.formatChangelog(change).each_with_index do |message, index| %> <% if index>0 %><br/><% end %> - <% if diff.newValue.present? %> - <%= message('issue.changelog.changed_to', :params => [message(key), diff.newValue()]) -%> - <% else %> - <%= message('issue.changelog.removed', :params => [message(key)]) -%> - <% end %> - <% if diff.oldValue.present? %> - (<%= message('issue.changelog.was', :params => [diff.oldValue]) -%>) - <% end %> + <%= message -%> <% end %> </td> </tr> 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 4c7d8a9a90b..9a8865a5dcc 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 @@ -62,13 +62,14 @@ public class InternalRubyIssueServiceTest { ActionService actionService = mock(ActionService.class); IssueFilterService issueFilterService = mock(IssueFilterService.class); IssueBulkChangeService issueBulkChangeService = mock(IssueBulkChangeService.class); + IssueChangelogFormatter issueChangelogFormatter = mock(IssueChangelogFormatter.class); @Before public void setUp() { ResourceDto project = new ResourceDto().setKey("org.sonar.Sample"); when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project); service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, issueStatsFinder, resourceDao, actionService, - issueFilterService, issueBulkChangeService); + issueFilterService, issueBulkChangeService, issueChangelogFormatter); } @Test 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 new file mode 100644 index 00000000000..6de106c78b8 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueChangelogFormatterTest.java @@ -0,0 +1,123 @@ +/* + * 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 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.issue.internal.FieldDiffs; +import org.sonar.core.i18n.I18nManager; + +import java.util.List; +import java.util.Locale; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class IssueChangelogFormatterTest { + + private static final Locale DEFAULT_LOCALE = Locale.getDefault(); + + @Mock + private I18nManager i18nManager; + + private IssueChangelogFormatter formatter; + + @Before + public void before(){ + formatter = new IssueChangelogFormatter(i18nManager); + } + + @Test + public void format_field_diffs_with_new_and_old_value(){ + FieldDiffs diffs = new FieldDiffs(); + diffs.setDiff("severity", "BLOCKER", "INFO"); + + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.severity", null)).thenReturn("Severity"); + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.changed_to", null, "Severity", "INFO")).thenReturn("Severity changed to INFO"); + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.was", null, "BLOCKER")).thenReturn("was BLOCKER"); + + List<String> result = formatter.format(DEFAULT_LOCALE, diffs); + assertThat(result).hasSize(1); + String message = result.get(0); + assertThat(message).isEqualTo("Severity changed to INFO (was BLOCKER)"); + } + + @Test + public void format_field_diffs_with_only_new_value(){ + FieldDiffs diffs = new FieldDiffs(); + diffs.setDiff("severity", null, "INFO"); + + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.severity", null)).thenReturn("Severity"); + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.changed_to", null, "Severity", "INFO")).thenReturn("Severity changed to INFO"); + + List<String> result = formatter.format(DEFAULT_LOCALE, diffs); + assertThat(result).hasSize(1); + String message = result.get(0); + assertThat(message).isEqualTo("Severity changed to INFO"); + } + + @Test + public void format_field_diffs_with_only_old_value(){ + FieldDiffs diffs = new FieldDiffs(); + diffs.setDiff("severity", "BLOCKER", null); + + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.severity", null)).thenReturn("Severity"); + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.removed", null, "Severity")).thenReturn("Severity removed"); + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.was", null, "BLOCKER")).thenReturn("was BLOCKER"); + + List<String> result = formatter.format(DEFAULT_LOCALE, diffs); + assertThat(result).hasSize(1); + String message = result.get(0); + assertThat(message).isEqualTo("Severity removed (was BLOCKER)"); + } + + @Test + public void format_field_diffs_without_value(){ + FieldDiffs diffs = new FieldDiffs(); + diffs.setDiff("severity", null, null); + + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.severity", null)).thenReturn("Severity"); + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.removed", null, "Severity")).thenReturn("Severity removed"); + + List<String> result = formatter.format(DEFAULT_LOCALE, diffs); + assertThat(result).hasSize(1); + String message = result.get(0); + assertThat(message).isEqualTo("Severity removed"); + } + + @Test + public void format_field_diffs_with_empty_old_value(){ + FieldDiffs diffs = new FieldDiffs(); + diffs.setDiff("severity", "", null); + + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.field.severity", null)).thenReturn("Severity"); + when(i18nManager.message(DEFAULT_LOCALE, "issue.changelog.removed", null, "Severity")).thenReturn("Severity removed"); + + List<String> result = formatter.format(DEFAULT_LOCALE, diffs); + assertThat(result).hasSize(1); + String message = result.get(0); + assertThat(message).isEqualTo("Severity removed"); + } + +} |