title: Reading JavaScript variables using Selenium WebDriver
body: <p>I'm using Selenium WebDriver (Java) and TestNG to do some testing on a website I created. In this website, I also have JavaScript and in some of the functions, it returns values and also outputs values to the browser console through <code>console.log()</code>.</p>
  
  <p><strong>I was wondering if there is an easy way for Selenium WebDriver to access some of this JavaScript information so I can perform assertions using TestNG.</strong></p>
  
  <p>I'm quite new to Selenium but I understand that you can do something like:</p>
  
  <pre><code>WebDriver driver = new ChromeDriver();
  driver.findElement(By.id("btn")).click();
  </code></pre>
  
  <p>So is there anything similar I can do using <code>WebDriver</code> to read the JavaScript on the site?</p>
  
  <hr>
  
  <h2>Clarification</h2>
  
  <p>It looks like people are making the assumption that I'm trying to "execute" JavaScript code through Selenium.</p>
  
  <p>Thats not the case. Instead, I'm trying to store already-defined JavaScript variable using Selenium.</p>
  
  <p>Basically, I want Selenium to be able to grab the JavaScript variable's value, store it locally, and then do an assertion test on it.</p>
  
  <hr>
  
  <h2>Attempt 1</h2>
  
  <p>Say I have the following JS code for my website:</p>
  
  <pre><code>$(document).ready(function() {
      var foo = $(#"input-field-val").val();
  
      function returnFoo() {
          return foo;
      }
  });
  </code></pre>
  
  <p>From what I've reading and understanding, in my seperate Selenium test file (Selenium.java), I should be able to do something like this?:</p>
  
  <pre><code>public class Selenium {
      WebDriver driver = new FirefoxDriver();
      JavascriptExecutor js = (JavascriptExecutor) driver;
  
      @Test
      public void testSample() {
          driver.get("www.mywebsite.com");
          js.executeScript("alert(returnFoo());");
      }
  }
  </code></pre>
  
  <p>I do something similar to what's above but no alert box pops up. Instead, I get an error message:</p>
  
  <pre><code>Exception in thread "main" org.openqa.selenium.WebDriverException: ReferenceError: returnFoo is not defined
  </code></pre>
  
  <p>I'm pretty sure I'm not understanding what it means when its said that the JS variable </p>
  
  <blockquote>
    <p>should not be part of a closure or local variable</p>
  </blockquote>
  
  <p>I have also tried defining a global variable above the <code>$(document).ready(function()...</code> and setting is within <code>function returnFoo()</code> but still doesn't work.</p>
  
  <hr>
  
  <h2>Attempt 2</h2>
  
  <p>I've moved both <code>foo</code> and <code>returnFoo()</code> outside of the <code>$(document).ready(function()...</code>. That has fixed <code>ReferenceError</code> message that I was getting in <em>Attempt 1</em> above.</p>
  
  <p>I hav also given <code>foo</code> a value so my JS code looks something like this:</p>
  
  <pre><code>var foo = "Selenium test run";
  
  $(document).ready(function() {
  ...
  });
  
  function returnFoo() {
      return foo;
  }
  </code></pre>
  
  <p>Now, I'm having a tough time assigning the return of <code>returnFoo()</code> to a local variable within my Selenium test. Here's what I've attempted:</p>
  
  <pre><code>public static void main(String[] args) {
          WebDriver driver = new FirefoxDriver();
          JavascriptExecutor js = (JavascriptExecutor) driver;
  
          driver.get("http://localhost:8080/HTML5TestApp/prod.html");
          Object val = js.executeScript("window.returnFoo();");
          System.out.println(val);
      } 
  </code></pre>
  
  <p>But the console display <code>null</code> instead of the actual value of <strong>"Selenium test run"</strong>.</p>
  
  <h2>Attempt 2 - SOLUTION</h2>
  
  <p>It looks like if I do <code>Object val = js.executeScript("alert(returnFoo());");</code> I get the value of <code>foo</code>.</p>
  
  <hr>
  
  <h2>SOLUTION</h2>
  
  <p>So here's the solution I've come up w/ to my problem thanks to the solution by Martin Foot below.</p>
  
  <p>In my JavaScript file, I created a <code>var</code> and a setter/getter function like so:</p>
  
  <p><strong>index.js</strong></p>
  
  <pre><code>var seleniumGlobal;
  
  $(document).ready(function() {
  ...
  )};
  
  function setSG(toSet) {
      seleniumGlobal = toSet;
  }
  
  function getSG() {
      return seleniumGlobal;
  }
  </code></pre>
  
  <p><strong>SampleTest.java</strong></p>
  
  <pre><code>// Do all the necessary imports
  
  public class SampleTest {
      WebDriver driver = new FirefoxDriver();
      JavascriptExecutor js = (JavascriptExecutor) driver;
  
      @Test
      public void testPrintVal() {
          String sgVal = (String) js.executeScript("alert(getSG());");
          Assert.assertEquals("new value for seleniumGlobal", sgVal);
      }
  }
  </code></pre>
  
  <p>So whenever some code in my JavaScript sets my <code>seleniumGlobal</code> variable through the setter method, I can call it through my Selenium test and do assertions on it.</p>
  
  <p>This is probably not the most efficient way to do but if someone else has a better solution, please let me know.</p>