How can I focus on an element using Webdriver JS? - webdriver

e.g. if I get an instance of an element using
var termsLink = driver.findElement(webdriver.By.id('wd-terms'));
There dont seem to be any methods available on the resulting WebElement object to set focus on the target element, in that case how can I do this using Webdriver JS?

It seems other the java bindings for webdriver have a method moveToElement but looking into the source code of my webdriver instance, "selenium-webdriver": "^2.46.1" obtained via NPM, the moveToElement method doesnt seem to exist.
The best technique I found was
driver.findElement(webdriver.By.id('some-id')).sendKeys('');
per this SO question

Related

Is there an easy way to traverse nested Shadow DOM when testing with Cucumber, Selenium & Capybara?

I am attempting to write automation tests for the front-end UI of an app , that has a lot of nested shadow-doms and I am unable to access them using the Capybara, Cucumber & Selenium (using chromedriver). The app is using AWS Amplify Authenticator . I keep getting the following error when I try to find an input element :
Unable to find css "input[id$='username']" (Capybara::ElementNotFound)
This is what my test looks like:
When('I type into the username field my {string}') do |string| find("input[id$='username']").set(string) end
I have read on other posts that chrome driver supports shadow-doms but not sure how it would be handled in this scenario
Currently you need to use evaluate_script to get access to the shadow-dom - like
element = find(...) # find element that contains shadow dom
shadow_root = #session.evaluate_script(<<~JS, element)
(function(root){
return root.shadowRoot;
})(arguments[0])
JS
shadow_root.find("input[id$='username']")
and then you can only use CSS based finders/actions/etc on the shadow DOM.
The WebDriver spec has been updated to bring more support for the shadow dom but it's not implemented in drivers yet - https://w3c.github.io/webdriver/#shadow-root

Selenium message:stale element reference: element is not attached to the page document [duplicate]

I am trying to learn the PageFactory model. I understood the fact that when we do a initElements, the WebElements are located. Say for example, I click on a webelement and because of which there is a change in one of the other webelements in DOM. Now, obviously I would get a StaleElementReferenceException here. How would I resolve this issue?
Should I find that specific WebElement again knowing the fact that there can be a change in the WebElement's properties in the DOM? or is there an another way to handle this?
StaleElementReferenceException
StaleElementReferenceException extends WebDriverException and indicates that the previous reference of the element is now stale and the element reference is no longer present on the DOM of the page.
Common Reasons
The common reasons behind facing StaleElementReferenceException are as follows:
The element has been deleted entirely.
The element is no longer attached to the DOM.
The webpage on which the element was part of has been refreshed.
The (previous) element has been deleted by a JavaScript or AjaxCall and is replaced by a (new) element with the same ID or other attributes.
Solution : If an (old) element has been replaced with new identical one, the simple strategy would be to use findElement() or findElements to look out for the element again.
Answering your queries
When we do a initElements, the WebElements are located : When you call initElements() method, all the WebElements of that page will get initialized. For example,
LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class);
This line of code will initialize all the static WebElements defined within the scope of the LoginPageNew.class whenever and wherever it is invoked from your Automation Script.
I click on a webelement and because of which there is a change in one of the other webelements in DOM : This is pretty much possible.
As an example, in general invoking click() on a <input> tag wouldn't trigger any change of any of the WebElements on the HTML DOM.
Where as invoking click() on a <button> tag or <a> tag may call a JavaScript or a Ajax which inturn may delete an element or can replace the (previous) element by a (new) element with the same ID or other attributes.
Conclusion
So, if WebDriver throws a StaleElementReferenceException, that implies even though the element still exists, the reference is lost. We should discard the current reference we have and replace it by locating the WebElement once again when it gets attached to the DOM. That means you have to again reinitialize the class through initElements() method which inturn reinitializes all the WebElements defined in that page.
Solution
If a old element has been replaced with new identical one, the simple strategy would be to invoke WebDriverWait inconjunction with ExpectedConditions to look out for the element.
You can find relevant detailed discussions in:
How to add explicit wait in PageFactory in PageObjectModel?
References
Here are the references of this discussion:
Stale Element Reference Exception
Class StaleElementReferenceException
Selenium: How to tell if RemoteWebDriver.findElements(By) can throw StaleElementReferenceException at all?
This is a known problem with the PageFactory implementation.
If you are unlucky enough for the element to become stale in the instant between the element being found, and then the element being clicked upon, you will get this error. Unfortunately the PageFactory code does not try to find the element again if it has become stale and it throws an Exception.
I would classify this as a bug with PageFactory, it should auto re-find the element if it ever becomes stale (unless the #CacheLookup annotation is used).
The suggestion to recall initElements isn't going to fix anything, you only need to init the elements once because that binds a Java proxy class to the element in question. The page factory implementation is supposed to remove the possibility of StaleElementReferenceExceptions (hence why this is a bug)
Stale element exception is thrown in two cases
The element is no longer attached to the DOM.
The element has been deleted entirely.
When this happen you wrap your code in try catch block then you can loop and retry as many times as you need until it succeeds.
public void waitForElementPresent(final By by, int timeout){
WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver,timeout)
.ignoring(StaleElementReferenceException.class);
wait.until(new ExpectedCondition<Boolean>(){
#Override
public Boolean apply(WebDriver webDriver) {
WebElement element = webDriver.findElement(by);
return element != null && element.isDisplayed();
}
});
}

Why use getAttribute and setAttribute?

I'm trying to better understand the fundamentals of A-Frame.
I understand how to use the getAttribute() and setAttribute() methods for
accessing component data. However I don't understand why we use them instead of just accessing the components attributes using dot notation.
A lot of people use something like:
document.querySelector("#myText").getAttribute('text').value
Why not use:
document.querySelector("#myText").components['text'].data.value
Is there something wrong with using that second way? What are the pitfalls? In my experiments I have experienced both ways returning "undefined" due to the code running before the scene is finished loading, but I have learned how to avoid that using the "loaded" event.
As you can see at this glitch example (https://glitch.com/~text-hierarchy) I've successfully printed data to the console using both ways.
Part of the standard
Both getAttribute(prop) and setAttribute(prop, value) are used to get/set attributes of any other DOM elements. MDN links here (get, set)
Compatible with aframe components
If you have a update() function in your a-frame component, setAttribute() calls it, notyfing, that a property of a component has changed.
It's not mandatory, it's even faster to modify some properties directly, but it has risks, like undefined behavior if a developer uses update() to monitor changes.

How to verify in CSS that text fields/other fields are disabled for editing in Selenium 2?

The page is created by CSS using jquery and I am using selenium2 and junit for verification. It would be of great help if anyone can provide a way to identify that the fields are disabled and use an assert statement.
I assume that you are using Selenium 2 for your tests.
The WebDriver class provides a way to retrieve all WebElements on the page using the findElement and findElements methods. Both of these methods take selectors in the form of instances of the By class. So, in your case, you would have to use a selector that finds the input fields you are looking for, for instance with
WebElement element = webDriver.findElement(By.name("password"));
You can then use
if (element.isDisplayed() && element.isEnabled()) {
//your code here
}
or
assert (element.isDisplayed() && element.isEnabled());
to verify that the field is both displayed and enabled.

WebDriver: add new element

Is there a method to add/insert an element in the current DOM?
Let me start by saying, this is a really bad idea. Think long and hard about why you want to do this. Then, if you still want to dynamically add elements, think about it some more. WebDriver is meant to mimic user interaction with your page, users don't typically add elements willy-nilly.
That said, if you're absolutely set on doing this I'd suggest using the JavascriptExecutor to add an element via JavaScript
WebDriver driver; // Assigned elsewhere
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("document.getElementById('myDiv').appendChild(document.createTextNode(' New Element'))")
It's ugly for a reason.

Resources