使用Selenium

时间:2017-08-01 00:33:15

标签: javascript c# selenium pseudo-element

我正在尝试使用Selenium来点击一个:: after伪元素。我意识到这不能通过WebDriver直接完成,但似乎无法通过Javascript找到一种方法。

以下是DOM的样子:

<em class="x-btn-split" unselectable="on" id="ext-gen161">
    <button type="button" id="ext-gen33" class=" x-btn-text">
        <div class="mruIcon"></div>
        <span>Accounts</span>
    </button>
    ::after
</em>

这就是上面这个元素的样子。对象的左侧是&#39;按钮&#39; element和:after元素是带箭头的右侧,单击时会显示下拉菜单。正如您所看到的那样,右侧没有任何标识符,这部分是使得这很难做到的。

Element to be clicked

我在stackoverflow中看到过这两个链接,并试图将答案组合起来形成我的解决方案,但无济于事。

Clicking an element in Selenium WebDriver using JavaScript
Locating pseudo element in Selenium WebDriver using JavaScript

这是我的尝试之一:

string script = "return window.getComputedStyle(document.querySelector('#ext-gen33'),':before')";
IJavaScriptExecutor js = (IJavaScriptExecutor) Session.Driver;
js.ExecuteScript("arguments[0].click(); ", script);

我收到此错误:

System.InvalidOperationException: 'unknown error: arguments[0].click is not a function
  (Session info: chrome=59.0.3071.115)
  (Driver info: chromedriver=2.30.477700 (0057494ad8732195794a7b32078424f92a5fce41),platform=Windows NT 6.1.7601 SP1 x86_64)'

我还尝试使用Selenium中的Actions类来引用鼠标左侧,类似于this answer。我想这可能是因为我不知道测量的偏移是什么,文档似乎没有给出任何指示。我认为它是以像素为单位?

Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).MoveByOffset(235, 15).Click().Build().Perform();

这种尝试似乎点击某处,因为它没有错误,但我不确定在哪里。

如果有帮助,我试图在c#中自动化Salesforce(Service Cloud)。

也许有人可以提供解决方案?

4 个答案:

答案 0 :(得分:5)

我在为Salesforce编写Selenium测试时遇到了同样的问题,并设法通过使用操作直接控制鼠标来解决它。

此按钮的包装表具有250px的硬编码宽度,您已发现它。要找到鼠标的位置,可以使用contextClick()方法而不是Click().它模拟鼠标右键,这样它将始终打开浏览器菜单。

如果你这样做:

Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).ContextClick().Build().Perform();

你会发现鼠标移动到WebElement的中间,而不是左上角(我认为它也是如此)。由于该元素宽度是常量,我们可以向右移动鼠标250 / 2 - 1,它将工作:) 代码:

Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).MoveByOffset(124, 0).Click().Build().Perform();

答案 1 :(得分:2)

对于那些试图在Python中执行此操作的人,解决方案如下:

elem= driver.<INSERT THE PATH TO ELEMENT HERE> ActionChains(driver).move_to_element_with_offset(elem,249,1).click().perform()

基本上我在DOM中找到我的元素并分配给WebElement。然后,WebElement将方法move_to_element_with_offset作为参数传递。

我从开发人员工具获得了该元素的 px 值。

PS:使用此导入 - 来自selenium.webdriver.common.action_chains导入ActionChains

您可以在此处详细了解动作链类及其方法 move_to_element_with_offset :<{p}}。

希望这有帮助。

答案 2 :(得分:1)

上面的Maciej'a答案适用于WebDriver,但不适用于针对Firefox V.56的RemoteWebDriver(Selenium 3.12.0)。我们需要一个适用于本地和远程的解决方案。使用键盘快捷键结束调用导航菜单下拉列表。作为额外的好处,这也消除了使用偏移的需要。

String navigationMenuDropdownShortcutKeys = Keys.chord(Keys.ESCAPE, "v");

new Actions(driver)
 .sendKeys(navigationMenuDropdownShortcutKeys)
 .perform();

答案 3 :(得分:0)

我将提供一种可能适用于某些情况的替代方法,至少它对我有用,并且相对容易通过JS脚本使用硒以任何语言实现。

在我的场景中,有一个:: after伪元素,其中包含按钮的功能。此按钮相对于其下另一个元素的位置包含。

所以我做了以下事情:

  1. 获取我可以的元素,在这种情况下,该范围就是该范围。
  2. 获取元素的坐标。
  3. 计算要单击的伪元素的该元素的实际坐标。
  4. 单击这些坐标。

这是我使用perl的代码,但是我确定您可以使用任何语言进行相同操作:

my $script="
function click_function(x, y)
{
    console.log('Clicking: ' + x + ' ' + y);

    var ev = new MouseEvent('click', {
        'view': window,
        'bubbles': true,
        'cancelable': true,
        'screenX': x,
        'screenY': y
    });

    var el = document.elementFromPoint(x, y);

    el.dispatchEvent(ev);
}

var element = document.getElementById('here_put_your_id'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
               document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?            

    document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
console.log('Coordiantes: ' + elementLeft + ' ' + elementTop)

click_function(elementLeft*1.88, elementTop*1.045) // here put yor relative coordiantes
    ";
    $driver->execute_script($script);