Trying to automatize a couple of tests for our projects using the selenium webdriver and C# and i got into the following situation:
When i try to test the main menu the flow goes something like this:
Click on the first menu item (located on top of the page)
Wait for the last element in the page to load so i can make sure the content is fully loaded (sometimes it takes 15-20 seconds for a full page load)
Assert the title text which is located in a div under the main menu
Click on the next menu item and continue with a similar flow
Now my problem is that after the page is loaded and the test must assert the title text (3), i get a crash. I understand that this is happening because C# only reads the content once and can't return to a previous element once it read it.
So my solution that i thought would get me out was to first define the body tag in a variable and then call it for assert and further navigation:
var body = driver.FindElement(By.TagName("body"));
driver.FindElement(By.XPath("/html/body/div[1]/div/div[2]/div[2]/div[2]")).Click(); // click on the first item in the main menu
driver.WaitForElement(By.XPath("/html/path_to_the_last/div[1]")); // waiting for the last element on the page
Assert.AreEqual("Title text", body.FindElement(By.XPath("/html/body/div[1]/div/div[3]/div[3]/div[1]/div/div[1]/div[1]/div[1]/div[1]/div")).Text.Trim()); // assert the title text by calling the initially set variable
body.FindElement(By.XPath("/html/body/div[1]/div/div[2]/div[2]/div[3]")).Click(); // click on the next item in the main menu.
// similar flow to follow until each menu was checked
The thing is that when the webdriver is about to execute the assert - where the variable was first called, it crashes with the following error:
OpenQA.Selenium.StaleElementReferenceException : Element not found in the cache - perhaps the page has changed since it was looked up
Any idea what i did wrong and how should i proceed?
My guess is that when finding items from body-element, your path can't start from the root. So in the assert you should have this:
body.FindElement(By.XPath("./div[1]/div/div[3]/div[3]/div[1]/div/div[1]/div[1]/div[1]/div[1]/div")
There the beginning dot means your body-element.
Related
I'm doing a test on a webpage by using c# and selenium.
The problem is that i've got 3 different select field.
Attached a photo.
The first one is always enabled, the second one is disabled until in the firstone a voice is selected, the same fo the 3rd one, that becomes selectable when in the second one a voice has been selected.
The code that i use to fill the fields is that one:
SelectElement selAppl = new SelectElement(driver.FindElement(By.Id("IdApplicazione")));
selAppl.SelectByValue(dataApp.ToString());
wait.Until(ExpectedConditions.StalenessOf(driver.FindElement((By.Id("IdDDLAmbito")))));
SelectElement selAmbito = new SelectElement(driver.FindElement(By.Id("IdDDLAmbito")));
selAmbito.SelectByValue(ambito);
wait.Until(ExpectedConditions.StalenessOf(driver.FindElement((By.Id("ddlFunzionalita")))));
SelectElement selFunzionalita = new SelectElement(driver.FindElement(By.Id("ddlFunzionalita")));
selFunzionalità.SelectByValue(funzionalita);
The problem is that the first two fields are selected correctly, but the 3rd desn't select nothing and the test fails with that message:
OpenQA.Selenium.StaleElementReferenceException : stale element reference: element is not attached to the page document (Session info: chrome=89.0.4389.114)
If i put a Thread sleep instead of:
wait.Until(ExpectedConditions.StalenessOf(driver.FindElement((By.Id("ddlFunzionalita")))));
SelectElement selFunzionalità = new SelectElement(driver.FindElement(By.Id("ddlFunzionalita")));
it works. The error is reported on the code line that corrispond the:
SelectElement selFunzionalità = new SelectElement(driver.FindElement(By.Id("ddlFunzionalita")));
So what i'm asking to myself, i've catched the dom variation of that element with the condition before, why does it doesn't find it?
What i'm doing wrong?
If you get 'StaleElementReferenceException' it means that the element was changed becase the DOM changed.
You need to to find that 3rd element again after clicking on the 1st and seconds element.
After you click on dropdowns (or other elements), the web page may changed. Other divs or span are added to the page or attributes of the same element you already found.
I am trying to automate the scheduling of pinning items to Pinterest using Tailwindapp.com. I am using a console app in .NET (C#) with Selenium Chromedriver. I start up the browser and enable the tailwind extension and login to tailwind. Then I go to the site I am trying to pin images from, get to the product page, search for the button and attempt to click it. That's where it falls apart. The 'Schedule' button in Tailwind appears over all images on the page as you hover. When I do an XPath search, it only returns a single button for the whole page (the console line below shows 1).
public static void ClickScheduleButton(IWebDriver driver) {
// get all the buttons and then use the first one
IList<IWebElement> buttons = driver.FindElements(By.XPath("//*[#id='tw_schedule_btn']"));
Console.WriteLine("Number of items found: " + buttons.Count());
IWebElement scheduleButton = buttons.ElementAt(0);
Actions actions = new Actions(driver);
actions.MoveToElement(scheduleButton).Click().Perform();
}
On the perform method, I get the following error: OpenQA.Selenium.WebDriverException: 'javascript error: Failed to execute 'elementsFromPoint' on 'Document': The provided double value is non-finite.
From what I've read, this seems to mean that there are more than 1 element but I seem to have ruled this out with the number of buttons found. I have attempted to do a wait to make sure it's available but I do not believe that is the issue.
I have tried to find an example just trying to do this with a Pinterest button because in theory it would be the same logic but I cannot find anything for that either.
My assumption is that it's a problem just getting the button to appear on the correct image? But that's just a guess.
If I'm understanding this correctly you want to click the button who appears in when you hoover the mouse in the image.
If you can hoover the mouse and wait until the expected xpath appears should solve it.
protected virtual void HooverMouse(By element)
{
Actions action = new Actions(driver);
action.MoveToElement(driver.FindElement(element)).Build().Perform();
}
The element will be the first image you have, so you must change your driver.findelements("the button") to the "images" and loop arround this.
In pseudo code will be:
Hoover(image) -> WaitButtonAppears -> ClickButton
The click event is not firing in firefox but works ok in chrome.
The test fails with the error: "Element not found on page."
Below is the code and HTML for the button I want to click.
Browser.ElementClickById("ctl00_ContentPlaceHolderBody_lvProducts_ctrl0_ctrl1_btnAddProductToCart_input");
and inside the elementclickbyid i have:
driver.FindElement(By.Id(elementID)).Click();
HTML code is:
event
You could try working around with a Javascript click.
// declare JS executor
var executor = (IJavaScriptExecutor)Driver;
// locate the input
var input = Driver.FindElement(By.XPath("//input[#type='submit']"));
// execute JS to click
executor.ExecuteScript("arguments[0].click();", input);
I've seen cases where regular Click(); does not work across browsers -- these cases are rare, but using JS click usually works across multiple browsers when I run into this issue.
driver.findElement(By.xpath("//input[#type='submit']")).click();
i am sure you are trying to use browser class to keep your methods there, but try to use xpath not id. just use this code to click what you need. don't use page object model or anything else. don't save it in your browser class under click method. just in your main code use this code to click. and before to run it make sure that you have only one type submit. if its gonna show to you 2 types then use this code
driver.findElement(By.xpath("//input[#type='submit'][1]")).click();
number 1 says click to first submit if the button which you need second then follow the logic and change the number to 2
driver.findElement(By.xpath("//input[#type='submit'][2]")).click();
for better answer share your code class and also URL where you are trying to click button and also which element you are trying to click
We have automated a few test cases using the Ranorex automation framework for a Silverlight web application. These test cases involve clicking buttons in order to invoke certain messages on the screen. In order to grab the button on the screen, we first create an Ranorex button object and then point it to the appropriate element using Ranorexpath. Then, we use the RanorexButton.Click() event to click the button. However, this event is unreliable. It works sometimes and at other times the button is not clicked. When the button is not clicked, we have to run the test case again from the start. What are we doing wrong? If this is a known problem of ranorex, please suggest workarounds.
I was facing the same problem but I am able to resolve the problem by introducing a Validate.Exists(infoObject) just before the click. Please make sure that you pass infoObject of your button or any element in Validate.Exists API.
Example:
Validate.Exists(repo.MyApp.LoginBtnInfo);
var button = repo.MyApp.LoginBtn;
button.Click();
With regards,
Avinash Nigam
I haven't heard about such a problem with Ranorex yet, maybe this is just a timing issue.
You could add a Validate.Exists(yourButton) right before the click, this ensures that the click is performed after the button was successfully loaded.
If it is a WebElement you could also use the PerformClick() method instead of the normal Click() method.
There are also different methods which will ensure that the button is in the visible area and has focus, like the EnsureVisible() or the Focus() method.
You will find the available methods of the used adapter in the online API of Ranorex.
If the Button is not within the area you can see without scrolling, you can use a
var button = repo.Buttons.button1;
button.EnsureVisible();
button.Click();
In this way the button is forced to be watched.
It might as well be an issue with the xpath and element Id-s.
If you have changing element Id-s even when the page is navigated away from and moved back (for example we have this issue with SAP related components) you might need to make a more robust xPath path variable using regular expressions.
Try to find object and parts of the path that do not change (eg. "iFrame id="MainContent"" or "btn id="ID_XXXX_Search_Button"") - ofcourse this will only help if the issue is within this.
Ranorex Regular Expression info can be found here: http://www.ranorex.com/support/user-guide-20/ranorexpath.html#c3294
A quick example of what I'm talking about:
Let's say we have an input field that has a changing ID in it's name:
US_EL.ID_F2B49DB60EE1B68131BD662A21B3432B:V_MAIN._046A-r
And I know that the part in the Id that doesn't change is:
:V_MAIN._046A-r
I can create a path for this searching the element by the ending of the elements' id that doesn't change using regular expression:
/dom[#domain='test.example.com']//iframe[#'identifier']//iframe[#'identifier2']//input[#id**~'^**:V_MAIN._046A-r']
The bold part will specify to search for an input element with an Id that ends with ":V_MAIN._046A-r".
An issue that might arrise from this is if you have elements using partially the same names you might get multiple elements returned for the same path. So it's wise to add a few more certain points to the path (eg. "iframe[#'identifier2']") when this issue arrises.
Given a page with a <select> element and some <option>s, that when clicked cause the browser to open a new URL, like (JavaScript code omitted):
<select>
<option value="here">go here</option>
<option value="there">go there</option>
</select>
When I automate this behavior with WebDriver I call
hereOrThereSelectElement.SelectByValue("here");
and then it waits until the new page has loaded.
In my case, the page load for the new location takes more than 60s (intentionally), so I had to increase the command timeout of the WebDriver instance. Unfortunately this timeout will affect all other tests created with the same WebDriver instance.
Also I would like to perform an explicit Wait for the new page to load (to mark it as long running in the test scenario), but in this condition the next command will be called after the SelectByValue command succeeded - so no Wait needed anymore.
I looked into the source and realized that SelectByValue command uses the Click logics which waits for a page to load if needed.
So my question is: How do I explicitly perform a SelectByValue (or Click) without waiting for a new page to load?
Update:
What I actually want to have in my code is:
// the following command should not wait for the new page to load
hereOrThereSelectElement.SelectByValueButDoNotWait("here");
webDriverWait.Until(/* some "page has loaded" check */)
Finally, I found a solution for this.
Meanwhile the problem has slightly shifted to a call to a WebElement's Click() method that ran into the timeout. Nethertheless the following solution applies also to the original problem with calling SelectByValue().
So, one can use Selenium's Actions low-level interactions builder to perform a click on an element.
var actions = new Actions(webDriver);
actions
.MoveToElement(aClickableWebElement);
.Click();
.Build()
.Perform();
Maybe this will help anyone having similar problems.