当我使用下面指定的代码填充表单时(在Cucumber测试中)并提交一个,我的params
哈希在控制器处完全为空。
我已经完成了一些调试,并且在Capybara的某个深层次,当它实际发送时,Nokogiri节点在value
调用之前没有设置click_button
属性。< / p>
visit '/'
click_link 'Sign out' if has_link? 'Sign out'
click_link 'Log in'
find(:css, '#user_email').set 'my@email.com'
find(:css, '#user_password').set 'foobar'
find(:css, '#user_remember_me').set true
click_button 'Sign in'
我在控制器上的params
哈希:
{"utf8"=>"✓", "user"=>{"email"=>"", "password"=>"", "remember_me"=>"1"}, "commit"=>"Sign in", "action"=>"create", "controller"=>"auth"}
表单HTML是这样的:
<form accept-charset="UTF-8" action="/users/sign_in" class="new_user" id="new_user" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓"><input name="authenticity_token" type="hidden" value="blah-blah-blah"></div>
<div class="email">
<label for="user_email" title="Email or LDAP username">Login</label>
:
<input autofocus="autofocus" id="user_email" name="user[email]" placeholder="EMAIL or LDAP" size="30" title="Email or LDAP username" type="text" value="">
</div>
<div class="password">
<label for="user_password">Password</label>
:
<input id="user_password" name="user[password]" placeholder="PASSWORD" size="30" type="password">
</div>
<div class="rememberable">
<label for="user_remember_me">Remember me</label>
:
<div class="checkbox">
<input name="user[remember_me]" type="hidden" value="0"><input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
</div>
</div>
<div class="signin">
<div class="wrapper">
<div class="input">
Sign in
<input name="commit" type="submit" value="Sign in">
</div>
</div>
</div>
</form>
运行cucumber features/my_feature.feature -vb
:
shybovycha@shybovycha-laptop:~/projects/rails/my_project$ cucumber features/my_feature.feature -vb
Using the default profile...
Code:
* features/support/env.rb
[RailsAdmin] RailsAdmin initialization disabled by default. Pass SKIP_RAILS_ADMIN_INITIALIZER=false if you need it.
Clearing database
Running db:migrate
Running db:seed for our instance
* features/support/capybara_headers.rb
* features/step_definitions/backoffice.rb
* features/step_definitions/content_verification .rb
* features/step_definitions/db_manipulation.rb
* features/step_definitions/forms_and_links.rb
* features/step_definitions/jenkins_integration.rb
* features/step_definitions/mobile_view.rb
* features/step_definitions/navigation.rb
* features/step_definitions/users_manipulation.rb
Features:
* features/my_feature.feature
Parsing feature files took 0m0.135s
Feature: my_feature
Scenario: do some actions # features/my_feature.feature:3
Given a logged in user # features/step_definitions/users_manipulation.rb:45
And some data exists # features/step_definitions/db_manipulation.rb:12
When I visit some page # features/step_definitions/navigation.rb:13
And click "Subscribe" link # features/step_definitions/forms_and_links.rb:6
no link with title, id or text 'Subscribe' found (Capybara::ElementNotFound)
/var/lib/gems/1.9.1/gems/capybara-1.1.3/lib/capybara/node/finders.rb:154:in `raise_find_error'
/var/lib/gems/1.9.1/gems/capybara-1.1.3/lib/capybara/node/finders.rb:27:in `block in find'
/var/lib/gems/1.9.1/gems/capybara-1.1.3/lib/capybara/node/base.rb:54:in `wait_until'
/var/lib/gems/1.9.1/gems/capybara-1.1.3/lib/capybara/node/finders.rb:27:in `find'
/var/lib/gems/1.9.1/gems/capybara-1.1.3/lib/capybara/node/actions.rb:27:in `click_link'
(eval):2:in `click_link'
/var/lib/gems/1.9.1/gems/capybara-1.1.3/lib/capybara/dsl.rb:161:in `click_link'
/home/shybovycha/projects/rails/my_project/features/step_definitions/forms_and_links.rb:8:in `block in <top (required)>'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/core_ext/instance_exec.rb:48:in `instance_exec'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/core_ext/instance_exec.rb:48:in `block in cucumber_instance_exec'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/core_ext/instance_exec.rb:69:in `cucumber_run_with_backtrace_filtering'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/core_ext/instance_exec.rb:36:in `cucumber_instance_exec'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/rb_support/rb_step_definition.rb:69:in `invoke'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/step_match.rb:25:in `invoke'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/step_invocation.rb:60:in `invoke'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/step_invocation.rb:38:in `accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:99:in `block in visit_step'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:98:in `visit_step'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/step_collection.rb:15:in `block in accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/step_collection.rb:14:in `each'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/step_collection.rb:14:in `accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:93:in `block in visit_steps'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:92:in `visit_steps'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/scenario.rb:55:in `block (2 levels) in accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime.rb:80:in `block (2 levels) in with_hooks'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime.rb:96:in `before_and_after'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime.rb:79:in `block in with_hooks'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime/support_code.rb:120:in `call'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime/support_code.rb:120:in `block (3 levels) in around'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/language_support/language_methods.rb:9:in `block in around'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/language_support/language_methods.rb:91:in `call'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/language_support/language_methods.rb:91:in `execute_around'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/language_support/language_methods.rb:8:in `around'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime/support_code.rb:119:in `block (2 levels) in around'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime/support_code.rb:117:in `call'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime/support_code.rb:117:in `around'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime.rb:91:in `around'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime.rb:78:in `with_hooks'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/scenario.rb:53:in `block in accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/scenario.rb:108:in `with_visitor'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/scenario.rb:47:in `accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:51:in `block in visit_feature_element'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:50:in `visit_feature_element'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/feature.rb:43:in `block in accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/feature.rb:42:in `each'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/feature.rb:42:in `accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:20:in `block in visit_feature'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:19:in `visit_feature'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/features.rb:29:in `block in accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/features.rb:17:in `each'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/features.rb:17:in `each'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/features.rb:28:in `accept'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:14:in `block in visit_features'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:163:in `broadcast'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/ast/tree_walker.rb:13:in `visit_features'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/runtime.rb:46:in `run!'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/cli/main.rb:43:in `execute!'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/lib/cucumber/cli/main.rb:20:in `execute'
/var/lib/gems/1.9.1/gems/cucumber-1.2.1/bin/cucumber:14:in `<top (required)>'
/usr/local/bin/cucumber:19:in `load'
/usr/local/bin/cucumber:19:in `<main>'
features/my_feature.feature:7:in `And click "Subscribe" link'
...
除了未找到内容之外,该错误不会告诉您任何内容。原因是,devise
不进行身份验证,因为 params
哈希为空。所以它可能没有用户数据。所以它无法验证一个。因此,它不允许用户查看页面并将其重定向到显示错误消息的主页。因此,找不到测试应该使用的内容。
答案 0 :(得分:2)
找到解决方案及问题的原因。
以某种方式 Capybara (即使使用 PhantomJS )也无法识别该元素是否可见。这是Capybara的内部,而不是我的测试。
请参阅,我们在一个页面上有两个表单 - 注册表单和表单登录。 两者都是隐藏的,但当用户点击登录或注册按钮时,会显示相应的表单。 这两种表单都包含字段 #user_email 和 #user_password 。 但注册表单包含 #user_password_confirmation ,而登录表单则包含 #user_remember_me 。
只需看一下表格的代码:
<div class="forms">
<div class="signup-form" style="display: block;">
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="viNleUNDfdlp92j9vVU9QravqMRbmCUZDqw3pV9jQK0=" />
</div>
<div class="email">
<input autofocus="autofocus" id="user_email" name="user[email]" placeholder="EMAIL or LDAP" size="30" type="email" value="" />
</div>
<div class="password">
<input id="user_password" name="user[password]" placeholder="PASSWORD" size="30" type="password" />
</div>
<div class="password">
<input id="user_password_confirmation" name="user[password_confirmation]" placeholder="PASSWORD CONFIRMATION" size="30" type="password" />
</div>
<div class="signup">
Sign up
<input name="commit" type="submit" value="Sign up" />
</div>
</form>
</div>
<div class="signin-form" style="display: none;">
<form accept-charset="UTF-8" action="/users/sign_in" class="new_user" id="new_user" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="viNleUNDfdlp92j9vVU9QravqMRbmCUZDqw3pV9jQK0=" />
</div>
<div class="email">
<input autofocus="autofocus" id="user_email" name="user[email]" placeholder="EMAIL or LDAP" size="30" title="Email or LDAP username" type="text" value="" />
</div>
<div class="password">
<input id="user_password" name="user[password]" placeholder="PASSWORD" size="30" type="password" />
</div>
<div class="rememberable">
<label for="user_remember_me">Remember me</label>:
<div class="checkbox">
<input name="user[remember_me]" type="hidden" value="0" />
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1" />
</div>
</div>
<div class="signin">
Sign in
<input name="commit" type="submit" value="Sign in" />
</div>
</form>
</div>
</div>
现在,在测试中,有一行应该可以使签名可见。然后测试尝试填充可见表单并将其发送到服务器。
然而,为什么Capybara不会忽视可见形式和隐形。所以它填写了第一种形式的输入,这是注册之一。
然后会有一个代码行点击登录按钮。看到?填写的表单是注册,提交的表单是登录。
请勿使用fill_in 'Input', :with => 'value'
。
改为使用find(:css, '#selector').set 'value'
或find(:xpath, '/selector').set 'value'
。
由于上述原因,fill_in
搜索了与给定的标签/ ID /标题相匹配的第一个可见元素 (Input
在我的示例中有几行以上)
如果您在一个页面上有一些输入具有相同的标签/ ID /标题但是在不同的表单中,则fill_in
可能是不明确的并且填充错误的元素。
find
方法搜索与给定的选择器规则匹配的第一个元素 (css selector
或xpath
,基于您的第一个参数'我提供了上述示例中的css selector
。
所以,总是尝试传递尽可能多的特定选择器。