Selenium can't find iframe after postback inside the iframe - c#

I am trying to create a test where I have to fill out some information inside an iframe. Getting access to the iframe work fine and I can fill out information inside the frame. The issue is that when I fill out a textbox 'A' it has a postback attached to it which reloads the content inside the iframe, to fill out another textbox 'B' depending on the information inside textbox A.
Here are my observations:
When I first locate the iframe it looks like this:
<iframe frameborder="0" src="<removed for clearity>">...</iframe>
After the postback has occurred it looks like this:
<iframe frameborder="0" src="<removed for clearity>" cd_frame_id_="668325d5a0a2a8cb76a92b9eb819d327">...</iframe>
So something changed.
In my C# code first find my frame like so (and yes that is the best way sadly):
var iframe = driver.FindElement(By.XPath("//div[#rawtitle=\"TIME\"]//table//tbody//tr//td//div//div//iframe"));
driver.SwitchTo().Frame(iframe);
I can easily enter text in textbox A:
var completed = driver.FindElement(By.Id("MainContent_txtCompletedHours"));
completed.SendKeys("0,25");
Then I wait for textbox B to be filled but at this point, I can't locate it and I can't locate the iframe either. I tried to relocate the frame again to switch to it again, but I can't find the element. It hasn't moved position. It just got that cd_frame_id attribute. Here is the code where I try to re-locate the iframe:
while (true)
{
try
{
iframe = driver.FindElement(By.XPath("//div[#rawtitle=\"TIME\"]//table//tbody//tr//td//div//div//iframe"));
driver.SwitchTo().Frame(iframe);
invoiced = driver.FindElement(By.Id("MainContent_txtInvoiceHours"));
if (invoiced.Text == "0,25") // and wait for it
break;
}
catch (NoSuchElementException e)
{
Debug.WriteLine("Could not find element, retrying...");
}
finally
{
Thread.Sleep(500);
}
}
The code fails when I try to get hold of the iframe element.
How can I get hold of the iframe again, after the postback inside the frame?

As you mentioned when you fill out a textbox 'A' it has a postback attached, so we will take help of a unique xpath hich identifies the <iframe> as follows :
//Ensure that you are back to the base frame
driver.SwitchTo().DefaultContent();
//SwitchTo the intended frame
driver.SwitchTo().Frame(driver.FindElement(By.XPath("//iframe[contains(#src,'<removed for clearity>')]")));

Related

Setting Content in RadEditor

I have visited the Telerik's website and viewed their demos etc...
But I am having problems trying to load content (html) in the RadEditor.
I have a Button_Click event where I get my html string and then set it to the RadEditor. The RadEditor is inside a RadWindow and only becomes visible when the button is clicked.
protected void btnSubmitHtml_Click(object sender, EventArgs e)
{
RadEditor1.Content = "<p>hello there</p>";
RadWindow1.Visible = true;
}
This doesn't show the html inside the RadEditor for some odd reason. I suspect it is the page life cycle that is involved with this problem.
Are there any suggestions to solve this?
I have encountered this problem multiple times and never found a "Proper" resolution.
However, a great work around is to simply set the content from the clientside via injected script. The end result is the same, and if you can tolerate the 10 millisecond delay, worthy of consideration.
EDIT after comment requested reference
Basically all you need to get an instance of the editor using ASP.NET WebForms $find function. That takes the html ID of the root of the rendered object and returns the client side viewModel if one exists.
The $(setEditorInitialContent) call at the end assumes that jQuery is present and delays the execution of the function till page load.
<telerik:radeditor runat="server" ID="RadEditor1">
<Content>
Here is sample content!
</Content>
</telerik:radeditor>
<script type="text/javascript">
function setEditorInitialContent() {
var editor = $find("<%=RadEditor1.ClientID%>"); //get a reference to RadEditor client object
editor.set_html("HEY THIS IS SOME CONTENT INTO YOUR EDITOR!!!!");
}
$(setEditorInitialContent);
</script>
Take a look here to see how to get a RadEditor to work in a RadWindow: http://www.telerik.com/help/aspnet-ajax/window-troubleshooting-radeditor-in-radwindow.html.
Said shortly, here is what you need to have in the OnClientShow event of the RadWindow:
function OnClientShow()
{
$find("<%=RadEditor1.ClientID %>").onParentNodeChanged();
}
To edit Html code only you can add -
EnableTextareaMode="true"
Add this property to the RadEditor.
I suspect that the way the control tries to interpret the html might be one of the problems. The other thing that may be causing this problem is the page life cycle.

Page out of frame load event runs several times

I have an iframe on my first page and am redirecting the frame to second page on my second page I am using javascript to jump out of iframe as follow :
<script language="JavaScript" type="text/javascript">
<!--
function breakout_of_frame() {
if (top.location != location) {
top.location.href = document.location.href;
}
}
-->
</script>
My problem is that this will make the page run several times and my code in load event will execute (say if i am sending email on load will send three times).
Now I have tried using boolean values to see when email is sent set it to true and dont send if false...but it still will not work. any suggestions to prevent this from happening?
A simple, rough and ready solution:
On your following request, append something to the query string of your request to identify the difference between the two pages.
When you read document.location.href, parse it for the differing element and react accordingly.
for example:
your-domain/your-path/your-file?donealready=yes
alert(document.location.href) //will have the parameter at the end
//parse this to determine how to react

How do I fire a aspx script when a dynamically added button is clicked?

Here is the context:
I am building a .aspx page that allows the user to administrate some xml documents we have on our server. The page content is loaded using AJAX, so buttons and forms are dynamically added to the document.
If I had static buttons that I was creating within the .aspx page before it loads on the client's machine, I could attach an event to it very easily. However, I'm dynamically adding and removing buttons and forms on the fly, using jQuery.
Here is a simplified example:
In the following jsFiddle, I'm pretending that the html document contains the following script:
<script language="C#" type="text/C#" runat="server">
void SaveAllChanges(Object sender, EventArgs e)
{
Button clickedButton = (Button)sender;
clickedButton.Text = "foobar";
}
</script>
And that I have a javascript file that contains the following:
$('button.buttonGenerator').click(function() {
$('.buttonContainer').append(
'<button onclick="SaveAllChanges">' +
'Save All Changes!' +
'</button>'
);
});
Obviously the buttons I am creating can not run the function SaveAllChanges with the way it is now. I added the onclick attribute to show what I needed to happen, in a pseudo-code kind of style.
How can I make it so that dynamically added buttons can run the C# method I have defined within the script tag at the top of the document?
Here is the jsfiddle: http://jsfiddle.net/2XwRJ/
Thanks.
You can give all buttons that must save changes a common class (e.g. class="ajaxButton") and have one jQuery method that responds to click events on elements matching that class (use live so that updates to the DOM are reflected).
$("button.ajaxButton").live("click", function(){
// Perform your Ajax callback to run server-side code
});
What you need to do is use something like ..
$(document).ready(function() {
$('button.buttonGenerator').click(function() {
$('.buttonContainer').append(
'<button id="#dynamicCommentButton" onclick="SaveAllChanges">' +
'Save All Changes!' +
'</button>'
);
});
$(document).on('click', '#dynamicCommentButton', function() {
alert($(this).attr('id'));
});
});
You are not going to be able to add the buttons like you have it there as this code here is just adding it as an HTML DOM element and the onclick attribute will be the on the client element. As a result clicking the button will try fire a SaveAllChanges javascript function
$('.buttonContainer').append(
'<button onclick="SaveAllChanges">' +
'Save All Changes!' +
'</button>'
);
What would be best would be to create that SaveAllChanges function in javascript and then you can handle it from there. Two of the ways I see you being able to do this are:
Have a http endpoint setup (script service, web api or just posting to a page) that you call using Ajax from your javascript. You can then pass through any needed arguments.
You could have a hidden element and hidden button on the page so that when the javascript is called it populates any arguments you need and then clicks the hidden button and posts the page back.
Personally I would choose the first approach from a user experience stand point as the page will not be posting back each time. I have used something similar to the second approach and it works fine but just feels very clunky.

Fix for Anchors while using faux full height Columns in CSS

When the Page_Load event gets called to load the page, how would I have the page load already scrolled to a particular id. I cannot use a named anchor # because it breaks my css.
I can use javascript's scrollto function but i don't know how to call javascript from the asp.net page_load event.
I have several headers, and a menu that sorts the contents within each header. So each header has a sort menu. When I sort say Header 2 by "Oldest" I reload the page and change the orderby stuff in my sql and repopulate the repeater under each header. On load I would like the page to load already scrolled to Header 2. I would normally just use #Header2 on the redirect, but I can't use the this anchor method because it breaks my code.
Is there any neat method to accomplish this?
The css issue has to do with full length columns and having a border in the gutter. I know I can use images, but the nature of my pages would require the css to be dynamic to account for the different widths and apply the appropriate background image.
I ended up setting the <body> tag to runat="server" and assigning an id="body". I then added this code in the Page_Load event:
if (Request.QueryString["view"] != null && Request.QueryString["view"] != "")
{
body.Attributes["onload"] = "scroll('" + Request.QueryString["view"] + "');";
}
else //Probably redundant, but I have partial postbacks
{
body.Attributes.Remove("onload");
}
It calls this JS function:
function scroll(id)
{
var a = document.getElementById(id);
if (a != null) {
window.scrollTo(0, a.offsetTop);
}
}
So instead of using #header2, I use a querystring of view=header2 because I have to do a postback anyway. If I just want to go to a named anchor I use onclick="scroll('header2')" in the link.

how to print the content of a label or panel in asp.net?

I have a label control in a page in asp.net 2.0 and a button Print.
Clicking on print button I need to print the content of the label and I need same for a panel also.
Is it possible to implement this?
If yes then how to implement that?
Please help.
What about Window.Print() method? Because execcommand method will not work other browsers that IE. Use CSS media option to control the print area.
You would need to add some client side javascript to your Print button to execute the brower's print command. The javascript below could be used to print the whole document page and would be a good place to start. Note: It isn't possible to do this without displaying the print dialog unless you use a third party component.
// Print Page
window.print();
If you wanted just to print certain sections of your page you can achieve this two ways. Firstly, you could render the content to be printed into a hidden iframe and then print just that frame. You would do this using the same code as above only from within the frame itself.
Secondly, you could use a media style print style sheet, a CSS that applies only when printing. Inside this sheet you would set the styles you wanted to print as normal and the styles you didn't want to print to "display:none". The link below contains more information on print stylesheets.
http://www.webcredible.co.uk/user-friendly-resources/css/print-stylesheet.shtml
One more approach could be to open new window and populate the contents of div you wanted to print and have print link/button on that page.
Ex:
var win = window.open(...)
win.document.body.appendChild(document.getElementById('divToPrintId'))
This is how the code will look like this approach is used to print the content/part of the page.
Use below code in button onclick event
ClientScript.RegisterStartupScript(this.GetType(), "PrintOperation", "PrintGridData()", true);
Above link will call function named PrintGridData() which is written in head section as below
<script type="text/javascript">
function PrintGridData()
{
var prtGrid = document.getElementById('<%=GridView.ClientID %>');
prtGrid.border = 0;
var prtwin = window.open('', 'PrintGridViewData', 'left=100,top=100,width=1000,height=1000,tollbar=0,scrollbars=1, status=0,resizable=1');
prtwin.document.write(prtGrid.outerHTML);
prtwin.document.close();
prtwin.focus();
prtwin.print();
prtwin.close();
}
</script>
in this script it will only print div name GridView and other part will not be printed

Categories

Resources