Christopher Johnson (WMDE) has submitted this change and it was merged.

Change subject: adds base phabricator.sprint.selenium browser test package
......................................................................


adds base phabricator.sprint.selenium browser test package

Bug:T87359
Change-Id: I3ae72548d150f91e20d2f83bcd088fb866f3377e
---
A src/tests/selenium/phabricator.sprint/.classpath
A src/tests/selenium/phabricator.sprint/.project
A src/tests/selenium/phabricator.sprint/.settings/org.eclipse.jdt.core.prefs
A src/tests/selenium/phabricator.sprint/.settings/org.eclipse.m2e.core.prefs
A src/tests/selenium/phabricator.sprint/bin/sprint/webdriver/FirstTestCase.class
A src/tests/selenium/phabricator.sprint/pom.xml
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/Pages.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/SprintTestCase.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/TestEnvironment.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/AppServer.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/DevMode.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/JUnit4TestBase.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/Browser.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.java
A 
src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.java
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/Pages.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/SprintTestCase.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/TestEnvironment.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/AppServer.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/DevMode.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase$1.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser$1.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder$LogLevel.class
A 
src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.class
37 files changed, 943 insertions(+), 0 deletions(-)

Approvals:
  Christopher Johnson (WMDE): Verified; Looks good to me, approved



diff --git a/src/tests/selenium/phabricator.sprint/.classpath 
b/src/tests/selenium/phabricator.sprint/.classpath
new file mode 100644
index 0000000..b3e7b1a
--- /dev/null
+++ b/src/tests/selenium/phabricator.sprint/.classpath
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" output="target/classes" path="src">
+               <attributes>
+                       <attribute name="optional" value="true"/>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" 
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+               <attributes>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" 
path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+               <attributes>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/src/tests/selenium/phabricator.sprint/.project 
b/src/tests/selenium/phabricator.sprint/.project
new file mode 100644
index 0000000..21665e6
--- /dev/null
+++ b/src/tests/selenium/phabricator.sprint/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>phabricator.sprint</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git 
a/src/tests/selenium/phabricator.sprint/.settings/org.eclipse.jdt.core.prefs 
b/src/tests/selenium/phabricator.sprint/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6249222
--- /dev/null
+++ b/src/tests/selenium/phabricator.sprint/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
diff --git 
a/src/tests/selenium/phabricator.sprint/.settings/org.eclipse.m2e.core.prefs 
b/src/tests/selenium/phabricator.sprint/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/src/tests/selenium/phabricator.sprint/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git 
a/src/tests/selenium/phabricator.sprint/bin/sprint/webdriver/FirstTestCase.class
 
b/src/tests/selenium/phabricator.sprint/bin/sprint/webdriver/FirstTestCase.class
new file mode 100644
index 0000000..3379932
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/bin/sprint/webdriver/FirstTestCase.class
Binary files differ
diff --git a/src/tests/selenium/phabricator.sprint/pom.xml 
b/src/tests/selenium/phabricator.sprint/pom.xml
new file mode 100644
index 0000000..351fd53
--- /dev/null
+++ b/src/tests/selenium/phabricator.sprint/pom.xml
@@ -0,0 +1,64 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>Phabricator</groupId>
+  <artifactId>Phabricator</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <build>
+    <sourceDirectory>src</sourceDirectory>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+       <groupId>junit</groupId>
+               <artifactId>junit</artifactId>
+               <version>4.12</version>
+       </dependency>
+       <dependency>
+               <groupId>org.seleniumhq.selenium</groupId>
+               <artifactId>selenium-firefox-driver</artifactId>
+               <version>2.44.0</version>
+       </dependency>
+       <dependency>
+               <groupId>org.seleniumhq.selenium</groupId>
+               <artifactId>selenium-java</artifactId>
+               <version>2.44.0</version>
+       </dependency>
+       <dependency>
+               <groupId>org.seleniumhq.selenium</groupId>
+               <artifactId>selenium-server</artifactId>
+               <version>2.44.0</version>
+       </dependency>
+       <dependency>
+               <groupId>org.hamcrest</groupId>
+               <artifactId>hamcrest-library</artifactId>
+       </dependency>
+       <dependency>
+               <groupId>org.seleniumhq.selenium</groupId>
+               <artifactId>selenium-htmlunit-driver</artifactId>
+       </dependency>
+  </dependencies>
+  <dependencyManagement>
+       <dependencies>
+               <dependency>
+                       <groupId>org.hamcrest</groupId>
+                       <artifactId>hamcrest-library</artifactId>
+                       <version>1.3</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.seleniumhq.selenium</groupId>
+                       <artifactId>selenium-htmlunit-driver</artifactId>
+                       <version>2.44.0</version>
+               </dependency>
+       </dependencies>
+  </dependencyManagement>
+</project>
+
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/Pages.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/Pages.java
new file mode 100644
index 0000000..fdcd82b
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/Pages.java
@@ -0,0 +1,42 @@
+package org.phabricator.sprint.selenium;
+
+import org.phabricator.sprint.selenium.environment.webserver.AppServer;
+
+public class Pages {
+       public String SprintProjectList;
+       public String SprintProjectReport;
+       public String SprintProjectBurn;
+       public String SprintProjectProfile;
+       public String SprintProjectTag;
+       public String SprintProjectBoard;
+       public String SprintProjectBoardMove;
+       public String SprintProjectBoardTaskEdit;
+       public String SprintProjectBoardTaskCreate;
+       public String SprintPhabricatorProjectArchive;
+       public String SprintPhabricatorProjectDetails;
+       public String SprintPhabricatorProjectFeed;
+       public String SprintPhabricatorProjectIcon;
+       public String SprintPhabricatorProjectMembers;
+       public String SprintPhabricatorProjectPicture;
+       public String SprintPhabricatorProjectUpdate;
+
+
+        public Pages(AppServer appServer) {
+                 SprintProjectList = appServer.whereIs("/project/sprint/");
+                 SprintProjectTag = appServer.whereIs("/tag/");
+                 SprintPhabricatorProjectArchive = 
appServer.whereIs("/project/sprint/archive/");
+                 SprintProjectBoard = 
appServer.whereIs("/project/sprint/board/");
+                 SprintProjectBoardTaskEdit = 
appServer.whereIs("/project/sprint/board/task/edit/");
+                 SprintProjectBoardTaskCreate = 
appServer.whereIs("/project/sprint/board/task/create/");
+                 SprintProjectBurn = 
appServer.whereIs("/project/sprint/burn/");
+                 SprintPhabricatorProjectDetails = 
appServer.whereIs("/project/sprint/details/");
+                 SprintPhabricatorProjectFeed = 
appServer.whereIs("/project/sprint/feed/");
+                 SprintPhabricatorProjectIcon = 
appServer.whereIs("/project/sprint/icon/");
+                 SprintPhabricatorProjectMembers = 
appServer.whereIs("/project/sprint/members/");
+                 SprintPhabricatorProjectPicture = 
appServer.whereIs("/project/sprint/picture/");
+                 SprintPhabricatorProjectUpdate = 
appServer.whereIs("/project/sprint/update/");
+                 SprintProjectBoardMove = 
appServer.whereIs("/project/sprint/move/");
+                 SprintProjectProfile = 
appServer.whereIs("/project/sprint/profile/");
+                 SprintProjectReport = 
appServer.whereIs("/project/sprint/report/");
+        }
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/SprintTestCase.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/SprintTestCase.java
new file mode 100644
index 0000000..443e526
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/SprintTestCase.java
@@ -0,0 +1,145 @@
+package org.phabricator.sprint.selenium;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.phabricator.sprint.selenium.testing.JUnit4TestBase;
+
+@RunWith(value = Parameterized.class)
+public class SprintTestCase extends JUnit4TestBase {
+       private final String projectName;
+       private final String projectId;
+       private final String boardColumnId;
+       private final String elementId;
+       private final String classValue;
+
+       public SprintTestCase(String testInstance, String projectName, String 
projectId, String boardColumnId, String elementId, String classValue) {
+               this.projectName = projectName;
+               this.projectId = projectId;
+               this.boardColumnId = boardColumnId;
+           this.elementId = elementId;
+           this.classValue = classValue;
+       }
+
+       @Parameterized.Parameters
+       public static Collection<Object[]> params() {
+          return Arrays.asList(new Object[][] {
+                { "new_test_sprint", "27", "35", "UQ0_0", "phui-workboard-view 
" },
+             });
+       }
+
+       @Test
+         public void test01() {
+          driver.get(pages.SprintProjectList);
+          WebElement div = driver.findElement(By.id(elementId));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo("phabricator-nav-content mlb"));
+          System.out.print("SprintListController is executed\n");
+         }
+
+         @Test
+         public void test02() {
+          driver.get((pages.SprintProjectTag) + projectName);
+          WebElement div = driver.findElement(By.id(elementId));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo(classValue));
+          System.out.print("/tag/<slug> route for " + projectName + " to 
SprintBoardViewController is executed\n");
+         }
+
+         @Test
+         public void test03() {
+          driver.get((pages.SprintProjectTag) + projectName + "/board");
+          WebElement div = driver.findElement(By.id(elementId));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo(classValue));
+          System.out.print("/tag/<slug>/board route for " + projectName + " to 
SprintBoardViewController is executed\n");
+         }
+
+         @Test
+         public void test04() {
+          driver.get((pages.SprintProjectBoard) + projectId);
+          WebElement div = driver.findElement(By.id(elementId));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo(classValue));
+          System.out.print("/project/sprint/board/<id> route for " + 
projectName + " to SprintBoardViewController is executed\n");
+          driver.quit();
+         }
+
+         @Test
+         public void test05() {
+          driver.get((pages.SprintProjectBoard) + projectId + "/column/" + 
boardColumnId + "/");
+          WebElement div = driver.findElement(By.id("UQ0_3"));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo("phabricator-nav-content mlb"));
+          System.out.print("/project/sprint/board/<id>/column/<columnid> route 
to SprintBoardColumnDetailController is executed\n");
+          driver.quit();
+         }
+
+         @Test
+         public void test06() {
+          driver.get((pages.SprintProjectBurn) + projectId + "/");
+          WebElement div = driver.findElement(By.id("UQ0_2"));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo("phabricator-nav-content mlb"));
+          System.out.print("/project/sprint/burn/<id> route to 
SprintDataViewController is executed\n");
+          driver.quit();
+         }
+
+         @Test
+         public void test07() {
+          driver.get((pages.SprintProjectReport) + "project/");
+          WebElement table = driver.findElement(By.tagName("table"));
+          String attribute = table.getAttribute("class");
+          assertThat(attribute, equalTo("aphront-table-view"));
+          System.out.print("/project/sprint/report/project route to 
SprintReportController Project View is executed\n");
+          driver.quit();
+         }
+
+         @Test
+         public void test08() {
+          driver.get((pages.SprintProjectReport) + "user/");
+          WebElement table = driver.findElement(By.tagName("table"));
+          String attribute = table.getAttribute("class");
+          assertThat(attribute, equalTo("aphront-table-view"));
+          System.out.print("/project/sprint/report/user route to 
SprintDataViewController User View is executed\n");
+          driver.quit();
+         }
+
+         @Test
+         public void test09() {
+          driver.get((pages.SprintProjectReport) + "burn/");
+          WebElement table = driver.findElement(By.tagName("table"));
+          String attribute = table.getAttribute("class");
+          assertThat(attribute, equalTo("aphront-table-view"));
+          System.out.print("/project/sprint/report/burn route to 
SprintDataViewController Burn View is executed\n");
+          driver.quit();
+         }
+
+         @Test
+         public void test10() {
+          driver.get((pages.SprintPhabricatorProjectFeed) + projectId);
+          WebElement div = driver.findElement(By.id("UQ0_2"));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo("phabricator-nav-content mlb"));
+          System.out.print("/project/sprint/feed/<id> route to 
PhabricatorProjectFeedController is executed\n");
+          driver.quit();
+         }
+
+         @Test
+         public void test11() {
+          driver.get((pages.SprintProjectProfile) + projectId);
+          WebElement div = driver.findElement(By.id("UQ0_3"));
+          String attribute = div.getAttribute("class");
+          assertThat(attribute, equalTo("phabricator-nav-content mlb"));
+          System.out.print("/project/sprint/profile/<id> route to 
SprintProjectProfileController is executed\n");
+          driver.quit();
+         }
+ }
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.java
new file mode 100644
index 0000000..c4ae593
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.java
@@ -0,0 +1,31 @@
+package org.phabricator.sprint.selenium.environment;
+
+public class GlobalTestEnvironment {
+
+         private static TestEnvironment environment;
+
+         public static boolean isSetUp() {
+           return environment != null;
+         }
+
+         public static TestEnvironment get() {
+           return environment;
+         }
+
+         public static void set(TestEnvironment environment) {
+           GlobalTestEnvironment.environment = environment;
+         }
+
+         public static synchronized <T extends TestEnvironment> T get(
+             Class<T> startThisIfNothingIsAlreadyRunning) {
+           if (environment == null) {
+             try {
+               environment = startThisIfNothingIsAlreadyRunning.newInstance();
+             } catch (Exception e) {
+               throw new RuntimeException(e);
+             }
+           }
+           return (T) environment;
+         }
+
+       }
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.java
new file mode 100644
index 0000000..ef90725
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.java
@@ -0,0 +1,36 @@
+package org.phabricator.sprint.selenium.environment;
+
+import org.phabricator.sprint.selenium.environment.webserver.AppServer;
+import 
org.phabricator.sprint.selenium.environment.webserver.PhabricatorAppServer;
+import org.openqa.selenium.net.NetworkUtils;
+import org.phabricator.sprint.selenium.testing.drivers.Browser;
+
+public class LabsTestEnvironment implements TestEnvironment {
+
+  private AppServer appServer;
+
+  public LabsTestEnvironment() {
+    String servingHost = getServingHost();
+    appServer = servingHost == null ? new PhabricatorAppServer() : new 
PhabricatorAppServer(servingHost);
+  }
+
+  public AppServer getAppServer() {
+    return appServer;
+  }
+
+
+  public static void main(String[] args) {
+    new LabsTestEnvironment();
+  }
+
+  private String getServingHost() {
+    Browser browser = Browser.detect();
+    if (browser == Browser.android) {
+      return "10.0.2.2";
+    }
+    if (browser == Browser.android_real_phone) {
+      return new 
NetworkUtils().getIp4NonLoopbackAddressOfThisMachine().getHostName();
+    }
+    return null;
+  }
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/TestEnvironment.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/TestEnvironment.java
new file mode 100644
index 0000000..07f0444
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/TestEnvironment.java
@@ -0,0 +1,9 @@
+package org.phabricator.sprint.selenium.environment;
+
+import org.phabricator.sprint.selenium.environment.webserver.AppServer;
+
+public interface TestEnvironment {
+
+  AppServer getAppServer();
+
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/AppServer.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/AppServer.java
new file mode 100644
index 0000000..199c0b8
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/AppServer.java
@@ -0,0 +1,17 @@
+package org.phabricator.sprint.selenium.environment.webserver;
+
+public interface AppServer {
+
+         String getHostName();
+
+         String getAlternateHostName();
+
+         String whereIs(String relativeUrl);
+
+         String whereElseIs(String relativeUrl);
+
+         String whereIsSecure(String relativeUrl);
+
+         String whereIsWithCredentials(String relativeUrl, String user, String 
password);
+
+       }
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.java
new file mode 100644
index 0000000..4b45622
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.java
@@ -0,0 +1,95 @@
+package org.phabricator.sprint.selenium.environment.webserver;
+
+import org.openqa.selenium.net.NetworkUtils;
+
+import java.io.File;
+
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+
+import static org.openqa.selenium.net.PortProber.findFreePort;
+
+public class PhabricatorAppServer implements AppServer {
+
+  private static final String HOSTNAME_FOR_TEST_ENV_NAME = "HOSTNAME";
+  private static final String ALTERNATIVE_HOSTNAME_FOR_TEST_ENV_NAME = 
"ALTERNATIVE_HOSTNAME";
+  private static final String FIXED_HTTP_PORT_ENV_NAME = "TEST_HTTP_PORT";
+  private static final String FIXED_HTTPS_PORT_ENV_NAME = "TEST_HTTPS_PORT";
+
+  private static final int DEFAULT_HTTP_PORT = 80;
+  private static final int DEFAULT_HTTPS_PORT = 2410;
+  private static final String DEFAULT_CONTEXT_PATH = "/";
+  private static final String JS_SRC_CONTEXT_PATH = "/javascript";
+  private static final String CLOSURE_CONTEXT_PATH = 
"/third_party/closure/goog";
+  private static final String THIRD_PARTY_JS_CONTEXT_PATH = "/third_party/js";
+
+  private static final NetworkUtils networkUtils = new NetworkUtils();
+
+  private int port;
+  private int securePort;
+  private File path;
+  private File jsSrcRoot;
+  private final String hostName;
+
+  public PhabricatorAppServer() {
+    this(detectHostname());
+  }
+
+  public static String detectHostname() {
+    String hostnameFromProperty = System.getenv(HOSTNAME_FOR_TEST_ENV_NAME);
+    return hostnameFromProperty == null ? "localhost" : hostnameFromProperty;
+  }
+
+  public PhabricatorAppServer(String hostName) {
+    this.hostName = "phab08.wmflabs.org";
+    this.port = DEFAULT_HTTP_PORT;
+  }
+
+  private int getHttpPort() {
+    String port = System.getenv(FIXED_HTTP_PORT_ENV_NAME);
+    return port == null ? findFreePort() : Integer.parseInt(port);
+  }
+
+  private int getHttpsPort() {
+    String port = System.getenv(FIXED_HTTPS_PORT_ENV_NAME);
+    return port == null ? findFreePort() : Integer.parseInt(port);
+  }
+
+  public String getHostName() {
+    return hostName;
+  }
+
+  public String getAlternateHostName() {
+    String alternativeHostnameFromProperty = 
System.getenv(ALTERNATIVE_HOSTNAME_FOR_TEST_ENV_NAME);
+    return alternativeHostnameFromProperty == null ?
+           networkUtils.getPrivateLocalAddress() : 
alternativeHostnameFromProperty;
+  }
+
+  public String whereIs(String relativeUrl) {
+    relativeUrl = getMainContextPath(relativeUrl);
+    return "http://"; + getHostName() + ":" + port + relativeUrl;
+  }
+
+  public String whereElseIs(String relativeUrl) {
+    relativeUrl = getMainContextPath(relativeUrl);
+    return "http://"; + getAlternateHostName() + ":" + port + relativeUrl;
+  }
+
+  public String whereIsSecure(String relativeUrl) {
+    relativeUrl = getMainContextPath(relativeUrl);
+    return "https://"; + getHostName() + ":" + securePort + relativeUrl;
+  }
+
+  public String whereIsWithCredentials(String relativeUrl, String user, String 
pass) {
+    relativeUrl = getMainContextPath(relativeUrl);
+    return "http://"; + user + ":" + pass + "@" + getHostName() + ":" + port + 
relativeUrl;
+  }
+
+  protected String getMainContextPath(String relativeUrl) {
+    if (!relativeUrl.startsWith("/")) {
+      relativeUrl = DEFAULT_CONTEXT_PATH + "/" + relativeUrl;
+    }
+    return relativeUrl;
+  }
+
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/DevMode.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/DevMode.java
new file mode 100644
index 0000000..e3375d6
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/DevMode.java
@@ -0,0 +1,16 @@
+package org.phabricator.sprint.selenium.testing;
+
+public class DevMode {
+         public static boolean isInDevMode() {
+           return isInDevMode("/org/openqa/selenium/firefox/webdriver.xpi");
+         }
+
+         public static boolean isInDevMode(String nameOfRequiredResource) {
+           return isInDevMode(DevMode.class, nameOfRequiredResource);
+         }
+
+         public static boolean isInDevMode(Class<?> resourceLoaderClazz, 
String nameOfRequiredResource) {
+           return resourceLoaderClazz.getResource(nameOfRequiredResource) == 
null &&
+               resourceLoaderClazz.getResource("/" + nameOfRequiredResource) 
== null;
+         }
+       }
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/JUnit4TestBase.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/JUnit4TestBase.java
new file mode 100644
index 0000000..05851cc
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/JUnit4TestBase.java
@@ -0,0 +1,109 @@
+package org.phabricator.sprint.selenium.testing;
+
+import java.util.logging.Logger;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.phabricator.sprint.selenium.Pages;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.htmlunit.HtmlUnitDriver;
+import org.phabricator.sprint.selenium.environment.GlobalTestEnvironment;
+import org.phabricator.sprint.selenium.environment.LabsTestEnvironment;
+import org.phabricator.sprint.selenium.environment.TestEnvironment;
+import org.phabricator.sprint.selenium.environment.webserver.AppServer;
+
+import org.phabricator.sprint.selenium.testing.drivers.WebDriverBuilder;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+
+@RunWith(SeleniumTestRunner.class)
+public abstract class JUnit4TestBase {
+
+  private static final Logger logger = 
Logger.getLogger(JUnit4TestBase.class.getName());
+
+  protected TestEnvironment environment;
+  protected AppServer appServer;
+  protected Pages pages;
+  private static ThreadLocal<WebDriver> storedDriver = new 
ThreadLocal<WebDriver>();
+  protected WebDriver driver;
+
+  @Before
+  public void prepareEnvironment() throws Exception {
+    environment = GlobalTestEnvironment.get(LabsTestEnvironment.class);
+    appServer = environment.getAppServer();
+
+    pages = new Pages(appServer);
+
+    String hostName = environment.getAppServer().getHostName();
+    String alternateHostName = 
environment.getAppServer().getAlternateHostName();
+
+    assertThat(hostName, is(not(equalTo(alternateHostName))));
+  }
+
+  @Before
+  public void createDriver() throws Exception {
+    driver = new HtmlUnitDriver();
+  }
+
+  @Rule
+  public TestRule traceMethodName = new TestWatcher() {
+    @Override
+    protected void starting(Description description) {
+      super.starting(description);
+      logger.info(">>> Starting " + description);
+    }
+
+    @Override
+    protected void finished(Description description) {
+      super.finished(description);
+      logger.info("<<< Finished " + description);
+    }
+  };
+
+  public WebDriver getWrappedDriver() {
+    return storedDriver.get();
+  }
+
+  public static WebDriver actuallyCreateDriver() {
+    WebDriver driver = storedDriver.get();
+
+    if (driver == null) {
+      driver = new WebDriverBuilder().get();
+      storedDriver.set(driver);
+    }
+    return storedDriver.get();
+  }
+
+  public static void removeDriver() {
+    if (Boolean.getBoolean("webdriver.singletestsuite.leaverunning")) {
+      return;
+    }
+
+    WebDriver current = storedDriver.get();
+
+    if (current == null) {
+      return;
+    }
+
+    try {
+      current.quit();
+    } catch (RuntimeException ignored) {
+      // fall through
+    }
+
+    storedDriver.remove();
+  }
+
+  protected boolean isIeDriverTimedOutException(IllegalStateException e) {
+    // The IE driver may throw a timed out exception
+    return e.getClass().getName().contains("TimedOutException");
+  }
+
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.java
new file mode 100644
index 0000000..48143e0
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.java
@@ -0,0 +1,36 @@
+package org.phabricator.sprint.selenium.testing;
+
+import com.google.common.base.Throwables;
+import static org.phabricator.sprint.selenium.testing.DevMode.isInDevMode;
+import org.junit.internal.runners.model.ReflectiveCallable;
+import org.junit.internal.runners.statements.Fail;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+import org.phabricator.sprint.selenium.testing.drivers.Browser;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class SeleniumTestRunner extends BlockJUnit4ClassRunner {
+
+
+  /**
+   * Creates a BlockJUnit4ClassRunner to run {@code klass}
+   *
+   * @param klass The class under test
+   * @throws org.junit.runners.model.InitializationError
+   *          if the test class is malformed.
+   */
+  public SeleniumTestRunner(Class<?> klass) throws InitializationError {
+    super(klass);
+
+    Browser browser = Browser.detect();
+    if (browser == null && isInDevMode()) {
+      browser = Browser.ff;
+    }
+
+  }
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/Browser.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/Browser.java
new file mode 100644
index 0000000..3068514
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/Browser.java
@@ -0,0 +1,48 @@
+package org.phabricator.sprint.selenium.testing.drivers;
+
+import java.util.logging.Logger;
+
+public enum Browser {
+
+  android,
+  android_real_phone,
+  chrome,
+  ff,
+  htmlunit {
+    @Override
+    public boolean isJavascriptEnabled() {
+      return false;
+    }
+  },
+  htmlunit_js,
+  ie,
+  ipad,
+  iphone,
+  none, // For those cases where you don't actually want a browser
+  opera,
+  opera_mobile,
+  phantomjs,
+  safari;
+
+  private static final Logger log = Logger.getLogger(Browser.class.getName());
+
+  public static Browser detect() {
+    String browserName = "htmlunit";
+    if (browserName == null) {
+      log.info("No browser detected, returning null");
+      return null;
+    }
+
+    try {
+      return Browser.valueOf(browserName);
+    } catch (IllegalArgumentException e) {
+      log.severe("Cannot locate matching browser for: " + browserName);
+      return null;
+    }
+  }
+
+  public boolean isJavascriptEnabled() {
+    return true;
+  }
+
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.java
new file mode 100644
index 0000000..c57bb91
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.java
@@ -0,0 +1,77 @@
+package org.phabricator.sprint.selenium.testing.drivers;
+
+import static org.openqa.selenium.remote.CapabilityType.HAS_NATIVE_EVENTS;
+
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+public class BrowserToCapabilities {
+  public static DesiredCapabilities of(Browser browser) {
+    if (browser == null) {
+      return null;
+    }
+
+    DesiredCapabilities caps;
+
+    switch (browser) {
+      case android:
+      case android_real_phone:
+        caps = DesiredCapabilities.android();
+        break;
+
+      case chrome:
+        caps = DesiredCapabilities.chrome();
+        break;
+
+      case ff:
+        caps = DesiredCapabilities.firefox();
+        break;
+
+      case htmlunit:
+        caps = DesiredCapabilities.htmlUnit();
+        caps.setJavascriptEnabled(false);
+        break;
+
+      case htmlunit_js:
+        caps = DesiredCapabilities.htmlUnit();
+        caps.setJavascriptEnabled(true);
+        break;
+
+      case ie:
+        caps = DesiredCapabilities.internetExplorer();
+        break;
+
+      case opera:
+        caps = DesiredCapabilities.opera();
+        break;
+
+      case phantomjs:
+        caps = DesiredCapabilities.phantomjs();
+        break;
+
+      case safari:
+        caps = DesiredCapabilities.safari();
+        break;
+
+      case ipad:
+        caps = DesiredCapabilities.ipad();
+        break;
+
+      case iphone:
+        caps = DesiredCapabilities.iphone();
+        break;
+
+      default:
+        throw new RuntimeException("Cannot determine browser config to use");
+    }
+
+    String version = System.getProperty("selenium.browser.version");
+    if (version != null) {
+      caps.setVersion(version);
+    }
+
+    caps.setCapability(HAS_NATIVE_EVENTS,
+        Boolean.getBoolean("selenium.browser.native_events"));
+
+    return caps;
+  }
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.java
new file mode 100644
index 0000000..2e61c8c
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.java
@@ -0,0 +1,56 @@
+package org.phabricator.sprint.selenium.testing.drivers;
+
+import static org.phabricator.sprint.selenium.testing.DevMode.isInDevMode;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.logging.Logger;
+
+import org.openqa.selenium.Capabilities;
+import org.openqa.selenium.WebDriver;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Throwables;
+
+public class DefaultDriverSupplier implements Supplier<WebDriver> {
+
+  private static final Logger log = 
Logger.getLogger(DefaultDriverSupplier.class.getName());
+  private Class<? extends WebDriver> driverClass;
+  private final Capabilities desiredCapabilities;
+  private final Capabilities requiredCapabilities;
+
+  public DefaultDriverSupplier(Capabilities desiredCapabilities,
+      Capabilities requiredCapabilities) {
+    this.desiredCapabilities = desiredCapabilities;
+    this.requiredCapabilities = requiredCapabilities;
+
+    try {
+      // Only support a default driver if we're actually in dev mode.
+      if (isInDevMode()) {
+        driverClass = 
Class.forName("org.openqa.selenium.htmlunit.HtmlUnitDriver")
+            .asSubclass(WebDriver.class);
+      } else {
+        driverClass = null;
+      }
+    } catch (ClassNotFoundException e) {
+      log.severe("Unable to find the default class on the classpath. Tests 
will fail");
+    }
+  }
+
+  @Override
+public WebDriver get() {
+    log.info("Providing default driver instance");
+
+    try {
+      return driverClass.getConstructor(Capabilities.class, 
Capabilities.class).
+          newInstance(desiredCapabilities, requiredCapabilities);
+    } catch (InstantiationException e) {
+      throw Throwables.propagate(e);
+    } catch (IllegalAccessException e) {
+      throw Throwables.propagate(e);
+    } catch (NoSuchMethodException e) {
+      throw Throwables.propagate(e);
+    } catch (InvocationTargetException e) {
+      throw Throwables.propagate(e.getTargetException());
+    }
+  }
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.java
 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.java
new file mode 100644
index 0000000..92b161b
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/src/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.java
@@ -0,0 +1,103 @@
+package org.phabricator.sprint.selenium.testing.drivers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.openqa.selenium.Capabilities;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+
+public class WebDriverBuilder implements Supplier<WebDriver> {
+  private Capabilities desiredCapabilities;
+  private Capabilities requiredCapabilities;
+  private final Browser browser;
+
+  public WebDriverBuilder() {
+    this(Browser.detect());
+  }
+
+  public WebDriverBuilder(Browser browser) {
+    this.browser = browser;
+  }
+
+  @Override
+public WebDriver get() {
+    Capabilities standardCapabilities = BrowserToCapabilities.of(browser);
+    Capabilities desiredCaps = new DesiredCapabilities(standardCapabilities,
+        desiredCapabilities);
+
+    List<Supplier<WebDriver>> suppliers = getSuppliers(desiredCaps,
+        requiredCapabilities);
+
+    for (Supplier<WebDriver> supplier : suppliers) {
+      WebDriver driver = supplier.get();
+      if (driver != null) {
+        modifyLogLevel(driver);
+        return driver;
+      }
+    }
+
+    throw new RuntimeException("Cannot instantiate driver instance: " + 
desiredCapabilities);
+  }
+
+  private void modifyLogLevel(WebDriver driver) {
+    Class<?>[] args = {Level.class};
+    Method setLogLevel;
+    try {
+      setLogLevel = driver.getClass().getMethod("setLogLevel", args);
+
+      String value = System.getProperty("selenium.browser.log_level", "INFO");
+      LogLevel level = LogLevel.valueOf(value);
+      setLogLevel.invoke(driver, level.getLevel());
+    } catch (NoSuchMethodException e) {
+      return;
+    } catch (InvocationTargetException e) {
+      throw Throwables.propagate(e);
+    } catch (IllegalAccessException e) {
+      throw Throwables.propagate(e);
+    }
+  }
+
+  private List<Supplier<WebDriver>> getSuppliers(Capabilities desiredCaps,
+      Capabilities requiredCaps) {
+    List<Supplier<WebDriver>> suppliers = Lists.newArrayList();
+    suppliers.add(new DefaultDriverSupplier(desiredCaps, requiredCaps));
+    return suppliers;
+  }
+
+  public WebDriverBuilder setDesiredCapabilities(Capabilities caps) {
+    this.desiredCapabilities = caps;
+    return this;
+  }
+
+  public WebDriverBuilder setRequiredCapabilities(Capabilities caps) {
+    this.requiredCapabilities = caps;
+    return this;
+  }
+
+  private enum LogLevel {
+    OFF("OFF", Level.OFF),
+    DEBUG("DEBUG", Level.FINE),
+    INFO("INFO", Level.INFO),
+    WARNING("WARNING", Level.WARNING),
+    ERROR("ERROR", Level.SEVERE);
+
+    private final String value;
+    private final Level level;
+
+    LogLevel(String value, Level level) {
+      this.value = value;
+      this.level = level;
+    }
+
+    public Level getLevel() {
+      return level;
+    }
+  }
+}
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/Pages.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/Pages.class
new file mode 100644
index 0000000..3c71d17
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/Pages.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/SprintTestCase.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/SprintTestCase.class
new file mode 100644
index 0000000..62cade8
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/SprintTestCase.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.class
new file mode 100644
index 0000000..9991e44
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/GlobalTestEnvironment.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.class
new file mode 100644
index 0000000..7bbe17f
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/LabsTestEnvironment.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/TestEnvironment.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/TestEnvironment.class
new file mode 100644
index 0000000..f11461d
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/TestEnvironment.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/AppServer.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/AppServer.class
new file mode 100644
index 0000000..1fa6cc5
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/AppServer.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.class
new file mode 100644
index 0000000..7bac047
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/environment/webserver/PhabricatorAppServer.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/DevMode.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/DevMode.class
new file mode 100644
index 0000000..8c65ccb
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/DevMode.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase$1.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase$1.class
new file mode 100644
index 0000000..d10dade
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase$1.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase.class
new file mode 100644
index 0000000..65741eb
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/JUnit4TestBase.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.class
new file mode 100644
index 0000000..571d2c4
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/SeleniumTestRunner.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser$1.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser$1.class
new file mode 100644
index 0000000..b58afa6
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser$1.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser.class
new file mode 100644
index 0000000..a4188d1
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/Browser.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.class
new file mode 100644
index 0000000..1d855a1
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/BrowserToCapabilities.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.class
new file mode 100644
index 0000000..b135c1e
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/DefaultDriverSupplier.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder$LogLevel.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder$LogLevel.class
new file mode 100644
index 0000000..08c016d
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder$LogLevel.class
Binary files differ
diff --git 
a/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.class
 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.class
new file mode 100644
index 0000000..f0cbad6
--- /dev/null
+++ 
b/src/tests/selenium/phabricator.sprint/target/classes/org/phabricator/sprint/selenium/testing/drivers/WebDriverBuilder.class
Binary files differ

-- 
To view, visit https://gerrit.wikimedia.org/r/188549
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I3ae72548d150f91e20d2f83bcd088fb866f3377e
Gerrit-PatchSet: 5
Gerrit-Project: phabricator/extensions/Sprint
Gerrit-Branch: master
Gerrit-Owner: Christopher Johnson (WMDE) <[email protected]>
Gerrit-Reviewer: Christopher Johnson (WMDE) <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to