]> source.dussan.org Git - sonarqube.git/commitdiff
Ability to use selenide and phantomjs in ITs
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 20 Jul 2016 20:17:16 +0000 (22:17 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Sun, 24 Jul 2016 18:39:36 +0000 (20:39 +0200)
* selenide should replace Selenese HTML tests
* phantomjs should replace Firefox in environments
that require XVFB

19 files changed:
.travis.yml
it/it-tests/pom.xml
it/it-tests/src/test/java/it/Category4Suite.java
it/it-tests/src/test/java/it/lite/LiteTest.java
it/it-tests/src/test/java/it/measure/ProjectOverviewTest.java
it/it-tests/src/test/java/it/qualityProfile/QualityProfilesPageTest.java
it/it-tests/src/test/java/it/ui/UiTest.java
it/it-tests/src/test/java/it/updateCenter/UpdateCenterTest.java
it/it-tests/src/test/java/it/user/AuthenticationTest.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/LoginPage.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/Navigation.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/RuleItem.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/RulesPage.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/SelenideConfig.java [new file with mode: 0644]
it/it-tests/src/test/java/util/ItUtils.java
it/it-tests/src/test/resources/measure/ProjectOverviewTest/should-display-nice-error-on-unknown-project.html [deleted file]
it/it-tests/src/test/resources/qualityProfile/QualityProfilesPageTest/not_found.html [deleted file]
it/it-tests/src/test/resources/ui/UiTest/footer.html [deleted file]
travis.sh

index 25114af6581875fb2d1377a64380de3cc3cf6a48..063a3632829c34b9a91c30d8a88e2658a3d0974d 100644 (file)
@@ -18,6 +18,7 @@ cache:
     - server/sonar-web/node
     - server/sonar-web/node_modules
     - $HOME/jvm
+    - $HOME/phantomjs
 
 before_cache:
   # remove all the artifacts (JAR, ZIP) that are installed in local repo because of mvn deploy
index c70e2d7d1b878b7826d76c07ea7927061570fabc..f13d10e223cfa54421d994f481d9d8e1c3553867 100644 (file)
       <type>pom</type>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>com.codeborne</groupId>
+      <artifactId>selenide</artifactId>
+      <version>3.7</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>-Xmx128m -Dsonar.runtimeVersion=${project.version} -Dmaven.localRepository=${settings.localRepository}</argLine>
+          <argLine>-Xmx128m -Dsonar.runtimeVersion=${project.version}
+            -Dmaven.localRepository=${settings.localRepository}
+          </argLine>
           <skipTests>${skipIts}</skipTests>
           <includes>
             <include>*/${category}Suite.java</include>
index 3596a72be42aa2ff2d5029caf5086c667a0912e3..15474220cbd04074108c66ffd4ff4c0fcd665d60 100644 (file)
@@ -37,6 +37,7 @@ import it.qualityProfile.QualityProfilesPageTest;
 import it.serverSystem.ServerSystemTest;
 import it.ui.UiTest;
 import it.uiExtension.UiExtensionsTest;
+import it.user.AuthenticationTest;
 import it.user.BaseIdentityProviderTest;
 import it.user.FavouriteTest;
 import it.user.ForceAuthenticationTest;
@@ -60,6 +61,7 @@ import static util.ItUtils.xooPlugin;
   MyAccountPageTest.class,
   FavouriteTest.class,
   // authentication
+  AuthenticationTest.class,
   ForceAuthenticationTest.class,
   LocalAuthenticationTest.class,
   BaseIdentityProviderTest.class,
index f013e3a5c9595e82675447417fd6dbef37ae69b9..02c423e6d05587252e992a6c2069a063ab2c3a43 100644 (file)
@@ -19,6 +19,8 @@
  */
 package it.lite;
 
+import com.codeborne.selenide.CollectionCondition;
+import com.codeborne.selenide.Condition;
 import com.sonar.orchestrator.Orchestrator;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -31,8 +33,13 @@ import org.sonarqube.ws.client.component.TreeWsRequest;
 import org.sonarqube.ws.client.issue.SearchWsRequest;
 import org.sonarqube.ws.client.measure.ComponentTreeWsRequest;
 import org.sonarqube.ws.client.measure.ComponentWsRequest;
+import pageobjects.Navigation;
+import pageobjects.RuleItem;
+import pageobjects.RulesPage;
 import util.ItUtils;
 
+import static com.codeborne.selenide.Condition.hasText;
+import static com.codeborne.selenide.Condition.or;
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -98,4 +105,20 @@ public class LiteTest {
       assertThat(c.getMeasuresList()).extracting(m -> m.getMetric()).containsOnly("lines", "ncloc");
     });
   }
+
+  @Test
+  public void open_page_rules() {
+    RulesPage rulesPage = Navigation.get(ORCHESTRATOR)
+      .openHomepage()
+      .clickOnRules();
+
+    // wait for rules to be displayed
+    rulesPage.getRules().shouldHave(CollectionCondition.sizeGreaterThan(0));
+
+    assertThat(rulesPage.getTotal()).isGreaterThan(0);
+    for (RuleItem ruleItem : rulesPage.getRulesAsItems()) {
+      ruleItem.getTitle().should(Condition.visible);
+      ruleItem.getMetadata().should(or("have type", hasText("Bug"), hasText("Code Smell"), hasText("Vulnerability")));
+    }
+  }
 }
index cdcf92f1e1c7a29d02d697e2ef6f6402899f918d..96f27688ea12213ab1d1d2ad3d24fa4551584225 100644 (file)
@@ -26,8 +26,10 @@ import it.Category1Suite;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
+import pageobjects.Navigation;
 import util.selenium.SeleneseTest;
 
+import static com.codeborne.selenide.Condition.text;
 import static util.ItUtils.projectDir;
 
 public class ProjectOverviewTest {
@@ -51,10 +53,11 @@ public class ProjectOverviewTest {
   }
 
   @Test
-  public void should_display_a_nice_error_when_requesting_unknown_project() {
-    Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("should_display_a_nice_error_when_requesting_unknown_project",
-      "/measure/ProjectOverviewTest/should-display-nice-error-on-unknown-project.html").build();
-    orchestrator.executeSelenese(selenese);
+  public void display_a_nice_error_when_requesting_unknown_project() {
+    Navigation nav = Navigation.get(orchestrator);
+    nav.open("/dashboard/index?id=unknown");
+    nav.getErrorMessage().should(text("The requested project does not exist. Either it has never been analyzed successfully or it has been deleted."));
+    // TODO verify that on global homepage
   }
 
   private void executeBuild(String projectLocation, String projectKey, String projectName) {
index d9ffc805ad6d2ed584977447132fb187450921ac..cd182dfe47db0f1b19acdc48927ec80d1ee88163 100644 (file)
  */
 package it.qualityProfile;
 
+import com.codeborne.selenide.Condition;
 import com.sonar.orchestrator.Orchestrator;
 import com.sonar.orchestrator.build.SonarScanner;
 import com.sonar.orchestrator.selenium.Selenese;
 import it.Category4Suite;
-import org.junit.*;
-import org.junit.experimental.categories.Category;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
 import org.sonarqube.ws.client.PostRequest;
 import org.sonarqube.ws.client.WsClient;
+import pageobjects.Navigation;
 import util.selenium.SeleneseTest;
 
+import static com.codeborne.selenide.Selenide.$;
 import static util.ItUtils.newAdminWsClient;
 import static util.ItUtils.projectDir;
 
@@ -82,9 +89,9 @@ public class QualityProfilesPageTest {
 
   @Test
   public void testNotFound() {
-    Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("test_not_found",
-      "/qualityProfile/QualityProfilesPageTest/not_found.html").build();
-    orchestrator.executeSelenese(selenese);
+    Navigation nav = Navigation.get(orchestrator);
+    nav.open("/profiles/show?key=unknown");
+    $(".quality-profile-not-found").should(Condition.visible);
   }
 
   @Test
index 7e3a84526bede7f165ae4b03631f7605bfe9d837..c4960f9192e7c1d081d8ee8c3c17ffa0163fd590 100644 (file)
 package it.ui;
 
 import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.selenium.Selenese;
 import it.Category4Suite;
+import java.util.Map;
 import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import util.selenium.SeleneseTest;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsResponse;
+import pageobjects.Navigation;
+import util.ItUtils;
+
+import static com.codeborne.selenide.Condition.hasText;
 
 public class UiTest {
 
   @ClassRule
-  public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+  public static final Orchestrator ORCHESTRATOR = Category4Suite.ORCHESTRATOR;
+
+  @Rule
+  public Navigation nav = Navigation.get(ORCHESTRATOR);
 
   @Test
-  public void test_footer() {
-    new SeleneseTest(
-      Selenese.builder().setHtmlTestsInClasspath("ui-footer",
-        "/ui/UiTest/footer.html"
-      ).build()).runOn(orchestrator);
+  public void footer_contains_information() {
+    nav.getFooter()
+      .should(hasText("Documentation"))
+      .should(hasText("SonarSource SA"));
   }
 
+  @Test
+  public void footer_contains_version() {
+    WsResponse status = ItUtils.newAdminWsClient(ORCHESTRATOR).wsConnector().call(new GetRequest("api/system/status"));
+    Map<String, Object> statusMap = ItUtils.jsonToMap(status.content());
+
+    nav.getFooter().should(hasText((String) statusMap.get("version")));
+  }
 }
index 1fea840524b3a1437832a6aa10978af44f32937e..04eaadb5de10b411b40546901006b9332eb63bf1 100644 (file)
@@ -25,7 +25,6 @@ import java.util.List;
 import org.apache.commons.lang.StringUtils;
 import org.junit.ClassRule;
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 import org.sonar.wsclient.services.Plugin;
 import org.sonar.wsclient.services.UpdateCenterQuery;
 import util.selenium.SeleneseTest;
diff --git a/it/it-tests/src/test/java/it/user/AuthenticationTest.java b/it/it-tests/src/test/java/it/user/AuthenticationTest.java
new file mode 100644 (file)
index 0000000..e15c6af
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 it.user;
+
+import com.codeborne.selenide.Condition;
+import com.sonar.orchestrator.Orchestrator;
+import it.Category4Suite;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import pageobjects.LoginPage;
+import pageobjects.Navigation;
+
+public class AuthenticationTest {
+
+  @ClassRule
+  public static Orchestrator ORCHESTRATOR = Category4Suite.ORCHESTRATOR;
+
+  @Rule
+  public Navigation nav = Navigation.get(ORCHESTRATOR);
+
+  @Test
+  public void log_in_with_correct_credentials_then_log_out() {
+    nav.shouldNotBeLoggedIn();
+
+    Navigation page = nav.logIn().submitCredentials("admin", "admin");
+    page.getRightBar().shouldHave(Condition.text("Administrator"));
+    nav.shouldBeLoggedIn();
+
+    nav.logOut();
+    nav.shouldNotBeLoggedIn();
+  }
+
+  @Test
+  public void log_in_with_wrong_credentials() {
+    LoginPage page = nav
+      .logIn()
+      .submitWrongCredentials("admin", "wrong");
+    page.getErrorMessage().shouldHave(Condition.text("Authentication failed"));
+
+    nav.openHomepage();
+    nav.shouldNotBeLoggedIn();
+  }
+}
diff --git a/it/it-tests/src/test/java/pageobjects/LoginPage.java b/it/it-tests/src/test/java/pageobjects/LoginPage.java
new file mode 100644 (file)
index 0000000..bf946b2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 pageobjects;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.SelenideElement;
+import org.openqa.selenium.By;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.page;
+
+public class LoginPage {
+
+  public LoginPage() {
+    $("#login_form").should(Condition.exist);
+  }
+
+  public Navigation submitCredentials(String login, String password) {
+    return submitCredentials(login, password, Navigation.class);
+  }
+
+  public LoginPage submitWrongCredentials(String login, String password) {
+    return submitCredentials(login, password, LoginPage.class);
+  }
+
+  public SelenideElement getErrorMessage() {
+    return $(By.cssSelector("#login_form .alert"));
+  }
+
+  private <T> T submitCredentials(String login, String password, Class<T> expectedResultPage) {
+    $("#login").val(login);
+    $("#password").val(password);
+    $(By.name("commit")).click();
+    return page(expectedResultPage);
+  }
+}
diff --git a/it/it-tests/src/test/java/pageobjects/Navigation.java b/it/it-tests/src/test/java/pageobjects/Navigation.java
new file mode 100644 (file)
index 0000000..395509c
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 pageobjects;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.Selenide;
+import com.codeborne.selenide.SelenideElement;
+import com.codeborne.selenide.WebDriverRunner;
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.rules.ExternalResource;
+import org.openqa.selenium.By;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.page;
+
+public class Navigation extends ExternalResource {
+
+  public static Navigation get(Orchestrator orchestrator) {
+    String browser = orchestrator.getConfiguration().getString("orchestrator.browser", "firefox");
+    SelenideConfig.INSTANCE
+      .setBrowser(browser)
+      .setBaseUrl(orchestrator.getServer().getUrl());
+    return new Navigation();
+  }
+
+  @Override
+  protected void before() throws Throwable {
+    WebDriverRunner.getWebDriver().manage().deleteAllCookies();
+    openHomepage();
+  }
+
+  public Navigation openHomepage() {
+    return open("/", Navigation.class);
+  }
+
+  public void open(String relativeUrl) {
+    Selenide.open(relativeUrl);
+  }
+
+  public <P> P open(String relativeUrl, Class<P> pageObjectClassClass) {
+    return Selenide.open(relativeUrl, pageObjectClassClass);
+  }
+
+  public void shouldBeLoggedIn() {
+    loggedInDropdown().should(Condition.visible);
+  }
+
+  public void shouldNotBeLoggedIn() {
+    logInLink().should(Condition.visible);
+  }
+
+  public LoginPage logIn() {
+    logInLink().click();
+    return Selenide.page(LoginPage.class);
+  }
+
+  public Navigation logOut() {
+    SelenideElement dropdown = loggedInDropdown();
+    // click must be on the <a> but not on the dropdown <li>
+    // for compatibility with phantomjs
+    dropdown.find(".dropdown-toggle").click();
+    dropdown.find(By.linkText("Log out")).click();
+    return this;
+  }
+
+  public RulesPage clickOnRules() {
+    $(By.linkText("Rules")).click();
+    return page(RulesPage.class);
+  }
+
+  public SelenideElement clickOnQualityProfiles() {
+    return $(By.linkText("Quality Profiles"));
+  }
+
+  public SelenideElement getRightBar() {
+    return $("#global-navigation .navbar-right");
+  }
+
+  public SelenideElement getFooter() {
+    return $("#footer");
+  }
+
+  public SelenideElement getErrorMessage() {
+    return $("#error");
+  }
+
+  private SelenideElement logInLink() {
+    return $(By.linkText("Log in"));
+  }
+
+  private SelenideElement loggedInDropdown() {
+    return $(".js-user-authenticated");
+  }
+
+}
diff --git a/it/it-tests/src/test/java/pageobjects/RuleItem.java b/it/it-tests/src/test/java/pageobjects/RuleItem.java
new file mode 100644 (file)
index 0000000..454b046
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 pageobjects;
+
+import com.codeborne.selenide.SelenideElement;
+
+public class RuleItem {
+
+  private final SelenideElement elt;
+
+  public RuleItem(SelenideElement elt) {
+    this.elt = elt;
+  }
+
+  public SelenideElement getTitle() {
+    return elt.$(".coding-rule-title");
+  }
+
+  public SelenideElement getMetadata() {
+    return elt.$(".coding-rule-meta");
+  }
+
+
+}
diff --git a/it/it-tests/src/test/java/pageobjects/RulesPage.java b/it/it-tests/src/test/java/pageobjects/RulesPage.java
new file mode 100644 (file)
index 0000000..6d5d134
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 pageobjects;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.ElementsCollection;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.openqa.selenium.By;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.$$;
+
+public class RulesPage {
+
+  public RulesPage() {
+    $(By.cssSelector(".coding-rules")).should(Condition.exist);
+  }
+
+  public ElementsCollection getRules() {
+    return $$(".coding-rules .coding-rule");
+  }
+
+  public List<RuleItem> getRulesAsItems() {
+    return getRules()
+      .stream()
+      .map(elt -> new RuleItem(elt))
+      .collect(Collectors.toList());
+  }
+
+  public int getTotal() {
+    // warning - number is localized
+    return Integer.parseInt($("#coding-rules-total").text());
+  }
+}
diff --git a/it/it-tests/src/test/java/pageobjects/SelenideConfig.java b/it/it-tests/src/test/java/pageobjects/SelenideConfig.java
new file mode 100644 (file)
index 0000000..a7e9bcf
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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 pageobjects;
+
+import com.codeborne.selenide.Configuration;
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+enum SelenideConfig {
+  INSTANCE;
+
+  private static final Set<String> SUPPORTED_BROWSERS = ImmutableSet.of("firefox", "phantomjs");
+
+  SelenideConfig() {
+    Configuration.reportsFolder = "target/screenshots";
+  }
+
+  public SelenideConfig setBrowser(String browser) {
+    checkArgument(SUPPORTED_BROWSERS.contains(requireNonNull(browser)), "Browser is not supported: %s", browser);
+    Configuration.browser = browser;
+    return this;
+  }
+
+  public SelenideConfig setBaseUrl(String s) {
+    Configuration.baseUrl = requireNonNull(s);
+    return this;
+  }
+
+}
index 50a2fc1d4144d2af228396ed4939f6b3cefbba20..795def12588b49749f69a194eae6cb7be44caf66 100644 (file)
@@ -24,6 +24,8 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
 import com.sonar.orchestrator.Orchestrator;
 import com.sonar.orchestrator.build.BuildResult;
 import com.sonar.orchestrator.build.SonarRunner;
@@ -31,10 +33,12 @@ import com.sonar.orchestrator.container.Server;
 import com.sonar.orchestrator.locator.FileLocation;
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Type;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.annotation.Nullable;
@@ -280,18 +284,24 @@ public class ItUtils {
   public static List<String> extractCeTaskIds(BuildResult buildResult) {
     String logs = buildResult.getLogs();
     return from(LINE_SPLITTER.split(logs))
-        .filter(new Predicate<String>() {
-          @Override
-          public boolean apply(String s) {
-            return s.contains("More about the report processing at");
-          }
-        }).transform(new Function<String, String>() {
-          @Nullable
-          @Override
-          public String apply(String s) {
-            return s.substring(s.length() - 20, s.length());
-          }
-        }).toList();
+      .filter(new Predicate<String>() {
+        @Override
+        public boolean apply(String s) {
+          return s.contains("More about the report processing at");
+        }
+      }).transform(new Function<String, String>() {
+        @Nullable
+        @Override
+        public String apply(String s) {
+          return s.substring(s.length() - 20, s.length());
+        }
+      }).toList();
   }
 
+  public static Map<String, Object> jsonToMap(String json) {
+    Gson gson = new Gson();
+    Type type = new TypeToken<Map<String, Object>>() {
+    }.getType();
+    return gson.fromJson(json, type);
+  }
 }
diff --git a/it/it-tests/src/test/resources/measure/ProjectOverviewTest/should-display-nice-error-on-unknown-project.html b/it/it-tests/src/test/resources/measure/ProjectOverviewTest/should-display-nice-error-on-unknown-project.html
deleted file mode 100644 (file)
index 3cbf2bf..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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>static-files</title>
-</head>
-<body>
-<table cellpadding="1" cellspacing="1" border="1">
-<tbody>
-<tr>
-  <td>open</td>
-  <td>/dashboard/index?id=unknown</td>
-  <td></td>
-</tr>
-<tr>
-  <td>waitForText</td>
-  <td>error</td>
-  <td>*The requested project does not exist. Either it has never been analyzed successfully or it has been deleted.*</td>
-</tr>
-</tbody>
-</table>
-</body>
-</html>
diff --git a/it/it-tests/src/test/resources/qualityProfile/QualityProfilesPageTest/not_found.html b/it/it-tests/src/test/resources/qualityProfile/QualityProfilesPageTest/not_found.html
deleted file mode 100644 (file)
index 220d398..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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>not_found</title>
-</head>
-<body>
-<table cellpadding="1" cellspacing="1" border="1">
-    <tbody>
-    <tr>
-        <td>open</td>
-        <td>/profiles/show?key=unknown</td>
-        <td></td>
-    </tr>
-    <tr>
-        <td>waitForElementPresent</td>
-        <td>css=.quality-profile-not-found</td>
-        <td></td>
-    </tr>
-    </tbody>
-</table>
-</body>
-</html>
\ No newline at end of file
diff --git a/it/it-tests/src/test/resources/ui/UiTest/footer.html b/it/it-tests/src/test/resources/ui/UiTest/footer.html
deleted file mode 100644 (file)
index 4fea7c4..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?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"/>
-</head>
-<body>
-<table cellpadding="1" cellspacing="1" border="1">
-  <thead>
-  <tr>
-    <td rowspan="1" colspan="3">footer</td>
-  </tr>
-  </thead>
-  <tbody>
-  <tr>
-       <td>open</td>
-       <td>/</td>
-       <td></td>
-</tr>
-<tr>
-       <td>waitForText</td>
-       <td>footer</td>
-       <td>*SonarSource SA*</td>
-</tr>
-</tbody>
-</table>
-</body>
-</html>
index 4af83f563645fa02e6ab2cd7c03e043cc5e829b6..6ac9d81517f8f75795ada65638a9d9ac38649cea 100755 (executable)
--- a/travis.sh
+++ b/travis.sh
@@ -2,6 +2,20 @@
 
 set -euo pipefail
 
+function installPhantomJs {
+  echo "Setup PhantomJS 2.1"
+  mkdir -p ~/phantomjs
+  pushd ~/phantomjs > /dev/null
+  if [ ! -d "phantomjs-2.1.1-linux-x86_64" ]; then
+    wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 -O phantomjs-2.1.1-linux-x86_64.tar.bz2
+    tar -xf phantomjs-2.1.1-linux-x86_64.tar.bz2
+    rm phantomjs-2.1.1-linux-x86_64.tar.bz2
+  fi
+  popd > /dev/null
+  export PHANTOMJS_HOME=~/phantomjs/phantomjs-2.1.1-linux-x86_64
+  export PATH=$PHANTOMJS_HOME/bin:$PATH
+}
+
 function configureTravis {
   mkdir ~/.local
   curl -sSL https://github.com/SonarSource/travis-utils/tarball/v31 | tar zx --strip-components 1 -C ~/.local
@@ -21,6 +35,14 @@ CI)
     set_maven_build_version $TRAVIS_BUILD_NUMBER
   fi
 
+  if [[ $INITIAL_VERSION =~ "-SNAPSHOT" ]]; then
+    echo "======= Found SNAPSHOT version ======="
+    # Do not deploy a SNAPSHOT version but the release version related to this build
+    set_maven_build_version $TRAVIS_BUILD_NUMBER
+  else
+    echo "======= Found RELEASE version ======="
+  fi
+
   if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
     echo 'Analyse and trigger QA of master branch'
 
@@ -68,7 +90,9 @@ CI)
         -Dsource.skip=true
   fi
 
-  ./run-integration-tests.sh "Lite" ""
+
+  installPhantomJs
+  ./run-integration-tests.sh "Lite" "" -Dorchestrator.browser=phantomjs
   ;;
 
 WEB)