You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NewIssuesEmailTemplateTest.java 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.server.issue.notification;
  21. import java.io.IOException;
  22. import java.nio.charset.StandardCharsets;
  23. import org.apache.commons.io.IOUtils;
  24. import org.junit.Rule;
  25. import org.junit.Test;
  26. import org.sonar.api.config.EmailSettings;
  27. import org.sonar.api.config.internal.MapSettings;
  28. import org.sonar.api.notifications.Notification;
  29. import org.sonar.plugins.emailnotifications.api.EmailMessage;
  30. import org.sonar.server.l18n.I18nRule;
  31. import static org.assertj.core.api.Assertions.assertThat;
  32. import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.ASSIGNEE;
  33. import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT;
  34. import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.EFFORT;
  35. import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.RULE;
  36. import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.RULE_TYPE;
  37. import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG;
  38. public class NewIssuesEmailTemplateTest {
  39. @Rule
  40. public I18nRule i18n = new I18nRule()
  41. .put("issue.type.BUG", "Bug")
  42. .put("issue.type.CODE_SMELL", "Code Smell")
  43. .put("issue.type.VULNERABILITY", "Vulnerability");
  44. private MapSettings settings = new MapSettings()
  45. .setProperty("sonar.core.serverBaseURL", "http://nemo.sonarsource.org");
  46. private NewIssuesEmailTemplate template = new NewIssuesEmailTemplate(new EmailSettings(settings.asConfig()), i18n);
  47. @Test
  48. public void no_format_is_not_the_correct_notification() {
  49. Notification notification = new Notification("my-new-issues");
  50. EmailMessage message = template.format(notification);
  51. assertThat(message).isNull();
  52. }
  53. @Test
  54. public void message_id() {
  55. Notification notification = newNotification(32);
  56. EmailMessage message = template.format(notification);
  57. assertThat(message.getMessageId()).isEqualTo("new-issues/org.apache:struts");
  58. }
  59. @Test
  60. public void subject() {
  61. Notification notification = newNotification(32);
  62. EmailMessage message = template.format(notification);
  63. assertThat(message.getSubject()).isEqualTo("Struts: 32 new issues (new debt: 1d3h)");
  64. }
  65. @Test
  66. public void subject_on_branch() {
  67. Notification notification = newNotification(32)
  68. .setFieldValue("branch", "feature1");
  69. EmailMessage message = template.format(notification);
  70. assertThat(message.getSubject()).isEqualTo("Struts (feature1): 32 new issues (new debt: 1d3h)");
  71. }
  72. @Test
  73. public void format_email_with_all_fields_filled() {
  74. Notification notification = newNotification(32)
  75. .setFieldValue("projectVersion", "42.1.1");
  76. addAssignees(notification);
  77. addRules(notification);
  78. addTags(notification);
  79. addComponents(notification);
  80. EmailMessage message = template.format(notification);
  81. // TODO datetime to be completed when test is isolated from JVM timezone
  82. assertThat(message.getMessage())
  83. .startsWith("Project: Struts\n" +
  84. "Version: 42.1.1\n" +
  85. "\n" +
  86. "32 new issues (new debt: 1d3h)\n" +
  87. "\n" +
  88. " Type\n" +
  89. " Bug: 1 Vulnerability: 10 Code Smell: 3\n" +
  90. "\n" +
  91. " Assignees\n" +
  92. " robin.williams: 5\n" +
  93. " al.pacino: 7\n" +
  94. "\n" +
  95. " Rules\n" +
  96. " Rule the Universe (Clojure): 42\n" +
  97. " Rule the World (Java): 5\n" +
  98. "\n" +
  99. " Tags\n" +
  100. " oscar: 3\n" +
  101. " cesar: 10\n" +
  102. "\n" +
  103. " Most impacted files\n" +
  104. " /path/to/file: 3\n" +
  105. " /path/to/directory: 7\n" +
  106. "\n" +
  107. "More details at: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&createdAt=2010-05-1");
  108. }
  109. @Test
  110. public void format_email_with_no_assignees_tags_nor_components_nor_version() {
  111. Notification notification = newNotification(32);
  112. EmailMessage message = template.format(notification);
  113. // TODO datetime to be completed when test is isolated from JVM timezone
  114. assertThat(message.getMessage())
  115. .startsWith("Project: Struts\n" +
  116. "\n" +
  117. "32 new issues (new debt: 1d3h)\n" +
  118. "\n" +
  119. " Type\n" +
  120. " Bug: 1 Vulnerability: 10 Code Smell: 3\n" +
  121. "\n" +
  122. "More details at: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&createdAt=2010-05-1");
  123. }
  124. @Test
  125. public void format_email_supports_single_issue() {
  126. Notification notification = newNotification(1);
  127. EmailMessage message = template.format(notification);
  128. assertThat(message.getSubject())
  129. .isEqualTo("Struts: 1 new issue (new debt: 1d3h)");
  130. assertThat(message.getMessage())
  131. .contains("1 new issue (new debt: 1d3h)\n");
  132. }
  133. @Test
  134. public void format_email_with_issue_on_branch() {
  135. Notification notification = newNotification(32)
  136. .setFieldValue("branch", "feature1");
  137. EmailMessage message = template.format(notification);
  138. // TODO datetime to be completed when test is isolated from JVM timezone
  139. assertThat(message.getMessage())
  140. .startsWith("Project: Struts\n" +
  141. "Branch: feature1\n" +
  142. "\n" +
  143. "32 new issues (new debt: 1d3h)\n" +
  144. "\n" +
  145. " Type\n" +
  146. " Bug: 1 Vulnerability: 10 Code Smell: 3\n" +
  147. "\n" +
  148. "More details at: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&branch=feature1&createdAt=2010-05-1");
  149. }
  150. @Test
  151. public void format_email_with_issue_on_branch_with_version() {
  152. Notification notification = newNotification(32)
  153. .setFieldValue("branch", "feature1")
  154. .setFieldValue("projectVersion", "42.1.1");
  155. EmailMessage message = template.format(notification);
  156. // TODO datetime to be completed when test is isolated from JVM timezone
  157. assertThat(message.getMessage())
  158. .startsWith("Project: Struts\n" +
  159. "Branch: feature1\n" +
  160. "Version: 42.1.1\n" +
  161. "\n" +
  162. "32 new issues (new debt: 1d3h)\n" +
  163. "\n" +
  164. " Type\n" +
  165. " Bug: 1 Vulnerability: 10 Code Smell: 3\n" +
  166. "\n" +
  167. "More details at: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&branch=feature1&createdAt=2010-05-1");
  168. }
  169. @Test
  170. public void do_not_add_footer_when_properties_missing() {
  171. Notification notification = new Notification(NewIssuesNotification.TYPE)
  172. .setFieldValue(RULE_TYPE + ".count", "32")
  173. .setFieldValue("projectName", "Struts");
  174. EmailMessage message = template.format(notification);
  175. assertThat(message.getMessage()).doesNotContain("See it");
  176. }
  177. private Notification newNotification(int count) {
  178. return new Notification(NewIssuesNotification.TYPE)
  179. .setFieldValue("projectName", "Struts")
  180. .setFieldValue("projectKey", "org.apache:struts")
  181. .setFieldValue("projectDate", "2010-05-18T14:50:45+0000")
  182. .setFieldValue(EFFORT + ".count", "1d3h")
  183. .setFieldValue(RULE_TYPE + ".count", String.valueOf(count))
  184. .setFieldValue(RULE_TYPE + ".BUG.count", "1")
  185. .setFieldValue(RULE_TYPE + ".CODE_SMELL.count", "3")
  186. .setFieldValue(RULE_TYPE + ".VULNERABILITY.count", "10");
  187. }
  188. private void addAssignees(Notification notification) {
  189. notification
  190. .setFieldValue(ASSIGNEE + ".1.label", "robin.williams")
  191. .setFieldValue(ASSIGNEE + ".1.count", "5")
  192. .setFieldValue(ASSIGNEE + ".2.label", "al.pacino")
  193. .setFieldValue(ASSIGNEE + ".2.count", "7");
  194. }
  195. private void addTags(Notification notification) {
  196. notification
  197. .setFieldValue(TAG + ".1.label", "oscar")
  198. .setFieldValue(TAG + ".1.count", "3")
  199. .setFieldValue(TAG + ".2.label", "cesar")
  200. .setFieldValue(TAG + ".2.count", "10");
  201. }
  202. private void addComponents(Notification notification) {
  203. notification
  204. .setFieldValue(COMPONENT + ".1.label", "/path/to/file")
  205. .setFieldValue(COMPONENT + ".1.count", "3")
  206. .setFieldValue(COMPONENT + ".2.label", "/path/to/directory")
  207. .setFieldValue(COMPONENT + ".2.count", "7");
  208. }
  209. private void addRules(Notification notification) {
  210. notification
  211. .setFieldValue(RULE + ".1.label", "Rule the Universe (Clojure)")
  212. .setFieldValue(RULE + ".1.count", "42")
  213. .setFieldValue(RULE + ".2.label", "Rule the World (Java)")
  214. .setFieldValue(RULE + ".2.count", "5");
  215. }
  216. private void assertStartsWithFile(String message, String resourcePath) throws IOException {
  217. String fileContent = IOUtils.toString(getClass().getResource(resourcePath), StandardCharsets.UTF_8);
  218. assertThat(sanitizeString(message)).startsWith(sanitizeString(fileContent));
  219. }
  220. /**
  221. * sanitize EOL and tabs if git clone is badly configured
  222. */
  223. private static String sanitizeString(String s) {
  224. return s.replaceAll("\\r\\n|\\r|\\s+", "");
  225. }
  226. }