+++ /dev/null
-/*
- * Copyright (C) 2009-2014 SonarSource SA
- * All rights reserved
- * mailto:contact AT sonarsource DOT com
- */
-package org.sonar.it;
-
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.sonar.orchestrator.locator.FileLocation;
-import java.io.File;
-import org.apache.commons.io.FileUtils;
-
-public class ItUtils {
-
- private ItUtils() {
- }
-
- private static final Supplier<File> HOME_DIR = Suppliers.memoize(new Supplier<File>() {
- @Override
- public File get() {
- File dir = new File("it");
-
- // intellij way
- if (dir.exists() && dir.isDirectory()) {
- return dir.getParentFile();
- }
-
- // maven way
- dir = new File("../it");
- if (dir.exists() && dir.isDirectory()) {
- return dir.getParentFile();
- }
-
- throw new IllegalStateException("Fail to locate home directory");
- }
- });
-
- public static FileLocation xooPlugin() {
- File target = new File(HOME_DIR.get(), "plugins/sonar-xoo-plugin/target");
- if (target.exists()) {
- for (File jar : FileUtils.listFiles(target, new String[] {"jar"}, false)) {
- if (jar.getName().startsWith("sonar-xoo-plugin-") && !jar.getName().contains("-source")) {
- return FileLocation.of(jar);
- }
- }
- }
- throw new IllegalStateException("XOO plugin is not built");
- }
-
- /**
- * Locate the directory of sample project
- *
- * @param relativePath path related to the directory it/projects, for example "qualitygate/xoo-sample"
- */
- public static File projectDir(String relativePath) {
- File dir = new File(HOME_DIR.get(), "it/projects/" + relativePath);
- if (!dir.exists() || !dir.isDirectory()) {
- throw new IllegalStateException("Directory does not exist: " + dir.getAbsolutePath());
- }
- return dir;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2009-2014 SonarSource SA
- * All rights reserved
- * mailto:contact AT sonarsource DOT com
- */
-package org.sonar.it.qualitygate;
-
-import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.build.SonarRunner;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.it.ItUtils;
-import org.sonar.wsclient.project.NewProject;
-import org.sonar.wsclient.qualitygate.NewCondition;
-import org.sonar.wsclient.qualitygate.QualityGate;
-import org.sonar.wsclient.qualitygate.QualityGateClient;
-import org.sonar.wsclient.services.Measure;
-import org.sonar.wsclient.services.Resource;
-import org.sonar.wsclient.services.ResourceQuery;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.it.ItUtils.projectDir;
-
-public class QualityGateTest {
-
- private static final String PROJECT_KEY = "sample";
-
- private long provisionnedProjectId = -1L;
-
- @ClassRule
- public static Orchestrator orchestrator = Orchestrator.builderEnv()
- .addPlugin(ItUtils.xooPlugin())
- .build();
-
- @Before
- public void cleanUp() throws Exception {
- orchestrator.resetData();
- provisionnedProjectId = Long.parseLong(orchestrator.getServer().adminWsClient().projectClient().create(NewProject.create().key(PROJECT_KEY).name("Sample")).id());
- }
-
- @Test
- public void do_not_compute_status_if_no_gate() {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
- orchestrator.executeBuild(build);
-
- assertThat(fetchResourceWithGateStatus()).isNull();
- }
-
- @Test
- public void status_ok_if_empty_gate() {
- QualityGate empty = qgClient().create("Empty");
- qgClient().setDefault(empty.id());
-
- try {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
- orchestrator.executeBuild(build);
-
- assertThat(fetchGateStatus().getData()).isEqualTo("OK");
- } finally {
- qgClient().unsetDefault();
- qgClient().destroy(empty.id());
- }
- }
-
- @Test
- public void test_status_ok() {
- QualityGate simple = qgClient().create("SimpleWithHighThreshold");
- qgClient().setDefault(simple.id());
- qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").operator("GT").warningThreshold("40"));
-
- try {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
- orchestrator.executeBuild(build);
-
- assertThat(fetchGateStatus().getData()).isEqualTo("OK");
- } finally {
- qgClient().unsetDefault();
- qgClient().destroy(simple.id());
- }
- }
-
- @Test
- public void test_status_warning() {
- QualityGate simple = qgClient().create("SimpleWithLowThreshold");
- qgClient().setDefault(simple.id());
- qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").operator("GT").warningThreshold("10"));
-
- try {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
- orchestrator.executeBuild(build);
-
- assertThat(fetchGateStatus().getData()).isEqualTo("WARN");
- } finally {
- qgClient().unsetDefault();
- qgClient().destroy(simple.id());
- }
-
- }
-
- @Test
- public void test_status_error() {
- QualityGate simple = qgClient().create("SimpleWithLowThreshold");
- qgClient().setDefault(simple.id());
- qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").operator("GT").errorThreshold("10"));
-
- try {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
- orchestrator.executeBuild(build);
-
- assertThat(fetchGateStatus().getData()).isEqualTo("ERROR");
- } finally {
- qgClient().unsetDefault();
- qgClient().destroy(simple.id());
- }
- }
-
- @Test
- public void use_server_settings_instead_of_default_gate() {
- QualityGate alert = qgClient().create("AlertWithLowThreshold");
- qgClient().createCondition(NewCondition.create(alert.id()).metricKey("ncloc").operator("GT").warningThreshold("10"));
- QualityGate error = qgClient().create("ErrorWithLowThreshold");
- qgClient().createCondition(NewCondition.create(error.id()).metricKey("ncloc").operator("GT").errorThreshold("10"));
-
- qgClient().setDefault(alert.id());
- qgClient().selectProject(error.id(), provisionnedProjectId);
-
- try {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
- orchestrator.executeBuild(build);
-
- assertThat(fetchGateStatus().getData()).isEqualTo("ERROR");
- } finally {
- qgClient().unsetDefault();
- qgClient().destroy(alert.id());
- qgClient().destroy(error.id());
- }
- }
-
- @Test
- public void conditions_on_multiple_metric_types() {
- QualityGate allTypes = qgClient().create("AllMetricTypes");
- qgClient().createCondition(NewCondition.create(allTypes.id()).metricKey("ncloc").operator("GT").warningThreshold("10"));
- qgClient().createCondition(NewCondition.create(allTypes.id()).metricKey("duplicated_lines_density").operator("GT").warningThreshold("20"));
- qgClient().setDefault(allTypes.id());
-
- try {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"))
- .setProperty("sonar.cpd.xoo.minimumLines", "2")
- .setProperty("sonar.cpd.xoo.minimumTokens", "5");
- orchestrator.executeBuild(build);
-
- Measure alertStatus = fetchGateStatus();
- assertThat(alertStatus.getData()).isEqualTo("WARN");
- assertThat(alertStatus.getAlertText())
- .contains("Lines of code > 10")
- .contains("Duplicated lines (%) > 20");
- } finally {
- qgClient().unsetDefault();
- qgClient().destroy(allTypes.id());
- }
- }
-
- @Test
- public void compute_gate_status_on_metric_variation() {
- QualityGate simple = qgClient().create("SimpleWithDifferential");
- qgClient().setDefault(simple.id());
- qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").period(1).operator("EQ").warningThreshold("0"));
-
- try {
- SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
- orchestrator.executeBuild(build);
- assertThat(fetchGateStatus().getData()).isEqualTo("OK");
-
- orchestrator.executeBuild(build);
- assertThat(fetchGateStatus().getData()).isEqualTo("WARN");
- } finally {
- qgClient().unsetDefault();
- qgClient().destroy(simple.id());
- }
- }
-
- private Measure fetchGateStatus() {
- return fetchResourceWithGateStatus().getMeasure("alert_status");
- }
-
- private Resource fetchResourceWithGateStatus() {
- return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(PROJECT_KEY, "alert_status").setIncludeAlerts(true));
- }
-
- private static QualityGateClient qgClient() {
- return orchestrator.getServer().adminWsClient().qualityGateClient();
- }
-}
--- /dev/null
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package qualitygate;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.selenium.Selenese;
+import com.sonar.orchestrator.util.NetworkUtils;
+import java.util.Iterator;
+import javax.mail.internet.MimeMessage;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.Sonar;
+import org.sonar.wsclient.qualitygate.NewCondition;
+import org.sonar.wsclient.qualitygate.QualityGate;
+import org.sonar.wsclient.qualitygate.QualityGateClient;
+import org.sonar.wsclient.services.Measure;
+import org.sonar.wsclient.services.PropertyUpdateQuery;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+import org.subethamail.wiser.Wiser;
+import org.subethamail.wiser.WiserMessage;
+import util.ItUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static util.ItUtils.projectDir;
+
+public class QualityGateNotificationTest {
+
+ private static final String PROJECT_KEY = "sample";
+
+ @ClassRule
+ public static Orchestrator orchestrator = Orchestrator.builderEnv()
+ .addPlugin(ItUtils.xooPlugin())
+
+ // 1 second. Required for notification test.
+ .setServerProperty("sonar.notifications.delay", "1")
+
+ .build();
+
+ @Before
+ public void cleanUp() throws Exception {
+ orchestrator.resetData();
+ }
+
+ @Test
+ public void status_on_metric_variation_and_send_notifications() throws Exception {
+ Wiser smtpServer = new Wiser(NetworkUtils.getNextAvailablePort());
+ try {
+ // Configure SMTP
+ smtpServer.start();
+ Sonar wsClient = orchestrator.getServer().getAdminWsClient();
+ wsClient.update(new PropertyUpdateQuery("email.smtp_host.secured", "localhost"));
+ wsClient.update(new PropertyUpdateQuery("email.smtp_port.secured", Integer.toString(smtpServer.getServer().getPort())));
+
+ // Create user, who will receive notifications for new violations
+ orchestrator.getServer().adminWsClient().post("api/users/create", "login", "tester", "name", "Tester", "email", "tester@example.org", "password", "tester");
+ Selenese selenese = Selenese
+ .builder()
+ .setHtmlTestsInClasspath("notifications",
+ "/selenium/qualitygate/notifications/email_configuration.html",
+ "/selenium/qualitygate/notifications/activate_notification_channels.html").build();
+ orchestrator.executeSelenese(selenese);
+
+ // Create quality gate with conditions on variations
+ QualityGate simple = qgClient().create("SimpleWithDifferential");
+ qgClient().setDefault(simple.id());
+ qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").period(1).operator("EQ").warningThreshold("0"));
+
+ SonarRunner analysis = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
+ orchestrator.executeBuild(analysis);
+ assertThat(fetchGateStatus().getData()).isEqualTo("OK");
+
+ orchestrator.executeBuild(analysis);
+ assertThat(fetchGateStatus().getData()).isEqualTo("WARN");
+
+ qgClient().unsetDefault();
+ qgClient().destroy(simple.id());
+
+ // Wait until all notifications are delivered
+ Thread.sleep(10000);
+
+ Iterator<WiserMessage> emails = smtpServer.getMessages().iterator();
+
+ MimeMessage message = emails.next().getMimeMessage();
+ assertThat(message.getHeader("To", null)).isEqualTo("<test@example.org>");
+ assertThat((String) message.getContent()).contains("This is a test message from Sonar");
+
+ assertThat(emails.hasNext()).isTrue();
+ message = emails.next().getMimeMessage();
+ assertThat(message.getHeader("To", null)).isEqualTo("<tester@example.org>");
+ assertThat((String) message.getContent()).contains("Quality gate status: Orange (was Green)");
+ assertThat((String) message.getContent()).contains("Quality gate threshold: Lines of code variation = 0 since previous analysis");
+ assertThat((String) message.getContent()).contains("/dashboard/index/sample");
+ assertThat(emails.hasNext()).isFalse();
+
+ } finally {
+ smtpServer.stop();
+ }
+ }
+
+ private Measure fetchGateStatus() {
+ return fetchResourceWithGateStatus().getMeasure("alert_status");
+ }
+
+ private Resource fetchResourceWithGateStatus() {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(PROJECT_KEY, "alert_status").setIncludeAlerts(true));
+ }
+
+ private static QualityGateClient qgClient() {
+ return orchestrator.getServer().adminWsClient().qualityGateClient();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package qualitygate;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.SonarRunner;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.project.NewProject;
+import org.sonar.wsclient.qualitygate.NewCondition;
+import org.sonar.wsclient.qualitygate.QualityGate;
+import org.sonar.wsclient.qualitygate.QualityGateClient;
+import org.sonar.wsclient.services.Measure;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+import util.ItUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static util.ItUtils.projectDir;
+
+public class QualityGateTest {
+
+ private static final String PROJECT_KEY = "sample";
+
+ private long provisionnedProjectId = -1L;
+
+ @ClassRule
+ public static Orchestrator orchestrator = Orchestrator.builderEnv()
+ .addPlugin(ItUtils.xooPlugin())
+
+ // 1 second. Required for notification test.
+ .setServerProperty("sonar.notifications.delay", "1")
+
+ .build();
+
+ @Before
+ public void cleanUp() throws Exception {
+ orchestrator.resetData();
+ provisionnedProjectId = Long.parseLong(orchestrator.getServer().adminWsClient().projectClient().create(NewProject.create().key(PROJECT_KEY).name("Sample")).id());
+ }
+
+ @Test
+ public void do_not_compute_status_if_no_gate() {
+ SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
+ orchestrator.executeBuild(build);
+
+ assertThat(fetchResourceWithGateStatus()).isNull();
+ }
+
+ @Test
+ public void status_ok_if_empty_gate() {
+ QualityGate empty = qgClient().create("Empty");
+ qgClient().setDefault(empty.id());
+
+ try {
+ SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
+ orchestrator.executeBuild(build);
+
+ assertThat(fetchGateStatus().getData()).isEqualTo("OK");
+ } finally {
+ qgClient().unsetDefault();
+ qgClient().destroy(empty.id());
+ }
+ }
+
+ @Test
+ public void test_status_ok() {
+ QualityGate simple = qgClient().create("SimpleWithHighThreshold");
+ qgClient().setDefault(simple.id());
+ qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").operator("GT").warningThreshold("40"));
+
+ try {
+ SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
+ orchestrator.executeBuild(build);
+
+ assertThat(fetchGateStatus().getData()).isEqualTo("OK");
+ } finally {
+ qgClient().unsetDefault();
+ qgClient().destroy(simple.id());
+ }
+ }
+
+ @Test
+ public void test_status_warning() {
+ QualityGate simple = qgClient().create("SimpleWithLowThreshold");
+ qgClient().setDefault(simple.id());
+ qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").operator("GT").warningThreshold("10"));
+
+ try {
+ SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
+ orchestrator.executeBuild(build);
+
+ assertThat(fetchGateStatus().getData()).isEqualTo("WARN");
+ } finally {
+ qgClient().unsetDefault();
+ qgClient().destroy(simple.id());
+ }
+
+ }
+
+ @Test
+ public void test_status_error() {
+ QualityGate simple = qgClient().create("SimpleWithLowThreshold");
+ qgClient().setDefault(simple.id());
+ qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").operator("GT").errorThreshold("10"));
+
+ try {
+ SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
+ orchestrator.executeBuild(build);
+
+ assertThat(fetchGateStatus().getData()).isEqualTo("ERROR");
+ } finally {
+ qgClient().unsetDefault();
+ qgClient().destroy(simple.id());
+ }
+ }
+
+ @Test
+ public void use_server_settings_instead_of_default_gate() {
+ QualityGate alert = qgClient().create("AlertWithLowThreshold");
+ qgClient().createCondition(NewCondition.create(alert.id()).metricKey("ncloc").operator("GT").warningThreshold("10"));
+ QualityGate error = qgClient().create("ErrorWithLowThreshold");
+ qgClient().createCondition(NewCondition.create(error.id()).metricKey("ncloc").operator("GT").errorThreshold("10"));
+
+ qgClient().setDefault(alert.id());
+ qgClient().selectProject(error.id(), provisionnedProjectId);
+
+ try {
+ SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"));
+ orchestrator.executeBuild(build);
+
+ assertThat(fetchGateStatus().getData()).isEqualTo("ERROR");
+ } finally {
+ qgClient().unsetDefault();
+ qgClient().destroy(alert.id());
+ qgClient().destroy(error.id());
+ }
+ }
+
+ @Test
+ public void conditions_on_multiple_metric_types() {
+ QualityGate allTypes = qgClient().create("AllMetricTypes");
+ qgClient().createCondition(NewCondition.create(allTypes.id()).metricKey("ncloc").operator("GT").warningThreshold("10"));
+ qgClient().createCondition(NewCondition.create(allTypes.id()).metricKey("duplicated_lines_density").operator("GT").warningThreshold("20"));
+ qgClient().setDefault(allTypes.id());
+
+ try {
+ SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample"))
+ .setProperty("sonar.cpd.xoo.minimumLines", "2")
+ .setProperty("sonar.cpd.xoo.minimumTokens", "5");
+ orchestrator.executeBuild(build);
+
+ Measure alertStatus = fetchGateStatus();
+ assertThat(alertStatus.getData()).isEqualTo("WARN");
+ assertThat(alertStatus.getAlertText())
+ .contains("Lines of code > 10")
+ .contains("Duplicated lines (%) > 20");
+ } finally {
+ qgClient().unsetDefault();
+ qgClient().destroy(allTypes.id());
+ }
+ }
+
+ private Measure fetchGateStatus() {
+ return fetchResourceWithGateStatus().getMeasure("alert_status");
+ }
+
+ private Resource fetchResourceWithGateStatus() {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(PROJECT_KEY, "alert_status").setIncludeAlerts(true));
+ }
+
+ private static QualityGateClient qgClient() {
+ return orchestrator.getServer().adminWsClient().qualityGateClient();
+ }
+}
--- /dev/null
+package util;/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.sonar.orchestrator.locator.FileLocation;
+import java.io.File;
+import org.apache.commons.io.FileUtils;
+
+public class ItUtils {
+
+ private ItUtils() {
+ }
+
+ private static final Supplier<File> HOME_DIR = Suppliers.memoize(new Supplier<File>() {
+ @Override
+ public File get() {
+ File dir = new File("it");
+
+ // intellij way
+ if (dir.exists() && dir.isDirectory()) {
+ return dir.getParentFile();
+ }
+
+ // maven way
+ dir = new File("../it");
+ if (dir.exists() && dir.isDirectory()) {
+ return dir.getParentFile();
+ }
+
+ throw new IllegalStateException("Fail to locate home directory");
+ }
+ });
+
+ public static FileLocation xooPlugin() {
+ File target = new File(HOME_DIR.get(), "plugins/sonar-xoo-plugin/target");
+ if (target.exists()) {
+ for (File jar : FileUtils.listFiles(target, new String[] {"jar"}, false)) {
+ if (jar.getName().startsWith("sonar-xoo-plugin-") && !jar.getName().contains("-source")) {
+ return FileLocation.of(jar);
+ }
+ }
+ }
+ throw new IllegalStateException("XOO plugin is not built");
+ }
+
+ /**
+ * Locate the directory of sample project
+ *
+ * @param relativePath path related to the directory it/projects, for example "qualitygate/xoo-sample"
+ */
+ public static File projectDir(String relativePath) {
+ File dir = new File(HOME_DIR.get(), "it/projects/" + relativePath);
+ if (!dir.exists() || !dir.isDirectory()) {
+ throw new IllegalStateException("Directory does not exist: " + dir.getAbsolutePath());
+ }
+ return dir;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>create_user_with_email</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <thead>
+ <tr>
+ <td rowspan="1" colspan="3">create_user_with_email</td>
+ </tr>
+ </thead>
+ <tbody>
+<tr>
+ <td>open</td>
+ <td>/sonar/sessions/new</td>
+ <td></td>
+</tr>
+<tr>
+ <td>type</td>
+ <td>login</td>
+ <td>tester</td>
+</tr>
+<tr>
+ <td>type</td>
+ <td>password</td>
+ <td>tester</td>
+</tr>
+<tr>
+ <td>clickAndWait</td>
+ <td>commit</td>
+ <td></td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/sonar/account/index</td>
+ <td></td>
+</tr>
+<tr>
+ <td>check</td>
+ <td>global_notifs_NewAlerts.EmailNotificationChannel</td>
+ <td></td>
+</tr>
+<tr>
+ <td>clickAndWait</td>
+ <td>//input[@value='Save changes']</td>
+ <td></td>
+</tr>
+</tbody>
+</table>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>email_configuration</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <tbody>
+ <tr>
+ <td>setTimeout</td>
+ <td>300000</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>open</td>
+ <td>/sonar/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>type</td>
+ <td>login</td>
+ <td>admin</td>
+ </tr>
+ <tr>
+ <td>type</td>
+ <td>password</td>
+ <td>admin</td>
+ </tr>
+ <tr>
+ <td>clickAndWait</td>
+ <td>commit</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>open</td>
+ <td>/sonar/email_configuration</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>verifyValue</td>
+ <td>smtp_host</td>
+ <td>localhost</td>
+ </tr>
+ <tr>
+ <td>type</td>
+ <td>to_address</td>
+ <td>test@example.org</td>
+ </tr>
+ <tr>
+ <td>clickAndWait</td>
+ <td>submit_test</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForVisible</td>
+ <td>info</td>
+ <td></td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>
.setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("1min"))
.setEffortToFixDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code");
+ repo.createRule(OneIssueOnDirPerFileSensor.RULE_KEY).setName("One Issue On Dir Per File")
+ .setHtmlDescription("Generate issues on directories");
+
NewRule oneIssuePerFile = repo.createRule(OneIssuePerFileSensor.RULE_KEY).setName("One Issue Per File")
.setHtmlDescription("Generate an issue on each file");
oneIssuePerFile.setDebtSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY)
assertThat(repo).isNotNull();
assertThat(repo.name()).isEqualTo("Xoo");
assertThat(repo.language()).isEqualTo("xoo");
- assertThat(repo.rules()).hasSize(7);
+ assertThat(repo.rules()).hasSize(8);
RulesDefinition.Rule rule = repo.rule(OneIssuePerLineSensor.RULE_KEY);
assertThat(rule.name()).isNotEmpty();