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.
Related
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();
}
});
}
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
I'm testing a website that opens in-browser pop-ups to display object details. These pop-ups are sometimes modal, by which I mean that they render the rest of the screen inoperative and trigger a gray transparent overlay that covers everything but the pop-up. This overlay is intended behavior, which means that I need a way to detect whether or not it was correctly triggered.
However, I am not familiar enough with the implementation of such overlays to determine where in the DOM I should look to find the properties that govern such behavior. As such, I was hoping someone with more information on how such overlays are usually configured could point me in the right direction.
The obvious solution is to simply try to click a button and see what happens but I was hoping to write a method that I could implement throughout the test suite rather than having to write a different check for each circumstance.
For those interested I'm scripting in Java using Selenium.
I know this is old, but it may still help someone else. I had just recently solved a similar problem for our React site. I believe we were using the react-block-ui module to implement our blocking overlays.
Basically, I was able to detect a certain element was blocked by an overlay because of 2 known facts:
The element was within a containing div ("the overlay") that followed a certain naming convention. In our case, it was section-overlay-X.
This overlay would have a class attribute (named av-block-ui) if it was blocking.
(Hopefully, you have access to this information, too... or something similarly useful.)
With this information, I wrote up a couple utility methods to help me determine whether or not that particular WebElement is blocked by an overlay. If it was blocked, throw a ElementNotInteractableException.
For Java:
...
By SECTION_OVERLAY_ANCESTOR_LOCATOR = By.xpath("./ancestor::div[contains(#id, 'section-overlay-')][1]");
...
private WebElement findUnblockedElement(By by) {
WebElement element = driver.findElement(by);
if (isBlockedByOverlay(element)) {
throw new ElementNotInteractableException(String.format("Element [%s] is blocked by overlay", element.getAttribute("id")));
} else {
return element;
}
}
private boolean isBlockedByOverlay(WebElement element) {
List<WebElement> ancestors = element.findElements(SECTION_OVERLAY_ANCESTOR_LOCATOR);
WebElement overlayAncestor = ancestors.get(0);
String overlayClass = overlayAncestor.getAttribute("class");
return !StringUtils.isBlank(overlayClass);
}
Here's my snippet on it:
https://bitbucket.org/snippets/v_dev/BAd9dq/findunblockedelement
This won't work in all situations, but I solved this problem by checking the overflow value of the body element. The flavor of modal I was trying to get past disabled scrolling of the page while it was active.
This is may be very noobish and a bit embarrassing but I am struggling to figure out how to make checkboxes 'checked' using CSS?
The case is that if a parent has a class setup (for example) I'd like to have all the checkboxes having setup as parent to be checked. I'm guessing this is not doable in pure CSS, correct? I don't mind using JS but am just very curious if I could toggle the state of the checkboxes along with that of their parent (by toggling the class).
Here's a fiddle to play around with.
A checkbox being "checked" is not a style. It's a state. CSS cannot control states. You can fake something by using background images of check marks and lists and what not, but that's not really what you're talking about.
The only way to change the state of a checkbox is serverside in the HTML or with Javascript.
EDIT
Here's a fiddle of that pseduo code. The things is, it's rather pointless.
It means you need to adding a CSS class to an element on the server that you want to jQuery to "check". If you're doing that, you might as well add the actually element attribute while you're at it.
http://jsfiddle.net/HnEgT/
So, it makes me wonder if I'm just miss-understanding what you're talking about. I'm starting to think that there's a client side script changing states and you're looking to monitor for that?
EDIT 2
Upon some reflection of the comments and some quick digging, if you want a JavaScript solution to checking a checkbox if there's some other JavaScript plugin that might change the an attribute value (something that doesn't have an event trigger), the only solution would be to do a simple "timeout" loop that continuously checks a group of elements for a given class and updates them.
All you'd have to do then is set how often you want this timeout to fire. In a sense, it's a form of "long polling" but without actually going out to the server for data updates. It's all client side. Which, I suppose, is what "timeout" is called. =P
Here's a tutorial I found on the subject:
http://darcyclarke.me/development/detect-attribute-changes-with-jquery/
I'll see if I can whip up a jQuery sample.
UPDATE
Here's a jsfiddle of a timeout listener to check for CSS classes being added to a checkbox and setting their state to "checked".
http://jsfiddle.net/HnEgT/5/
I added a second function to randomly add a "checked" class to a checkbox ever couple of seconds.
I hope that helps!
Not possible in pure css.
However, you could have a jQuery event which is attached to all elements of a class, thereby triggering the check or uncheck based on class assignments.
Perhaps like this:
function toggleCheck(className){
$("."+className).each( function() {
$(this).toggleClass("checkedOn");
});
$(".checkedOn").each( function() {
$(this).checked = "checked";
});
}
I have written a ASP.NET program for a customer, I want to add a message similar to "Preview version, ABD Consulting" on the master.master page, I had thought to use Response.write but it messes up the look of the page as it seems to move page elemets. If I use a label the customer can remove it from the Master.master file, any suggestions? The customer is in a different country so I want to ensure I'm paid.
Many thanks
Serve it on your own server. If it's a preview, they shouldn't have access to the code anyway.
There is nothing you can do unless you host it or control the web server it runs on. Nothing you do in code will matter if they are smart enough. They can write their on HTTP Handlers and replace anything they want.
If you programmatically write out the label during the OnPrerender or Render of the page then the client will not be able to remove it. If you then randomize the ID given to the element, they will find it incredibly hard to apply any javascript functions or CSS styles to it, especially if you directly add the styles to it.
Something like this (pseudo code):
HtmlGenericControl label = new HtmlGenericControl("div");
label.ID = Guid.NewGuid().ToString();
label.InnerText = "My copyright or ownership text";
label.Style.Add(HtmlTextWriterStyle.Height, "50px");
label.Style.Add(HtmlTextWriterStyle.Width, "100px");
if you then absolutely position it, it should always show up. Note that it isn't totally untouchable and fool proof, but you want to just make it hard enough that the client doesn't try to remove it.
Obfuscate it in a dll and use the Current Context to write a pretty div like the one that StackOverflow.com uses on top.
I'm with George and Rick - don't let them have the source and serve it up from a server you control. In addition, I'd created a background image that says "Demo". This will remind that they need to pay up.