Merge "js/core: Retry the caveat page"
diff --git a/test/ui/src/test/java/io/v/webdriver/TestFailureWatcher.java b/test/ui/src/test/java/io/v/webdriver/TestFailureWatcher.java
index 474c1f3..e4f2fa3 100644
--- a/test/ui/src/test/java/io/v/webdriver/TestFailureWatcher.java
+++ b/test/ui/src/test/java/io/v/webdriver/TestFailureWatcher.java
@@ -31,6 +31,9 @@
 
   @Override
   protected void failed(Throwable e, Description description) {
+    // Grab all the browser logs and print them out.
+    uiTest.printConsoleLogs();
+
     // Take a screenshot for the current screen and write the html report.
     HTMLReportData data = uiTest.getCurrentHTMLReportData();
     Util.takeScreenshot((TakesScreenshot)driver, "test-failed.png", "Test Failed", data);
diff --git a/test/ui/src/test/java/io/v/webdriver/Util.java b/test/ui/src/test/java/io/v/webdriver/Util.java
index b677e80..4fb0d25 100644
--- a/test/ui/src/test/java/io/v/webdriver/Util.java
+++ b/test/ui/src/test/java/io/v/webdriver/Util.java
@@ -14,6 +14,10 @@
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
 
 /**
  * Utility functions.
@@ -89,4 +93,27 @@
 
     htmlReportData.addScreenshotData(fullFileName, caption);
   }
+
+  /**
+   * Prints the address of each network interface on the machine.
+   * Taken from http://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java
+   */
+  public static void printIPAddresses() {
+    try {
+      Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
+      while(e.hasMoreElements())
+      {
+          NetworkInterface n = e.nextElement();
+          Enumeration<InetAddress> ee = n.getInetAddresses();
+          while (ee.hasMoreElements())
+          {
+              InetAddress i = ee.nextElement();
+              System.out.println(i.getHostAddress());
+          }
+      }
+    } catch(SocketException e) {
+      System.err.println("Could not print IP addresses");
+      e.printStackTrace();
+    }
+  }
 }
diff --git a/test/ui/src/test/java/io/v/webdriver/VanadiumUITestBase.java b/test/ui/src/test/java/io/v/webdriver/VanadiumUITestBase.java
index 549ecf7..909a6d9 100644
--- a/test/ui/src/test/java/io/v/webdriver/VanadiumUITestBase.java
+++ b/test/ui/src/test/java/io/v/webdriver/VanadiumUITestBase.java
@@ -11,15 +11,24 @@
 import org.openqa.selenium.chrome.ChromeDriver;
 import org.openqa.selenium.chrome.ChromeDriverService;
 import org.openqa.selenium.chrome.ChromeOptions;
+import org.openqa.selenium.logging.LogEntries;
+import org.openqa.selenium.logging.LogEntry;
+import org.openqa.selenium.logging.LogType;
+import org.openqa.selenium.logging.LoggingPreferences;
+import org.openqa.selenium.remote.CapabilityType;
+import org.openqa.selenium.remote.DesiredCapabilities;
 
 import io.v.webdriver.Util;
 import io.v.webdriver.htmlreport.HTMLReportData;
 import io.v.webdriver.commonpages.ChromeSignInPage;
+import io.v.webdriver.commonpages.CaveatTabPage;
 import io.v.webdriver.commonpages.ExtensionInstallationPage;
 import io.v.webdriver.commonpages.ExtensionOptionPage;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Date;
+import java.util.logging.Level;
 
 /**
  * The base class for all Vanadium UI tests.
@@ -91,6 +100,9 @@
    */
   @Before
   public void setup() throws IOException {
+    // TODO(alexfandrianto): Used to debug the IP address of the machine. Possibly remove.
+    Util.printIPAddresses();
+
     String chromeDriverBin = System.getProperty(PROPERTY_CHROME_DRIVER_BIN);
     botUsername = System.getProperty(PROPERTY_GOOGLE_BOT_USERNAME);
     botPassword = System.getProperty(PROPERTY_GOOGLE_BOT_PASSWORD);
@@ -99,16 +111,25 @@
         .usingAnyFreePort().build();
     service.stop();
     service.start();
+
+    // Set up the ability to grab the console.log from the browser.
+    DesiredCapabilities capabilities = DesiredCapabilities.chrome();
+    LoggingPreferences logPrefs = new LoggingPreferences();
+    logPrefs.enable(LogType.BROWSER, Level.ALL);
+    capabilities.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
+
+    // If an extension was chosen, use that.
     String vanadiumExtensionPath = System.getProperty(PROPERTY_VANADIUM_EXTENSION_PATH);
-    if (vanadiumExtensionPath == null) {
-      driver = new ChromeDriver(service);
-    } else {
+    if (vanadiumExtensionPath != null) {
       ChromeOptions options = new ChromeOptions();
       options.addArguments("load-extension=" + System.getProperty("vanadiumExtensionPath"));
-      driver = new ChromeDriver(service, options);
+
+      capabilities.setCapability(ChromeOptions.CAPABILITY, options);
       hasExtension = true;
     }
 
+    // Create the driver and start using it.
+    driver = new ChromeDriver(service, capabilities);
     driver.manage().window().maximize();
 
     testFailureWatcher.setup(this, driver, service);
@@ -140,6 +161,16 @@
   }
 
   /**
+   * Grab all of the log entries from the browser and print them out.
+   */
+  public void printConsoleLogs() {
+    LogEntries logEntries = driver.manage().logs().get(LogType.BROWSER);
+    for (LogEntry entry : logEntries) {
+        System.out.println(new Date(entry.getTimestamp()) + " " + entry.getLevel() + " " + entry.getMessage());
+    }
+  }
+
+  /**
    * Sign in and install the extension, if necessary.
    * A simple wrapper around signIn and installExtension.
    */
@@ -179,4 +210,12 @@
     ExtensionOptionPage extensionOptionPage = new ExtensionOptionPage(driver, reportData);
     extensionOptionPage.go();
   }
+
+  /**
+   * UI tests will commonly need to bypass a caveat page.
+   */
+  protected void handleCaveatTab(HTMLReportData reportData) throws Exception {
+    CaveatTabPage caveatTabPage = new CaveatTabPage(driver, reportData);
+    caveatTabPage.bless();
+  }
 }
diff --git a/test/ui/src/test/java/io/v/webdriver/commonpages/CaveatTabPage.java b/test/ui/src/test/java/io/v/webdriver/commonpages/CaveatTabPage.java
new file mode 100644
index 0000000..543ad95
--- /dev/null
+++ b/test/ui/src/test/java/io/v/webdriver/commonpages/CaveatTabPage.java
@@ -0,0 +1,96 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.webdriver.commonpages;
+
+import com.google.common.base.Function;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.TakesScreenshot;
+import org.openqa.selenium.TimeoutException;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import io.v.webdriver.RobotHelper;
+import io.v.webdriver.Util;
+import io.v.webdriver.htmlreport.HTMLReportData;
+
+import java.awt.AWTException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+import java.util.Set;
+
+/**
+ * Vanadium extension caveat tab page.
+ *
+ * @author jingjin@google.com
+ */
+public class CaveatTabPage extends PageBase {
+  public CaveatTabPage(WebDriver driver,
+      HTMLReportData htmlReportData) throws UnsupportedEncodingException {
+    super(driver, "", htmlReportData);
+  }
+
+  private static final int WAIT_TIME = 60; // 60s wait time
+
+  public void bless() {
+    log("Waiting for Caveat Tab...");
+    Util.takeScreenshot((TakesScreenshot)driver, "waiting-caveats.png", "Waiting for Caveats", htmlReportData);
+    final String mainTabHandle = driver.getWindowHandle();
+    // Wait until the corresponding tab is there, which means we should get two window handles.
+    // Wait at most 1 minute, then try again once.
+
+
+    String selectCaveatsTabHandle = null;
+    try {
+      log("Attempt #1");
+      selectCaveatsTabHandle = waitForCaveatTab(mainTabHandle);
+    } catch(TimeoutException e) {
+      log("Timeout occurred");
+      e.printStackTrace();
+    }
+    if (selectCaveatsTabHandle == null) {
+      Util.takeScreenshot((TakesScreenshot)driver, "found-caveats.png", "Found Caveats? No", htmlReportData);
+      log("Attempt #2");
+      // Refresh the page and try again.
+      driver.navigate().refresh(); 
+      selectCaveatsTabHandle = waitForCaveatTab(mainTabHandle);
+    } else {
+      Util.takeScreenshot((TakesScreenshot)driver, "found-caveats.png", "Found Caveats? Yes", htmlReportData);
+    }
+
+    driver.switchTo().window(selectCaveatsTabHandle);
+
+    log("Accept blessing");
+    // We need to click on the "Bless" button in the "select caveats" page.
+    WebElement btnBless =
+        wait.until(ExpectedConditions.elementToBeClickable(By.id("submit-caveats")));
+    Util.takeScreenshot((TakesScreenshot)driver, "select-caveats.png", "Selecting Caveats", htmlReportData);
+    btnBless.click();
+    driver.switchTo().window(mainTabHandle);
+  }
+
+  // Attempts to wait until the caveat tab page shows up.
+  // Returns the handle to it.
+  private String waitForCaveatTab(final String mainTabHandle) throws TimeoutException {
+    return new WebDriverWait(driver, WAIT_TIME).until(new Function<WebDriver, String>() {
+      @Override
+      public String apply(WebDriver input) {
+        Set<String> handles = driver.getWindowHandles();
+        if (handles.size() != 2) {
+          return null;
+        }
+        for (String handle : handles) {
+          if (!handle.equals(mainTabHandle)) {
+            return handle;
+          }
+        }
+        return null;
+      }
+    });
+  }
+}