3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.server.qualitygate.notification;
22 import com.tngtech.java.junit.dataprovider.DataProvider;
23 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
24 import com.tngtech.java.junit.dataprovider.UseDataProvider;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 import org.sonar.api.config.EmailSettings;
29 import org.sonar.api.notifications.Notification;
30 import org.sonar.server.issue.notification.EmailMessage;
32 import static org.hamcrest.CoreMatchers.is;
33 import static org.hamcrest.CoreMatchers.nullValue;
34 import static org.junit.Assert.assertThat;
35 import static org.mockito.Mockito.mock;
36 import static org.mockito.Mockito.when;
38 @RunWith(DataProviderRunner.class)
39 public class QGChangeEmailTemplateTest {
41 private QGChangeEmailTemplate template;
45 EmailSettings configuration = mock(EmailSettings.class);
46 when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org");
47 template = new QGChangeEmailTemplate(configuration);
51 public void shouldNotFormatIfNotCorrectNotification() {
52 Notification notification = new Notification("other-notif");
53 EmailMessage message = template.format(notification);
54 assertThat(message, nullValue());
58 public void shouldFormatAlertWithSeveralMessages() {
59 Notification notification = createNotification("Failed", "violations > 4, coverage < 75%", "ERROR", "false");
61 EmailMessage message = template.format(notification);
62 assertThat(message.getMessageId(), is("alerts/45"));
63 assertThat(message.getSubject(), is("Quality gate status changed on \"Foo\""));
64 assertThat(message.getMessage(), is("" +
66 "Version: V1-SNAP\n" +
67 "Quality gate status: Failed\n" +
69 "Quality gate thresholds:\n" +
70 " - violations > 4\n" +
71 " - coverage < 75%\n" +
73 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
77 public void shouldFormatAlertWithSeveralMessagesOnBranch() {
78 Notification notification = createNotification("Failed", "violations > 4, coverage < 75%", "ERROR", "false")
79 .setFieldValue("branch", "feature");
81 EmailMessage message = template.format(notification);
82 assertThat(message.getMessageId(), is("alerts/45"));
83 assertThat(message.getSubject(), is("Quality gate status changed on \"Foo (feature)\""));
84 assertThat(message.getMessage(), is("" +
87 "Version: V1-SNAP\n" +
88 "Quality gate status: Failed\n" +
90 "Quality gate thresholds:\n" +
91 " - violations > 4\n" +
92 " - coverage < 75%\n" +
94 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"));
98 public void shouldFormatNewAlertWithSeveralMessages() {
99 Notification notification = createNotification("Failed", "violations > 4, coverage < 75%", "ERROR", "true");
101 EmailMessage message = template.format(notification);
102 assertThat(message.getMessageId(), is("alerts/45"));
103 assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\""));
104 assertThat(message.getMessage(), is("" +
106 "Version: V1-SNAP\n" +
107 "Quality gate status: Failed\n" +
109 "New quality gate thresholds:\n" +
110 " - violations > 4\n" +
111 " - coverage < 75%\n" +
113 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
117 public void shouldFormatNewAlertWithOneMessage() {
118 Notification notification = createNotification("Failed", "violations > 4", "ERROR", "true");
120 EmailMessage message = template.format(notification);
121 assertThat(message.getMessageId(), is("alerts/45"));
122 assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\""));
123 assertThat(message.getMessage(), is("" +
125 "Version: V1-SNAP\n" +
126 "Quality gate status: Failed\n" +
128 "New quality gate threshold: violations > 4\n" +
130 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
134 public void shouldFormatNewAlertWithoutVersion() {
135 Notification notification = createNotification("Failed", "violations > 4", "ERROR", "true")
136 .setFieldValue("projectVersion", null);
138 EmailMessage message = template.format(notification);
139 assertThat(message.getMessageId(), is("alerts/45"));
140 assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\""));
141 assertThat(message.getMessage(), is("" +
143 "Quality gate status: Failed\n" +
145 "New quality gate threshold: violations > 4\n" +
147 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
151 public void shouldFormatBackToGreenMessage() {
152 Notification notification = createNotification("Passed", "", "OK", "false");
154 EmailMessage message = template.format(notification);
155 assertThat(message.getMessageId(), is("alerts/45"));
156 assertThat(message.getSubject(), is("\"Foo\" is back to green"));
157 assertThat(message.getMessage(), is("" +
159 "Version: V1-SNAP\n" +
160 "Quality gate status: Passed\n" +
163 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
167 public void shouldFormatNewAlertWithOneMessageOnBranch() {
168 Notification notification = createNotification("Failed", "violations > 4", "ERROR", "true")
169 .setFieldValue("branch", "feature");
171 EmailMessage message = template.format(notification);
172 assertThat(message.getMessageId(), is("alerts/45"));
173 assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo (feature)\""));
174 assertThat(message.getMessage(), is("" +
176 "Branch: feature\n" +
177 "Version: V1-SNAP\n" +
178 "Quality gate status: Failed\n" +
180 "New quality gate threshold: violations > 4\n" +
182 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"));
186 public void shouldFormatBackToGreenMessageOnBranch() {
187 Notification notification = createNotification("Passed", "", "OK", "false")
188 .setFieldValue("branch", "feature");
190 EmailMessage message = template.format(notification);
191 assertThat(message.getMessageId(), is("alerts/45"));
192 assertThat(message.getSubject(), is("\"Foo (feature)\" is back to green"));
193 assertThat(message.getMessage(), is("" +
195 "Branch: feature\n" +
196 "Version: V1-SNAP\n" +
197 "Quality gate status: Passed\n" +
200 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"));
204 public static Object[][] alertTextAndFormattedText() {
205 return new Object[][] {
206 {"violations > 0", "violations > 0"},
207 {"violations > 1", "violations > 1"},
208 {"violations > 4", "violations > 4"},
209 {"violations > 5", "violations > 5"},
210 {"violations > 6", "violations > 6"},
211 {"violations > 10", "violations > 10"},
212 {"Code Coverage < 0%", "Code Coverage < 0%"},
213 {"Code Coverage < 1%", "Code Coverage < 1%"},
214 {"Code Coverage < 50%", "Code Coverage < 50%"},
215 {"Code Coverage < 100%", "Code Coverage < 100%"},
216 {"Custom metric with big number > 100000000000", "Custom metric with big number > 100000000000"},
217 {"Custom metric with negative number > -1", "Custom metric with negative number > -1"},
218 {"custom metric condition not met", "custom metric condition not met"},
220 {"Security Review Rating > 1", "Security Review Rating worse than A"},
221 {"Security Review Rating on New Code > 4", "Security Review Rating on New Code worse than D"},
222 {"Security Rating > 1", "Security Rating worse than A"},
223 {"Maintainability Rating > 3", "Maintainability Rating worse than C"},
224 {"Reliability Rating > 4", "Reliability Rating worse than D" }
228 @UseDataProvider("alertTextAndFormattedText")
230 public void shouldFormatNewAlertWithThresholdProperlyFormatted(String alertText, String expectedFormattedAlertText) {
231 Notification notification = createNotification("Failed", alertText, "ERROR", "true");
233 EmailMessage message = template.format(notification);
234 assertThat(message.getMessageId(), is("alerts/45"));
235 assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\""));
236 assertThat(message.getMessage(), is("" +
238 "Version: V1-SNAP\n" +
239 "Quality gate status: Failed\n" +
241 "New quality gate threshold: " + expectedFormattedAlertText + "\n" +
243 "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"));
247 private Notification createNotification(String alertName, String alertText, String alertLevel, String isNewAlert) {
248 return new Notification("alerts")
249 .setFieldValue("projectName", "Foo")
250 .setFieldValue("projectKey", "org.sonar.foo:foo")
251 .setFieldValue("projectId", "45")
252 .setFieldValue("projectVersion", "V1-SNAP")
253 .setFieldValue("alertName", alertName)
254 .setFieldValue("alertText", alertText)
255 .setFieldValue("alertLevel", alertLevel)
256 .setFieldValue("isNewAlert", isNewAlert)
257 .setFieldValue("ratingMetrics", "Maintainability Rating,Reliability Rating on New Code," +
258 "Maintainability Rating on New Code,Reliability Rating," +
259 "Security Rating on New Code,Security Review Rating," +
260 "Security Review Rating on New Code,Security Rating");