Selenium: Do not wait even for initial html - selenium

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.

Related

NightwatchJS: Safari can't find nested iFrame

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.

dynamic HTML with worklight?

Is there any way to perform "last minute" substitutions in the HTML (or other) resources that are part of your worklight application?
For example, I want to set the lang and dir attribute on the <html> element based on the end-user's locale.
some background:
I realize I can do dynamic DOM manipulation, but my question comes more from a background of client-server architecture where you have an opportunity on the server-side to replace some variables etc. in your HTML (or other resources) based on the requester's context. We have an existing app already and I'm investigating what it would take to integrate it with worklight including (for performance reasons) moving files from the server-side to the client-side without incurring too much refactoring of the current code.
Update: per the edit to your question, I don't think the below will make any significant impact on your app. Since you say you may move files from the server to client, this means like network traffic and with today's devices I suspect this may even be a boost to the performance rather than a penalty.
My suggestion is to try the below if the above is what you're planning to do.
I'm not even sure how else would you even do that from the server - change the application's UI based on the user's device local's, from the server. Doesn't make much sense to me to do that remotely.
To answer your question, I'll provide some background information that is relevant, I think, to a good user experience in this kind of scenario (as I see it):
By default, Worklight dismisses the splash screen once the framework has finished loading.
However, if you're using Worklight 6.2 then you can use the extended Splash Screen feature to display the splash screen for a longer duration, and during that time you could perform the required tasks -- like altering the UI based on the user's locale. Once you're done, you can then programmatically dismiss the splash screen on your own.
Reading materials:
Common UI Controls training module (slide #29)
Managing the splash screen user documentation topic (for both JS and Native support)
Example:
You need to uncomment the following in common\js\initOptions.js:
// # To disable automatic hiding of the splash screen uncomment this property and use WL.App.hideSplashScreen() API
//autoHideSplash: false,
You can then dismiss the splash screen when ready:
function wlCommonInit() {
function changeUiBasedOnLocale();
...
...
}
function changeUiBasedOnLocale() {
... // get device local
... // use JS to alter CSS
WL.App.hideSplashScreen();
}
Any basic DOM manipulation will help. Here is one example with D3.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script type="text/javascript" src="d3.js"></script>
</head>
<body>
<script type="text/javascript">
d3.select("html").attr("lang","en_EN");
</script>
</body>
</html>

How to handle many bootstrap modals on a single html page

I would have 10 bootstrap buttons on a single html page.
Each button opens a ootstrap modal filled with a html fragmen via an ajax request.
<div class="modal fade" id="myModal"></div>
$('#myModal').modal();
Should I create 10 different divs with 10 different ids? Or even 10 different instances?
var dialogInstance1 = new BootstrapDialog({
title: 'Dialog instance 1',
message: 'Hi Apple!'
});
or
should I create ONE dialog?
I would expect kind of caching problems when I open modal1, then just when I open modal2 I see still for some miliseconds modal1 html fragment from a prvious ajax request.
And how should I create those modals? The samples should this:
$('#myModal').modal();
and the instantiation? This is very confusing.
Can someone please share his experience how to approach with many bootstrap modals?
I would expect kind of caching problems when I open modal1, then just when I open modal2 I see still for some miliseconds modal1 html fragment from a prvious ajax request.
Assuming you're referring to data-remote's caching, you will probably be able to disable that in Bootstrap v3.2.0 (see https://github.com/twbs/bootstrap/pull/13183/ ).
However, I'd still recommend against using data-remote since it doesn't give you much control. It:
doesn't provide or easily let you do any error handling
doesn't give any "loading..." indication
forces you have to generate modal HTML on the server side (as opposed to, e.g., returning JSON from the server and using client-side templating)
IMO, you should:
include just one instance of the blank modal markup
setup your own click event handlers on the buttons that summon your modal
initiate the AJAX request in your click event handler
use client-side templating to generate a corresponding modal using the results of the request
use $(...).modal() or $(...).modal('show') (depends on how your templating works) to show the modal after the templating completes

selenium: test "disable on submit" behavior

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>

Re-captcha's widget buttons reload the whole page

I have Google's re-captcha implemented and working in Chrome perfectly (AJAX APIs). IE is the problem...
I have: localhost://myapp/index.html and a link for Forgot your password. When this link is clicked jQuery click handler is called. Handler function changes the div's content and also calls for Recaptcha.create(...) The widget is displayed correctly and works as expected in Chrome, but in IE if I click on reload icon or the sound button it reloads the whole page.
If I manually call for Recaptcha.reload() it reloads without any problem ?!
HTML I have is:
<div id="recaptcha" style="width:120px"></div>
[...]
<script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
[...]
//In a jquery click handler I call
Recaptcha.create("6LxxxxxxxxxxxxxxxxxxxxxxIrpV5RO8P",
"recaptcha",
{
theme:'white',
callback: Recaptcha.focus_response_field
}
);
So far so good... Captcha gets loaded well in all browsers. In IE8 and 9 when I click the widgets buttons for reload and mp3 version the whole page gets reloaded
I tried changing http for https and vice-versa, but still without any luck...
When Recaptcha.create(); is called, Google's re-captcha RELOAD and IMAGE/TEXT buttons' code looks something like this:
<a href="javascript:Recaptcha.reload();">
and I don't know why the page gets reloaded in my app in IE when the button is pressed and in the demo Google provided DEMO it sends a async request...
Since I can't change the javascript in href attribute I had to add a onclick handler in jQuery $(document).ready();
My solution was this:
$("#recaptcha).on("click", "id_of_the_reload_button", function(e){
e.preventDEfault();
Recaptcha.reload();
});
I basically blocked the natural behavior of the anchor google provides and called the reload() function myself.
I've never found out what was causing my page to reload in the first place