I have a page that is dynamically loaded and contains a button. I am trying to wait for the button to be available to be clicked with selenium using the C# bindings. I have the following code:
WebDriverWait wait = new WebDriverWait(Driver.Instance, TimeSpan.FromSeconds(30));
wait.Until(ExpectedConditions.ElementToBeClickable(By.Id("addInspectionButton")));
var button = Driver.Instance.FindElement(By.Id("addInspectionButton"));
button.Click();
this doesn't work though. The click event is never fired. The selenium script doesn't throw an exception alerting that the element with an ID of "addInspectionButton" doesn't exist. It just isn't able to click it. If i add a Thread.Sleep(3000) Between the wait statement and the line where I get a handle on the button element it works.
Am i not using the ExpectedConditions.ElementToBeClickable correctly here?
It turns out that an event was being bound to the button after the button was dynamically added to the page. So the button WAS being clicked but nothing was happening. The sleep thread being placed in the code was just giving the client side event time to be bound.
My solution was to click the button, check for the expected result, and then repeat if the expected result wasn't in the DOM yet.
Since the expected result was for a form to open I polled the DOM like this:
button.Click();//click button to make form open
var forms = Driver.Instance.FindElements(By.Id("inspectionDetailsForm"));//query the DOM for the form
var times = 0;//keep tabs on how many times button has been clicked
while(forms.Count < 1 && times < 100)//if the form hasn't loaded yet reclick the button and check for the form in the DOM, only try 100 times
{
button.Click();//reclick the button
forms = Driver.Instance.FindElements(By.Id("inspectionDetailsForm"));//requery the DOM for the form
times++;// keep track of times clicked
}
Related
I have been attempting to fill in a few HTML input boxes from a C# form application. So far I am able to fill in the form and click buttons without issue. Triggering the form validation fields has been a whole different story. When I look at the events in the source, I see more then onfocus that is listed in code below. I was trying to avoid firing the javascript manually and I know this question has been asked, but none of the answers I see are working.I have attempted to simulate clicks, but still doesn't allow the form to be submitted and complains the input box is still empty until I click in it.
Events I see listed in browser debugger. These could be up stream and not correct, regardless I have attempted to fire them.
blur
click
focus
mouseout
mouseover
shown
code from input box that needs to be triggered.
onfocus="if (!this.tc) addLoadEvent(function() {var e = gel('sys2.incident_group'); if (!e.ac) new AJAXReferenceCompleter(gel('sys2.incident_group'), 'sys2.incident_group', '', 'true'); e.ac.onFocus();})" aria-required="true" aria-expanded="false">
var obj = webBrowser1.Document.Window.Frames[0].Document.GetElementsByTagName(tag).GetElementsByName(field);
HtmlElement ele = obj[0];
if (ele.Name == field)
{
ele.Focus();
ele.InvokeMember("blur");
ele.InvokeMember("click");
ele.InvokeMember("mousedown");
ele.InvokeMember("focus");
ele.InvokeMember("mouseout");
ele.InvokeMember("mouseover);
ele.InvokeMember("shown);
}
Update: attempted to use synchronous task and no change occurred. It almost appears lag from when the field's are being populated are keeping everything from working correctly. I can fire off one method filling in the boxes, then use a button for second and I pass the validation. When I see my submit button fire it occurs before the boxes are populated.
I have a C# 4.0 WinForms application, which has a WebBrowser control and 2-buttons.
Clicking the first button sends a URL to the browser to navigate to a specified webSite.
Clicking the second button parses the OuterHtml of the webBrowser1.Document, looking for an "https://..." link for File Download.
The code then uses a webClient.DownloadFileAsync to pull down a file for further use in the application.
The above code successfully works, if I manually click those buttons.
In an effort to automate this for the end-user, I place the first button's click event, i.e. btnDisplayWeb.PerformClick(); in the form's Form1_Load event. This also works, allowing the webBrowser1 to populate its Document with the desired webSite.
However, I am unable to programatically click the 2nd button to acquire the web link for file download.
I have tried to place the 2nd buttons click event within the browser's DocumentCompleted event, as shown below.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
btnMyUrl.PerformClick();
}
However, from what I've read on StackOverFlow and other sites, it's possible that this particular event gets called more than once, and hence it fails.
I've also attempted to loop for a number of seconds, or even use a Thread.Sleep(xxxx), but the browser window fails to populate until the sleep or timer stops.
I attempted to use the suggestions found on the following StackOverFlow site shown below.
How to use WebBrowser control DocumentCompleted event in C#?
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
string url = e.Url.ToString();
if (!(url.StartsWith("http://") || url.StartsWith("https://")))
{
// in AJAX
}
if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath)
{
// IFRAME
}
else
{
// REAL DOCUMENT COMPLETE
}
}
However, in parsing the OuterHtml, nothing is returned in the first two sections, and in the third section, other elements are returned instead of the desired "https://..." link for File Download.
Interestingly, if I use a webBrowser1.ReadyState event, as shown below, and place a MessageBox inside DocumentCompleted, this seems to allow the browser document to complete, because after clicking the OK button, the parsing is successful.
if (webBrowser1.ReadyState == WebBrowserReadyState.Complete)
{
MessageBox.Show("waiting", "CHECKING");
btnMyUrl.PerformClick();
}
However, I then have the difficulty of finding a way to click the OK button of the MessageBox.
Is there another event that occurs after the DocumentCompleted event.
OR, can someone suggest how to programmatically close the MessageBox?
If this can be done in code, then I can perform the buttonClick() of the 2nd button in that section of code.
After finding that the addition of a MessageBox allows the webBrowser1.Document to complete, and using webBrowser1.ReadyState event within the webBrowser_DocumentCompleted event, all I needed to do, was to find a way to programmatically close the MessageBox.
Further searching on StackOverFlow revealed the following solution on the site below.
Close a MessageBox after several seconds
Implementing the AutoClosingMessageBox, and setting a time interval, closed the MessageBox and allowed my button click, i.e. btnMyUrl.PerformClick(); to successfully parse the OuterHtml and now the code works properly.
Hopefully, if someone else discovers that placing a MessageBox within the webBrowser_DocumentCompleted event allows the document to complete; the aforementioned AutoClosingMessageBox will assist them as well.
I have a page that consists of an updatepanel with a DropDownList, a textbox and a button in it. The updatepanel has a trigger for the button. This works fine for all my "error" cases, such as "No input!", when I pop an alert with
ScriptManager.RegisterStartupScript(UpdatePanel1, UpdatePanel1.GetType(),"noName", "window.onload = function(){alert('Please enter a username!');window.location ='Accounts.aspx';}", true); and the like.
But when I don't hit the alerts and the button event runs all it should I seem to land in some dead zone. My alerts stop displaying even though the code runs (checked by debugging), the button event does still preform all tasks as it should. However, if I refresh the page I get the classic:
To display webpage again. After I click retry my "latest" message pops up and then it works just like on first load.
So, I'm guessing that the PostBackTrigger on my button triggers a PostBack before or during the event execution since when the event is done nothing more happens until I reload. I'm thinking I need to add a reload at the end of my button event. Therefore my question is: How do I add a reload of the page/panel at the end of a button event?
Edit:
Forgot to mention that when the button event runs all it should it edits the web.config file, if this somehow could cause my issue.
I found a solution to my problem, by removing my triggers and instead using:
ScriptManager1.RegisterPostBackControl(Button);
Then I could also put an:
UpdatePanel1.Update();
At the end of my button event.
In the Page_Load section of my code I am dynamically creating a form. Each row has a save button at the end and I want the form to asynchronously post back when someone clicks the "save" button at the end of a row. I can't seem to achieve this though. I click the button and nothing happens. The click event is not even firing so my guess is that the trigger is not being added properly. Any ideas how I can get this functionality working?
Here is a snippet of my code that I believe is where the problem lies.
Button submit = new Button();
submit.ID = "Submit_" + reader["SEQN"];
submit.Text = "Save";
submit.Click += submitTest;
AsyncPostBackTrigger apt = new AsyncPostBackTrigger();
apt.ControlID = submit.UniqueID;
UpdatePanel1.Triggers.Add(apt);
A couple things i see. Set the trigger Event to the event you want executed: apt.EventName = . The second thing is the id of the button correct after final page rendering. Check the Buttons id value from web inspector or firebug and see if its the same as what you set for controlid.
My app needs to click a button on a page x number of times (user defined).
The page works like this: After you click a button, the page reloads with the same yes/no buttons. Using my code, the app goes crazy and starts clicking way too fast and then crashes.
What can I do so it waits until the page reloads?
int toGet = Convert.ToInt32(numberOfTimes.Text);
int got = 0;
while (got < toGet)
{
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
webBrowser1.Document.GetElementById("votea").InvokeMember("click");
got++;
}
Add a delay, e.g. 500ms, between the clicks inside your while loop by using setTimeout() function