C# Selenium RC - How to test a jQuery button click? - c#

What is the correct way to run a jQuery .click() in a selenium test? The element being clicked is a hyperlink.
HTML:
<div id="buttons">
<a class="button" id="btnRun" href="javascript:void(0)">Run</a>
</div>
<div id="output" />
jQuery
$(document).ready(function () {
$('#btnRun').click(function () {
$("#output").html("hello world");
});
})
Selenium:
[Test]
public void TestOutput()
{
selenium_local = new DefaultSelenium("localhost", 4444,
"*firefox", "https://localhost");
selenium_local.Start();
selenium_local.Open("/TestPage");
selenium_local.WaitForPageToLoad("30000");
Assert.That(selenium_local.IsElementPresent("id=btnRun"), Is.True);
selenium_local.Click("id=btnRun");
Thread.Sleep(5000);
// also tried without success:
// selenium_local.FireEvent("id=btnRun","click");
// selenium_local.Click("xpath=//a[#id='btnRun']");
// selenium_local.Click("dom=document.getElementById('btnRun')");
Assert.That(selenium.GetValue("id=output"), Is.EqualTo("hello world"));
}
When I run the test the button click does not occur, and after the 2nd WaitForPageToLoad, the test finishes and reports failure (because the text hello world was not found, because the button click never occurred)

(Note: I use selenium with java, so there might be a difference, but I strongly doubt it)
I have similar problems sometimes, but we're using plain-ol'-javascript in some places, gwt in others, and mootools in some other places (don't ask why so many) for our different ajax calls so it's possible our problems are completely unrelated. But, maybe I can help regardless.
I have to sometimes use mouseOver then click. Sometimes I even have to do mouseDown and then mouseUp. Or a combination of the two. And even in some cases we have to retry the click.
(Also, unless clicking the link/button causes a full page load, the WaitForPageToLoad is going to cause issues because it waits for a page loaded event. Here's how I ended up waiting for Ajax calls to finish, however you should be able to come up with a cleaner solution if you're only using JQuery)

Some JavaScript libraries respond to the mouse-up event as indicating a "click". If so, MouseDown() followed by MouseUp() ought to do the job.

Related

ASP.NET WebForms Confirm

I'm new to web programming with .NET.
I am developing a web page with webforms, and I want at a certain moment to programmatically show a modal window, for the user to accept or cancel, according to a question. Exactly what does the "confirm" function of JavaScript.
I tried to get it calling a JavaScript function:
Page.ClientScript.RegisterStartupScript (this.GetType (), "CallMyFunction", "MyFunction()", true);
But I need to do it without reloading the page, and I also need to control if the user has accepted or canceled and I do not know how to do it.
I've also tried getting it using the ModExPopupExtender control from DevExpress.
Can someone tell me a simple way to get what I want?
I can not understand how something so usual in web programming, and that PHP + javascript would not pose any problem can be so complicated.
All start in a one-button event on the code behind:
protected void btn1_Click(object sender, EventArgs e)
{
//I make a series of checks
//If certain conditions I want to show the confirm
//According to the user has chosen ok or cancel will perform a certain action
}
Onclientclick does not help me because before launching the "confirm" I have to do some checks on the server side.
Thank you very much.
You can use OnClientClick which is a property on most web controls.
I like to just bring up a simple confirm() dialog which executes the server code if the user clicks OK and does nothing if the user cancels the action:
<asp:Button runat="server" ID="btnSave" Click="btnSave_Click" Text="Save"
OnClientClick="return confirm('Are you sure you want to do this thing?');" />
You can do other things with it as well, but the key thing to remember is that anything you do in OnClientClick will happen before the page gets posted back to the server.
This is also perfectly valid:
<asp:Button runat="server" ID="btnSave"
OnClientClick="showModalConfirm('some message goes here');" ... />
<script>
function showModalConfirm(msg)
{
$(".modal .message").innerHtml(msg);
$(".modal").Show();
}
</script>
You can set the action that OnClientClick should perform in your codebehind in exactly the same way:
protected void Page_Load(object sender, EventArgs e)
{
btnSave.OnClientClick = "return confirm('Are you sure you want to do this thing?');";
}
You can use below code in c# to call javascript function. Below code will execute afterpostback() javascript function:
ClientScript.RegisterStartupScript(GetType(), Javascript, "javascript:afterpostback();", true);
And you can write code in javascript function to display any div or popup:
<script language="javascript" type="text/javascript">
function afterpostback() {
//Here you can write javascript to display div/modal
}
</script>
One way I've handled this previously was to have 2 buttons on the page. The first would be initially visible and labeled "Submit". The second would be initially hidden and labeled "Confirm". The "Submit" button would postback upon click and perform your server side checks/validation. If those checks failed, an appropriate error message would be displayed. If those checks passed, an appropriate "Please confirm your submission"-type message would be displayed, the "Submit" button would become hidden, and the second "Confirm" button would become visible. When that Confirm button was clicked, it would postback again and fully submit.
EDIT: I forgot to mention, there's a bit more to this that occurred to me after I initially posted. You'll have to protect the fields from being edited in the event the server-side verification is successful as you obviously don't want the user changing values and then clicking the Confirm button. That means disabling all the input controls - which could be a pain if you have a lot. You also have to give them a way to (intentionally) Edit in case the server side verification passes, you display the Confirmation, and they change their minds - so basically you'd need a third "Cancel/Edit"-type button that would put the form back in edit mode and show your initial Submit button.

Selenium Click() does not work with ASP.NET LinkButton

I'm Writing a Selenium text case for an ASPX page. I want to click this ASP.NET asp:LinkButton element:
<asp:LinkButton runat="server" OnClick="Test_Click" Text="Just try to click me" ID="testtest123"></asp:LinkButton>
Which appears like this in the HTML page generated by .NET:
<a id="testtest123" href="javascript:__doPostBack('testtest123','')">Just try to click me</a>
But while Selenium has no problem finding the element, the Click() does nothing. I get no element missing exceptions or timeouts, the testcase just runs on as if the click fired properly.
Here's the simple line for clicking the element;
Browser.Driver.FindElement(By.Id("testtest123")).Click();
This code works fine with other ASP elements such as buttons and text boxes. I use C# to write my test cases using the 64 bit webdriver and IE 11.
I researched the solutions here: ASP.Net LinkButton Prevent Postback Not Working - JavaScript but they do not seem to apply to my situation:
Any help would be greatly appreciated!
EDIT: I posted another thread about the issue on this website:
https://code.google.com/p/selenium/issues/detail?id=7846&can=8&colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary
I had a similar problem where some controls were rendered as espected and other don't, so are you sure the link ID is "testtest123"?
You have to set Client ID Mode to static in order to make the HTML ID be the same as in the .NET (the default is inherit, but in the web.config it is generlly set to be AutoID).
<asp:LinkButton runat="server" OnClick="Test_Click" Text="Just try to click me" ID="testtest123" ClientIDMode ="Static"></asp:LinkButton>
If the rendered HTML is actually <A id=testtest123 then that is not valid HTML since the attribute does not have quotation marks around the value. If this is actual value then the problem is further upstream than Selenium
One possibility is that selenium is correctly clicking the element, but that the linkbutton's javascript code is not executing quickly enough for the rest of your test. This is because when selenium encounters an <input type="submit"> tag (like asp.net button controls), it knows that it has to wait for the form submission before going to the next test step. However, a linkbutton is just an <a> tag, and worse, it has javascript as the href as opposed to a url. So it's possible that the postback javascript takes 50 milliseconds to execute or whatever, in that case, it's possible a test like this:
step n: click linkbutton - selenium does not know how long this takes so proceeds to next step
step n+1: click some button - if this happens before the js finishes executing, it would be like step n did not happen at all
This is plausible in the case of selenium because it operates at the speed of a program, whereas a human tester would never be able to click the next step quickly enough to cause such a problem. The fix for this is to add a delay step, or, to add a watch step on a javascript variable that you set on click of your linkbutton.
Edit:
Ok, so then this is not the issue. I'm almost positive it has something to do with the javascript in the href, though, so could you try the answer here: https://stackoverflow.com/a/18847713/1981387 ?

Run Javascript when Asp.net page is loading

I wonder if there is way to run JS code whenever a asp.net page is contacting the server.
I.e. I'm looking for a general event handler that is triggered whenever a call to the server is made for runat="server" components.
I know there's a way to get jQuery.ajax() to run JS code before and after a call to the server is made, but I'm not sure how to do it in asp.net. Especially, since this projects uses a lot of custom components.
The goal here is to show some kind of loading image when a button is clicked, to prevent the user to click a button twice and also to show the user that the system is working.
If the click causes the page or an updatepanel to refresh, I'd only like to display the loading image before the refresh, eg. User clicks, "loading" is shown, page/update panel is refreshed (causing the "loading" to disappear), the new page/content is displayed as normal.
Update 1:
I can't use UpdateProgress because some of the buttons aren't inside UpdatePanels. What I really want to do is to fire a JS as soon as any button/control that will contact the server is clicked. I.e. if the user clicks a dropdown which doesn't contact the server, nothing should happend. But if that dropdown has any connection to the server, a JS should be run.
I understand that this is ASP.NET Ajax and not jQuery Ajax, I only used jQuery as an example. Because I've used a jQuery method before (with jQuery Ajax) to trigger JS before the server call was made. Eg. to lock the element that was clicked or to display a "Loading..." screen.
I could of course add a bit of a JS hack to every page which adds a "onclick" event to every button manually, but I thought it would be better if there was a general solution for this (since I've got lots of pages, each with a few buttons that contact the server on them).
Update 2:
When I think about it, it doesn't necessarily need to be a JS that is triggered. It would be good enough if the page somehow only made sure that the same button wasn't clicked twice. Either by disabeling the button or by adding something in front of it (like a "Loading..." screen).
You can use an UpdateProgress for this to use with update panels, but if you are doing a full page postback (i.e. not ajax) the only loading animation you can have is the browsers own.
UpdateProgress:
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
Shiny loading aninmation
</ProgressTemplate>
</asp:UpdateProgress?
Here is how you can do it using jquery:
$(function() {
$('a[href]').on('click', function(e) {
var self = this;
e.preventDefault();
loadAsync($(self).attr('href'));
});
});
function loadAsync(url) {
$('div#result').fadeOut(200, function() {
$('div#loader').fadeIn(200, function() {
$.get(url, function(data) {
$('div#result').html($(data));
}).done(function() {
console.log('done');
}).fail(function() {
$('div#result').html('Error');
}).always(function() {
$('div#loader').fadeOut(200, function() {
$('div#result').fadeIn(200);
});
});
});
});
}

Show a loading animation while function completes

I have a function inside my .aspx.cs code which takes wuite a long time to do the processing until when I want to display a cool loading animation. I looked some of the earlier posts but either these didn't work for me, or were having solution specific to Page loading scenario (not loading a while a function completes).
I guess the right approach would be to fire a Javascript startLoader() function just before the the main function starts (which takes a long time), and then call a stopLoader() from the .aspx.cs itself to stop the loader when the function ends. Any suggestions how to implement this?
Yes, I've done this in ASP.NET Web From (not a ASP.NET MVC solution). You need to provide OnSubmit client side event handler. It basically break down to three parts: Javascript, HTML Div, and one line code behind:
Javscript:
function ShowLoading(e) {
// var divBg = document.createElement('div');
var divBg = document.getElementById('blockScreen');
var divLoad = document.createElement('div');
var img = document.createElement('img');
img.src = 'images/ajax-loader.gif';
divLoad.setAttribute("class", "blockScreenLoader");
divLoad.appendChild(img);
divBg.appendChild(divLoad);
document.getElementById('blockScreen').style.display = 'block';
// These 2 lines cancel form submission, so only use if needed.
//window.event.cancelBubble= true;
//e.stopPropagation();
}
function HideLoading() {
//alert('hideloading');
document.getElementById("form1").onsubmit = null;
document.getElementById('blockScreen').style.display = 'none';
//alert('done');
}
Add following DIV
<div id="blockScreen" class="blockScreen" style="display:none"> </div>
Finally, add the following to Page_Load in code behind.
Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), "submit", "ShowLoading()");
Now, all of your page postbacks are essentially have to call onsubmit event. It will display the animation before the page postback finishes.
if you really want to do, then the only way is webworkers. You've probably heard about them, or if not, i seriously recommend to have a look.
Yes, fire startLoader() on OnCliencClick of your button or whatever element you are using to fire the server-side event and call stopLoader() from the server-side at the end of your process. Something like this:
//rest of the server-side code above ...
Page.ClientScript.RegisterStartupScript(this.GetType(), "someKey", "stopLoader();", true);
If you don't mind that the browser is not responsive in the meantime, the simplest way of doing this is using an animated gif:
Activity indicators
ajaxload.info
webscriptlab
The trick is showing the image when starting your processing, and hiding it when finished. You can show it in an img, and use jQuery or whatever you want to show/hide it.
If you need the browser to keep responsive, use Web Workers. But be aware that some of the older browsers don't support it. See this reference

Animation Extender Problems

I have just started working with the AnimationExtender. I am using it to show a new div with a list gathered from a database when a button is pressed. The problem is the button needs to do a postback to get this list as I don't want to make the call to the database unless it's needed. The postback however stops the animation mid flow and resets it. The button is within an update panel.
Ideally I would want the animation to start once the postback is complete and the list has been gathered. I have looked into using the ScriptManager to detect when the postback is complete and have made some progress. I have added two javascript methods to the page.
function linkPostback() {
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(playAnimation)
}
function playAnimation() {
var onclkBehavior = $find("ctl00_btnOpenList").get_OnClickBehavior().get_animation();
onclkBehavior.play();
}
And I’ve changed the btnOpenList.OnClientClick=”linkPostback();”
This almost solves the problem. I’m still get some animation stutter. The animation starts to play before the postback and then plays properly after postback. Using the onclkBehavior.pause() has no effect. I can get around this by setting the AnimationExtender.Enabled = false and setting it to true in the buttons postback event. This however works only once as now the AnimationExtender is enabled again. I have also tried disabling the AnimationExtender via javascript but this has no effect.
Is there a way of playing the animations only via javascript calls? I need to decouple the automatic link to the
buttons click event so I can control when the animation is fired.
Hope that makes sense.
Thanks
DG
The flow you are seeing is something like this:
Click on button
AnimationExtender catches action and call clickOn callback
linkPostback starts asynchronous request for page and then returns flow to AnimationExtender
Animation begins
pageRequest returns and calls playAnimation, which starts the animation again
I think there are at least two ways around this issue. It seems you have almost all the javascript you need, you just need to work around AnimationExtender starting the animation on a click.
Option 1: Hide the AnimationExtender button and add a new button of your own that plays the animation. This should be as simple as setting the AE button's style to "display: none;" and having your own button call linkPostback().
Option 2: Re-disable the Animation Extender once the animation has finished with. This should work, as long as the playAnimation call is blocking, which it probably is:
function linkPostback() {
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(playAnimation)
}
function playAnimation() {
AnimationExtender.Enabled = true;
var onclkBehavior = $find("ctl00_btnOpenList").get_OnClickBehavior().get_animation();
onclkBehavior.play();
AnimationExtender.Enabled = false;
}
As an aside, it seems your general approach may face issues if there is a delay in receiving the pageRequest. It may be a bit weird to click a button and several seconds later have the animation happen. It may be better to either pre-load the data, or to pre-fill the div with some "Loading..." thing, make it about the right size, and then populate the actual contents when it arrives.
With help from the answer given the final solution was as follows:
Add another button and hide it.
<input id="btnHdn" runat="server" type="button" value="button" style="display:none;" />
Point the AnimationExtender to the hidden button so the firing of the unwanted click event never happens.
<cc1:AnimationExtender ID="aniExt" runat="server" TargetControlID="btnHdn">
Wire the javascript to the button you want to trigger the animation after the postback is complete.
<asp:ImageButton ID="btnShowList" runat="server" OnClick="btnShowList_Click" OnClientClick="linkPostback();" />
Add the required Javascript to the page.
function linkPostback() {
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(playOpenAnimation)
}
function playOpenAnimation() {
var onclkBehavior = ind("ctl00_aniExt").get_OnClickBehavior().get_animation();
onclkBehavior.play();
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.remove_endRequest(playOpenAnimation)
}

Categories