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.
"
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'm using Selenium from C# to try and periodically do a search on a website and pull in updated data. Unfortunately the website needs a login I can't make public so I can't actually give any kind of reproducible test case.
Using the Selenium IDE I've made a script that successfully logs in and pulls the data, so the task is possible. However when exporting that script to C#, there's a failure when trying to use an iframe that appears during the process.
By reading around I've discovered I need to add code to explicitly find and switch to the iframe, which I've done;
driver.SwitchTo().Frame(driver.FindElement(By.Id("popup_iframe")));
Inside that frame is an area to the left with items to click. Each item when clicked changes the visible controls to the right. When I break at this point and click manually, everything works as expected. If I call the .Click on the IWebElement representing the object, nothing happens so the next step in the program fails because it gets another object, tries to click it and an exception's thrown because the object isn't visible.
I'm leaving 5s delays between operations in case delays are needed.
The code on the website in this area is;
<div id="ctl00_popup_workarea_left_container" class="popup-workarea-left-container" style="overflow: auto; height: 337px; display: block;">
<a id="LBTN1" class="navbutton navbutton_Disabled_Selected">Basic Search</a>
<a id="LBTN2" class="navbutton">Advanced Search</a>
<a id="LBTN3" class="navbutton">Permit Holder Search</a>
<a id="LBTN4" class="navbutton">Assessor Search</a>
</div>
The code I'm using to get and click the IWebElement is
driver.FindElement(By.Id("LBTN3")).Click();
I've also tried
Actions act = new Actions(driver);
act.MoveToElement(driver.FindElement(By.Id("LBTN3"))).Click().Perform();
Aside from the fact these don't throw exceptions, I've confirmed I'm getting an IWebElement interactively;
driver.FindElement(By.Id("LBTN3"))
{Element (id = f42435b5-139c-4334-be12-4a1f9f48221f)}
Coordinates: {OpenQA.Selenium.Remote.RemoteCoordinates}
Displayed: true
Enabled: true
Id: "f42435b5-139c-4334-be12-4a1f9f48221f"
Location: {X = 0 Y = 112}
LocationOnScreenOnceScrolledIntoView: {X = 0 Y = 112}
Selected: false
Size: {Width = 200 Height = 29}
TagName: "a"
Text: "Permit Holder Search"
WrappedDriver: {OpenQA.Selenium.Firefox.FirefoxDriver}
So I'm getting the element. The HTML appears to show that it really is the element- I'm not accidentally using the ID of something containing it. The original script created in the Selenium IDE works fine- I just can't automate it so it kicks off unattended in the early hours. I know this is vague because I can't give people access to play to reproduce it, but does anyone have an idea of what could be going wrong and how to fix?
For completeness I thought I'd better put an answer here.
I never identified why none of the attempts I made worked, but I discovered that injecting Javascript into the page to click the element I wanted to click did work. So assuming .FindElement() is able to get the element to click, the following snippet worked for me in a number of places where IWebElement.Click() proved uncooperative.
IWebElement ibtn3 = driver.FindElement(By.Id("LBTN3"));
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
executor.ExecuteScript("arguments[0].click();", ibtn3);
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
I'm struggling a little with a method I need. Here is what I want to do:
I want to load a webpage
On that webpage, I want to wait until a specific element and it's style attribute contains "hidden: true;". When this style is present, the page has been fully loaded so I can continue my tests
I need to continue refreshing the webpage until the above condition is true - Please assume I need to keep refreshing. I know it seems stupid.
Here is what I'm trying
Step 1:
Navigating to a webpage (writing code from memory):
driver.Navigate().GoToUrl("http://example.com");
Step 2:
Find the style from the specific element (Writing code from memory)
Iwebelement MyElement = driver.findElement(By.id("example"));
Iwebelement MyElementStyle = MyElement.GetAttribute("style");
Step 3:
If the element has a style of "hidden: true;" on page load then do nothing else perform a page refresh until the element doesn't contain a style of "hidden: true;" (Writing code from memory)
if(MyElementStyle.Contains("hidden: true;"))
{
// do nothing
}
else
{
driver.Navigate().GoToUrl("http://example.com");
}
This appears to be working but the above code will only refresh the page one time so I need to loop rather than use an if statement.
Would anyone be able to offer a few pointers or suggest a better way of approaching this?
I am not sure what language binding you are using but looks like a mixture of C# and java and if that's the real test code it will not work.
Use do while loop to do a post check and check if the attribute has expected value or not.
IWebElement MyElement = Driver.FindElement(By.Id("example"));
string MyElementStyle = MyElement.GetAttribute("style");
do
{
Driver.Navigate().Refresh();
} while (MyElementStyle.Contains("hidden: true;"));
Without posting pages of C# code and markup, has anyone got a reason why this code
var link = _driver.FindElement(By.Id(field + "Field"));
var id = link.GetAttribute("id");
var text = link.Text;
given this markup
<a id="ForenameField" href="/MyUrl/MyFolder/MyId">3 errors</a>
Assigns an empty string to the text variable, but if I put a breakpoint on the second or third line and inspect the link variable, I can see the inner text of the element against the Text property on the inspector, it reads "3 errors", but the value of text is an empty string. It is not hidden, I can see the text if I add a watch or use quickview, any ideas?
Ok, it's my bad. Using jquery to toggle class on the div that contains the html in the question, meant that although users see the div appearing, the class that hides the div is still in the tag. A bit like this
<div class="hideThis showThis"><!-- my elements /--></div>
This makes it so that Selenium is right not give me a text value. It is strange however that the Visual studio debugger thinks that there should be a value. Visual Studio seems to go with what I can see, but Selenium is more pedantic about the hideThis class being there.
I go with the idea that if you can't see it you can't interact with it, so it is worth looking up the html graph from the element you expect to have a value to see if any class is present which would hide your element.
Feel free to recommend that I delete this rather obvious wisdom.
I know this was posted over a year ago, but I had this exact problem too and came across this thread. I was able to solve it by just waiting for the DOM to load--some elements aren't visible until the DOM is updated. So just putting Thread.Sleep(6000) or whatever after navigating to the page got it to work for me.