]> source.dussan.org Git - sonarqube.git/commitdiff
Add QualityGateNotificationTest
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 26 Jun 2015 15:37:54 +0000 (17:37 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 29 Jun 2015 09:03:32 +0000 (11:03 +0200)
it/tests/src/test/java/org/sonar/it/ItUtils.java [deleted file]
it/tests/src/test/java/org/sonar/it/qualitygate/QualityGateTest.java [deleted file]
it/tests/src/test/java/qualitygate/QualityGateNotificationTest.java [new file with mode: 0644]
it/tests/src/test/java/qualitygate/QualityGateTest.java [new file with mode: 0644]
it/tests/src/test/java/util/ItUtils.java [new file with mode: 0644]
it/tests/src/test/resources/selenium/qualitygate/notifications/activate_notification_channels.html [new file with mode: 0644]
it/tests/src/test/resources/selenium/qualitygate/notifications/email_configuration.html [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java

diff --git a/it/tests/src/test/java/org/sonar/it/ItUtils.java b/it/tests/src/test/java/org/sonar/it/ItUtils.java
deleted file mode 100644 (file)
index aba015a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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;
-  }
-}
diff --git a/it/tests/src/test/java/org/sonar/it/qualitygate/QualityGateTest.java b/it/tests/src/test/java/org/sonar/it/qualitygate/QualityGateTest.java
deleted file mode 100644 (file)
index 3fbefca..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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();
-  }
-}
diff --git a/it/tests/src/test/java/qualitygate/QualityGateNotificationTest.java b/it/tests/src/test/java/qualitygate/QualityGateNotificationTest.java
new file mode 100644 (file)
index 0000000..12e3ca3
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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();
+  }
+}
diff --git a/it/tests/src/test/java/qualitygate/QualityGateTest.java b/it/tests/src/test/java/qualitygate/QualityGateTest.java
new file mode 100644 (file)
index 0000000..e13f8bb
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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();
+  }
+}
diff --git a/it/tests/src/test/java/util/ItUtils.java b/it/tests/src/test/java/util/ItUtils.java
new file mode 100644 (file)
index 0000000..875ff17
--- /dev/null
@@ -0,0 +1,62 @@
+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;
+  }
+}
diff --git a/it/tests/src/test/resources/selenium/qualitygate/notifications/activate_notification_channels.html b/it/tests/src/test/resources/selenium/qualitygate/notifications/activate_notification_channels.html
new file mode 100644 (file)
index 0000000..8e0bce0
--- /dev/null
@@ -0,0 +1,54 @@
+<?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>
diff --git a/it/tests/src/test/resources/selenium/qualitygate/notifications/email_configuration.html b/it/tests/src/test/resources/selenium/qualitygate/notifications/email_configuration.html
new file mode 100644 (file)
index 0000000..3d32118
--- /dev/null
@@ -0,0 +1,64 @@
+<?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>
index 4843a0525f977f3f0061e639086c717feeeb49cb..b7d826a03a801003667a72f829e6642bbaa484f4 100644 (file)
@@ -56,6 +56,9 @@ public class XooRulesDefinition implements RulesDefinition {
       .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)
index 399f77cf3a6897648ee5373644d9edfb56842664..556ce27aa8815e53dee949a9987b453224b97d23 100644 (file)
@@ -37,7 +37,7 @@ public class XooRulesDefinitionTest {
     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();