StaleElementException Clicking accept terms - c#

I am trying to click an accept terms checkbox while signing up for an account in selenium. My code seems to work, but it only works on some of my customers computers. On those who it doesn't work, it throws a staleelementexception. I have looked online to find a way to handle it such as
bool result = false;
int attempts = 0;
Thread.Sleep(500);
while (attempts < 100)
{
Thread.Sleep(700);
try
{
driver.Navigate().Refresh();
IJavaScriptExecutor javascriptExecutor = (IJavaScriptExecutor)driver;
Actions action = new Actions(driver);
IWebElement db = driver.FindElement(By.XPath("/html/body/div[1]/div/div[2]/form/div[1]/label/span[2]"));
action.MoveToElement(db).Build().Perform();
javascriptExecutor.ExecuteScript("arguments[0].click();", db);
result = true;
break;
}
catch (WebDriverException ee)
{}
attempts++;
}
nextPage(driver, wait);
I have also tried just clicking on it with the driver and clicking with actions, but nothing seems to be working for certain users. I am at the point of not knowing the solution or not knowing what else I can do.
UPDATE 1:
While I mentioned this in the comments, I still do receive a stale element, but I seem to of found the cause. When using specific country proxies, it seems that this is thrown. Now the element is still there, but why would the proxies cause this to happen?

A stale element usually means the DOM changed from the moment you found the element. There are a few things you can try:
Inspect the page and try to determine what is changing for those users. Maybe MoveToElement triggers a tooltip or some classes to change. If you can identify such change you can wait for it to be done and then get the element
Try using fluent waits as explained here
Try clicking the element as soon as it is identified driver.findElement(by.xpath(xpath)).click();
Note: The JavaScript click that you are using in the snippet works well for CLickIntercepted exceptions, not so much for StaleElements. The element will be stale regardless on how you click it

Related

CodedUI Selenium QTAgent32.exe Stale Element Reference Exception on control Exists

In Visual Studio, C#, I have this test:
BrowserWindow.CurrentBrowser = "chrome";
var browser = BrowserWindow.Launch(BaseURL + "/wizard");
var button = new HtmlButton(browser);
button.SearchProperties.Add(HtmlButton.PropertyNames.Id, "NewUser");
ClickButton(browser, "Login");
Playback.Wait(10000);
try {
bool exists = button.Exists;
} catch {}
ClickButton initiates a javascript function which:
1. Hides all of the buttons.
2. initiates an ajax promise.
3. On Success, redirects to a dashboard page
4. On failure, un-hides the buttons.
As you'd imagine, 10 seconds after clicking the Login button, the "NewUser" button is certainly gone/stale since I am logged in.
If I debug, I can see that I get a StaleElementReferenceException. If I run the tests, the browser explodes saying QTAgent32.exe has stopped working.
If I comment out the button.Exists line, I get no errors.
What I'm really attempting is a loop which checks for either the existence of the NewUser button, or the existence of a field on the Dashboard, so I know the result of the button click.
My problem is that the browser explodes when I run the tests.
Instead of using Exists use button.TryFind() which will give you a boolean value and wont cause an exception.
Note: this my slow the process - to solve this:
reduce the Playback.PlaybackSettings.SearchTimeout before the search and return it to default value after search has finished:
var def = Playback.PlaybackSettings.SearchTimeout;
Playback.PlaybackSettings.SearchTimeout = 1000;
{
Do workd
}
Playback.PlaybackSettings.SearchTimeout = def ;

JavaScript window.open returns null sometimes

I am attempting maintenance on a system I did not write (and aren't we all?). It is written in C Sharp and JavaScript, with Telerik reports.
It has the following code included in JavaScript that runs when the user clicks a button to display a report in a separate window:
var oIframe = $("iframe id='idReportFrame' style='display:none' name='idReportFrame' src=''>");
oIframe.load(function() { parent.ViewReports(); });
oIframe.appendTo('body');
try
{
$('#idReportForm').attr('target', 'idReportFrame');
$('#idReportForm').submit();
}
catch (err) { // I did NOT write this
}
Then the load function:
function ViewReports()
{
var rptName = $("#ReportNameField").val();
if (rptName == '') { return false; }
var winOption = "fullscreen=no,height=" + $(window).height() + "left=0,directories=yes,titlebar=yes,toolbar=yes,location=yes,status=no,menubar=yes,scrollbars=no,resizable=no, top=0, width=" + $(window).width();
var win = window.open('#Url.Action("ReportView", "MyController")?pReportName=' + rptNameCode, 'Report', winOption);
win.focus();
return false;
}
When I execute this (in Chrome, at least), it does pop up the window and put the report in it. However, breakpoints in the c# code indicate that it is getting called 2 or 3 times. Breakpoints in the JavaScript and examination of the little log in the JavaScript debugging environment in Chrome show that the call to win.focus() fails once or twice before succeeding. It returns an undefined value, and then it appears that the first routine above is executed again.
I am inclined to think it some kind of timing issue, except that the window.open() call is supposed to be synchronous as far as I can tell, and I don't know why it would succeed sometimes and not others. There is a routine that gets executed on load of the window, perhaps that's somehow screwing up the return of the value from open().
I am not a JavaScript person much, as those of you that are can likely tell by this time. If there is something with the code I've put here that you can tell me is incorrect, that's great; what I'm more hopeful for is someone who can explain how the popup-report-in-frame is supposed to work. Hopefully I can do it without having to replace too much of the code I've got, as it is brittle and was not, shall we say, written with refactoring in mind.
From what I could find the window.open will return null when it fails to open. Something may be keeping the browser from opening additional windows a couple of times; maybe it is a popup blocker.
The actual loading of the url and creation of the window are done asynchronously.
https://developer.mozilla.org/en-US/docs/Web/API/Window.open
Popup blocking
In the past, evil sites abused popups a lot. A bad page could open
tons of popup windows with ads. So now most browsers try to block
popups and protect the user.
Most browsers block popups if they are called outside of
user-triggered event handlers like onclick.
For example:
// popup blocked
window.open('https://javascript.info');
// popup allowed
button.onclick = () => {
window.open('https://javascript.info');
};
Source: https://javascript.info/popup-windows
I just ran into this and it seems to be because I had a breakpoint on the line that calls window.open and was stepping through the code, in Chrome dev tools. This was extremely hit-and-miss and seemed to fail (return null, not open a window, whether one already existed or not) more times that it succeeded.
I read #Joshua's comment that the creation is done asynchronously, so I figured that forcing the code to 'stop' each time I step might be screwing things up somehow (though on a single line like var w = window.open(...) doesn't seem like this could happen).
So, I took out my breakpoint.. and everything started working perfectly!
I also took note of https://developer.mozilla.org/en-US/docs/Web/API/Window/open where they specify that if you are re-using a window variable and name (the second argumen to window.open) then a certain pattern of code is recommended. In my case, I am wanting to write HTML content to it, rather than give it a URL and let it async load the content over the network, and I may call the whole function repeatedly without regard for the user closing the window that pops up. So now I have something like this:
var win; // initialises to undefined
function openWindow() {
var head = '<html><head>...blahblah..</head>';
var content = '<h1>Amazing content<h1><p>Isn\'t it, though?</p>';
var footer = '</body></html>';
if (!win || win.closed) {
// window either never opened, or was open and has been closed.
win = window.open('about:blank', 'MyWindowName', 'width=100,height=100');
win.document.write(head + content + footer);
} else {
// window still exists from last time and has not been closed.
win.document.body.innerHTML = content;
}
}
I'm not convinced the write call should be given the full <html> header but this seems to work 100% for me.
[edit] I found that a Code Snippet on Stackoverflow has a some kind of security feature that prevents window.open, but this jsfiddle shows the code above working, with a tweak to show an incrementing counter to prove the content update is working as intended. https://jsfiddle.net/neekfenwick/h8em5kn6/3/
A bilt late but I think it's due to the window not beeing actually closed in js or maybe the memory pointer not being dereferenced.
I was having the same problem and I solved it by enclosing the call in a try finally block.
try {
if (!winRef || winRef.closed) {
winRef = window.open('', '', 'left=0,top=0,width=300,height=400,toolbar=0,scrollbars=0,status=0,dir=ltr');
} else {
winRef.focus();
}
winRef.document.open();
winRef.document.write(`
<html>
<head>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
${$(id).remove('.print-exclude').html()}
</body>
</html>
`);
winRef.document.close();
winRef.focus();
winRef.print();
} catch { }
finally {
if (winRef && !winRef.closed) winRef.close();
}

How to test whether an element on the page or not under Selenium Webdriver, C#

I searched on uncountable webpages, and did not get a good answer to my question. I'm on Selenium 2.30 using C#.
I tried
if (browser.FindElement(By.XPath("xpath")).Displayed)
I tried
if (browser.FindElements(By.XPath("xpath")).Count !=0)
And also
IWebElement element = browser.FindElement(By.XPath("xpath"));
if (element.Displayed == true)
They only work when the element exist, but if not, it will pull out the exception. But that's not necessary an exception, I have something in else{} statement to handle it, I don't want the webdriver just stop me at the first point.
What I'm doing right now is
IWebElement element = null;
try
{
element = browser.FindElement(By.XPath("xpath"));
}
catch
{
}
if (element != null)
This way works so far, but I don't think this is the best solution. I appreciate if someone can show me a better way.
The way you are doing it is acceptable, but at times you will be trying to run this after performing a prior action (eg. navigating to a page) and it is usually best to give a timeout value and utilise the following WebDriverWait method:
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 0, timeout));
element = _wait.Until(x => x.FindElement(By.XPath(searchAttribute.attributeValue)));
This allows you to wait until the element exists on the page up to the timeout value (I use 5 seconds on the application I test). However, simple you can just use your code of if(element == null) then it is was not found. If you use the WebDriverWait, you will have to catch the exception if you do not want it to throw after the timeout.

Page Load Timeout - Selenium Webdriver using C#

I am using Selenium 2.25 WebDriver
I'm having a issue with finding the elements on the page and some times my test cases able to find element and sometime the page is does not load and its due to page load and if i add this below line and it seems like working:
driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(2));
my question is, i dont want to have my code scatter with the above line of code, is there a way to make it centerlize in one place?
Any help would be greatly appreciated, thanks!
If you set the timeout once, it's set for the lifetime of the driver instance. You don't need to keep resetting it. You can set this immediately after creating the driver.
IWebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts.SetPageLoadTimeout(TimeSpan.FromSeconds(2));
The only caveat for using this timeout is that not every browser may support it completely (IE does for sure, Firefox does too I think, but I don't think Chrome does).
You can try a workaround like this:
Observe the element that loads last in your page and find its id (or any other identifier). Then do something like this:
while (true)
{
try
{
IWebElement element = driver.FindElement(By.Id(...));
if (element.Displayed)
{
break;
}
}
catch (Exception)
{
continue;
}
}
This will keep looping till the element which is loaded last is displayed and breaks thereupon. The element not found exception is caught and loop is put into continuation till the element is not displayed.

How to fix "The requested resource is in use. (Exception from HRESULT: 0x800700AA)"

How can I solve this error?
"The requested resource is in use. (Exception from HRESULT: 0x800700AA)".
This appears while navigating to a different website using the WebBrowser control in C# .NET. Why?
The WebBrowser control is considered "in use" if either a navigation action is currently being processed, or any blocking dialog from the control is currently open (including context menu, Javascript alerts, NTLM login dialog, etc.). You can use the WebBrowser.IsBusy property to detect these states.
If due to a currently incomplete navigation action, you could try to stop the current navigation (if you indeed want to stop when the page is not completed loaded) or add the new navigation to a request queue and use a timer to wait until WebBrowser.IsBusy returns false.
If instead the busy state is due to one or more open blocking dialogs, you could do the same wait technique and perhaps Messagebox.Show() the user a message that pending navigation is delayed due to an open dialog window.
I had this same issue. Calling WebBrowser.Stop() did not help, and WebBrowser.IsBusy never became false.
It turns out that if the page creates any sort of dialog (alert() popups, javascript errors, NTLM login popups etc.) you can't navigate away from the page until the dialog is closed.
My solution was to prevent the dialogs from showing in the first place. Apparently preventing all of these popups is simple; just set
webBrowser.ScriptErrorsSuppressed = true;
bool go = false;
string SiteContent1 = string.Empty;
string SiteContent2 = string.Empty;
int index = 0;
WebBrowser wb = new WebBrowser();
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
try
{
if (go)
{
SiteContent2 = wb.DocumentText;
// Code to compare to contents of the webbrowser
index++;
go = false;
steps = 1;
}
if (!go)
{
if (index >= TotalSiteCount)
{
Stop();
}
else if (steps == 1)
{
wb.Navigate(UrltocompareList[index].Url1);
}
else if (steps == 2)
{
SiteContent1 = wb.DocumentText;
wb.Navigate(UrltocompareList[index].Url2);
go = true;
}
steps++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
UrltocompareList is a collection of 2 sites to compare.
TotalSiteCount is the number of items in UrltocompareList.
The form for this inherit IOleClientSite to remove media such as images, videos and no active X download to have a faster rendering time in webbrowser control.
I use this method instead of system.net.webclient to get the html of a webpage then compare them.
I got this error when it hits the wb.Navigate method.
An issue I ran into when running specflow tests with watin in windows 10 is that win10 by default uses MS Edge, so I had never opened IE, and when watin started it IE was stuck on the prompt for using default settings. Selecting options, closing browser and running tests again worked for me.
Just something to watch
This can be solved pretty easily.
This error occurs when the browser commits an action while he's already performing an action.
For example, you are navigating to some website while you rightclick in the web browser.
To solve this, I did the follow:
//if my webbrowser isn't performing any actions
if(!myWebBrowser.IsBusy)
{
//Navigate
myWebBrowser.Navigate("http://www.google.com");
}
First Try
1- Please Check Navigate URL's (if you check, please check again compiled folder)
2- Delete WebBrowser Control and Add New
Me forget copy original file App.Path + "\error.html" and see this problem.
Guarantee Method
I Fix This Error in VB6
Add WebBrowserControl wb(0) (Name wb , Index=0)
And Before Ever Navigate
For i = 1 To wb.UBound
Unload wb(i)
Next
Load wb(1)
wb(0).Visible = False
wb(1).Visible = true
wb(1).Navigate URL

Categories