selecting pulldown in htmlunit - java

I am using htmlunit in jython and am having trouble selecting a pull down link. The page I am going to has a table with other ajax links, and I can click on them and move around and it seems okay but I can't seem to figure out how to click on a pulldown menu that allows for more links on the page(this pulldown affects the ajax table so its not redirecting me or anything).
Here's my code:
selectField1 = page.getElementById("pageNumSelection")
options2 = selectField1.getOptions()
theOption3 = options2[4]
This gets the option I want, I verify its right. so I select it:
MoreOnPage = selectField1.setSelectedAttribute(theOption3, True)
and I am stuck here(not sure if selecting it works or not because I don't get any message, but I'm not sure what to do next. How do I refresh the page to see the larger list? When clicking on links all you have to do is find the link and then select linkNameVariable.click() into a variable and it works. but I'm not sure how to refresh a pulldown. when I try to use the webclient to create an xml page based on the the select variable, I still get the old page.
to make it a bit easier, I used htmlunit scripter and got some code that should work but its java and I'm not sure how to port it to jython. Here it is:
try
{
page = webClient.getPage( url );
HtmlSelect selectField1 = (HtmlSelect) page.getElementById("pageNumSelection");
List<HtmlOption> options2 = selectField1.getOptions();
HtmlOption theOption3 = null;
for(HtmlOption option: options2)
{
if(option.getText().equals("100") )
{
theOption3 = option;
break;
}
}
selectField1.setSelectedAttribute(theOption3, true );

Have a look at HtmlForm getSelectedByName
HtmlSelect htmlSelect = form.getSelectByName("stuff[1].type");
HtmlOption htmlOption = htmlSelect.getOption(3);
htmlOption.setSelected(true);

Be sure that WebClient.setJavaScriptEnabled is called. The documentation seems to indicate that it is on by default, but I think this is wrong.
Alternatively, you can use WebDriver, which is a framework that supports both HtmlUnit and Selenium. I personally find the syntax easier to deal with than HtmlUnit.

If I understand correctly, the selection of an option in the select box triggers an AJAX calls which, once finished, modifies some part of the page.
The problem here is that since AJAX is, by definition, asynchronous, you can't really know when the call is finished and when you may inspect the page again to find the new content.
HtmlUnit has a class named NicelyResynchronizingAjaxController, which you can pass an instance of to the WebClient's setAjaxController method. As indicated in the javadoc, using this ajax controller will automatically make the asynchronous calls coming from a direct user interaction synchronous instead of asynchronous. Once the setSelectedAttribute method is called, you'll thus be able to see the changed made to the original page.
The other option is to use WebClient's waitForBackgrounfJavascript method after the selection is done, and inspect he page once the background JavaScript has ended, or the timeout has been reached.

This isn't really an answer to the question because I've not used HtmlUnit much before, but you might want to look at Selenium, and in particular Selenium RC. With Selenium RC you are able to control the interactions with a page displayed in a native browser (Firefox for example). It has developer API's for Java and Python amongst others.
I understand that HtmlUnit uses its own javascript and web browser rendering engine and I'm wondering whether that may be a problem.

Related

Customize the browser icon when running a Selenium session?

I have some Selenium sessions where, if certain events occurs, I spawn a new browser and leave the old one as is so I later on can manually intervene. The problem is that it is hard to distinguish between such a deserted browser session and the one that is currently running.
Ideally I would like to add a badge to the browser icon that is displayed in the application switcher (cmd-tab) and the dock (but other solutions/suggestions are also welcome, like add something to the name of the browser). Is that possible?
Using Java on a Mac. A solution can be platform specific.
You can use below execute_script (This python code use java equalent)
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get(
"https://stackoverflow.com/questions/9943771/adding-a-favicon-to-a-static-html-page")
head = driver.find_element_by_tag_name("head")
link = driver.find_element_by_css_selector('link[rel="shortcut icon"]')
driver.execute_script('''var link = document.createElement("link");
link.setAttribute("rel", "icon");
link.setAttribute("type", "image/png");
link.setAttribute("href", "https://i.stack.imgur.com/uOtHF.png?s=64&g=1");
arguments[1].remove();
arguments[0].appendChild(link);
''',head,link)
time.sleep(70000)
you can use link element on head tag to add favicon. THe above code is an exaple where stackoverflow site will showup with my avatar
Output:
You should find the current link the website uses, remove it and replace it with your new link as shown in the code

replacing Result's html

I have an URL which shows me a coupon form based on id:
GET /coupon/:couponId
All the coupon forms are different and submit different POST params to:
POST /saveCoupon/:id
I want to have a convenient way of debugging my coupons and be able to have a way of viewing actual POST params submitted.
I've made a controller on URL POST /outputPOST/saveCoupon/:id which saves nothing, but prints to browser POST params received.
Now I want to have an URL like GET /changeActionUrl/coupon/:couponId which calls GET /coupon/:couponId and then substitutes form's action URL POST /saveCoupon/:id with POST /outputPOST/saveCoupon/:id .
In other words I want to do something like:
Result.getHtml().replace("/saveCoupon/","/outputPOST/saveCoupon/");
With this I can easily debug my coupons just by adding "/outputPOST" in the browser.
You could just use a bookmarklet and javascript to replace all of the forms' action attributes. That way your developer can do it with one click instead of changing urls.
Something like this will prefix all form actions on the page with "/outputPOST".
javascript:(function(){var forms=document.getElementsByTagName('FORM');for(i=0;i<forms.length;++i){forms[i].setAttribute('action','/outputPOST'+forms[i].getAttribute('action'));}})();
I don't understand, at least not everything ;)
In general you can debug every piece of Play app using debugger (check for your favorite IDE tips how to do that) - this will be always better, faster, etc etc, than modifying code only for checking incoming values.
I.e. Idea 13+ with Play support allows for debbuging like a dream!

Java ScriptEngine and parent window functions

I am using the Java ScriptEngine to call a JS function from a backing bean under certain conditions in the program. The catch is that the JSF page is running in an iFrame. Although the iFrame is not the real problem at this stage, I want it to be able to browse to a new page. For this, I have used top.window.location and parent.location and they work on a button click to load the page out of the iFrame without a problem.
This is a sample of the code I'm using for this:
ScriptEngine se = new ScriptEngineManager().getEngineByName("JavaScript");
se.eval("function someFunc(){parent.location = \"www.someurl.com\";}");
Invocable invocableJS = (Invocable) se;
invocableJS.invokeFunction("someFunc");
With parent.location and top.window.location I have read that they are called from the browser itsself, and are not JavaScript. So because of this, I get the following error:
javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "parent" is not defined. (<Unknown source>#1) in <Unknown source> at line number 1
It does exactly the same with document.getElementById("someComponent") and other similar. And it seems that the error remains with sun.org.mozilla..... in Chrome, IE, and FF all together.
So the question: How can I get the JS function to possibly use the parent.location? I imagine that I would need to check for the browser used and then import or call something from there depending on the browser, but I am not sure how I should go to work to do this. Any light that can possibly be shed on this problem will be very helpful.
Thanks in advance.
I have solved this problem, by checking for the cookies before the redirect in a Javascript method, and simply calling the JS method before the page loads using onload="someMethod();" in the body tag. Everything worked out fine, by using the parent.location to navigate to the new page. Tested in FF, Chrome and IE. Thus there was also no need for the ScriptEngine in this situation.

Hard Refresh in GWT

Using Google Web Toolkit, I'd like to code the equivalent of a hard refresh (control + F5).
I don't believe (or know) if GWT's Window.Location will work.
import com.google.gwt.user.client.Window.Location;
Window.Location = currentPage; // I don't think it'll be hard refresh
For reloading the current page you need to call Window.Location.reload() method.
Reloads the current browser window. All GWT state will be lost.
Or you can even specify your own JSNI (below how todo), because by default force reload is false :
public static native void forceReload() /*-{
$wnd.location.reload(true);
}-*/;
According to https://developer.mozilla.org/en-US/docs/DOM/window.location#Methods you would need to call window.location.reload(true) to force the reload of the current page.
Unfortunately GWT wraps only the window.location.reload() via Window.Location.reload(), and it is up to the browser to retrieve the page from the cache or from another get. This is done to achieve the most cross-browser solution.
Never tried but you should be able to use the following.
public static native void reload(boolean force) /*-{
$wnd.location.reload(force);
}-*/;
For reload gwt page, you have two options:
1) Window.Location.reload();
Reloads the current browser window. All GWT state will be lost.
2) Window.Location.replace("newurl");
Replaces the current URL with a new one. All GWT state will be lost. In the browser's history, the current URL will be replaced by the new URL.

How to deal with file uploading in test automation using selenium or webdriver

I think that everybody who uses Webdriver for test automation must be aware of its great advantages for web development.
But there is a huge issue if file uploading is part of your web flow. It stops being test automation. The security restriction of browsers (invoking file selection) practically makes it impossible to automate tests.
Afaik the only option is to have Webdriver click the file upload button, sleep the thread, have developer/tester manually select the file, and then do the rest of the web flow.
How to deal with this, is there a workaround for it? Because it really can't be done like this. It wouldn't make sense.
This is the only case I know of when browser security restrictions do not apply:
<script language=javascript>
function window.onload(){
document.all.attachment.focus();
var WshShell=new ActiveXObject("WScript.Shell")
WshShell.sendKeys("D:\MyFile.doc")
}
</script>
Webdriver can handle this quite easily in IE and Firefox. Its a simple case of finding the element and typing into it.
driver = webdriver.Firefox()
element = driver.find_element_by_id("fileUpload")
element.send_keys("myfile.txt")
The above example is in Python but you get the idea
Using AWT Robots is one option, if you're using Java, which you are. But it's not a good option, it is not very dependable, and not clean at all. Look here
I use HttpClient and run a few tests outside of Selenium. That's more dependable and cleaner.
See the code below. You'll need more exception handling and conditionals to get it to suit your job.
HttpClient c = new HttpClient();
String url = "http://" + cargoHost + ":" + cargoPort + contextPath + "/j_security_check";
PostMethod post = new PostMethod(url);
post.setParameter("j_username", username);
post.setParameter("j_password", password);
c.executeMethod(post);
url = "http://" + cargoHost + ":" + cargoPort + contextPath + "/myurl.html";
MultipartPostMethod mPost = new MultipartPostMethod(url);
String fileNameWithPath = this.getClass().getClassLoader().getResource(filename).getPath();
File f1 = new File(fileNameWithPath);
mPost.addParameter(elementName, f1);
mPost.addParameter("action", "upload");
mPost.addParameter("ajax", "true");
c.executeMethod(mPost);
mPost.getResponseBodyAsString();
The suggestion of typing into the text box works only if the textbox is enabled.
Quite a few applications force you to go through the file system file browser for obvious reasons.
What do you do then?
I don't think the WebDriver mavens thought of just presenting keys into the KeyBoard buffer (this used to be a "no brainer" in earlier automation days)
===
After several days of little sleep, head banging and hair pulling I was able to get some of the Robot-based solution suggested here (and elsewhere).
The problem i encountered was that the dialog text box that was populated with the correct file path and name could not respond to the KeyPress/Release Events of terminating the file name with VK_ENTER as in:
private final static int Enter = KeyEvent.VK_ENTER;
keyboard.keyPress(Enter);
keyboard.keyRelease(Enter);
What happens is that the file path and file name are typed in correctly but the dialog remains opened - against my constant hoping and praying that the key emulation will terminate it and get processed by the app under testing.
Does anyone know how to get this robot to behave a bit better?
Just thought I'd provide an FYI to author's original post of using ActiveX. Another workaround would be to integrate with desktop GUI automation tools to do the job. For example, google "Selenium AutoIt". For a more cross-platform solution, consider tools like Sikuli over AutoIt.
This of course, is not considering WebDriver's support for uploads on IE & Firefox via SendKeys, or considering for other browsers where that method doesn't work.
After banging my head on this problem for far too many hours, I wanted to share with the community that Firefox 7.0.1 seems to have an issue with the FirefoxDriver sendKeys() implementation noted above (at least I couldn't get it to work on my Windows 7 x64 box), I haven't found a workaround, but updating to Firefox 8.0.1 seems to have fixed the problem. For those of you wondering, it's also possible to use Selenium RC to solve this problem (though you need to account for all of your target operating systems and the native key presses required to interact with their file selection dialogs). Hopefully the issues I had to work around save other people some time, in summary:
https://gist.github.com/1511360
If you have your are using a grid, you could make the folder of the testfiles open for sharing.
This way you could select the upload input field and set its value to \\pc-name\myTestFiles
If you're not, you should go with local files on each system.

Categories