I've been using Selenium WebDriver with Java and TestNG to conduct testing on a website that I developed. This website includes JavaScript, which returns values and also outputs them to the browser console using console.log()
.
I'm curious if there's an effortless way for Selenium WebDriver to retrieve this JavaScript data for me to carry out assertions using TestNG.
Although I am new to Selenium, I understand that you can do something like:
WebDriver driver = new ChromeDriver();
driver.findElement(By.id("btn")).click();
So, is there a similar approach I can take using WebDriver
to access the JavaScript on the site?
Clarification
It seems like some people assume that I want to "execute" JavaScript code through Selenium.
That's not my intention. Instead, I aim to store pre-defined JavaScript variables using Selenium.
In essence, I want Selenium to capture the value of the JavaScript variable, store it locally, and then run an assertion test on it.
Attempt 1
Let's say I have the following JavaScript code for my website:
$(document).ready(function() {
var foo = $(#"input-field-val").val();
function returnFoo() {
return foo;
}
});
Based on what I've read and understood so far, in my separate Selenium test file (Selenium.java), I should be able to do something like this?:
public class Selenium {
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
@Test
public void testSample() {
driver.get("www.mywebsite.com");
js.executeScript("alert(returnFoo());");
}
}
I've attempted something akin to the above but no alert box appears. Instead, I receive an error message:
Exception in thread "main" org.openqa.selenium.WebDriverException: ReferenceError: returnFoo is not defined
It's evident that I may be misunderstanding when it's mentioned that the JS variable
should not be part of a closure or local variable
I have even tried declaring a global variable above the $(document).ready(function()...
and setting it within function returnFoo()
, yet it still doesn't work.
Attempt 2
I have now moved both foo
and returnFoo()
outside of the $(document).ready(function()...
. This has resolved the ReferenceError
message from Attempt 1.
I have also assigned a value to foo
, so my JS code looks something like this:
var foo = "Selenium test run";
$(document).ready(function() {
...
});
function returnFoo() {
return foo;
}
Currently, I'm facing difficulty assigning the return value of returnFoo()
to a local variable within my Selenium test. Here's what I've tried:
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);
}
However, the console displays null
instead of the actual value of "Selenium test run".
Attempt 2 - SOLUTION
It appears that if I use
Object val = js.executeScript("alert(returnFoo());");
, I obtain the value of foo
.
SOLUTION
Therefore, here's how I've addressed my issue, thanks to Martin Foot's solution below.
In my JavaScript file, I created a var
and setter/getter function like this:
index.js
var seleniumGlobal;
$(document).ready(function() {
...
)};
function setSG(toSet) {
seleniumGlobal = toSet;
}
function getSG() {
return seleniumGlobal;
}
SampleTest.java
// 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);
}
}
If any segment of my JavaScript code sets my seleniumGlobal
variable via the setter method, I can call it in my Selenium test and perform assertions on it.
This might not be the most efficient method, so if anyone has a better solution, please share it with me.