Bradley Atkins Bradley Atkins - 5 months ago 40
Ruby Question

Cannot set text for form element using Watir in Ruby

I have just started tinkering with watir after having successfully written some code to interact with a small web site hosted on my laptop using mechanize. But I am struggling to get watir to work at all.

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


I find that printing f.name works and I see that the login form is called "Login". But if I add the line to set the text I get a timeout.

Looking at FF I can see that the form has rendered so I'm puzzled as to why I can't seem to interact with it.

I've tried other methods of setting the values like:

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


But to no avail.

The tutorials online make this look so easy that I suspect I'm just making a rookie blunder and am too tired to see it.

Any help appreciated.

Brad

Thanks for the reply. Sorry, that's what you get for posting when your tired. As for the exception, I'm seeing it is not rendered unless I put in the wait and a timeout if I do. If there is a way of forcing it to tell me my syntax is in error I would appreciate knowing how to do that.

Here is the form:

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


I've discovered a good tutorial online that has showed me how to use a hash to further qualify the address of the element but I'm still having no luck with this 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')


I'm still getting an exception for a timeout or with no wait:

[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/<'


Zeroing in a little more, this prints the id of the text field:

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


but this fails to set the text:

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


This is looking more and more like something to do with the page rather than my grasp of water syntax:

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'


Gives me this output that shows the element clearly exists but I see this weird "scroll" stack trace for the double click.

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


Feels like I'm getting closer to the problem:

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


This show false for visible and present but true for exists.

Why this element is invisible to watir while visible to me is the next question I must answer...

Answer

Woo! Finally...

So the Selenium java code gave me the right direction and I have managed to fill the form like this:

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