【问题标题】:How to access and interact with Shadow DOM using Watir?如何使用 Watir 访问 Shadow DOM 并与之交互?
【发布时间】:2018-05-11 06:13:33
【问题描述】:

我需要访问此页面 chrome://downloads/ 并检查是否已下载文件,但它是 Shadow DOM。

我发现这篇文章如何使用 Selenium Webdriver 访问 DOM 元素。 http://jeremysklarsky.github.io/blog/2015/06/13/accessing-shadow-dom-elements-with-selenium-webdriver/

但是这是用JS写的

driver.executeScript("return $('body /deep/ <#yourSelector>')")

driver.executeScript("return $('body /deep/ ._mm_column')[0].textContent").then(function(title){
  title.should.contain(segmentName);
});

将其更改为 Watir 语法后,我的代码可以工作,但没有返回我想要的结果:

    execute_script("return $('<#file-link>')")

    execute_script("return $( '<:contains(test-file.mp3)>')")

我只是在控制台中得到 nils。

enter image description here

但我想要确保元素存在。

【问题讨论】:

  • 作为 execute_script 的参数给出的所有内容都将是 javascript,因为您要求浏览器执行您在此处提供的任何内容。如果调用的语言是 Ruby 或 Java 或JS 如果您尝试按照示例进行操作,您可能还需要在代码中包含示例中显示的 body /deep/ 部分。

标签: jquery ruby selenium watir shadow-dom


【解决方案1】:

正如titusfortner 删除的答案所述,Selenium Easy 有一篇相关文章“Working with Shadow DOM Elements using Webdriver”。事实证明,您可以通过 JavaScript 获取影子元素,然后像往常一样与它的后代进行交互。

但是,由于 Watir 的编写方式,我必须对 Watir::Browser 进行猴子补丁才能使其正常工作。我会看看我是否可以得到一个更永久的修复,但现在,这是一个工作示例:

require 'watir'

# Monkey-patch due to being unable to check the tag name of the shadow root
class Watir::Browser
  def wrap_element(scope, element)
    Watir.element_class_for(element.tag_name.downcase).new(scope, element: element)
  rescue Selenium::WebDriver::Error::UnknownError # need a better rescue
    Watir::Element.new(scope, element: element)
  end
end

def expand_root_element(element, browser)
    browser.execute_script("return arguments[0].shadowRoot", element)
end

browser = Watir::Browser.new

# Create a download item
browser.goto('https://chromedriver.storage.googleapis.com/2.33/chromedriver_win32.zip')
browser.goto('chrome://downloads')

# Navigate the shadow DOM to the download items
download_manager = browser.element(css: 'downloads-manager')
shadow_download_manager = expand_root_element(download_manager, browser)

download_items = shadow_download_manager.elements(css: '#downloads-list downloads-item')
shadow_download_items = download_items.map { |s| expand_root_element(s, browser) }

# Find a specific download item by file name
expected_file = /chromedriver_win32/
download = shadow_download_items.find { |s| s.span(id: 'name').text_content =~ expected_file }

# Do something with the download - eg wait for the download to complete
download.link(id: 'show').wait_until_present

【讨论】:

    【解决方案2】:

    我想让人们知道这个猴子补丁不再有效,我不知道有什么好的解决方法。

    Justin 解决的最初问题是附加到元素的 shadow dom 实际上没有标签名称。因此他的猴子补丁。但是随着更新,该补丁不再有效。最初的错误是 JS 错误的变化(参见下面的项目符号 #1)。新问题是 shadow dom 附加到真实元素上,但 shadowRoot 本身并不是真实元素。它就像一个准元素。

    • 错误现在是 Selenium::WebDriver::Error::JavascriptError,因此您的救援行需要更新以纠正错误。
    • 即使你解决了这个问题,你也会得到更多的错误javascript error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'这是对有线协议的内部 API 调用的结果。例如,我将错误追踪到 selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/http/default.rb:81 API 调用返回内部 500 错误,负载为 "{"value":{"error":"javascript error","message":"javascript error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.\n (Session info: chrome=87.0.4280.88)" 我不知道如何解决这个问题。

    【讨论】:

      猜你喜欢
      • 2021-11-11
      • 2019-05-05
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多