如何使用 Watir/ruby 在 google 文档中插入 text/value

How do you insert text/value in google doc using Watir/ruby

google 文档嵌入在 iframe 内的网站上。

这是我用来尝试在 google 文档中插入随机文本的代码

 sample_text = Faker::Lorem.sentence
 $browser.iframe(id: 'google_iframe').div(xpath: "//div[@class='kix-lineview']//div[contains(@class, 'kix-lineview-content')]").send_keys (sample_text)
 $advanced_text_info['google_doc_article'] = sample_text

但是当我 运行 测试

时出现错误
  element located, but timed out after 30 seconds, waiting for #<Watir::Div: located: true; {:id=>"google_iframe", :tag_name=>"iframe"} --> {:xpath=>"//div[@class='kix-lineview']//div[contains(@class, 'kix-lineview-content')]", :tag_name=>"div"}> to be present (Watir::Exception::UnknownObjectException)

问题

问题的根源在于 Google Docs 如何实施他们的应用程序。您正在写入的 div 不包含 contenteditable 属性:

<div class="kix-lineview-content" style="margin-left: 0px; padding-top: 0px; top: -1px;">

因此,Selenium 不认为此元素处于可交互状态。引发 Selenium::WebDriver::Error::ElementNotInteractableError 异常。绕过Watir直接调用Selenium可以看到:

browser.div(class: 'kix-lineview-content').wd.send_keys('text')
#=> Selenium::WebDriver::Error::ElementNotInteractableError (element not interactable)

Watir 通过隐藏异常来混淆问题。如以下代码所示,不可交互错误作为元素不存在异常引发 - UnknownObjectException。我不确定这是故意的(例如向后兼容性)还是疏忽。

rescue Selenium::WebDriver::Error::ElementNotInteractableError
  raise_present unless browser.timer.remaining_time.positive?
  raise_present unless %i[wait_for_present wait_for_enabled wait_for_writable].include?(precondition)
  retry

总而言之,问题在于该元素不被视为可交互,而不是因为它不存在。

解决方案

我认为最好的方法是在尝试设置文本之前使 div 可交互。您可以通过自己添加 contenteditable 属性来做到这一点:

content = browser.div(class: 'kix-lineview-content') # This was sufficient when using Google Docs directly - update this for your specific iframe
content.execute_script('arguments[0].setAttribute("contenteditable", "true")', content)
content.send_keys(sample_text)