WebDriver Explicit wait in Page Object model - java

We currently have a big selenium junit project which uses the page object model. We make use of the #FindBy annotation to declare our WebElements. Now when we run the tests, we randomly get the NoSuchelementException, which means the page might not have finished loading. We don't want to use an implicit wait because that won't provide a complete solution (an element might be present in the DOM but not interactable yet). An explicit wait might solve this problem. However, how do we use it in this page model architecture without having to take away the #FindBy annotation? This might have been asked before, but I don't seem to find any solutions yet.

There's a 4 ways I've see you can do this. None of them are fun, although, they get better as you go along (and more complicated to program)
Copy your selector into an explicit wait
Put your #FindBy on a List<WebElement> and wait until the size is not 0.
Create a function that accepts a WebElement and calls isDisplayed() (or some other non-action function) until it doesn't throw an exception
A final solution you could implement is to use the Decorator pattern around WebElement. This means that you will need to create your own FieldDecorator, and then use that decorator when you initialize your decorated WebElements. The decorated webelement would have a exists() function that would basically be a try/catch around NoSuchElementExceptions.
If you are confused about any of these solutions, I can provide code for them, but I think it really good practice to learn how WebElementWait and Page Objects really work (by implementing your chosen solution), so I won't post it now.

Related

JCEF - access browser window object

I need to access the browser window object to assign some objects and functions to it. I have read that it may be possible on onContextCreated call but I even don't know on which object it is called and how to access this object. I read https://magpcss.org/ceforum/viewtopic.php?f=10&t=12367 but those 'fancy' links don't help...
Also, I fetched both JCEF and Pandomium, which wraps jcef natives... but didn't found any hint in any of them (searched by calls of onContextCreated).
I have only found CefMessageRouter, but it seems to provide only basic function calls and callbacks (I also need to pass an object which contains function also), which not exactly makes me happy.
To say more, I know that assigning values may be possible with CefV8Value... but didn't found implementation (and even declaration) of it in java files.
Maybe it is possible to hack this like pass name of the existing function and then allow js to find this one in the scope, but the problem is I would not like to not give my web app too much knowledge about being embedded...
I appreciate any help.

Is there any reason why both WebElements and locators shouldn't be used in one Selenium test project

In my Selenium tests, I sometimes need to use locators (eg. driver.findElement(locator)) and sometimes I need to use webElements (eg. List). I wonder if there is any reason, that using these to in one project is not correct and I should stick to one type and declare only locators or only webElements in every pageObject.
Thanks for your help!
If I am correctly understanding what you are asking, I've found that while it is generally possible and most convenient to declare all or most of what you need for testing as webElements on a pageObject, it is sometimes necessary to dynamically use locators directly in the tests to identify certain elements. I'm guessing that's what you've run in to when you say you "sometimes need to use locators".
In general, I'd say it is generally easier to read something like
myCheckBox.click();
rather than
driver.findElement(possiblyCrypticLocator);
and obviously it would be convenient to define webElements whenever you need to reuse them.
However I don't see an inherent reason to avoid "mixing" locators and webElements if you need to use the locators dynamically. Others might disagree.
If I have understood you Question properly, your Question is regarding the Locators and finding element(s)
Locators :
Locators are used to search for elements in the Current Browsing Context. As per the current W3C WebDriver Specs the following table of location strategies lists the keywords and states defined for this attribute:
Locator Examples:
We are free to use any of the following locators to find/search/identify element(s):
CSS
driver.findElement(By.cssSelector("my_cssSelector"));
Link Text
driver.findElement(By.linkText("my_linkText"));
Partial Link Text
driver.findElement(By.partialLinkText("my_partialLinkText"));
Tag Name
driver.findElement(By.tagName("My_iframe"));
Xpath
driver.findElement(By.xpath("my_xpath"));
Finding WebElement(s):
WebElement is an interface which represents an HTML element. Generally, all the user operations to interact with a page will be performed through this interface. findElement() and findElements() are two among the several implemented methods. These methods call will do a check to ensure that the element reference is still valid as per the current state of the DOM Tree. This essentially determines whether the intended element is still attached to the HTML DOM or not.
findElement()
findElement(By by) //Find the first WebElement using the given method.
findElements()
findElements(By by) //Find all elements within the current context using the given mechanism.
The major difference between the two is, findElement() returns the WebElement where as findElements() returns a List<WebElement>. But we can use any of the above two methods anywhere in our Project as per necessity and requirement.

Start Selenium test after Javascript finish

I´m using Selenium, and I need to start testing my page not only when the page is render, but when all javascript initialization is done. I´m looking to avoid Race condition on my test because some elements are not initialized properly yet.
Simple question there´s any way to ask the DOM when all javascript render has finish?.
We know when render has done because of onDocumentReady. But then, we can start initializing some javascripts, and doing some business logic.
I want to know if there´s any mechanism to know when all javascript execution has finish.
I read the use of promise object for some async initialization, but I was looking for a more generic way to know it.
There is no generic way to know that JavaScript code has finished doing its initialization. A single page can load dozens of JavaScript libraries that can all do their own thing. Even if you can detect that an initial Ajax operation has completed, there is generally no way to know that this initial operation won't be followed by other operations that are also part of the initialization.
What you have to do is find a way to determine that, as far as your test is concerned, the page is initialized enough for the test to start. How you do this depends on the JavaScript code that is running on your page. Here's an example. For some of my applications I use DataTables to manage some of my tables. The data that appears in a table is loaded through an Ajax call. For some tests, I know that once the data is loaded, the table will have X number of rows so I wait for this many rows to appear in the table and then proceed with the test. This works for some tests. For other tests that do more complicated testing, I have to register an event handler and listen for a table redraw event before the test can proceed. If the only thing I'm testing is the table, it would be wasteful to wait until other stuff on the page has finished initializing.

Cancelling method calls when the same method is called multiple time

I think there's probably a name for what I'm describing here, but I don't know it. So my first question would be to know the name of this technique.
Here's an example: suppose you're implementing live search on a web page. Everytime the user types in the search box, you fire a new search query, and the results are updated as often as possible.
This is a stupid thing to do because you'll send much more queries than you actually need. Sending a request once per 2-3 letters or at most once per 100 ms is probably sufficient.
A technique is thus to schedule the queries to be executed soon after a key is typed, and if there are still queries that were planned but not executed, cancel them since they're obsolete now.
Now more specifically, are there specific patterns or librairies for solving this problem in Java ?
I had to solve the problem in a Swing app, and I used an ExecutorService, which returned ScheduledFutures that I could cancel. The problem is that I had to manually create a Runnable for each method call I wanted to "buffer", and keep track of each Future to cancel it.
I'm sure I'm not the first person to implement something like this, so there must be a reusable solution somewhere ? Possibly something in Spring with annotations and proxies ?
Given the other answers, and after some searching, it seems there's indeed no library that does what I wanted.
I created one and put it on GitHub. Future readers of this question may find it interesting.
https://github.com/ThomasGirard/JDebounce
I don't think it's very good yet but at least it works and can be used declaratively:
#Debounce(delayMilliseconds = 100)
public void debouncedMethod(int callID, DebounceTest callback) { }
This is not solvable in Java without using some extra infrastructure like you did with executor and futures. It is not possible to solve this in syntactically concise manner in Java.
You will always need some sort of method result wrapper, because the mechanism returns immediately but the actual result is retrieved later. In your case this was accomplished via Future.
You will always need to be able to specify code to be executed in a manner that will allow delayed execution. In most languages this is accomplished using function pointers or function values or closures. In Java, lacking these language features, this is usually accomplished by passing an object that implements some sort of interface such as Runnable, Callable, that allows delayed execution of a block of code. There are other options but none of them are simple, such as using a dynamic proxy.
tl;dr
Can't do this in concise manner in Java.
What you need is called debouncing. You should check the jQuery Throttle/Debounce plugin (which is btw totally independent of jQuery except for using the same namespace). What you need is covered by the debounce part:
Using jQuery throttle / debounce, you can pass a delay and function to
$.debounce to get a new function, that when called repetitively,
executes the original function just once per “bunch” of calls,
effectively coalescing multiple sequential calls into a single
execution at either the beginning or end.
Underscore.js has the same method:
_.debounce(function, wait, [immediate])
Creates and returns a new debounced version of the passed function
which will postpone its execution until after wait milliseconds have
elapsed since the last time it was invoked. Useful for implementing
behavior that should only happen after the input has stopped arriving.
For example: rendering a preview of a Markdown comment, recalculating
a layout after the window has stopped being resized, and so on.
// example: debounce layout calculation on window resize
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
[Edit]
I mistakenly read "Javascript" instead of Java. Actual Java solution was written by OP afterwards.

When to Stop Defining FindBy's in the Object and Move Them to the Test

So I have an interesting conundrum I was curious to get some feedback from other Webdriver framework architects. Currently I follow a pretty standard execution model:
baseobject
pageobject (extends baseobject)
Junit testobject (references one or multiple pageobjects)
Within my pageobjects I chose to define my findBy UI mappings as variables, and in-turn reference them within the various methods I write for that pageobject. I find this works very well. However, one item I am waffling on is how to handle method design for pages (and their respective pageobject) when there exist potentially 50 separate hyperlinks.
My inclination and design thus far has been to create methods (I think of them as services really) for each link on most pageobjects I've created so that #Test I can simply call the method I want and be done with it. This eliminates the potential for test maintenance...standard practice I know. But I am now trying to decide...does it make sense to create 50 methods, one for each link for a page object, or do I go against my wishes and pass in linktext from the test itself, feeding into a single method that builds the findBy using that passed in parameter.
On one hand there is way less code within the pageobject, but on the other, tests become more brittle. There is potential for these links to be references in hundreds of tests.
Here is a brief example of my model:
classname extends baseobject{
By someLocator = By.linkText("some text");
By someOtherLocator = By.linkText("some other text");
By andAnotherLocator = By.id("someid");
public void someLinkMethod(){
driver.findElement(someLocator).click();
}
public void someOtherLinkMethod(){
driver.findElement(someOtherLocator).click();
}
public void someidMethod(){
driver.findElement(andAnotherLocator).click();
}
}
Thus we come to the end of the question. This model works great for test design. My services (methods) are insulated and easily maintainable. But what would I do if there were 50 UI mappings for links instead of 2 as I have shown above? I toyed with the following design, but really dislike it #Test:
public void selectFromLeftBar(String barItem){
driver.findElement(by.linkText(barItem)).click();
}
Any thoughts would be greatly appreciated!
Do it in your page object class. Here are the reasons:
What does your code do if your page changes the link text? You have to go into each test and change that text, even if the link does the same thing.
What happens if your page removes that link? You are stuck with the same problem, namely, having to find each time you call that link. If its a method...then you delete the method, and your IDE notifies you of each instance that you used it.
Finally, you are providing a standard interface for the test. If you make an exception here, what would stop you from passing other things into your page?
As a side note, I would recommend only mapping elements that you are going to use. I've found that if I map out every element I could possibly ever need then I end up with a massive class filled with fluff and less time on my hands.

Categories

Resources