We're using Selenium WebDriver to test a form that has a double-post prevention behavior. There's some simple javascript that disables the button upon click, so that users won't accidentally post the same thing twice.
How do we test this?
The issues is that the button.click() blocks until the next page has loaded, at which point we certainly can't assert anything about the button on the previous page. Even if we were to somehow get the .click() to be non-blocking, there's an inherent race condition; if the browser/javascript is much faster than the test system, it will be able to unload the page before the test can assert anything about the button.
Bonus points for solutions without javascript injection hacks.
Based on the assumption that Esc cancels page loading in every browser and OS, this should work:
WebElement input = driver.findElement(By.tagName("input"));
input.sendKeys(Keys.ENTER, Keys.ESCAPE);
Assert.assertFalse(input.isEnabled());
It sends Enter and Esc to the button in rapid succession, so that the JavaScript is fired, but the page load has no chance of kicking in. The only problem I can see is that you won't be able to get to the next page with this test unless you refresh and send a new form. But we should only test one feature at a time anyway, so you're fine ;-).
EDIT (to address your comment)
Actually, yes! You can try to se send a click and the Esc key at the same time via The Advanced User Interactions API (JavaDocs). You can also achieve a nonblocking click this way.
Anyway, this approach still sends two requests which isn't the fastest imaginable thing to do, but it (sometimes barely) passes my test, so you might give it a try:
WebElement input = driver.findElement(By.tagName("input"));
new Actions(driver)
.click(input)
.sendKeys(input, Keys.ESCAPE)
.perform();
Test environment: IE8 and FF18 with a locally stored file and Selenium 2.29.1; Win XP SP3.
The test file looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<a href="http://google.com/">
<input type="button" value="Hello." onclick="this.disabled='true';" />
</a>
</body>
</html>
Related
I'm having difficulty testing a piece of code using NightwatchJS with Selenium and SafariDriver.
I have an open issue for this on nightwatch repo, although am not sure if it is an issue with nightwatch or something deeper.
The HTML content to be tested looks something like:
<body>
<iframe id="top-iframe" src="about:blank">
#document
<html>
<body>
<container>
<!-- access this iframe to test -->
<iframe id="nested-iframe" src="news.google.com"></iframe>
</container>
</body>
</html>
</iframe>
</body>
Where #nested-frame will need to be accessed from the top level document for inspection of content.
The test code is using NightwatchJS, more details about config, setup and code are in the GitHub issue.
The Gist of the issue:
The problem is that to access the nested iFrame, it needs to first find #top-frame web element, use the returned web element and pass it to frame which makes the WebDriver call to change context of test session to that frame. This is all good with Chrome, FF, and Safari as they can all find this frame web element and make the switch into the frame context. My test that Safari was changing iFrame context, although not sure how good it is, was to try and find another DOM element other than the nested frame, which it could find. The problem comes when with Safari, after switching into #top-frame, it cannot find the #nested-frame web element, and Nightwatch returns a 404 no such element from the HTTP call. Strange, right?
It is very puzzling, my latest thinking was maybe it was a cross origin issue. But then I read on WebDriver switch to frame:
NOTE WebDriver is not bound by the same origin policy, so it is always possible to switch into child browsing contexts, even if they are different origin to the current browsing context.
And I also tried checking Disable Cross Origin Restrictions from Safari Developer menu.
As mentioned before, I can find another DOM element in the #top-frame. I tried things like 10-15s timeouts thinking maybe it needed to load. I can inspect the browser with debugger and see that #nested-frame is there and the content loads as expected. There are not console errors indicating any content failed to load.
It's very puzzling to me and I'm not sure how to further debug. Maybe someone else with a fresh perspective could have a suggestion or if someone has run into a similar situation as this. Throwing this out into the universe as information is limited on the topic too, so maybe this could help someone else. TIA!
iframes
As per the documentation iframe is a construct which embeds a document into an HTML document so that embedded data is displayed inside a subwindow of the browser's window. This does not mean full inclusion and the two documents are independent, and both them are treated as complete documents, instead of treating one as part of the other.
iframe structure and details
Generally, an iframe element is in the form of:
<iframe src="URL" more attributes>
alternative content for browsers which do not
support iframe
</iframe>
Browsers which support iframe display the document referred to by the URL in a subwindow, typically with vertical and/or horizontal scroll bars. Such browsers ignore the content of the iframe element (i.e. everything between the start tag <iframe...> and the end tag </iframe>). Browsers which do not support iframe (or have such support disabled) does the opposite, i.e. process the content as if the <iframe...> and </iframe> tags were not there. Thus, the content matters, despite being ignored by some browsers.
This usecase
As the top-level <iframe> is having src="about:blank" it is highly unlikely there can be any child <iframe>. Hence, in absence of any child <iframe> your attempt to access any nested <iframe> will fail.
Reference
You can find a relevant detailed discussion in:
Ways to deal with #document under iframe
After discussion with Selenium team, this appears to be a bug with Apple.
I have filed a ticket with Apple here.
I would like to use selenium to test a webpage where the initial html contents builds up in a "streaming" fashion.
As simple example, assume that the webpage html is
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
<p id="p1">foo</p>
<p id="p2">bar</p>
</body>
</html>
and that the
webserver sends everything up to including #p1 immediately, then waits for 10s, then sends the rest of the page.
I would basically like to open that page in selenium, "manually" wait until the id #p1 exists,
check that foo is in the page text (or html) so far but bar is not; wait for 10s and then check that bar is here.
It seems that this is not covered by "Page loading strategy": According to the docs (and to my attempt), even none "waits until the initial page is downloaded".
Question: Is there a "Page loading strategy" that allows me to continue before the html is loaded? Or is there some option for / alternative to the usual navigation command that lets me immediately continue with selenium? (Such as: Instead of navigate to the page, simulate entering the url in the address bar and pressing return, or whatever..)
As a work around . We can interrupt the loading of page by using page load timeout
Page load timeout - Provides the timeout limit used to interrupt an explicit navigation attempt.
By Default value is set to '300,000' milliseconds
In Java
driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.SECONDS);
driver.get("url")
driver.get() - > It will throw timeout exception if page is not loaded in 1 second. You can catch the exception and continue with other operations.
I am a javascript dummy. I downloaded colorbox and jquery. They work great. I followed tutorials and read the example code but I cant figure this out.
When I open a colorbox ,it opens to the correct url, I can then click links in the box and surf other sites. That is all great. I need to have the url show in a address block at the top of the window. When I use a java popup it will work fine. You can goto other urls and the address shows in the address bar at the top of the window.
So I assume that I can do it with colorbox. This would make my page look much better than a plain popup. Can this be done. here is my code.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"> </script>
<script src="http://www.mysite.com/colorbox/jquery.colorbox.js"></script>
<link rel="stylesheet" href="http://www.mysite.com/colorbox/colorbox.css" />
<script>
parent.jQuery.colorbox.close();
$(function ()
{
$(".iframe").colorbox({iframe:true, width:"80%", height:"80%"});
})
</script>
and my link to open the box
<a class='iframe' href="http://www.ebay.com">ebay </a></p>
If you chooes to help I beg you to show me where the new code go's. If you tell me to add a line of code I will not understand where to put it. I am trying hard to learn javascript but I am a very newbe. Thanks.
I don't think ColorBox is the right plugin for you to use, given its default design and your skill set. ColorBox is not designed to be "browser like" and let the user surf to other sites.
It is possible to change that design assumption, but it would require more advanced JS skills than you admit to.
Maybe you can achieve your aim by simply opening a new browser instance using a plain HTML anchor tag (<a>) and using the "target=" parameter.
Best,
KJM
I have decided to have some fun with VB.NET and make a bot for some online games.
First of all, I plan on viewing the game through a webview control, which I believe is perfectly possible... unless I can't see Flash/Java content?
If it is possible, I've been wondering how would you "simulate a click" in the web view control? And, of course, keyboard input?
Perhaps a little late and I have no experience with VB.NET but to work with keys on a web page you need to use Javascript. For example:
<html>
<head>
<script>
document.onkeyup = function(event){ console.log(event); };
</script>
</head>
<body>
press a key within this document.
</body>
</html>
Cursor keys don't generate a keypress event hence the use of onkeyup. Also note it's lowercase. onKeyUp is not correct. If you're using Chrome or Firefox console.log will output the object that you can inspect. Not sure about IE but I think later versions support this too. Properties and methods can be used to get the keycode, character and any modifiers.
This code was tested on Chrome 12 beta. There are differences between IE and other browsers (as usual). This page shows an example of some of the differences: http://www.w3schools.com/jsref/event_onkeypress.asp
Not sure what you mean by "simulate a click" but I suspect you're not referring to testing.
Try for WatiN, its like testing a web application
Solution:
Today (2011-04-13) handles Selenium RC the confirmation boxes under Firefox 4 badly.
I had to change back to Firefox 3.16 and then this problem disappears. Thanks again.
Original Question:
Hello Selenium gurus,
I am trying to execute an automated browser test from Java using Selenium 2.0b3 as the Java client and standalone server too.
The server starts a Firefox 4 with a specific profile.
The test is stuck at a "click" command; it waits and no timeout/exception/any error happens. During this click comes up a confirmation box, so I guess that is the problem, but I do not know why this gets stuck. In Selenium IDE comes not this confirmation box, only in RC.
The problem is not that, that the click does not happens (because the confirmation box appears), but that this confirmation box hangs.
I tried these but did not help:
selenium.click("css=div[id=command_Delete]");
selenium.click("id=command_Delete");
String JSscript = "jQuery('#command_Delete').click();" // See http://api.jquery.com/click/
selenium.runScript(JSscript);
These are just ways how to start the click.
Maybe I have to start a different Thread according these link: http://www.sqaforums.com/showflat.php?Cat=0&Number=567974&an=&page=0&vc=1
Thanks: Andras
Java code:
selenium.click("//div[#id='command_Delete']/span");
//stucks here
//so this is not reached:
String confirmation = selenium.getConfirmation();
HTML:
<div id="command_Delete" class="...">
<div>...</div>
<span>Delete</span>
<div>...</div>
<br><br>
</div>
Javascript:
<script type="text/javascript">
$('command_Delete').addEvent('click',function(){
var isConfirmTrue = confirm('Do you want to delete?');
if (isConfirmTrue) {
var myForm = getFormObj(document, "deleteForm");
submitForm(myForm);
}
});
</script>
And in the Java, it hangs waiting the selenium rc to answer:
HttpURLConnection.getInputStream() line: 912 [local variables unavailable]
HttpURLConnection(HttpURLConnection).getResponseCode() line: 367 [local variables unavailable]
HttpCommandProcessor.getResponseCode(HttpURLConnection) line: 147
HttpCommandProcessor.getCommandResponseAsString(String) line: 167
HttpCommandProcessor.executeCommandOnServlet(String) line: 107
HttpCommandProcessor.doCommand(String, String[]) line: 89
DefaultSelenium.click(String) line: 167
...
Have you tried replacing
selenium.click("//div[#id='command_Delete']/span");
with
selenium.click("id=command_Delete");
?
It seems to me that since the event is binded to the div itself that should work.
Additionally, you can execute the click action directly by doing this, I'm using jQuery since you seem to already have it loaded on the page and it makes things easier (especially for cross-browser testing):
String JSscript = "jQuery('#command_Delete').click();" // See http://api.jquery.com/click/
selenium.runScript(JSscript);
You'd just need to evaluate if this solution is good for you.
If a confirmation box is popping up the test will block until that confirmation box has been removed. You can do a quick manual test to see if this is your problem.
Run your test and when the confirmation box comes up manuall y interact with it, if everything else is fine the test should continue from that point as per normal.
Selenium is waiting for the page to load, but the pop up box is blocking the page from loading which is eventually resulting in a timeout.
You can try and work around this using selenium.chooseOkOnNextConfirmation(); before your click.
Are you sure your widget can afford a click?
I would try the CSS identifier:
selenium.click("css=div[id=command_Delete]");