How to verify that html is stable (finished changing) in Selenium WebDriver? - java

I'm testing online Game here http://slotmachinescript.com/
I want to create a test to verify if credits value is the same after page refresh
public class VerifyGameAfterRefresh extends BaseTest{
#Test(invocationCount = 1)
public void testAfterRefresh(){
GamePage gamePage = new GamePage(driver);
gamePage.isLoaded();
int times = getRandInt(2,5);
//change bet value
gamePage.clickSpinUpButton(times);
//click on spin button
gamePage.clickSpinButton(times);
int creditsValue = gamePage.getCreditsValue();
gamePage.pageRefresh();
int creditsValueAfterRefresh = gamePage.getCreditsValue();
Assert.assertEquals(creditsValue,creditsValueAfterRefresh,"Credit after refresh are not the same");
Assert.assertTrue(gamePage.getBetValue() == 1, "Bet value was not set to default");
}
}
Method to get creditsValue :
public int getCreditsValue(){
//wait.until(ExpectedConditions.
int value = Integer.parseInt(creditsValue.getText());
return value;
}
Everything works perfect until the case when after last click on spin user wins. In this case <span id="credits">value</span> value is changing dynamically, but my method does not wait till the end of the changing and grab the value at the beginning that after leads to test fail.
May I use some functionality of
wait.until(ExpectedConditions.
just to wait for my value to be stable?
Or what would you recommend?

Unfortunately there is no easy way to track whether page was refreshed or not, you could do smthn like ExpectedConditions.refreshed and ExpectedConditions.stalenessOf(WebElement). However the problem is, there is now way for webdriver to find out whether refresh already happened or it's going to happen in the future.
Best way to do it is to wait for smthn that actually changes to change, i.e. you're clicking button and see that state of button changes back and forth. Or maybe some other elements on page change? Also, be aware of the fact if page itself remains the same you may end up having StaleReferenceException in this case it'll be necessary to implement custom ExpectedCondition.
Alternatively you could try to do following things:
Wait for document.ready state
Wait for ajax state by checking jQuery.active state

Related

How to perform custom navigation through JFace Eclipse Wizard pages?

I have Eclipse JFace wizard with five pages. In the first, I have check buttons to select which pages are to be shown - if you check all, you will pass through the whole wizard, but you can also select only specific pages, and then only that pages will be shown.
So far, I used iterator with enum objects representing each page. I called next object of iterator in getNextPage function and its if..else cases to return certain pages in proper order. The problem is, getNextPage is called not only when Next button is pressed, but also when pageComplete event firing, etc. so iterator does not update its cursor when I want, and it ends up to fast. This is snippet of my assumption:
else if(page == FirstPage )
{
// iterator contains SelectedAction - enum objects representing pages
this.pageIterator = page.getWizardPagesList().iterator();
if(pageIterator.hasNext())
{
return selectedActionToPage(pageIterator.next());
}
}
else
{
if(pageIterator.hasNext())
{
SelectedAction action = pageIterator.next();
if(!pageIterator.hasNext())
{
// we check if current page was last one
setFinished(true);
setLastPage(selectedActionToPage(action));
}
// selectedActionToPage converts enum object to WizardPage class
return selectedActionToPage(action);
}
else if((pageIterator != null) && !pageIterator.hasNext())
{
return page;
}
}
return page;
Especially, things I want to know are:
First, is there any other way to capture Next button click? I know there is NextPressed method in WizardDialog class, but I don't know how to call its instance from my Wizard class, or WizardPage.
Second, is there other way to customize navigation through pages, to go to specified pages?
No, you should not try to intercept the Next button click that logic is private to the wizard dialog and you should not be trying to interfere with it,
You can either override the WizardPage:
public IWizardPage getNextPage()
method or you can override the Wizard
public IWizardPage getNextPage(IWizardPage page)
You may also need to override the matching getPreviousPage method. You must make your code work regardless of when the method is called. You are given the information about which is the current page, your code should use that to determine the next page.

Selenium - Text entered in same field, even though intended to type in different fields

Using selenium, when trying to enter username and password in login form, sometimes the text is entered on the same field. Username and password are having unique identifier.
For sending keys, the following steps are done.
sendKeys(By.id("login_username"), "abc");
sendKeys(By.id("login_password"), "efg");
public void sendKeys(By locator, String text) {
WebElement element = findElement(locator);
if(element != null) {
element.clear();
element.sendKeys();
}
}
public WebElement findElement(By locator) {
return wait(org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated(locator));
}
public WebElement wait(ExpectedCondition<WebElement> condition) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).pollingEvery(1, TimeUnit.SECONDS)
.withTimeout(60, TimeUnit.SECONDS)
.ignoreAll(Arrays.asList(NoSuchElementException.class, TimeoutException.class));
return wait.until(condition);
}
But somehow, when entering text, both the username and password texts are getting typed onto the password field. This is not happening always though. Not able to understand what could possibly go wrong or what to check. Any suggestions...
platform: Ubuntu 16.04.1 LTS 64-bit
chromedriver version: 2.25
chrome browser version: 55.0.2883.87
Thanks in advance.
The sendKeys() action performs the following steps:
Gets the coordinates of the element
Clicks at the coordinates it got (using a mouse action)
"Types" the text (that will be received by whatever element is currently focused)
It can go wrong if the element can't be focused when starting the action (because it's disabled for example), or if the coordinates change between getting the coordinates and clicking/focusing the element (because the layout is still changing).
Another common cause can be onClick action hooked on the element, that can lead to race conditions. Without seeing the actual page, it is possible that after selenium clicks, an onClick action is still working when the text is being typed. This basically looks like this:
Selenium clicks
onClick action starts (element might get focused only after it finishes)
Selenium starts typing (onClick haven't
returned yet, so the wrong elements gets the text)
the onClick
action finishes, but by that time Selenium finished too.
As a solution you can try focusing the element directly, and wait until it is really focused before sending the keys. This question might be of use for this case.

Selenium Web driver gets blocked after getting a popup from another popup (IE driver)

I'm facing an issue when application I'm testing is opening a second level popup (I mean, a popup that rises another popup). I'm using Selenium for Java, version 2.42.2, with IE Driver.
My code currently manages all other flows and single pop ups windows, but when a second level popup appears my webdriver object gets irresponsive and just stuck in any method that try to get invoked. When this happens, I need to manually close the popup window and then driver method continues the execution of invoked method.
Maybe it worth mentioning, if I call the second popup from the main page (not from another popup) I am able to manage it without problems, so the problem seems to be related with the number of nested windows more than a specific problem for the page.
Take a look on below code:
String url = "/example.jsp"
int counter = 0;
boolean windowDetected = false;
// Waiting until page with given url gets detected
// It tries 10 times before it continues
while (counter++ < 10 && !windowDetected) {
waitForSeconds(1); // Just invokes Thread.sleep method,
System.out.println("before getting handlers, iteration " + counter + " of 10");
Set<String> handlers = driver.getWindowHandles();
System.out.println("after getting handlers, number of handlers: " + handlers.size());
for (String handler : handlers) {
try {
System.out.println("Moving to " + handler);
driver.switchTo().window(handler);
}
catch (NoSuchWindowException e) {
System.out.println("Window not found, it probably redirected to a different window");
break;
}
if (driver.getCurrentUrl().contains(url)) {
windowDetected = true;
waitForPageLoading(); // It just verify current page status to be completed
break;
}
}
}
I am able to position properly the driver in specific window with above code in other application pages, but when having the second level popup it just hangs on line Set handlers = driver.getWindowHandles(); that is the first method called on driver object after popup appeared. Similarly, if I had called another driver method like driver.getPageSource() the same would have happened in that method.
I am not able to change application structure (my scope is only for testing it), so doing changes in web application code is not an option for me now. I have read on different options like trying Robot class, but I think it will be difficult to implement with more complex pages and difficult to maintain.
Any idea of how can I solve this issue? Many thanks in advance.
Best regards,
Alberto.
After taking a look on IEDriverServer changelog, moving to a newer version of this driver solved the issue. Previous was 2.24.2, and now using 2.44. A slightly different behavior but that accomplishes what I wanted

GXT 3 ToggleButtonCell not updating data store

I have a GXT 3 app and I'm trying to use a ToggleButtonCell to allow the user to modify a Boolean value.
Here's the code for the data:
public class InspectionListGridData {
private Boolean posted;
public InspectionListGridData(InspectionListGridData dataToCopy) {
setPosted(dataToCopy.getPosted());
}
public Boolean getPosted() {
return posted;
}
public void setPosted(Boolean posted) {
this.posted = posted;
}
}
For the grid to access the data, I provide this property access interface:
interface ListProperties extends PropertyAccess<InspectionListGridData> {
ValueProvider<InspectionListGridData, Boolean> posted();
}
The Grid & column config are declared like this:
final ListProperties properties = GWT.create(ListProperties.class);
final List<ColumnConfig<InspectionListGridData,?>> columnConfigList = new ArrayList<ColumnConfig<InspectionListGridData,?>>();
final ListStore<InspectionListGridData> store = new ListStore<InspectionListGridData>(
new ModelKeyProvider<InspectionListGridData>() {
#Override
public String getKey(InspectionListGridData item) {
return item.getInspectionDocumentId().toString();
}
}
});
final ColumnConfig<InspectionListGridData, Boolean> postedColumnConfig = new ColumnConfig<InspectionListGridData, Boolean>(properties.posted(), 5, "Posted");
ToggleButtonCell postedButtonCell = new ToggleButtonCell();
postedButtonCell.setText("posted");
postedButtonCell.setIcon(SafedoorPM.localizedResources.postedIcon());
postedButtonCell.setIconAlign(IconAlign.TOP);
postedColumnConfig.setCell(postedButtonCell);
postedColumnConfig.setSortable(false);
columnConfigList.add(postedColumnConfig);
Grid<InspectionListGridData> inspectionListGrid = new Grid<InspectionListGridData>(store, columnModel);
When I load this screen, the buttons do not initialize to the corresponding state indicated by the data. [EDIT: the failed loading of initial values was due to a different bug. Once I fixed that the initial values loaded correctly]
Once the screen is loaded, if I click a button it changes state just fine but the store doesn't get updated. I set breakpoint on the InspectionListGridData.setPosted() method, it is not called when I click on the button.
Can anyone see what I'm doing wrong? Or am I just wrong in thinking this is supposed to just work? I thought that was the point of the ValueProvider interfaces.
Bonus extra weirdness, the grid displays the red triangle in the corner to indicate that the cell is dirty when it is clicked and button does display properly when clicked i.e. it stays down or up. It just doesn't seem to read or update the data store.
Two questions here, at first I only keyed off of the first one (which I still can't answer, but more info might help), but the second is very clear.
When I load this screen, the buttons do not initialize to the corresponding state indicated by the data.
This is confusing, and contradicted by a quick sample I put together, as I indicated in my comment It could be that you are changing the data after drawing the grid and not informing the store or grid that the data has changed, but if you are building the data with both true and false values, the grid should be displaying with both true and false values.
I set breakpoint on the InspectionListGridData.setPosted() method, it is not called when I click on the button.
By default, this is expected while store.isAutoCommmit() is true, which is the default value. This tells the store that it should queue up changes rather than applying them directly to the objects in the store. These changed values are marked in the UI with the red triangle you noticed, and other code can check for changed values through the Store.getRecord(M) method or Store.getModifiedRecords() calls. Calling store.commitChanges() will apply all of them to the underlying models, or you can commit to specific models with Record.commit(). You can also reject changes with Store.rejectChanges() or Record.revert().
When this is turned off, the setPosted method should be called by clicking the button. No change tracking can occur, so no dirty flag will be set, either visually or in the store's records.
If you change an object that is already rendered, you have two (main) choices - you can modify the object directly via its setters and inform the store, or you can use the store's record objects. If autocommit is false and you invoke store.getRecord(object).addChange(properties.posted(), true), then instead of creating a new change to be committed, this will call setPosted(true), so these methods are effectively the same when autocommit is false. If you directly call a setter, be sure to inform the store that the object has changed via store.update.

How do you get selenium to recognize that a page loaded?

In certain unknown situations selenium does not detect that a page has loaded when using the open method. I am using the Java API. For example (This code will not produce this error. I don't know of an externally visible page that will.):
Selenium browser = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com");
browser.start();
browser.open("http://www.google.com/webhp?hl=en");
browser.type("q", "hello world");
When the error occurs, the call to 'open' times out, even though you can clearly see that the page has loaded successfully before the timeout occurs. Increasing the timeout does not help. The call to 'type' never occurs, no progress is made.
How do you get selenium to recognize that the page has loaded when this error occurs?
I faced this problem quite recently.
All JS-based solutions didn't quite fit ICEFaces 2.x + Selenium 2.x/Webdriver combination I have.
What I did and what worked for me is the following:
In the corner of the screen, there's connection activity indicator.
<ice:outputConnectionStatus id="connectStat"
showPopupOnDisconnect="true"/>
In my Java unit test, I wait until its 'idle' image comes back again:
private void waitForAjax() throws InterruptedException {
for (int second = 0;; second++) {
if (second >= 60) fail("timeout");
try {
if ("visibility: visible;".equals(
selenium.getAttribute("top_right_form:connectStat:connection-idle#style"))) {
break;
}
} catch (Exception e) {
}
Thread.sleep(1000);
}
}
You can disable rendering of this indicator in production build, if showing it at the page is unnecessary, or use empty 1x1 gifs as its images.
Works 100% (with popups, pushed messages etc.) and relieves you from the hell of specifying waitForElement(...) for each element separately.
Hope this helps someone.
Maybe this will help you....
Consider the following method is in page called Functions.java
public static void waitForPageLoaded(WebDriver driver) {
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
WebDriverWait wait = new WebDriverWait(driver,30);
try {
wait.until(expectation);
} catch(Throwable error) {
Assert.assertFalse(true, "Timeout waiting for Page Load Request to complete.");
}
}
And you can call this method into your function. Since it is a static method, you can directly call with the class name.
public class Test(){
WebDriver driver;
#Test
public void testing(){
driver = new FirefoxDriver();
driver.get("http://www.gmail.com");
Functions.waitForPageLoaded(driver);
}
}
When I do Selenium testing, I wait to see if a certain element is visible (waitForVisible), then I do my action. I usually try to use an element after the one I'm typing in.
Using 'openAndWait' in place of 'open' will do the trick.
From the website:
Many Actions can be called with the "AndWait" suffix, e.g. "clickAndWait". This suffix tells Selenium that the action will cause the browser to make a call to the server, and that Selenium should wait for a new page to load.
Enabling the 'multiWindow' feature solved the issue, though I am not clear why.
SeleniumServer(int port, boolean slowResources, boolean multiWindow)
SeleniumServer server = new SeleniumServer(4444, false, true);
Any clarification would be helpful.
I've run into similar issues when using Selenium to test an application with iFrames. Basically, it seemed that once the primary page (the page containing the iframes) was loaded, Selenium was unable to determine when the iframe content had finished loading.
From looking at the source for the link you're trying to load, it looks like there's some Javascript that's creating additional page elements once the page has loaded. I can't be sure, but it's possible that this is what's causing the problem since it seems similar to the situation that I've encountered above.
Do you get the same sort of errors loading a static page? (ie, something with straight html)
If you're unable to get a better answer, try the selenium forums, they're usually quite active and the Selenium devs do respond to good questions.
http://clearspace.openqa.org/community/selenium_remote_control
Also, if you haven't already tried it, add a call to browser.WaitForPageToLoad("15000") after the call to open. I've found that doing this after every page transition makes my tests a little more solid, even though it shouldn't technically be required. (When Selenium detects that the page actually has loaded, it continues, so the actual timeout variable isn't really a concern..
Not a perfect solution, but I am using this method
$t1 = time(); // current timestamp
$this->selenium->waitForPageToLoad(30);
$t2 = time();
if ($t2 - $t1 >= 28) {
// page was not loaded
}
So, it is kind of checking if the page was not loaded during the specified time, so it is not loaded.
another idea is to modify AJAX API (to add some text after AJAX actions).
After ajax action was finished, before return, set invisible field to TRUE, selenium will find it and read as green-light
in html:
<input type='hidden' id="greenlight">
in selenium
if(driver.findElement(By.id("greenlight")).getAttr("value").equals("TRUE")){
// do something after page loading
}
If you page has no AJAX, try to seek footer of page (I also use Junit fail(""), you may use System.err.println() instead):
element.click();
int timeout =120;
// one loop = 0.5 sec, co it will be one minute
WebElement myFooter = null;
for(int i=0; i<timeout; i++){
myFooter = driver.findElement(By.id("footer"));
if(myFooter!= null){
break;
}
else{
timeout--;
}
}
if(timeout==0 && myFooter == null){
fail("ERROR! PAGE TIMEOUT");
}

Categories

Resources