【问题标题】:Cannot set text for form element using Watir in Ruby无法在 Ruby 中使用 Watir 为表单元素设置文本
【发布时间】:2016-10-12 14:08:55
【问题描述】:

在成功编写了一些代码以使用 mechanize 与我的笔记本电脑上托管的一个小型网站进行交互之后,我刚刚开始修补 watir。但我很难让 wirr 工作。

require 'watir-webdriver'

b = Watir::Browser.new :firefox
b.goto('https://dev.mitdev.org.uk/login')
body = b.body
body.forms.each do |f|
  p f.name
  f.text_field(:name, 'IDToken1').wait_until_present(5).set('test')
end

我发现打印 f.name 有效,并且我看到登录表单称为“登录”。但是,如果我添加行来设置文本,我会超时。

看着 FF,我可以看到表单已经呈现,所以我很困惑为什么我似乎无法与之交互。

我尝试了其他设置值的方法,例如:

body.text_field(:name => 'IDToken2').wait_until_present(5).set('Password')

但无济于事。

在线教程使这看起来如此简单,以至于我怀疑我只是犯了一个新手错误并且太累了,看不到它。


感谢您的回复。至于异常,我看到它不会呈现,除非我等待并且如果我这样做了超时。如果有办法强制它告诉我我的语法有误,我将不胜感激。

这是表格:

<form id="Login" name="Login" action="/login" method="post">
    <div class="sign-in">
        <fieldset>
            <legend class="form-title heading-large">Sign in</legend>
            <div class="form-group">
                <label  class="form-label" for="IDToken1">
                    User ID
                </label>
                <input class="form-control" type="text" name="IDToken1" id="IDToken1" value="" maxlength="50" tabindex="1" />
            </div>
            <div class="form-group">
                <label class="form-label" for="IDToken2">
                    Password
                </label>
                <input type="hidden" id="goto" name="goto" value=""/>
                <input class="form-control" type="password" name="IDToken2" id="IDToken2" value="" maxlength="100" autocomplete="off" tabindex="2" />
                <input type="hidden" name="_csrf_token" value=" deleted ">
            </div>
        </fieldset>
        <nav class="module-content-navigation">
            <input name="Login.Submit" type="submit" class="button" value="Sign in" tabindex="3" />
            <ul class="content-navigation__secondary">
                <li>
                    <a href="/forgotten-password" tabindex="4">Forgotten password</a>
                </li>
            </ul>
        </nav>
    </div>
    <input name="IDButton" type="hidden" style="display: none;">
</form>

我在网上发现了一个很好的教程,它向我展示了如何使用哈希来进一步限定元素的地址,但我仍然无法使用这种形式:

b = Watir::Browser.new
b.goto('https://dev.mitdev.org.uk/login')
b.wait(3)
b.text_field(:class => 'form-control',
             :type => 'text',
             :name => 'IDToken1',
             :id => 'IDToken1').set('test')

我仍然收到超时或没有等待的异常:

[remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-12708-sjjxdp/extensions/fxdriver@googlecode.com/components/command-processor.js:10092:in `fxdriver.preconditions.visible': Element is not currently visible and so may not be interacted with (Selenium::WebDriver::Error::ElementNotVisibleError)
    from [remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-12708-sjjxdp/extensions/fxdriver@googlecode.com/components/command-processor.js:12644:in `DelayedCommand.prototype.checkPreconditions_'
    from [remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-12708-sjjxdp/extensions/fxdriver@googlecode.com/components/command-processor.js:12661:in `DelayedCommand.prototype.executeInternal_/h'
    from [remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-12708-sjjxdp/extensions/fxdriver@googlecode.com/components/command-processor.js:12666:in `DelayedCommand.prototype.executeInternal_'
    from [remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-12708-sjjxdp/extensions/fxdriver@googlecode.com/components/command-processor.js:12608:in `DelayedCommand.prototype.execute/<'

再调零一点,这将打印文本字段的 id:

p b.text_field(:type => 'text',
             :name => 'IDToken1',
             :id => 'IDToken1').id

但这无法设置文本:

b.text_field(:type => 'text',
             :name => 'IDToken1',
             :id => 'IDToken1').when_present(5).set('test')

这看起来越来越像是与页面有关,而不是我对水语法的掌握:

p b.text_field(:name => /Token1/).name
p b.text_field(:type => 'text',
             :name => 'IDToken1',
             :id => 'IDToken1').id
p b.text_field(:name => /Token1/).exists?
b.text_field(:name => /Token1/).double_click
b.text_field(:name => /Token1/).set 'test'

给我这个显示元素明显存在的输出,但我看到这个奇怪的“滚动”堆栈跟踪双击。

"IDToken1"
"IDToken1"
true
[remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-2812-w3soqr/extensions/fxdriver@googlecode.com/components/driver-component.js:11072:in `FirefoxDriver.prototype.mouseMoveTo': Offset within element cannot be scrolled into view: (5, 17.5): [object HTMLInputElement] (Selenium::WebDriver::Error::MoveTargetOutOfBoundsError)
    from [remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-2812-w3soqr/extensions/fxdriver@googlecode.com/components/command-processor.js:12661:in `DelayedCommand.prototype.executeInternal_/h'
    from [remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-2812-w3soqr/extensions/fxdriver@googlecode.com/components/command-processor.js:12666:in `DelayedCommand.prototype.executeInternal_'
    from [remote server] file:///var/folders/f4/6vwp2t_d75v803226gs84v100000gp/T/webdriver-profile20160612-2812-w3soqr/extensions/fxdriver@googlecode.com/components/command-processor.js:12608:in `DelayedCommand.prototype.execute/<'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/response.rb:70:in `assert_ok'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/response.rb:34:in `initialize'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/http/common.rb:78:in `new'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/http/common.rb:78:in `create_response'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/http/default.rb:90:in `request'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/http/common.rb:59:in `call'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/bridge.rb:649:in `raw_execute'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/bridge.rb:627:in `execute'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/remote/bridge.rb:419:in `mouseMoveTo'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/common/mouse.rb:71:in `move_to'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/common/mouse.rb:81:in `move_if_needed'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/common/mouse.rb:40:in `double_click'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/common/action_builder.rb:363:in `block in perform'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/common/action_builder.rb:362:in `each'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/selenium-webdriver-2.53.1/lib/selenium/webdriver/common/action_builder.rb:362:in `perform'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/watir-webdriver-0.9.1/lib/watir-webdriver/elements/element.rb:147:in `block in double_click'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/watir-webdriver-0.9.1/lib/watir-webdriver/elements/element.rb:598:in `element_call'
    from /Users/atkinsb/.rvm/gems/ruby-2.2.1/gems/watir-webdriver-0.9.1/lib/watir-webdriver/elements/element.rb:147:in `double_click'

感觉我离问题越来越近了:

p b.text_field(:name => /Token1/).exists?
p b.text_field(:id => /Token1/).visible?
p b.text_field(:name => /Token1/).present?

这表示可见和存在为假,但存在为真。

为什么这个元素对我来说是可见的而对我来说是不可见的,这是我必须回答的下一个问题......

【问题讨论】:

  • 这将有助于提供您看到的异常以及您正在使用的 HTML。 .wait_until_present(5).set('test') 不是一个有效的语法,它应该是 when_present(5).set('test')。但是,这将导致未定义的方法错误而不是超时。
  • 谢谢贾斯汀,我现在添加了更多细节
  • 异常表示该元素不可见。当您运行脚本时,您能看到文本字段吗?您确定在文本字段对人可见之前没有必须执行的操作吗?
  • 这就是让我难过的地方。我可以清楚地看到浏览器中的文本字段。如果我将等待时间设置为 120 并单击文本框,我可以手动输入文本,甚至可以通过标签进入密码字段,但 watir 坚持认为它不可见。我注意到的一件奇怪的事情是,页面顶部有一个横幅,告诉我该站点使用 cookie,但没有 x 来关闭它。我不知道这是否会导致这种情况......
  • 这可能是你的问题,如果横幅挡住了文本字段,那么 watir 无法点击它

标签: ruby automation automated-tests watir web-testing


【解决方案1】:
p b.text_field(:name => /Token1/).exists?
p b.text_field(:id => /Token1/).visible?

这两行对我有帮助。谢谢。

【讨论】:

    【解决方案2】:

    哇!终于……

    所以 Selenium java 代码给了我正确的方向,我设法填写了这样的表格:

    b.element(:xpath => "//*[contains(@id,'_tid1')]").send_keys('user')    
    b.element(:xpath => "//*[contains(@id,'_tid2')]").send_keys('password')
    b.element(:name => "Login.Submit").click
    

    【讨论】:

    • 这是否意味着您要查找的元素不是提供的 HTML 中的元素?我没有看到任何包含“_tid1”的 id 属性。请注意,这可以更简洁地写成b.element(id: /_tid1/).send_keys('user')
    • 嗨,贾斯汀,感谢您指出缺失的元素。我抓取了页面的 HTML 表单视图源,它没有复制我可以在开发工具中看到的隐藏字段。我没有注意到。最终问题被追溯到开发人员放入了一些只能通过上面的 xpath 解决的 java 脚本。
    【解决方案3】:

    我已经尝试过你的脚本。它在我的最后工作

    require 'watir-webdriver'
    
    b = Watir::Browser.new :chrome
    b.goto 'file:///D:/WORKSPACE/Learning/demo1.html'
    b.text_field(:name, 'IDToken1').when_present(5).set('test')
    

    但不适用于形式和主体。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2012-09-01
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 2018-03-22
      • 2018-06-17
      相关资源
      最近更新 更多