I am having an issue with selenium js
I have created my components in json like:
"usernameInputField": {
"selector": {
"xpath": "//*[#id='username']"
}
}
and I am calling webdriver :
var webdriver = require('selenium-webdriver');
using the data like this:
console.log(webdriver.By.xpath("//*[#id='username']"));
it calls correctly
however when I try to run console.log(webdriver.By(usernameInputField.selector));
I get an error (TypeError: Class constructors cannot be invoked without 'new')
what am I doing wrong here?
You can use regular findElement directly without having to use the By "class":
driver.findElement(usernameInputField.selector);
Related
In my index.js I have a class
class Digit() {
//construct
add() {
//do whatever
}
}
and
let C = new Digit();
I pass this to the client using
WS.send(JSON.stringify(C))
which is recieved/interpreted in index.html. This all works perfectly and the issue is not with this proccess.
However when I try to use C.add(), I get the TypeError: function add does not exist. In my eyes either the error is that there is no 'context' for the class and thus the methods cannot be accessed, there is some namespace error, or JSON.stringify cannot properly send objects of custom classes. So how do I fix this error?
I'm trying to develop my first Vaadin 14 application, I'm also using Spring boot framework for it.
I've created a javascript file, I put it into the folder frontend/src with the name of teams.js and I'm trying to import it with #JsModule("src/teams.js"). My root view class looks like this:
#Route("")
#PageTitle("Teams organization store init")
#Slf4j
#JsModule("src/teams.js")
#Tag("TeamsEntry")
public class TeamsEntryView extends VerticalLayout implements BeforeEnterObserver {
public TeamsEntryView() {
initTeams();
}
private void initTeams() {
var ui = UI.getCurrent();
var page = ui.getPage();
log.info("Teams initialization...");
page.executeJs(getTeamsConfig()).toCompletableFuture().whenComplete(((jsonValue, throwable) ->
log.info("Teams initialization completed: {} with throwable {}", jsonValue.toJson(), throwable.getMessage())
));
}
private String getTeamsConfig() {
return """
console.log('ss');
window.initTeams();
console.log('xx');
return true;
""";
}
...
My js file looks like this:
window = {
initTeams: function () {
console.log('initTeams...');
}
}
In this case, I see "ss" in the browser's console, but nothing more.
If I remove the window.initTeams(); line I get "ss" and "xx" as well.
If I declare a simple function in the js file and call it without the "window" class I get similar results.
If I use #Javascript or page.addJavascript("src/teams.js") I get this error when the page loads: "> unexpected character"
If I try to call join() or get() on the completable future the browser freeze.
If I use #Javascript("frontend://src/teams.js") I get some CORS error like if it is trying to download something from the "frontend" host.
I've tried to put the #JsModule on a component instead of my view.. it does not work.
I've tried to put my js file to the root, and to the resources folder.
I could not find any other solution to import and use my js file into vaadin14 with spring boot.
Also, I'm not sure why the browser freeze if I call "join()" on completable future, and also the on the result of it sentToBrowser returns false even if I see the console logs in the browsers log...
Can somebody explain to me how should I do the javascript import, why my current code does not work, and why the "join()" freezes the browser, please?
Thank you in advance!
#Edit
I have also tried with this annotation #JavaScript("./src/teams.js") and a js like this:
function initTeams () {
console.log('initTeams...');
console.log("Teams initialized!")
}
#Edit
Okay so finally I got it working.
The js file has to be under root/src/main/webapp/src folder.
Nor #JavaScript and nor the #JsModule worked for me, so I had to import my js file as:
var ui = UI.getCurrent();
var page = ui.getPage();
page.addJavaScript("src/teams.js");
Then I can call it like window.initTeams() or like initTeams() and both works fine. Altough the completable future below still never executes, and isSentToBrowser() always returns false.
page.executeJs(getTeamsConfig()).toCompletableFuture().whenComplete(((jsonValue, throwable) ->
log.info("Teams initialization completed: {} with throwable {}", jsonValue.toJson(), throwable.getMessage())
));
I must mention if I start the path with '.' like page.addJavaScript(".src/teams.js"); then it does not find the file.
Does anybody have an answer, why the completable future never executes?
The problem is that the following code redefines the window object:
window = {
initTeams: function () {
console.log('initTeams...');
}
}
Did you meant to add a function to the window object? Like so:
window.initTeams = function () {
console.log('initTeams...');
};
If you want to keep code visually similar to yours:
window = {
...window,
{
initTeams: function() {
console.log('initTeams...');
}
}
}
Other options:
window['initTeams'] = function() {...}
Object.assign(window, {initTeams: function() {...}})
Object.defineProperty(window, 'initTeams', {value: function() {console.log('foo')}});
Gotta love JavaScript...
Also, for more knowledge, the code mentioned in your #Edit section could not be called. Calling initTeams() is equivalent to window.initTeams(). The function must exist in the window object. This is why, for example, you see some custom elements defined like customElements.define(...) and window.customElements.define(...).
Code :
var assert = require('assert');
describe('webdriver.io api page', function() {
it('should open login page', function () {
browser.url('/login');
browser.pause(10000);
})
it('Should enter login details and submit', function() {
browser.pause(10000);
browser.element(By.xpath("//input[#type='text' and #aria-label='user name']")).sendKeys("mikestr");
})
});
I am new to webdriverIO and trying to locate username textbox using xpath but it throws me error. I look around many webdriverIO material but did not get solution for this yet.
WebdriverIO's Selectors are different than Selenium Webdriver. It will accept the String value for either "XPath" or "CSS" selectors. The "By is not defined" Error you're seeing is because it's looking for a "String" value of a selector.
Documentation:
http://webdriver.io/guide/usage/selectors.html#CSS-Query-Selector
In your situation you would only need to pass something like:
browser.element('"//input[#type='text' and #aria-label='user name']"')
.setValue('mikestr')
Alternatively you could set the variable and pass a variable like:
var XPath = "//input[#type='text' and #aria-label='user name']"
browser.element(XPath).setValue('mikestr')
The locator has to be a string
For setting value , you can use setValue
browser.setValue("//input[#type='text' and #aria-label='user name']", 'mikestr');
I had a different issue using angular with the same By is not defined error. For anyone else that might end up here the solution for me was to add the import
import { By } from "#angular/platform-browser";
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 console.log().
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.
I'm quite new to Selenium but I understand that you can do something like:
WebDriver driver = new ChromeDriver();
driver.findElement(By.id("btn")).click();
So is there anything similar I can do using WebDriver to read the JavaScript on the site?
Clarification
It looks like people are making the assumption that I'm trying to "execute" JavaScript code through Selenium.
Thats not the case. Instead, I'm trying to store already-defined JavaScript variable using Selenium.
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.
Attempt 1
Say I have the following JS code for my website:
$(document).ready(function() {
var foo = $(#"input-field-val").val();
function returnFoo() {
return foo;
}
});
From what I've reading and understanding, in my seperate 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 do something similar to what's above but no alert box pops up. Instead, I get an error message:
Exception in thread "main" org.openqa.selenium.WebDriverException: ReferenceError: returnFoo is not defined
I'm pretty sure I'm not understanding what it means when its said that the JS variable
should not be part of a closure or local variable
I have also tried defining a global variable above the $(document).ready(function()... and setting is within function returnFoo() but still doesn't work.
Attempt 2
I've moved both foo and returnFoo() outside of the $(document).ready(function().... That has fixed ReferenceError message that I was getting in Attempt 1 above.
I hav also given foo a value so my JS code looks something like this:
var foo = "Selenium test run";
$(document).ready(function() {
...
});
function returnFoo() {
return foo;
}
Now, I'm having a tough time assigning the return of returnFoo() to a local variable within my Selenium test. Here's what I've attempted:
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);
}
But the console display null instead of the actual value of "Selenium test run".
Attempt 2 - SOLUTION
It looks like if I do Object val = js.executeScript("alert(returnFoo());"); I get the value of foo.
SOLUTION
So here's the solution I've come up w/ to my problem thanks to the solution by Martin Foot below.
In my JavaScript file, I created a var and a setter/getter function like so:
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);
}
}
So whenever some code in my JavaScript sets my seleniumGlobal variable through the setter method, I can call it through my Selenium test and do assertions on it.
This is probably not the most efficient way to do but if someone else has a better solution, please let me know.
All you have to do is:
Object val = js.executeScript("return returnFoo();");
That will give you what you are looking for.
No JavaScript functions need be defined. Nor is alert() needed.
Object result = js.executeScript("return globalVar");
For Python:
result = driver.execute_script("return globalVar")
In Ruby you can use page.execute_script to evaluate a JavaScript variable (if it is accessable from the scope of the web browser). It looks like there is a similar method in Java here.
Edit: This might be a use case that is more suited to a JavaScript unit testing framework such as Jasmine.
I'm having a problem since I wrapped my javascript functions inside of a namespace.
Version 1 of my code worked fine. Originally, to call the javascript from inside Silverlight I used to use this code:
HtmlPage.Window.Invoke("hideMyDiv");
My javascript looked like this:
function hideMyDiv() {
$('#MyDiv').fadeOut();
}
Now, I've refactored my javascript to be contained in a namespace. So it now looks like this:
var activity = {
message: null,
hideMyDiv: function() {
$('#MyDiv').fadeOut();
} };
I can call this refactored function in javascript, it works like before:
$("document").ready(function() {
activity.hideMyDiv(); });
But when I try to use it from Silverlight, I get this error: Failed to Invoke: activity.updateInfo. This is my current Silverlight code:
HtmlPage.Window.Invoke("activity.hideMyDiv");
What am I doing wrong? (and thanks!)
This is the correct way..
ScriptObject so = HtmlPage.Window.Eval("activity") as ScriptObject;
so.Invoke("hideMyDiv");