Can I handle events when running Selenium tests? - javascript

I am a Selenium newbie ...
As a JavaScript programmer, I think I want to handle JavaScript events in my Selenium-2 tests (JUnit). I am joining a team where all of the existing tests have "waitForSomethingToBeRendered" methods. Is there some way my Selenium tests can handle/listen for DOM (or custom) events?
Also, I've read on SO where developers use FireBug to write/debug Selenium-2 tests. How does this work? I don't see FireBug in the browser launched by Selenium. Similarly, why does the following appear to have no effect? Am I trying something Selenium/JUnit does not support?
selenium().getEval("alert('hello');");
selenium().getEval("debugger;");

You don't see the firebug extension because selenium opens a stripped firefox. I'm guessing the reason is it's much faster. It's possible (and quite easy in selenium-2) to add the plugin.
The alert doesn't work because selenium-1 (I don't know how selenium-2 handles them) swallows the alerts. There's an api for handling alerts.
Plus, in selenium-1, the JS runs in a different window. So the equivalent of document.getElementById() is sel.getEval("selenium.browserbot.getCurrentWindow().document.getElementById()").
Finally, I don't know about events but you can wait for conditions: sel.wait_for_condition().

Firstly if you are getting started with Selenium I suggest using the 2.0 API which is for WebDriver. To evaluate JavaScript in 2.0 simply cast your WebDriver object to a JavascriptExecutor object and use the methods provided by it. 'waitForSomethingToBeRendered' needs to be done in a few steps. First of all you must ensure the DOM object is available on the page. For this you can do something like this:
WebElement e = null;
try {
e = driver.findElement( By.id("asdf") );
} catch {
...
}
Or:
driver.findElements( By.id("asdf") ).size() != 0
After determining whether the DOM object is available you can do:
e.isDisplayed()
Which will return to you whether the element is currently displayed.
In regards to what you have seen about FireBug and Selenium I am guessing you are confusing Selenium IDE which is a Firefox plugin with Selenium RC/WebDriver which is not a plugin.

Use Firebug for Firefox while normally browsing your site to explore your DOM to determine the correct element and class ids to select in your Selenium script. If you are using extjs you are going to have some extra fun in determining which elements to select, as extjs randomizes element ids. The best way is to add an extra css class to find the correct element, then select by that class.

Related

Selenium IDE 2.91 jQuery Evaluation

As part of a script I'm creating I am required click elements with a certain text value (exact case). To establish if I need to click anymore I intended to scroll to the bottom and as the page dynamically adds elements I wanted to use the below identify if any new element had appeared:
jQuery("button[rel='follow-button']").filter(function () { return jQuery(this).text() === 'Follow' }).length
Note jQuery is setup the same way as this answer: Get element with jquery and selenium IDE 1.0.8
However, whenever I try to store this value using the Selenium IDE (needed so I can loop the logic with the help of the Sideflow extension. It does not work as I had hoped.
I have found that this will work:
javascript{window.innerHeight}
This will generate a value not just return the variable name again when using Echo.
However whenever I replace this expression with my jQuery one above I get the following error in my Selenium IDE log:
[error] Unexpected Exception: Error: Permission denied to access property Symbol("Symbol.toStringTag").
Due to business requirements I must use the Selenium IDE, so any advise or tips to get around this issue would be much appreciated, as I don't have much experience with it yet and typically use Selenium Webdriver in C#

Can't use Advanced User Interactions in Webdriverjs

I am trying to use webdriverjs to click on a flash animation.
I tried using the Advanced User interactions, but I can't seem to click where I want.
Not even when I try to click a normal web element, such as a button.
Optimally, I would like to do something like the following:
element = driver.findElement(webdriver.By.Id("elementID"));
driver.actions()
.mouseMove(element)
.mouseClick()
.perform();
-or-
driver.actions()
.click(element)
.perform();
However, the feedback I get from the standalone server is always in the form of [someaction: nothing].
I tried enabling firefox native events in browser capabilities via 'nativeEvents': true, but it didn't help.
I can use webdriverjs to click on elements on a page normally otherwise. (except for flash)
Selenium cannot interact with Flash objects.
If you want to do this you would need to modify the source code of the flash object to provide some test hooks that JavaScript could access and then use something like:
https://code.google.com/p/flex-ui-selenium/
https://code.google.com/p/flash-selenium/

Programatically retrieve count of javascript errors on page

I'd like to write a test case (using Selenium, but not the point of this question) to validate that my web application has no script errors\warnings or unhanded exceptions at certain points in time (like after initializing a major library).
This information can easily be seen in the debug consoles of most browsers. Is it possible to execute a javascript statement to get this information programatically?
It's okay if it's different for each browser, I can deal with that.
not so far read about your issue (as far as I understood your problem) here
The idea be the following:
I found, however, that I was often getting JavaScript errors when the page first loaded (because I was working on the JS and was introducing errors), so I was looking for a quick way to add an assert to my test to check whether any JS errors occurred. After some Googling I came to the conclusion that there is nothing built into Selenium to support this, but there are a number of hacks that can be used to accomplish it. I'm going to describe one of them here. Let me state again, for the record, that this is pretty hacky. I'd love to hear from others who may have better solutions.
I simply add a script to my page that will catch any JS errors by intercepting the window.onerror event:
<script type="text/javascript">
window.onerror=function(msg){
$("body").attr("JSError",msg);
}
</script>
This will cause an attribute called JSError with a value corresponding to the JavaScript error message to be added to the body tag of my document if a JavaScript error occurs. Note that I'm using jQuery to do this, so this specific example won't work if jQuery fails to load. Then, in my Selenium test, I just use the command assertElementNotPresent with a target of //body[#JSError]. Now, if any JavaScript errors occur on the page my test will fail and I'll know I have to address them first. If, for some strange reason, I want to check for a particular JavaScript error, I could use the assertElementPresent command with a target of //body[#JSError='the error message'].
Hope this fresh idea helps you :)
try {
//code
} catch(exception) {
//send ajax request: exception.message, exception.stack, etc.
}
More info - MDN Documentation

Testing User Interaction with JavaScript

I can't get Lettuce / Splinter or JsTestDriver to run tests of user interaction with Backbone-generated DOM objects. For example, at the hello backbone tutorial, I want to simulate the user's click on the button labeled "Add list item", then verify that a <li> element of text "hello world1" has appeared.
JsTestDriver: I can get a reference to the button element and call click() on it, but then document.getElementsByTagName("li") fail (or return null?).
Johansen's excellent book says that testing event handlers isn't properly a unit testing task. So I tried my BDD (?) tools for Django:
Lettuce / Splinter / Django: The Splinter Browswer object can't see the text in the button, never mind get a reference to it or click it. (It does handle these operations for elements created via HTML.) Neither world.browser.is_text_present() nor find_by_id() work; passing a wait time to the former didn't help.
I would really prefer to avoid going straight to Selenium, and thought that these tools made that unnecessary. So now what?
While firing DOM events may technically not be "unit testing", it doesn't mean you can't use a unit testing framework to do it :) This is more of a case of definition.
Anyway, you can achieve what you want with e.g. JsTestDriver, but I would advise against doing it manually through e.g. click() (which likely does not do what you expect it to). I usually use jQuery to fire events, and this can safely be done with e.g. JsTestDriver. This should work even if you don't use jQuery in your production code.

alternative when an older browser does not accept jquery

I have just been altered to the fact that a user of my website is using a very old browser which does not run jquery (in this case Safari 1.x) and as a result can not access the login panel which uses jquery's slideToggle function.
Can anyone think of a fix which detects whether a browser is able to use jquery - and if not make that link go to a different page rather than showing the login panel?
You could a little conditional check like
if(!'jQuery' in window) {
// jQuery is not available
}
or, if Safari 1.x doesn't know about the IN operator (I'm not sure) use
if(!window.jQuery) {
}
I think there are alternative answers to this, but for me, I would have to weigh up the time it will take you to support his obsolete browser (I'm sure there may be other things inside the site), versus the payback to you...
In the plain HTML source code for the the href= of the login link, set that to a plain HTML login page.
Using jQuery, attach the click handler to the link, if this part fails, thats ok, the browser will just follow the href in the link to the plain login page, allowing your old-browser-user to login still.
$(document).ready(function(){
$('#login_link_id').click(function(){
// Your code here
});
});
If you use javascript/jQuery you should ALWAYS ensure your site works perfectly without it. In this case if you have a login popup box; you probably assign a click event assigned after the DOM has loaded.
What you should do is ensure that if jQuery isn't present the link loads a "normal" login webpage as opposed to the popupbox. I use something similar to this:
Log in
<script>
if(!'jQuery' in window) {
$(document).ready(function(){
//assign on click event to loginlink
});
}
</script>
If jQuery doesn't exist then login.html will be opened normally.
Wow, seriously?! Safari 1.x?? Anyhow, try this...
var isJQSupported = false;
$(function() { //shorthand for document.ready
isJQSupported = true;
//your usual code
});
if (!isJQSupported) {
window.location = "http://www.apple.com/safari/download/";
}
To me it sounds like safari 1.X has problems with jQuery internally. Which means simple checks like whether $ exists in the global space or whether $(function) does anything are not going to help.
The most likely root cause will be that javascript throws an error in loading of jQuery itself which will then stop the rest of your javascript code from execution.
There are four viable options here.
Either make the website work with noscript. Replace your login control with pure HTML and postbacks and ask the user to turn javascript off. This option is useful since you won't be fixing the issue for safari 1.x problems specifically.
You can make javascript check for safari 1.X and other non-supported browsers and only load jQuery through script tag injection or ajax if your user is using a supported browser. If the user is using a browser not compatible with jQuery then you can instead use plain javascript.
Get a copy of safari 1.x and see why jQuery breaks. Then fix it and ask for it to pulled into the release of jQuery 1.5. This relies on the fix being something that does can be done without hacking and that the jQuery team agrees is worth adding in.
Ask the user to use a compliant browser.
There might be some more options. I would personally lean towards asking the user to use a compliant browser because supporting Safari 1.x is ridiculous.
This seems like a case where progressive enhancement is needed.
You have to do multiple checks
see if $ exists
see if $.fn exists
[not sure if needed] check if $.support is a function
check for feature support as needed with $.support() http://api.jquery.com/jQuery.support/
At the end of the check, when jQuery reports that features you need are present - the rest of the script can run.
If you're not sure which features mentioned in the support you use, then this might need a single test on Safari 1.x to see what are the values returned by $.support(), but that is what your nasty old-browser-user can do for you (if you prepare code and publish) and report the resulting text. Then you compare the list with other [old] browsers that are accessible and determine features that are required.
The easy way would be to require everything and cancel all scripts if suport for any feature is missing. This will also rule out IE6 and IE7 and opera below 9.something and firefox below 2.0 or including - I'm not sure.
Use a server side language to detect if it's the old safari based on user-agent and load a different javascript file

Categories