I've got a webpage with a button which Selenium keeps insisting is not visible, although it most definitely is.
The page source:
<button id="product-catalog-page_order-selected-button" class="btn btn-grey
mq-apla-button opens-overlay" data-bind="click: runOrderWizard, enable:
hasSelection"><span localize-me="">Order Selected</span></button>
<span localize-me="">Order Selected</span>
Below this, there is a dynamic table with a list of entries. The entries have a checkbox in the first cell. Before checking this box, the above button is disabled. However, immediately after clicking it the button is enabled.
I've tried accessing (clicking) this button with both the ID and the XPath. I've tried the XPath for both the <button and the <span elements. Every time I try, I get this error:
Result StackTrace:
at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response
errorResponse)
at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String
driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.Remote.RemoteWebElement.Click()
at Common.Navigation.Elements.Button.ClickById(String id) in d:\Source
\Workspaces\QA\NewMySite\Common\Elements\PageElements.cs:line 51
at MyAutomation.Pages.NewOrderPage.OrderSelected() in d:\Source
\Workspaces\QA\NewMySite\MyAutomation\Pages\NewOrderPage.cs:line 36
at Tests.RegressionTests.Ordering.Ordering.User_Order_New_Hardware() in
d:\Source\Workspaces\QA\NewMySite\Tests\RegressionTests\Ordering
\Ordering.cs:line 29
Result Message:
Test method
Tests.RegressionTests.Ordering.Ordering.User_Order_New_Hardware threw
exception:
OpenQA.Selenium.ElementNotVisibleException: **element not visible**
(Session info: chrome=62.0.3202.94)
(Driver info: chromedriver=2.33.506120
(e3e53437346286c0bc2d2dc9aa4915ba81d9023f),platform=Windows NT 10.0.15063
x86_64)
I've also stopped the Selenium test immediately after the checkbox is clicked and before the button is clicked (there's a 3 sec. hard wait). Then I've manually tried to click the button, and it works fine.
There are no duplicate IDs, either; Only one element has this ID on the page.
Any ideas what I'm doing wrong here, or how to get around this if it's Selenium being dumb?
Here's the relevant program/test code:
Button.ClickById("product-catalog-page_order-selected-button"));
public class Button {
public static void ClickById (string id) {
FindById(id).Click();
}
private static IWebElement FindById (string id) {
return GCDriver.Instance.FindElement(By.Id(id));
}
}
I've also tried waiting for the element to be visible, using this code. No luck. The wait just times out.
Wait.WaitForVisibleId("product-catalog-page_order-selected-button");
public class Wait {
public static void WaitForVisibleId (string id) {
GCDriver.WaitForVisibleId(id);
}
}
public class GCDriver {
public static void WaitForVisibleId (string id) {
var wait = new WebDriverWait(GCDriver.Instance,
TimeSpan.FromSeconds(30));
wait.Until(driver => driver.FindElement(By.Id(id)).Displayed);
}
}
A while back, I had another button on this very site that I couldn't access with Selenium. That was a file upload button. I don't remember the Exception, but I solved that one with this code:
public static void ActionsUploadButtonId (string id, string filepath) {
Actions actions = new Actions(GCDriver.Instance);
actions.MoveToElement(GCDriver.Instance.FindElement(By.Id(id)));
actions.Click();
actions.Build().Perform();
}
This doesn't work here, though. It seems to do something, though: When I feed the ID of the problematic button ("product-catalog-page_order-selected-button") to that method, it selects the VERY FIRST clickable element on the page, which is the Front Page link, with its own unique ID, located several hundred lines of HTML code above the element with the actual ID.
Update
To troubleshoot, I followed a tip I found in another thread on Stack Overflow: To use Submit() instead of Clic(). However, that resulted in another (probably logical) exception:
OpenQA.Selenium.NoSuchElementException: no such element: Element was not in a form, so could not submit.
Update 2
I also tried getting the button by the class. There are two button with the exact same classes, but maybe it then would get the first one? Anyway, that results in the exact same ElementNotVisible exception.
Update 3
Both waiting for visible and waiting for clickable times out.
wait.Until(driver => driver.FindElement(By.Id(id)).Displayed);
wait.Until(ExpectedConditions.ElementToBeClickable(By.Id(id)));
Update 4
The html code for the checkbox (which enables the button when selected):
<td class="table-column-checkbox">
<input type="checkbox" data-bind="checked: $parent.selected, checkedValue: href" value="/Api/CatalogProducts/ProductOfferings/PO-6E32-CE4C-C169">
</td>
Update 5
The button is invisible to Selenium whether or not it's enabled or not:
Checkbox not selected
-
- Button disabled
Result: OpenQA.Selenium.ElementNotVisibleException: element not visible
Checkbox selected
-
- Button enabled
Result: OpenQA.Selenium.ElementNotVisibleException: element not visible
Update 6
Looking at the source code, there are no elements on the page set to "invisible", so that should eliminate any invisible parent element messing up.
The only thing of not I can find is that there are two blocks of HTML code with a button with the same ID that are commented out on the page. These appear before the button in question, but I wouldn't expect Selenium to bother about commented-out HTML code?