Selenium: how to wait for RichFaces ajax requests to complete - ajax

I use selenium to test a JSF/RichFaces application. The tests randomly fail due to 'Element not found' errors. This is as described in Selenium: intermittent “element not found” issues, but it relates only to jQuery ajax calls.
The challenge here is to make the selenium test execution wait for all ajax requests to complete using selenium.waitForCondition(jsExpression, timeout). What is the best jsExpression when using RichFaces ajax calls?

I investigated the generated html for the a4j:status. The code below does the job for now, it's better than wait() statements, but I'm looking for a better solution.
// depends on <a4j:status> present in the page under test
selenium.waitForCondition(
"selenium.browserbot.getCurrentWindow().document.getElementById(
"_viewRoot:status.start\").style.display == 'none'",
"3000");

I once found myself in the same situation as you. Additionally, I had a lot of elements that were actually found, but weren't visible - JSF wasn't quick enough to make them visible yet. Also, I got tired of writing selenium again and again.
So I sat down and wrote the code below. It waits for all elements to be present on the page and visible before interacting with them (or fails after a timeout). I have since moved to WebDriver, so I don't have the original code, but it was something like this:
public static long WAIT = 10000; // ten seconds
private void waitForElement(String locator) {
long targetTime = System.currentTimeMillis() + WAIT;
boolean found;
do {
found = selenium.isElementPresent(locator) && selenium.isVisible(locator);
} while (!found && (targetTime < System.currentTimeMillis()));
if (!found) {
throw new SeleniumException("Element " + locator + " not found");
}
}
public void click(String locator) {
waitForElement(locator);
selenium.click(locator);
}
public void type(String locator, String text) {
waitForElement(locator);
selenium.type(locator, text);
}
As for waitForCondition() this should be a code detecting whether an element exists or not:
String locator = "id=anything";
String script =
"var retValue = true;" +
"try {" +
" selenium.browserbot.findElement('" + locator + "');" +
"} catch(e) {" +
" retValue = false;" +
"}" +
"retValue;";
selenium.waitForCondition("!!selenium.browserbot.findElement('" + locator + "')", "10000");
selenium.click(locator);
and just the plain JavaScript:
var retValue = true;
try {
selenium.browserbot.findElement('" + locator + "');
} catch(e) {
retValue = false;
}
retValue;

Related

How to paste the text copied in clipboard through Selenium and Java on MacOS

I want to paste some text in one of the textbox in MACOS. I am trying below code. But Control + v and Command + v both are not working. I have also seen that this is known issue, but not sure if it is resolved or not.
https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/5919
The code is as below.
public void copyToClipbord(String copyTo)
{
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection str = new StringSelection(copyTo);
clipboard.setContents(str, null );
}
// And paste into required input/testfield/testarea field object
public void pasteText(WebElement element, String value)
{
copyToClipbord(value);
element.click();
//new Actions( driver ).contextClick( element ).sendKeys( "P" ).sendKeys("\n").perform();
element.sendKeys(Keys.CONTROL, "V");
}
I have also tried context click, that also does not work. I have validated that copyToClipboard function is working properly. Please suggest me, if there are any work around to this.
Thanks,
Umang
You have to select paste option in pop up which open after right and then click on paste option.
You can write code like this.
new Actions(driver ).contextClick(element).sendKeys(Keys.ARROW_DOWN)
.sendKeys(Keys.ARROW_DOWN)
.sendKeys(Keys.ARROW_DOWN).sendKeys(Keys.ARROW_DOWN).
sendKeys(Keys.ARROW_DOWN).sendKeys(Keys.ENTER).perform();
For me Paste option is present at 5th position. So I have written sendKeys(Keys.ARROW_DOWN) 5 times. You can write this as per your requirement.
I hope this will work for you.
As you have mentioned copyToClipboard() function is working properly moving forward to send the character sequence through sendKeys() you can use the following solution:
import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
copyToClipbord(value);
String data = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
element.sendKeys(data);
public String copyFromClipboard() {
boolean found = false
String data = ''
int count = 0
while (found == false) {
count++
try {
WebDriver driver = DriverFactory.getWebDriver()
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
data = ((Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor)) as String)
if (!(data.contains('https'))) {
found = false
} else {
println((('Found the data in the ' + count) + ' try: ') + data)
return data
found = true
break
}
}
catch (UnsupportedFlavorException e) {
println(e)
}
catch (IOException e) {
println(e)
}
}
}

Xamarin.Forms Sip: 'Internal server error 500' When Placing Outgoing Calls

I am using Linphone SDK in Xamarin.forms project for the sip calling. I am able to make the connection using following code:
var authInfo = Factory.Instance.CreateAuthInfo(username.Text,
null, password.Text, null, null,domain.Text);
LinphoneCore.AddAuthInfo(authInfo);
String proxyAddress ="sip:"+username.Text+"#192.168.1.180:5160";
var identity = Factory.Instance.CreateAddress(proxyAddress);
var proxyConfig = LinphoneCore.CreateProxyConfig();
identity.Username = username.Text;
identity.Domain = domain.Text;
identity.Transport = TransportType.Udp;
proxyConfig.Edit();
proxyConfig.IdentityAddress = identity;
proxyConfig.ServerAddr = domain.Text + ":5160;transport=udp";
proxyConfig.Route = domain.Text;
proxyConfig.RegisterEnabled = true;
proxyConfig.Done();
LinphoneCore.AddProxyConfig(proxyConfig);
LinphoneCore.DefaultProxyConfig = proxyConfig;
LinphoneCore.RefreshRegisters();
After Successful connection, I am using the code for placing the code.
if (LinphoneCore.CallsNb == 0)
{
string phoneCall = "sip:"+address.Text+ "#192.168.1.180:5160";
var addr = LinphoneCore.InterpretUrl(phoneCall);
LinphoneCore.InviteAddress(addr);
}
else
{
Call call = LinphoneCore.CurrentCall;
if (call.State == CallState.IncomingReceived)
{
LinphoneCore.AcceptCall(call);
}
else
{
LinphoneCore.TerminateAllCalls();
}
}
And the listener that is listening to call state changed event is as:
private void OnCall(Core lc, Call lcall, CallState state, stringmessage)
{
call_status.Text = "Call state changed: " + state;
if (lc.CallsNb > 0)
{
if (state == CallState.IncomingReceived)
{
call.Text = "Answer Call (" + lcall.RemoteAddressAsString + ")";
}
else
{
call.Text = "Terminate Call";
}
if (lcall.CurrentParams.VideoEnabled) {
video.Text = "Stop Video";
} else {
video.Text = "Start Video";
}
}
else
{
call.Text = "Start Call";
call_stats.Text = "";
}
}
The call status is giving 'Internal Server Error'. I am able to receive the calls using Linphone or X-lite Soft Phone in my code, But I am not able to place the calls. I don't know whether this issue is related to server or it is related to my code. Please suggest.
Internal Server Error (HTTP Status code 500) means that an unexpected error occurred on the server. So I would suspect the problem is rather there than with your app's code.
500 - A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
It could be that your request doesn't satisfy the expectations of the endpoint you are calling, but even then, the server should then respond with a more meaningful error, than crashing with 500.

could not complete operation due to error c00ce514

I have this code as an excel downloader. After the excel has been generated.
But I'm having an error. As stated in the question Title.
The error occurs at the line:
var strResponeText = XMLHttpRequestObject.responseText;
var strUrl = "POSSellThroughReportExcelOpener.aspx?getstatus=1&DateFrom=" + hdnDateFrom.value + "&DateTo=" + hdnDateTo.value + "&customer_id=" + hdnCustomerID.value + "&intdisplayby=" + hdnDisplayBy.value + "&monthorweek=" + hdnMonthOrWeek.value;
if (XMLHttpRequestObject) {
XMLHttpRequestObject.open("POST", strUrl);
XMLHttpRequestObject.onreadystatechange = function () {
if ((XMLHttpRequestObject.readyState == 4) && (XMLHttpRequestObject.status == 200)) {
var hdnRedirectUrl = document.getElementById("hdnRedirectUrl");
var strResponeText = XMLHttpRequestObject.responseText;
var intResponse = new Number(strResponeText);
var spanCallBackStatus = document.getElementById("spanCallBackStatus");
var trClose = document.getElementById("trClose");
if (!isNaN(intResponse)) {
if (intResponse == 1) {
spanCallBackStatus.innerHTML = "Excel Report has been generated."
trClose.style.display = "";
Init();
window.location.href = hdnRedirectUrl.value;
}
else {
GetStatus();
}
}
else {
spanCallBackStatus.innerHTML = strResponeText;
}
}
}
XMLHttpRequestObject.send(null);
}
Any help is greatly appreciated.
Many thanks.
UPDATE - FEB 20,2014 3:55PM (PHILIPPINE TIME)
Hi Guys,
I have found the cause of the error, it is because the content-type is called two times. During Page_Load event and at last line of the Generate Excel function which is not supposed to be. That is why the current content-type after the page loads has been replaced after the generate excel function. Hehe my bad I guess.
Anyway thanks for all the help, advice and useful links.
Good day to all. :D
Internet Explorer can't handle binary responses to AJAX requests like XMLHttpRequestObject, as discussed in this question. You need to handle the response in some other way, depending on what you need to do with it.

Using Find.BySelector with the :visible filter in WatiN throws error

I am using WatiN 2.1 to drive Internet Explorer for automated integration testing. For one of my tests, I want to select an item in a dynamically created popup menu after clicking on a button that creates the menu. The menu itself is a jQuery plug-in that creates an unordered list with a specific class.
I am using WatiN 2.0's new Find.BySelector method to search via this specific class and that works great. However, in tests where multiple menus are created, I'm having a difficult time selecting the menu that is visible at the time. For this, I thought I would use the :visible filter to limit my results to only those menus that are visible (only one can be visible at a time). However, when I use the following code:
WebBrowser.Current.ElementOfType<List>(Find.BySelector("li.fg-menu:visible"));
I get a WatiN.Core.Exceptions.RunScriptException thrown with the message: "System.Runtime.InteropServices.COMException: Exception from HRESULT: 0x80020101" While searching for this specific HRESULT, people have recommended running Visual Studio as an Administrator, but this does not fix the problem. Without the :visible filter it works fine. When I execute that selector directly in the console window of the browser (using jQuery), it returns what I want.
To fix this, I could use WatiN's built-in ability to execute my own JavaScript to return an element, but I'm wondering if anyone else has been successful at using :visible with Find.BySelector.
For now, I've gone with this solution. It executes the selector in JavaScript using a "real" copy of jQuery already on the page. I've modified it a bit to dynamically insert the helper JavaScript based on whether it's already been inserted. It is also generic so you can specify the type of Element you want returned. Here is all the relevant extension methods for the browser object:
public static bool IsJavascriptEvaluateTrue(this Browser browser, string javascript)
{
var evalResult = browser.Eval("if (" + javascript + ") {true;} else {false;}");
return evalResult == "true";
}
public static TElementType FindViaJQuery<TElementType>(this Browser browser, string cssSelector) where TElementType : Element
{
if (!browser.IsJavascriptEvaluateTrue("typeof('WatinSearchHelper') == 'function'"))
{
var js = "WatinSearchHelper = function () { " +
" var earTagId = 1; " +
" var getElementId = function (cssSelector) { " +
" var resultId = \"_no_element_\"; " +
" var el = $(cssSelector); " +
" if (el.length > 0) { " +
" var firstEl = el[0]; " +
" if (firstEl.id == \"\") { " +
" firstEl.id = \"_watin_search_\" + earTagId++; " +
" } " +
" resultId = firstEl.id; " +
" } " +
" return resultId; " +
" }; " +
" return { getElementId: getElementId }; " +
"} (); ";
browser.Eval(js);
}
var elementId = browser.Eval(string.Format("WatinSearchHelper.getElementId(\"{0}\")", cssSelector));
if (elementId == "_no_element_")
{
throw new ArgumentException("Unable to find element on page with selector '" + cssSelector + "'", "cssSelector");
}
return browser.ElementOfType<TElementType>(Find.ById(elementId));
}

Using sockets (nsIServerSocket) in XPCOM component (Firefox Extension) (sockets + new window = seg faults)

PLEASE READ THE UPDATE #2 BELOW IF YOU ARE INTERESTED IN THIS PROBLEM ;)
Say I put this code into the JS of my extension.
var reader = {
onInputStreamReady : function(input) {
var sin = Cc["#mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
sin.init(input);
sin.available();
var request = '';
while (sin.available()) {
request = request + sin.read(512);
}
console.log('Received: ' + request);
input.asyncWait(reader,0,0,null);
}
}
var listener = {
onSocketAccepted: function(serverSocket, clientSocket) {
console.log("Accepted connection on "+clientSocket.host+":"+clientSocket.port);
input = clientSocket.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
output = clientSocket.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
input.asyncWait(reader,0,0,null);
}
}
var serverSocket = Cc["#mozilla.org/network/server-socket;1"].
createInstance(Ci.nsIServerSocket);
serverSocket.init(-1, true, 5);
console.log("Opened socket on " + serverSocket.port);
serverSocket.asyncListen(listener);
Then I run Firefox and connect to the socket via telnet
telnet localhost PORT
I send 5 messages and they get printed out, but when I try to send 6th message I get
firefox-bin: Fatal IO error 11 (Resource temporarily unavailable) on X server :0.0.
Even worse, when I try to put this same code into an XPCOM component (because that's where I actually need it), after I try sending a message via telnet I get
Segmentation fault
or sometimes
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: failed to allocate 32 bytes
aborting...
Aborted
printed to the terminal from which I launched firefox.
This is really weird stuff.. Can you spot something wrong with the code I've pasted or is smth wrong with my firefox/system or is the nsIServerSocket interface deprecated?
I'm testing with Firefox 3.6.6.
I would really appreciate some answer. Perhaps you could point me to a good example of using Sockets within an XPCOM component. I haven't seen many of those around.
UPDATE
I just realised that it used to work so now I think that my Console
component breaks it. I have no idea how this is related. But if I
don't use this component the sockets are working fine.
Here is the code of my Console component. I will try to figure out
what's wrong and why it interferes and I'll post my findings later.
Likely I'm doing something terribly wrong here to cause Segmentation
faults with my javascript =)
Voodoo..
components/Console.js:
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Console.prototype = (function() {
var win;
var initialized = false;
var ready = false;
var _log = function(m, level, location) {
if (initialized&&ready) {
var prefix = "INFO: ";
switch (level) {
case "empty":
prefix = ""
break;
case "error":
prefix = "ERORR: "
break;
case "warning":
prefix = "WARNING: "
break;
}
win.document.getElementById(location).value =
win.document.getElementById(location).value + prefix + m + "\n";
win.focus();
} else if (initialized&&!ready) {
// Now it is time to create the timer...
var timer = Components.classes["#mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
// ... and to initialize it, we want to call
event.notify() ...
// ... one time after exactly ten second.
timer.initWithCallback(
{ notify: function() { log(m); } },
10,
Components.interfaces.nsITimer.TYPE_ONE_SHOT
);
} else {
init();
log(m);
}
}
var log = function(m, level) {
_log(m, level, 'debug');
}
var poly = function(m, level) {
_log(m, "empty", 'polyml');
}
var close = function() {
win.close();
}
var setReady = function() {
ready = true;
}
var init = function() {
initialized = true;
var ww = Components.classes["#mozilla.org/embedcomp/window-
watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
win = ww.openWindow(null, "chrome://polymlext/content/
console.xul",
"console", "chrome,centerscreen,
resizable=no", null);
win.onload = setReady;
return win;
}
return {
init: init,
log : log,
poly : poly,
}
}());
// turning Console Class into an XPCOM component
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function Console() {
this.wrappedJSObject = this;
}
prototype2 = {
classDescription: "A special Console for PolyML extension",
classID: Components.ID("{483aecbc-42e7-456e-b5b3-2197ea7e1fb4}"),
contractID: "#ed.ac.uk/poly/console;1",
QueryInterface: XPCOMUtils.generateQI(),
}
//add the required XPCOM glue into the Poly class
for (attr in prototype2) {
Console.prototype[attr] = prototype2[attr];
}
var components = [Console];
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule(components);
}
I'm using this component like this:
console = Cc["#ed.ac.uk/poly/console;1"].getService().wrappedJSObject;
console.log("something");
And this breaks the sockets :-S =)
UPDATE #2
Ok, if anyone is interested in checking this thing out I would really
appreciate it + I think this is likely some kind of bug (Seg fault
from javascript shouldn't happen)
I've made a minimal version of the extension that causes the problem,
you can install it from here:
http://dl.dropbox.com/u/645579/segfault.xpi
The important part is chrome/content/main.js:
http://pastebin.com/zV0e73Na
The way my friend and me can reproduce the error is by launching the
firefox, then a new window should appear saying "Opened socket on
9999". Connect using "telnet localhost 9999" and send a few messages.
After 2-6 messages you get one of the following printed out in the
terminal where firefox was launched:
1 (most common)
Segmentation fault
2 (saw multiple times)
firefox-bin: Fatal IO error 11 (Resource temporarily unavailable) on
X
server :0.0.
3 (saw a couple of times)
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: failed
to
allocate 32 bytes
aborting...
Aborted
4 (saw once)
firefox-bin: ../../src/xcb_io.c:249: process_responses: Assertion
`(((long) (dpy->last_request_read) - (long) (dpy->request)) <= 0)'
failed.
Aborted
If you need any more info or could point me to where to post a bug
report :-/ I'll be glad to do that.
I know this is just one of the many bugs... but perhaps you have an
idea of what should I do differently to avoid this? I would like to
use that "console" of mine in such way.
I'll try doing it with buffer/flushing/try/catch as people are suggesting, but I wonder whether try/catch will catch the Seg fault...
This is a thread problem. The callback onInputStreamReady happened to be executed in a different thread and accessing UI / DOM is only allowed from the main thread.
Solution is really simple:
change
input.asyncWait(reader,0,0,null);
to
var tm = Cc["#mozilla.org/thread-manager;1"].getService();
input.asyncWait(reader,0,0,tm.mainThread);

Resources