]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8300 add ITs
authorStas Vilchik <vilchiks@gmail.com>
Mon, 7 Nov 2016 14:48:53 +0000 (15:48 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Mon, 7 Nov 2016 14:49:00 +0000 (15:49 +0100)
it/it-tests/src/test/java/it/Category1Suite.java
it/it-tests/src/test/java/it/projectSearch/ProjectsPageTest.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/Navigation.java
it/it-tests/src/test/java/pageobjects/projects/FacetItem.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/projects/ProjectItem.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/projects/ProjectsPage.java [new file with mode: 0644]
server/sonar-web/src/main/js/apps/projects/components/PageHeader.js
server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js
server/sonar-web/src/main/js/apps/projects/components/ProjectCardMeasures.js
server/sonar-web/src/main/js/apps/projects/filters/Filter.js

index efc2f42d24a3f405dfef2a81704837a3383852b1..7190c2f5f9e288b15c4c8e695f3bb7f659180bfd 100644 (file)
@@ -39,6 +39,7 @@ import it.projectAdministration.BackgroundTasksTest;
 import it.projectAdministration.BulkDeletionTest;
 import it.projectAdministration.ProjectAdministrationTest;
 import it.projectAdministration.ProjectLinksPageTest;
+import it.projectSearch.ProjectsPageTest;
 import it.qualityGate.QualityGateNotificationTest;
 import it.qualityGate.QualityGateTest;
 import it.qualityGate.QualityGateUiTest;
@@ -87,6 +88,7 @@ import static util.ItUtils.xooPlugin;
   // measure
   ProjectMeasuresPageTest.class,
   ProjectDashboardTest.class,
+  ProjectsPageTest.class,
   MeasuresWsTest.class,
   // measure history
   DifferentialPeriodsTest.class,
diff --git a/it/it-tests/src/test/java/it/projectSearch/ProjectsPageTest.java b/it/it-tests/src/test/java/it/projectSearch/ProjectsPageTest.java
new file mode 100644 (file)
index 0000000..235a0c0
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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.projectSearch;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.SonarScanner;
+import it.Category1Suite;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import pageobjects.Navigation;
+import pageobjects.projects.ProjectsPage;
+
+import static util.ItUtils.projectDir;
+
+public class ProjectsPageTest {
+
+  @ClassRule
+  public static Orchestrator ORCHESTRATOR = Category1Suite.ORCHESTRATOR;
+
+  @Rule
+  public Navigation nav = Navigation.get(ORCHESTRATOR);
+
+  @BeforeClass
+  public static void setUp() {
+    ORCHESTRATOR.resetData();
+    ORCHESTRATOR.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample")).setProjectKey("key-foo"));
+    ORCHESTRATOR.executeBuild(SonarScanner.create(projectDir("duplications/file-duplications")).setProjectKey("key-bar"));
+  }
+
+  @Test
+  public void should_display_projects() {
+    ProjectsPage page = nav.openProjects();
+    page.shouldHaveTotal(2);
+    page.getProjectByKey("key-foo")
+      .shouldHaveMeasure("reliability_rating", "A")
+      .shouldHaveMeasure("security_rating", "A")
+      .shouldHaveMeasure("sqale_rating", "A")
+      .shouldHaveMeasure("duplicated_lines_density", "0.0%")
+      .shouldHaveMeasure("ncloc", "13")
+      .shouldHaveMeasure("ncloc", "Xoo");
+  }
+
+  @Test
+  public void should_display_facets() {
+    ProjectsPage page = nav.openProjects();
+    page.getFacetByProperty("duplications")
+      .shouldHaveValue("1", "1")
+      .shouldHaveValue("2", "1")
+      .shouldHaveValue("3", "1")
+      .shouldHaveValue("4", "1")
+      .shouldHaveValue("5", "1");
+  }
+
+  @Test
+  public void should_filter_using_facet() {
+    ProjectsPage page = nav.openProjects();
+    page.shouldHaveTotal(2);
+    page.getFacetByProperty("duplications").selectValue("3");
+    page.shouldHaveTotal(1);
+  }
+
+}
index 071df520c6eefde7bace198f6ec99e257421371f..f3f9102b55aaf52ce3909bb81ac093ffd927bee1 100644 (file)
@@ -30,6 +30,7 @@ import javax.annotation.Nullable;
 import org.junit.rules.ExternalResource;
 import org.openqa.selenium.By;
 import pageobjects.licenses.LicensesPage;
+import pageobjects.projects.ProjectsPage;
 import pageobjects.settings.SettingsPage;
 
 import static com.codeborne.selenide.Selenide.$;
@@ -55,6 +56,10 @@ public class Navigation extends ExternalResource {
     return open("/", Navigation.class);
   }
 
+  public ProjectsPage openProjects() {
+    return open("/projects", ProjectsPage.class);
+  }
+
   public ProjectDashboardPage openProjectDashboard(String projectKey) {
     // TODO encode projectKey
     String url = "/dashboard?id=" + projectKey;
diff --git a/it/it-tests/src/test/java/pageobjects/projects/FacetItem.java b/it/it-tests/src/test/java/pageobjects/projects/FacetItem.java
new file mode 100644 (file)
index 0000000..936e641
--- /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.projects;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.SelenideElement;
+
+public class FacetItem {
+
+  private final SelenideElement elt;
+
+  public FacetItem(SelenideElement elt) {
+    this.elt = elt;
+  }
+
+  public FacetItem shouldHaveValue(String key, String value) {
+    this.elt.$(".facet[data-key=\"" + key + "\"] .facet-stat").shouldHave(Condition.text(value));
+    return this;
+  }
+
+  public void selectValue(String key) {
+    this.elt.$(".facet[data-key=\"" + key + "\"]").click();
+  }
+}
diff --git a/it/it-tests/src/test/java/pageobjects/projects/ProjectItem.java b/it/it-tests/src/test/java/pageobjects/projects/ProjectItem.java
new file mode 100644 (file)
index 0000000..723b845
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.projects;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.SelenideElement;
+
+public class ProjectItem {
+
+  private final SelenideElement elt;
+
+  public ProjectItem(SelenideElement elt) {
+    this.elt = elt;
+  }
+
+  public ProjectItem shouldHaveMeasure(String metricKey, String value) {
+    this.elt.$(".project-card-measure[data-key=\"" + metricKey + "\"]").shouldHave(Condition.text(value));
+    return this;
+  }
+}
diff --git a/it/it-tests/src/test/java/pageobjects/projects/ProjectsPage.java b/it/it-tests/src/test/java/pageobjects/projects/ProjectsPage.java
new file mode 100644 (file)
index 0000000..a87863c
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.projects;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.ElementsCollection;
+import com.codeborne.selenide.SelenideElement;
+
+import static com.codeborne.selenide.Condition.text;
+import static com.codeborne.selenide.Condition.visible;
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.$$;
+
+public class ProjectsPage {
+
+  public ProjectsPage() {
+    $("#projects-page").shouldBe(visible);
+  }
+
+  public ElementsCollection getProjects() {
+    return $$(".projects-list > .boxed-group");
+  }
+
+  public ElementsCollection getFacets() {
+    return $$(".search-navigator-facet-box");
+  }
+
+  public ProjectItem getProjectByKey(String projectKey) {
+    SelenideElement element = getProjects().find(Condition.attribute("data-key", projectKey));
+    return new ProjectItem(element);
+  }
+
+  public FacetItem getFacetByProperty(String facetProperty) {
+    SelenideElement element = getFacets().find(Condition.attribute("data-key", facetProperty));
+    return new FacetItem(element);
+  }
+
+  public ProjectsPage shouldHaveTotal(int total) {
+    // warning - number is localized
+    $("#projects-total").shouldHave(text(String.valueOf(total)));
+    return this;
+  }
+}
index 346ed06e7e462e635ca20382a0d29ab1d23227f0..1c02d020db4bcfdf13af0b551b34034d86cb2cdf 100644 (file)
@@ -39,7 +39,7 @@ export default class PageHeader extends React.Component {
 
             {this.props.total != null && (
                 <span>
-                <strong>{this.props.total}</strong> {translate('projects._projects')}
+                <strong id="projects-total">{this.props.total}</strong> {translate('projects._projects')}
               </span>
             )}
           </div>
index 04dbdb15fc379d266f7d95d3b67f43635c392bd9..9b9ec7fc11f0d813cb20e1349f0c2b20f8c8ec9c 100644 (file)
@@ -38,7 +38,7 @@ export default class ProjectCard extends React.Component {
     const className = classNames('boxed-group', 'project-card', { 'boxed-group-loading': this.props.measures == null });
 
     return (
-        <div className={className}>
+        <div data-key={project.key} className={className}>
           {this.props.measures != null && (
               <div className="boxed-group-actions">
                 <ProjectCardQualityGate status={this.props.measures['alert_status']}/>
index d8004d2de665bd4c1c33b3d23f5c24f133cb99e3..a6ea6ec3e9709c0bdc5fd94d4b1724eb116d4814 100644 (file)
@@ -41,7 +41,7 @@ export default class ProjectCardMeasures extends React.Component {
 
     return (
         <div className="project-card-measures">
-          <div className="project-card-measure">
+          <div className="project-card-measure" data-key="reliability_rating">
             <div className="project-card-measure-inner">
               <div className="project-card-measure-number">
                 <Rating value={measures['reliability_rating']}/>
@@ -52,7 +52,7 @@ export default class ProjectCardMeasures extends React.Component {
             </div>
           </div>
 
-          <div className="project-card-measure">
+          <div className="project-card-measure" data-key="security_rating">
             <div className="project-card-measure-inner">
               <div className="project-card-measure-number">
                 <Rating value={measures['security_rating']}/>
@@ -63,7 +63,7 @@ export default class ProjectCardMeasures extends React.Component {
             </div>
           </div>
 
-          <div className="project-card-measure">
+          <div className="project-card-measure" data-key="sqale_rating">
             <div className="project-card-measure-inner">
               <div className="project-card-measure-number">
                 <Rating value={measures['sqale_rating']}/>
@@ -74,7 +74,7 @@ export default class ProjectCardMeasures extends React.Component {
             </div>
           </div>
 
-          <div className="project-card-measure">
+          <div className="project-card-measure" data-key="coverage">
             <div className="project-card-measure-inner">
               <div className="project-card-measure-number">
                 {measures['coverage'] != null && (
@@ -91,7 +91,7 @@ export default class ProjectCardMeasures extends React.Component {
             </div>
           </div>
 
-          <div className="project-card-measure">
+          <div className="project-card-measure" data-key="duplicated_lines_density">
             <div className="project-card-measure-inner">
               <div className="project-card-measure-number">
                 <span className="spacer-right">
@@ -106,7 +106,7 @@ export default class ProjectCardMeasures extends React.Component {
             </div>
           </div>
 
-          <div className="project-card-measure">
+          <div className="project-card-measure" data-key="ncloc">
             <div className="project-card-measure-inner">
               <div className="project-card-measure-number">
                 <span className="spacer-right">
index 1b0a7ad8c82a5d8d1157a9e788e30b0b9d8b1bb4..cab64031e7d655906b212cd13a9511d7e0dba3dd 100644 (file)
@@ -81,7 +81,7 @@ export default class Filter extends React.Component {
     const facetValue = (facet && getFacetValueForOption) ? getFacetValueForOption(facet, option) : null;
 
     return (
-        <Link key={option} className={className} to={path}>
+        <Link key={option} className={className} to={path} data-key={option}>
           <span className="facet-name">
             {this.props.renderOption(option, option === value)}
           </span>
@@ -105,7 +105,7 @@ export default class Filter extends React.Component {
 
   render () {
     return (
-        <div className="search-navigator-facet-box">
+        <div className="search-navigator-facet-box" data-key={this.props.property}>
           {this.renderHeader()}
           {this.renderOptions()}
         </div>