C#和Selenium:声明按钮元素在

时间:2017-11-28 13:42:29

标签: c# selenium-webdriver

我有一个带有按钮的网页,Selenium一直坚持这个按钮是不可见的,尽管它肯定是。

页面来源:

<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>

在此之下,有一个包含条目列表的动态表。条目在第一个单元格中有一个复选框。在选中此框之前,上面的按钮被禁用。但是,点击它后立即启用按钮。

我尝试使用ID和XPath访问(单击)此按钮。我已经为&lt; button和&lt; span元素尝试了XPath。每次我尝试,我都会收到此错误:

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)

在单击复选框并单击按钮之前,我也立即停止了Selenium测试(等待3秒钟)。然后我手动尝试点击按钮,它运行正常。

也没有重复的ID;页面上只有一个元素具有此ID。

任何想法我在这里做错了什么,或者如果它的硒是愚蠢的,如何解决这个问题?

这是相关的程序/测试代码:

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));
    }
}

我还尝试使用此代码等待元素可见。没运气。等待时间过了。

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);
    }
}

前段时间,我在这个网站上有另一个按钮,我无法通过Selenium访问。那是一个文件上传按钮。我不记得Exception,但是我用这段代码解决了这个问题:

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();
}
但是,这并不适用于此。但它似乎做了一些事情:当我将有问题的按钮的ID(&#34; product-catalog-page_order-selected-button&#34;)提供给该方法时,它会选择页面上非常第一个可点击的元素,这是Front Page链接,有自己唯一的ID,在元素上方有几百行HTML代码和实际ID。

如果问题中缺少任何相关信息,请告诉我而不是downvoting。

更新: 要进行故障排除,我按照我在StackOverflow上的另一个线程中找到的提示:使用Submit()而不是Clic()。但是,这导致了另一个(可能是逻辑的)异常:

OpenQA.Selenium.NoSuchElementException: no such element: Element was not in a form, so could not submit.

更新2: 我也尝试过上课时按钮。有两个按钮具有完全相同的类,但也许它会得到第一个?无论如何,这导致完全相同的ElementNotVisible异常。

更新3: 两者都在等待可见并等待可点击的时间。

wait.Until(driver => driver.FindElement(By.Id(id)).Displayed);
wait.Until(ExpectedConditions.ElementToBeClickable(By.Id(id)));

更新4: 复选框的html代码(在选中时启用按钮):

<td class="table-column-checkbox">
    <input type="checkbox" data-bind="checked: $parent.selected, checkedValue: href" value="/Api/CatalogProducts/ProductOfferings/PO-6E32-CE4C-C169">
</td>

更新5: 该按钮对Selenium是不可见的,是否启用它是否已启用:

  • 未选中复选框
    • 禁用按钮
  • 结果:OpenQA.Selenium.ElementNotVisibleException:元素不可见

  • 选中复选框

    • 启用按钮
  • 结果:OpenQA.Selenium.ElementNotVisibleException:元素不可见

更新6:

查看源代码,页面上没有任何元素设置为&#34;隐藏&#34;,因此应该消除任何不可见的父元素搞乱。

唯一不能找到的是,有两个HTML代码块,其中一个具有相同ID的按钮在页面上被注释掉。这些出现在相关按钮之前,但我不希望Selenium对注释掉的HTML代码感到烦恼吗?

2 个答案:

答案 0 :(得分:1)

我从未发现Selenium对此类事情有误。我总是认为Selenium是正确的,你的定位器是关闭的,或者在你不知道的页面中发生了什么。

我找到定位器的第一种方法是在Chrome中使用开发控制台。我个人最喜欢Chrome开发工具,但这是个人偏好(大多数情况下)。使用$$(locator)测试CSS选择器,使用$x(locator)测试XPath。这些将返回由这些定位器找到的元素集合。您可以立即判断您是否找到了多个,如果您想要的不是第一个,等等。我通常只是通过浏览页面来做到这一点,但如果您仍然遇到问题,请设置断点并停止违规行,然后在浏览器中执行此操作。

如果仍然无效,我会添加一些调试命令来调查违规行之前的页面,例如

Console.WriteLine(Driver.FindElements(locator).Count);

并确保定位器找到正确的元素,找到预期的元素数量等

您还可以在导致问题的行上放置断点,在调试模式下运行脚本,然后使用“立即”窗口测试代码。

其他评论

我在评论中提到你应该传递By个类而不是字符串,并且你要求一个例子。

public class Button
{
    public static void Click(By locator)
    {
        Find(locator).Click();
    }

    private static IWebElement Find(By locator)
    {
        return GCDriver.Instance.FindElement(locator);
    }
}

你会称之为

Button.Click(By.Id("id"));

您的WaitForVisible()方法比它需要的更复杂。你应该阅读ExpectedConditions。有许多已经可用的东西需要等待,这将照顾你需要的90%以上的等待时间。我也会传递一个TimeSpan,这样你就可以控制等待时间,而不必总是等待硬编码的30秒。

public class GCDriver
{
    public static void WaitForVisible(By locator, TimeSpan timeout)
    {
        new WebDriverWait(GCDriver.Instance, timeout).Until(ExpectedConditions.ElementIsVisible(locator));
    }
}

你甚至可以更进一步传递Func,这将允许你等待任何,而不仅仅是可见。

public class GCDriver
{
    public static void Wait(Func<IWebDriver, IWebElement> func, TimeSpan timeout)
    {
        new WebDriverWait(GCDriver.Instance, timeout).Until(func);
    }
}

并将其称为

GCDriver.Wait(ExpectedConditions.ElementIsVisible(locator), TimeSpan.FromSeconds(10));

答案 1 :(得分:0)

经过数小时的故障排除后,我找到了原因。或者,至少是其中的一部分。

当我使用FindElements而不是FindElement时,它会计算具有相同ID的两个元素。当我在单击按钮时拍摄页面源的快照时,这些不可见。

但是,原因是包含该按钮的页面有3个选项卡。所有标签的按钮应该相同,因为它是&#34;订购所选&#34;按钮和选项卡包含要订购的事物列表。但由于最近才实现了唯一ID,因此在创建此页面时并未考虑到这一点。

因此,DOM包含至少2个相同的ID,这些ID在页面源中不可见。但奇怪的是,FindElements应该返回3个元素而不是2.或者DOM可能更加混乱。

无论如何:当我告诉Selenium单击SECOND元素时,就像这样,

GCDriver.Instance.FindElements(By.Id(id))[1].Click();

它有效。