Unable to control Javascript popup in Firefox browser in Ruby Watir - javascript

In a page, when I click on a certain button, I get a javascript popup with 'Ok' and 'Cancel' buttons. I want to click 'Ok' button in that popup using Ruby Watir script. So I use the following code. I get the FAIL message since javascript popup comes and goes out within fraction of a second in Firefox browser. So to check whether the script catches the alert, I did print p browser.alert.present? and I get that as false. How to handle such a issue?
if (certain_button_click)
p browser.alert.present? #I get this as 'false'
browser.wait_until(30) {
browser.alert.present?
} rescue nil
p browser.alert.present? #I get this as 'false'
if browser.alert.present?
browser.alert.ok
message = 'Click Ok - PASS'
else
message = 'Click Ok - FAIL'
end
end
Please help. Thanks in advance.
Thanks,
Ashwin

Honestly I can't tell what you are trying to accomplish here, but I see what your code is doing.
Selenium raises an UnhandledAlertError whenever an alert is present, but a non-alert related action is taken with the driver. What your code is doing is rescuing that exception (well, all exceptions, which you should avoid doing when you know which exception you want to avoid). Firefox has different behavior than Chrome in this respect in that it also closes the alert when it raises the exception. So your code is doing exactly what you are telling it to do.
if you use Watir 6.0 you don't have to specify the waits any longer. If you only want to dismiss an alert when it shows up, this code will automatically wait for the alert to show up and click ok when it does. If the alert never shows up it will give a timeout error.
element_causing_alert.click
browser.alert.ok
If you are trying to test that the alert shows up, then you can use this code:
begin
browser.alert.ok
true
rescue Watir::Wait::TimeoutError
false
end
Or if you want to specify the time to wait before timing out:
begin
browser.alert.wait_until(timeout: 5, &:present?).ok
true
rescue Watir::Wait::TimeoutError
false
end

Here's an alternate idea. You can use execute_script in the browser which 'stubs out' the alert call to set a global variable. Then another execute_script which checks that the variable was set.
Example:
def stub_alert
script = <<-JS
window.alert = function(){ window.alerted = true }
JS
browser.execute_script stub_alert
end
def check_for_alert
script = <<-JS
return window.alerted == true
JS
browser.execute_script stub_alert
end
Watir uses selenium under the hood, and there's some tricky things about working with alerts. I've experienced the situation where Selenium's reference to the alert disappeared if I ran any javascript before handling the alert.

Related

Protractor Random Alert Box "Error:jQuery not found."

jQuery Error
I've done some extensive searching, and have found samples of code to handle an alert box when you expect it; but I haven't been able to find anything on handling a random alert box that might, or might not appear.
The website I'm dealing with is very stubborn to begin with. Several elements without any kind of ID's, timeouts, network failures, etc.
98% of the time when I run the tests, they run without getting the alert box error and everything is good. When the alert box does popup the other 2% of the time which says "Error:jQuery not found," all my other tests fail with unexpected alert errors.
My first question is, could it be something in my code that's causing the error to happen? (see code below) My gut tells me it's probably the website. So if that's the case, could someone please show me an example that would handle a "possible" alert box and accept it, without failing my test? The swithTab() test is running first, and then the setDates() test is running next. The alert box error pops up after the switch tab, as the page is loading. I've tried using a deferred promise to handle the alert, and catch the error, but it fails before it can even catch the error. It fails as soon as it hits browser.switchTo().alert() because the alert usually doesn't exist. I really appreciate any help I could get.
this.switchTab = function(){
browser.getAllWindowHandles().then(function(handles){
browser.switchTo().window(handles[1]);
browser.sleep(2000);
var lockBoxTitle = element(by.css('td.title'));
browser.driver.wait(EC.visibilityOf(lockBoxTitle),5000);
});
}
this.setDates = function(yesterdayDate){
browser.sleep(3000);
//handleAlert();
startDateTextBox.clear();
startDateTextBox.sendKeys(yesterdayDate);
endDateTextBox.clear();
endDateTextBox.sendKeys(yesterdayDate);
retrieveBtn.click();
browser.sleep(5000);
expect(validateStart.getText()).toEqual(yesterdayDate);
expect(validateEnd.getText()).toEqual(yesterdayDate);
}
You can check if popup is displayed and if is displayed click the button for closing it:
var popUpElm = element(by.model(""));
var closeBtn= element(by.model(""));
popUpElm.isDisplayed().then(function(isDisplayed) {
if (isDisplayed) {
closeBtn.click();
console.log("Popup is closed");
} else {
console.log("Popup is not displayed");
}
});

How do we correctly click on a link or button using Javascript?

I'm using the PHP + Ajax version of this template: http://192.241.236.31/themes/preview/smartadmin/1.5/ajaxversion/, Codeception WebDriver (Selenium) to perform my tests. Most of them are working fine, but I have some random, yes, random!, failing tests, so I always get back to them and try to harden, hoping it will not randomly fail sometime in the future. One of the failing reasons are usually due to wrong clicks on the interface. I tell Codeception to click the #element-id and when it fails, I see that it actually had a different page showing in the output png, but the link activated showing it tried to click the correct link. Sometimes I just have to load a different page before clicking that particular link and wait 10 seconds for it to render, and it works, silly huh? Yeah, but sometimes this doesn't work either.
This is how I used to test things:
$I->click('#element-id');
And I have to use the element id, because it's a multi-language app, all (mostly) strings come from a strings file and they might change at some point and break tests.
After too many random tests failing, I decided to make the frontend itself responsible for clicking things during tests, it's a long and silly circunventing shot, but it should be work, so I created a functionalHelper:
public function clickElement($element)
{
$I = $this->getDriver();
$I->executeJS("clickElement('{$element}');");
}
And two Javascript functions:
function clickElement(element)
{
element = jQuery(element);
if(typeof element !== undefined)
{
fakeClick(element[0]);
}
return true;
}
function fakeClick(object)
{
if (object.click)
{
object.click();
}
else if(document.createEvent)
{
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var allowDefault = object.dispatchEvent(evt);
}
}
I'm using jQuery in the first one because it's already available in the template and it's easier to select non-id'ed things.
This is working fine, and you can test it yourself by
1) Opening the page:
http://192.241.236.31/themes/preview/smartadmin/1.5/ajaxversion/
2) Loading the script in your browser console by executing
loadScript('https://www.dropbox.com/s/kuh22fjjsa8zq0i/app.js?dl=1');
3) And clicking things:
Calendar
clickElement($x('//*[#id="left-panel"]/nav/ul/li[7]/a/span'));
Widgets
clickElement($x('//*[#id="left-panel"]/nav/ul/li[8]/a/span'));
Because the template is using the hash character to control the ajax part of the page and not reload everything, I had to (programatically) add the referer-url to all my href links, so I could, in my app, redirect back to the referer, as the hash part uf the accessed url is not sent to the server. This is a link example:
<a href="/users?referer-href-url=/dashboard" title="Users" id="users-navigation">
<span class="menu-item-parent">Users</span>
</a>
Wich basically means the user was looking at the dashboard when she clicked the users link. If something wrong happens, the app will redirect the user back to the dashboard, with an error message.
The problem is that, somehow, during tests, the current url, when tested using:
$I->seeCurrentUrlEquals('/#/clients?referer-href-url=/clients');
Becomes
/#/clients
Instead of
/#/clients?referer-href-url=/clients
This happens sometimes, because some other it also works. If I browse the site manually it works in 100% of the time and I always see the correct URL in the address bar. And if I manually execute clickElement() it also works fine. The problem only heppens my my suite is running.
Here's an example of it passing (green):
And the exact same test randomly failing (red):
This is the code related to the failing test:
$I->clickElement('#clients-navigation');
$I->waitForText('Jane Doe', 10);
$I->seeCurrentUrlEquals('/#/clients?referer-href-url=/clients');
I usually wait for something after a click, so the page can have time to render.
You can also see that there are a lot of "I click element", using those PHP and Javascript functions without a problem.
I'm using:
Ubuntu 14.04
PHP 5.5.9
Codeception 2.0.7
Selenium 2.44.0
Firefox 33.0
So, what could be the problem here?
Is this the correct way to click an element in Javascript?
In the process I also experience tests which does not fail when ran singly and fails when in batch, but this might be a different question, right?

Is there any way to get the origin of an alert box?

I work with some very large and confusing JavaScript files that I did not write. Sometimes an alert will come up but I don't know where it's coming from.
You could search all files for the text contained in the alert but if that text is dynamic it won't work.
Is there a way to set a breakpoint in order to intercept an alert?
At the very top of your HTML:
window.alert = function() {
debugger;
}
debugger is a statement that invokes any debugging functionality available. With developer tools open, you'll automatically hit a breakpoint whenever alert is called. You can then inspect the call stack to see exactly what called the custom alert function.
It may or may not be helpful to you, but you can overwrite the alert function to do whatever you want with it. For example, instead of alert boxes, you could have it log the message to the console.
window.alert = function(msg) {
console.log(msg);
}
alert('test');
I agree with Brian Glaz, but in order to get more details (line number) you might try to throw an error when alerting something and outputting the error on the console. this way, the console will point you to the right line number where the alert function was called.
Put this snippet at the top of your document and give it a try :
var originalAlert = window.alert;
window.alert = function(){
try{
throw new Error('alert was called');
} catch(e){
console.warn(e);
}
return originalAlert.apply(window, arguments);
}
Open Chrome push F12 key and go to Sources.
Then choose a script file Ctrl+F and search for alert.
You can put breakpoint on any line you wish

Phonegap App Error - connection to the server was unsuccessful

I have the following issue and I'm a bit new to Phonegap! On my index page I have three functions that will create a Javascript Prompt asking the user for their name, email and title (position) and store each to the localStorage. Three items like this:
function promptName(){
var salesPName = prompt("Bitte geben Sie Ihren Namen","");
if(salesPName == null || salesPName == ""){
promptName()
}else{
localStorage.setItem("salesP", salesPName);
}
}
Then using $(document).ready I call these three functions:
$(document).ready(function(){
if(!localStorage.getItem("salesP")){
promptName();
promptEmail();
promptPosition();
}
});
This is all working well, however when deploying to my Android device I get the prompts but before I can complete all three I get an error dialog stating:
The connection to the server was unsuccessful (file:///android_asset/www/appname/index.html)
Removing the prompts removes the error but I need this functionality. I have tried different ways of calling the functions, for example on the body tag's onload event or using .load(). I still get this error. I thought about setting a Javascript interval to call this after a few seconds (once the page is loaded) as I'm sure the problem is due to Javascript's blocking nature. Has anyone come across this before?
Please note that I added the following to the com.mypackage.xxx.java file (as advised from phonegap, connection to server unsuccessful)
super.setIntegerProperty("loadUrlTimeoutValue", 10000);
And I still get the problem!
with nothing working I put a setTimeout() around my condition like so...
$(document).ready(function(){
setTimeout(function (){if(!localStorage.getItem("salesP")){
// item doesn't exist... so let's raise some dialogs to capture the name, email address and title
promptName();
promptEmail();
promptPosition();
}
}, 5000)
});
now it works fine... a bit of a fudge but so what, if anyone has any ideas on a better solution or any objections to this please let me know

IE Follows Link Even After onclick="return false;"

I'm writing a Rails 2.3.8 app, and using the standard link_to helper. I have a reasonable number of links that user methods other than GET, so I pass a :method => :whatever option to link_to, and it generates a link with an onclick handler like so (indentation added for readability):
<a
onclick="
var f = document.createElement('form');
f.style.display = 'none';
this.parentNode.appendChild(f);
f.method = 'POST';
f.action = this.href;
var s = document.createElement('input');
s.setAttribute('type', 'hidden');
s.setAttribute('name', 'authenticity_token');
s.setAttribute('value', '31M3q8SJkRz7f0R80l42Z2W7O2N7ZrzufhWQYql/Zd8=');
f.appendChild(s);
f.submit();
return false;"
href="/transactions/1015/transcribe"
>
Enter Data
</a>
Now, for whatever reason, IE (both 7 & 8 - the two I've tested) has decided that the return false; at the end there isn't enough to stop it from following the link, and I end up getting two requests to my server: The POST request from the onclick handler, which I want, and the GET request from the link itself, which I don't. In fact, that route doesn't exist for anything other than a POST request, so when the browser follows the GET request, the user gets dumped on a 'Bad URL' error screen. Not good.
Has anyone seen this before, and can tell me what's causing it? Or, better yet, does anyone know a good workaround?
PS: I'd prefer NOT to
Monkey-patch link-to, or
Write my own version of link_to
but if that's what it takes, that's what it takes. And I'm using jQuery 1.5.something, if that helps.
In general, when IE decides to "ignore" a return false; from an onclick handler, it is because one of the lines before the return false; threw an exception. This will cause a silent failure of the onclick handler, and the browser will then attempt to access the href link. This applies to all browsers, not just IE, but it's often the case that IE will throw exceptions in cases where other browsers will not, hence why it seems that only IE is ignoring the return false;.
One quick patch for this is to set href="#", which will keep the browser on the page even if the onclick handler fails. The proper way to debug it, however, is to wrap your onclick code in something like try { ... } catch (ex) { alert(ex); } to see what the exception is, and then fix the onclick code so that it no longer throws the exception.
To prevent form submission in JQuery, we often use
event.preventDefault();
So in your example, you could use this (as discussed in comments) :
$('a[onclick]').click(function(e) {e.preventDefault();});
Hope that helps!
I have had this problem with IE before, and found that a solution that works (which I believe is what jQuery's event.preventDefault() does under the covers), is to do BOTH return false; for normal browsers, but also event.returnValue = false; (before the actual return, obviously) for IE. IE will respect that.
Unfortunately though, I don't know how to slip that into the link_to helper without hacking it. That's actually what I came here looking for. :)
I believe that the problem that you are submiting your new form:
f.submit();
and you are submiting it right to your link href
f.action = this.href;
so you are folowing to this address. Your link returns false, but submited form leads you to this location.
So your link_to is ok. Problem is inside of your strange javascript.

Categories

Resources