Usage of relative=up in selenium - selenium-rc

Can any one explain me the usage of
selenium.selectFrame("relative=up");
sample code:
selenium.selectFrame("frame");
String Error_MSG_1 = selenium.getText("//div");
selenium.selectFrame("relative=up"); -----> here if I remove this
statement it throws an exceptions
if (selenium.isTextPresent("error message")) {
assertEquals("","");
}
//Close error pop-up
selenium.click(Close_popup);

If your web applications implement iframes, often times, while testing, say, a text string, you can clearly see it being displayed in the browser, but upon playback, the selenium script may fail. This is because the script may not be placing the right iframe into context. selenium.selectFrame(...) is used to set the right frame in which the assertion/verification is to be performed.
Specifically, selenium.selectFrame(“relative=up”) is used to move one iFrame up a level. In a related manner, you can use selenium.selectFrame(“relative=top”) to select the top level iFrame.

Related

How do I save Cypress's testrunner's "console log" (left hand side) to a file

I would like to save the data from the left-hand-side of the TestRunner to a text file (json, plain text, or any kind of text).
I feel like this should be very easy, and that I'm simply just missing something. However, I cannot find anything to explain this. I have checked this other S.O. question: Cypress pipe console.log and command log to output, which references this currently open issue -- but this appears to be focused on collecting the browsers console log.
I even tried one of the workarounds suggested in the discussion of that open issue, cypress-log-to-output - but that put a ton of output in the terminal from which I launched the test. I did try to correlate the extra output to the relatively few entries from the TestRunner's left-hand-side, but did not see anything to match them up.
I'm just hoping to get a text file that looks like this (with perhaps a bit of detail for each entry):
1 visit /
(xhr) GET 200 /todos
2 wait #todos
(req) GET /todos Received todos
...
Or perhaps JSON.
My motivation comes from having to write Cypress tests for our CI that will be testing a very old AjaxSwing based application that makes heavy use of XHR requests, and it can be a different number of XHR requests for each test run (sometimes 8, sometimes 12 just to load the first page).
The AjaxSwing app is not changing, so I have to figure this out as best as possible. So I wanted to see a whole text file with all the information from the TestRunner's left hand side. Perhaps even compare separate runs to see if I can spot some "header" or "body" value I could use to distinguish the right XHR request to wait for.
Any help would be appreciated.
One approach using the log:added event
// top of spec
const logs = []
Cypress.on('log:added', (log) => {
const message = `${log.consoleProps.Command}: ${log.message}`
logs.push(message)
})
it('writes to logs', () => {
... // some commands that log
cy.writeFile('logs.txt', logs)
});

Non helpfull error message Calabash with page objects pattern

I'm currently using Calabash framework to automate functional testing for a native Android and IOS application. During my time studying it, I stumbled upon this example project from Xamarin that uses page objects design pattern which I find to be much better to organize the code in a Selenium fashion.
I have made a few adjustments to the original project, adding a file called page_utils.rb in the support directory of the calabash project structure. This file has this method:
def change_page(next_page)
sleep 2
puts "current page is #{current_page_name} changing to #{next_page}"
#current_page = page(next_page).await(PAGE_TRANSITION_PARAMETERS)
sleep 1
capture_screenshot
#current_page.assert_info_present
end
So in my custom steps implementation, when I want to change the page, I trigger the event that changes the page in the UI and update the reference for Calabash calling this method, in example:
#current_page.click_to_home_page
change_page(HomePage)
PAGE_TRANSITION_PARAMETERS is a hash with parameters such as timeout:
PAGE_TRANSITION_PARAMETERS = {
timeout: 10,
screenshot_on_error: true
}
Just so happens to be that whenever I have a timeout waiting for any element in any screen during a test run, I get a generic error message such as:
Timeout waiting for elements: * id:'btn_ok' (Calabash::Android::WaitHelpers::WaitError)
./features/support/utils/page_utils.rb:14:in `change_page'
./features/step_definitions/login_steps.rb:49:in `/^I enter my valid credentials$/'
features/04_support_and_settings.feature:9:in `And I enter my valid credentials'
btn_ok is the id defined for the trait of the first screen in my application, I don't understand why this keeps popping up even in steps ahead of that screen, masking the real problem.
Can anyone help getting rid of this annoyance? Makes really hard debugging test failures, specially on the test cloud.
welcome to Calabash!
As you might be aware, you'll get a Timeout waiting for elements: exception when you attempt to query/wait for an element which can't be found on the screen. When you call page.await(opts), it is actually calling wait_for_elements_exist([trait], opts), which means in your case that after 10 seconds of waiting, the view with id btn_ok can't be found on the screen.
What is assert_info_present ? Does it call wait_for_element_exists or something similar? More importantly, what method is actually being called in page_utils.rb:14 ?
And does your app actually return to the home screen when you invoke click_to_home_page ?
Unfortunately it's difficult to diagnose the issue without some more info, but I'll throw out a few suggestions:
My first guess without seeing your application or your step definitions is that #current_page.click_to_home_page is taking longer than 10 seconds to actually bring the home page back. If that's the case, simply try increasing the timeout (or remove it altogether, since the default is 30 seconds. See source).
My second guess is that the element with id btn_ok is not actually visible on screen when your app returns to the home screen. If that's the case, you could try changing the trait definition from * id:'btn_ok' to all * id:'btn_ok' (the all operator will include views that aren't actually visible on screen). Again, I have no idea what your app looks like so it's hard to say.
My third guess is it's something related to assert_info_present, but it's hard to say without seeing the step defs.
On an unrelated note, I apologize if our sample code is a bit outdated, but at the time of writing we generally don't encourage the use of #current_page to keep track of a page. Calabash was written in a more or less stateless manner and we generally encourage step definitions to avoid using state wherever possible.
Hope this helps! Best of luck.

Firefox Extension: responding to an http-on-modify-request observed in the parent with a message to the child frame responsible for the load

I'm trying to enhance an existing Firefox extension which relies on nsIContentPolicy to detect and abort certain network loads (in order to block the resulting UI action, i.e. tab navigation). Then handle loading that resource internally. Under rare circumstances, only after handling the load, it turns out we shouldn't have interrupted the load at all, so we flag it to be ignored and re-start it.
Under e10s/multi-process, that means the parent (where the content policy is running) must send a message to the child (handling the UI for the content) to restart the load. Today, that's done by:
function findMessageManager(aContext) {
// With e10s off, context is a <browser> with a direct reference to
// the docshell loaded therein.
var docShell = aContext && aContext.docShell;
if (!docShell) {
// But with e10s on, context is a content window and we have to work hard
// to find the docshell, from which we can find the message manager.
docShell = aContext
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem;
}
try {
return docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
} catch (e) {
return null;
}
};
Which is crazy complex, because e10s is crazy complex. But it works; it generates some object in the parent, upon which I can call .sendAsyncMessage(), and then the addMessageListener() handler in my frame/child script receives it, and does what it needs to do.
I'd like to switch from nsIContentPolicy to http-on-modify-request as it presents more information for making a better determination (block and handle this load?) earlier. Inside that observer I can do:
var browser = httpChannel
.notificationCallbacks.getInterface(Ci.nsILoadContext)
.topFrameElement;
Which gives me an object which has a .messageManager which is some kind of message manager, and which has a .sendAsyncMessage() method. But when I use that .sendAsyncMessage(), the message disappears, never to be observed by the child.
Context: https://github.com/greasemonkey/greasemonkey/issues/2280
This should work in principle, although the docshell tree traversal may do different things in e10s and non-e10s, so you have to be careful there. In e10s rootTreeItem -> nsIContentFrameMessageManager should give you the MM equivalent to a frame script and topFrameElement.frameLoader.messageManager should give you the <browser>'s MM, which pretty much is the parent side counterpart to it.
Potential sources of confusion:
e10s on vs. off
process MM vs. frame MM hierarchy
listening in the wrong frame for the message (registering in all frames might help for debugging purposes)
This is the function I use to find the content message manager:
function contentMMFromContentWindow_Method2(aContentWindow) {
if (!gCFMM) {
gCFMM = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
}
return gCFMM;
}
So maybe get the content window that triggered that request, and then use this function.

Locale string comparison does not work properly in Firefox extension web worker

The localeCompare() function does not behave the same in a Firefox extension main code and in a web worker (or chrome worker).
For instance, in the main code, I have this code:
var array = ["École", "Frère", "frère", "école"];
array.sort(function(a, b) {
return a.localeCompare(b);
});
console.log('Main: ' + array);
it shows:
Main: �cole,�cole,Fr�re,fr�re
Which is the right sorting (the encoding is not my problem).
In the worker, I have this code:
var array = ["École", "Frère", "frère", "école"];
array.sort(function(a, b) {
return a.localeCompare(b);
});
self.postMessage(array);
it prints:
Frère,frère,école,�0cole
which is in the wrong order (once again, the encoding is not my problem).
The sorting in the main code is ok, but not the one in the web worker.
I tried to change the options of the localeCompare() function in the web worker, but it does not change anything.
Why is the sorting different in the web worker and how to get it right in the web worker?
(For some reason, I could not send the data to the main code, do the sorting and send it back to the web worker. I still got the wrong order (gives me école,�0cole,Frère,frère).)
Thanks for your help.
localeCompare is still broken in Firefox Web Workers.
Wladimir mentioned Bug 616841, which indeed fixed it almost everywhere... except for web workers, which were left broken because the Intl backend was (is?) not thread-safe, or some other thread-safety issues. The corresponding "Dead end" patch was never reviewed nor checked in.
I now filed Bug 903780, with a test case based on your code, so that localeCompare hopefully will be fixed in the future.

How do you test an Ajax application with Selenium and keep it stable?

Our team has been testing our application with Selenium as it's heavily JavaScript driven we've always had issues with tests occasionally failing. As the number of tests has increased the probability of at least one two tests failing in a complete run has become a certainty.
What we recently figured out is that we probably have a race condition where selenium will click links before the initialization JavaScript has had a chance to attach event handlers to the element that is being clicked. Of course at this point the effects we're looking for don't happen and we get a failing test.
For the time being we've added a slight delay before clicks to give the initialization JavaScript code time to finish, this is obviously a bit hackish, adds time to overall test execution, and doesn't guarantee tests won't still fail so we're looking for a better solution.
The best idea we've come up with so far is to inject a hidden element into the DOM that Selenium can wait for, before firing the click event to know that it's ready. This will be a lot of extra overhead in terms of developer time when we're working our asynchronous events, removing and adding the element. Also it adds extra stuff to our pages that really isn't necessary for the application.
Does anyone have any better strategies? What have you done to effectively solve this problem?
We moved to Selenium 2 (WebDriver) and are using Page Objects pattern with PageFactory/AjaxElementLocatorFactory - an example of this is here
I did exactly like you : add some delay and wait for some elements to be present on the page. And I'm perfectly fine with it. Maybe switching to Webdriver / selenium 2.0 would help though. Test execution can be trimmed down if you work with an in-memory database or sharing the same selenium/selenium server between tests, or even with parallelization (easy with TestNG for instance).
Have you tried the waitForElementPresent command, and then make it click ?
To eliminate race conditions use Selenium's runScript(String initCondition) combined with waitForCondition(String jsConditional, String timeout) methods.
For example, if the AJAX functionality you want to test causes a new element to be added to the dom you can use something like the following.
String jsPoll = "";
jsPoll += "selenium.browserbot.getCurrentWindow()";
jsPoll += ".document.getElementById('DOMID')";
selenium.waitForCondition(jsPoll, "30000");
The condition will evaluate true when the element is added and the method will continue. If your AJAX function swaps elements (ie: one div for another similarly identified div), you can initialize your conditional with something like the following.
String jsInit = "";
jsInit += "!selenium.browserbot.getCurrentWindow()";
jsInit += ".document.getElementById('DOMID').setAttribute('SELENIUMTEST','1')";
String jsPoll = "";
selenium.runScript(jsInit);
jsPoll += "selenium.browserbot.getCurrentWindow()";
jsPoll += ".document.getElementById('DOMID').getAttribute('SELENIUMTEST') != 1";
selenium.waitForCondition(jsPoll, "30000");
The condition evaluates true when the element is swapped out by the AJAX function.

Resources