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.
Related
I just started with implementing some UItests for a new WebApplication and noticed that sometimes tests are failing when I wait for an Element to Exist while the same test succeeds when waiting for the Element to be Visible.
So my question is, is there a fixed order in which a webelement becomes "existing", "clickable", "visible","displayed" etc. or does this fully depends on how the developer has implemented the webpage or maybe the JS Framework which is used implementing the application?
It all depends on how the page was written.
Web element does not evolve from one status to another. It may change, but as a result of some dynamic content, actions performed on the page etc.
What those statuses tell us:
Existing - is when the element is in the page DOM. It does not necessarily has to be visible or interactable. It is the basic status, as element cannot have other statuses, without existing. Using the driver.FindElement(By.Xpath(".//*")) will find all elements on the page.
Displayed - when element exists it may be visible. Use IWebElement.Displayed (C# syntax) to check if the element is displayed.
Clickable - sometimes when you try to click the element, the exception may be thrown, saying that something else would get the click. To deal with those issues, see this answer.
How do you check if the element exists? If you are just searching for element, it will throw exception, when element is not found. I suggest using WebDriverWait, to look for element, for certain time period, to deal with loading:
Wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSecond));
Wait.Until(d => d.FindElement(by));
Precisely, Selenium can deal with 3 distinct states of a WebElement with in the HTML DOM:
Element is Exists i.e. Present.
Element is Visible.
Element is Interactive / Clickable.
Honestly, you don't have to keep track of the order in which a webelement becomes existing, clickable, visible, displayed etc.
If your usecase is to validate the existence of any element you need to induce WebDriverWait setting the ExpectedConditions as ElementExists() which is the expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible. So the effective line of code will be:
IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until(ExpectedConditions.ElementExists(By.CssSelector("element_cssSelector")));
If your usecase is to extract any attribute of any element you need to induce WebDriverWait setting the ExpectedConditions as ElementIsVisible(locator) which is an expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0. So in your usecase effectively the line of code will be:
IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until(ExpectedConditions.ElementIsVisible(By.ClassName("element_classname")));
If your usecase is to invoke click() on any element you need to induce WebDriverWait setting the ExpectedConditions as ElementToBeClickable() which is an expectation for for checking an element is visible and enabled such that you can click it. So in your usecase effectively the line of code will be:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("element_xpath"))).Click();
I have a WebElement in which cannot be found in IE 10 but works in FF 47.1 and Chrome 51.
[FindsBy(How = How.XPath, Using = "Foo's XPath")]
IWebElement Foo = null;
At runtime I have also called
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("Foo's XPath")));
But am receiving a NullReferenceException for IE10 Only. I have even tried a sleep as well. Can someone please advise me what else I can do b/c my program has to run IE.
As of the time this question was asked we have upgraded to IE 11 but am still seeing the exact same issue. I can't provide specific html code but I want to elaborate a little on the webelement foo.
The radio button which I have called "foo" is wrapped in the following
div
table
tbody
tr
td
input id = "foo"
When I call the xpath (I have tried id and css selector as well)
.//*[#id='foo_rblArgType_4']
the application itself defaults to the 1st value of the radio buttons and I can't seem to get it to select the 4th value which I need. Can anyone offer advice or suggestions of something else I can try?
Depending of what elements are siblings you can have selectors like:
//tr[4]//*[contains(#id, 'foo')]
//td[4]/*[contains(#id, 'foo')]
//*[contains(#id, 'foo')][4]
You can also use the entire id if is not changing by replacing [contains(#id, 'foo')] with [#id='foo']
If none of this are working then please provide the structure for all 4 inputs.
Try identifying element by id.
[FindsBy(How = How.Id, Using = "foo")]
IWebElement Foo = null;
Also make sure that the element is not hidden. Also try increasing the size of the element as sometimes web-driver is not able to locate element.
If you still have issues performing any operations on radio button, try using JavaScriptExecutor.
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
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.
I use to pick items from drop-down menus using `SelectElement` class in my automated tests and they worked just fine until I upgraded to Selenium 2.39 .
ALL (!) tests that use this class fail and I get error message: `"Element is not currently visible and so may not be interacted with".`
I presume there is a bug in 2.39. Tested on Firefox 26.0. Anyone knows how to fix this problem?
//Here's a piece of my HTML:
<select id="CodGender" class="ui-selectmenu-element" name="CodGender" data-val-required="Mandatory attribute" data-val="true" aria-disabled="false">
<option value=""></option>
<option value="M">Male</option>
<option value="Z">Female</option>
</select>
//and here's how I'd pick an item from the drop-down:
{ var dropDownList = driver.FindElement(By.XPath("[#id='CodGender']"));
var selectElement = new SelectElement(dropDownList);
selectElement.SelectByText("Male");
}
Here's a quick watch window result for "dropDownList" after passing the second line of code:
Displayed false
Enabled true
Location {X = -1658 Y = 791}
Selected false
Size {Width = 200 Height = 30}
TagName "select"
Text ""
... and here's the one for "selectElement" :
AllSelectedOptions Count = 1
IsMultiple false
Options Count = 3
[0] {OpenQA.Selenium.Firefox.FirefoxWebElement}
[1] {OpenQA.Selenium.Firefox.FirefoxWebElement}
[2] {OpenQA.Selenium.Firefox.FirefoxWebElement}
... then option No. 2 looks like:
[OpenQA.Selenium.Firefox.FirefoxWebElement] {OpenQA.Selenium.Firefox.FirefoxWebElement}
Displayed false
Enabled true
Location {X = -1656 Y = 851}
Selected false
Size {Width = 197 Height = 16}
TagName "option"
Text ""
...
It looks like you need an explicit wait for the element to become visible or enabled.
The fact you do not get a NoSuchElementException indicates that webdriver is aware of the element's presence. I would suggest adding a wait for the dropdown to be visible, and for safety you can also add a wait for the desired text to be visible. This will stop webdriver trying to select the option before the option is available.
This is an answer that came from James of Selenium Team:
He thoroughly explained the mentioned issue as well as provided some guides how to fix it ...
"
Okay, what's probably happening here is that your site is using some sort of JavaScript UI widget framework (jQueryUI maybe?), which simulates a drop-down by use of and elements, but stores the actual data inside a element. The element holding the actual data is not visible, probably hidden by the 'ui-selectmenu-element' CSS class.
WebDriver cannot interact with (click, send keys to, etc.) hidden elements, full stop. The fact that you could manipulate the invisible element in previous versions of WebDriver was a bug, which has now been fixed.
You have three options now. First, you can use the UI elements actually visible in the UI to select the appropriate values. Second, you could use JavaScript, along with the API of whatever JavaScript UI toolkit you're using, to programmatically manipulate the "dropdown" control. For either of these two options, you won't be able to use the SelectElement class to manipulate the control, because the elements you're manipulating won't be elements. Finally, you could somehow cause the actual element to become visible, but you'll need to figure out the inner workings of your UI widget framework to manipulate the element to become visible.
"
I am trying to automate sharepoint site new item form but what ever method i try it is showing not found.
I tried switchTo() to a new iframe, window...
Tried this code which finds the outer content
IWebElement table1 = WebElement.FindElement(By.XPath("//table[#class=\"s4-wpTopTable\"]"));
int table1count = WebElement.FindElements(By.XPath("//table[#class=\"s4-wpTopTable\"]")).Count;
MessageBox.Show(table1count.ToString());
above code displays the table count as 2. Going beyond this element does not show any element.
And I am using IE as the browser.
I used Xpath and could identify till the red mark and it does not identify beyond that.. i am trying to identify the elements marked in green.
var iframecount = driver.FindElement(By.XPath("//html/body/form/div[8]/div/div[4]/div[2]/div[2]/div/div/table/tbody/tr/td
Here is the xpath is used taken from FireBug
var iframecount = driver.FindElement(By.XPath("//html/body/form/div[8]/div/div[4]/div[2]/div[2]/div/div/table/tbody/tr/td/div/span/table/tbody/tr/td[2]/span/span/input"));
i have found answer for this...
Sharepoint New item form (i.e modal pop up) has 3 iframes without id or name so switching to iframe using the below code works
driver.SwitchTo().Frame(2);
i.e frames start from 0 index.