Capybara模棱两可的匹配错误

时间:2017-04-02 13:29:18

标签: capybara ruby-on-rails-5

这个项目是对原版的重新启动,我正在努力掌握各种宝石 - 除了我之外,轨道作曲家对所有事情都做得非常出色。

我得到的这个Capybara错误与注册代码有关(我有几个使用该调用的规范,但是这里只包含其中一个,因为它们都调用了相同的帮助程序)。

 Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching field "Password"

我看过StackOverflow(好几次),并使用了Messr Google的力量 - 他主要建议我看看这里。

起初我认为这与

不匹配有关
fill_in 'Email', with: email

fill_in 'Email', :with => email

但似乎没有任何区别。

通过阅读rubydoc.info capybara fill-in处的文档(我知道:羞愧地垂头丧气),填充内容包含一个定位器和一个选项数组。

我的理解是fill_in 'Password', with: password会匹配Password定位符,这是html的id="user_password"部分。我在页面上看不到任何其他人,所以我现在正在寻求帮助。

我的所有代码都在项目Github project branch to match this question的SO001分支上。

sign_up_spec.rb

feature 'Sign Up', :devise do
  # Scenario: Visitor can sign up with valid email address and password
  #   Given I am not signed in
  #   When I sign up with a valid email address and password
  #   Then I see a successful sign up message
  scenario 'visitor can sign up with valid email address and password' do
    sign_up_with('test@example.com', 'please123', 'please123')
    txts = [I18n.t( 'devise.registrations.signed_up'), I18n.t( 'devise.registrations.signed_up_but_unconfirmed')]
    expect(page).to have_content(/.*#{txts[0]}.*|.*#{txts[1]}.*/)
  end
    # ... others snipped for space
end

规格/支持/助手/ session_helpers.rb

module Features
  module SessionHelpers
    def sign_up_with(email, password, confirmation)
      visit new_user_registration_path
      save_and_open_page
      fill_in 'Email', with: email
      fill_in 'Password', with: password
      fill_in 'Password confirmation', :with => confirmation
      click_button 'Sign up'
    end

    def signin(email, password)
      visit new_user_session_path
      fill_in 'Email', with: email
      fill_in 'Password', with: password
      click_button 'Sign in'
    end
  end
end

设计new.html.erb代码是

注册

<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :email, required: true, autofocus: true %>
    <%= f.input :password, required: true, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length) %>
    <%= f.input :password_confirmation, required: true %>
  </div>

  <div class="form-actions">
    <%= f.button :submit, "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

html的表单部分有

<form novalidate="novalidate" class="simple_form new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" />


  <div class="form-inputs">
    <div class="form-group email required user_email">
        <label class="control-label email required" for="user_email">
            <abbr title="required">*</abbr> Email
        </label>
        <input class="form-control string email required" autofocus="autofocus" required="required" aria-required="true" type="email" value="" name="user[email]" id="user_email" />
    </div>
    <div class="form-group password required user_password">
        <label class="control-label password required" for="user_password">
            <abbr title="required">*</abbr>
            Password</label>
        <input class="form-control password required" required="required" aria-required="true" type="password" name="user[password]" id="user_password" />
        <p class="help-block">6 characters minimum</p>
    </div>
    <div class="form-group password required user_password_confirmation">
        <label class="control-label password required" for="user_password_confirmation">
            <abbr title="required">*</abbr>
            Password confirmation
        </label>
        <input class="form-control password required" required="required" aria-required="true" type="password" name="user[password_confirmation]" id="user_password_confirmation" />
    </div>
  </div>

  <div class="form-actions">
    <input type="submit" name="commit" value="Sign up" class="btn btn-default" data-disable-with="Sign up" />
  </div>
</form>

1 个答案:

答案 0 :(得分:5)

如文档所述,Capybara的fill_in将匹配其id或name属性上的元素,或匹配关联标签元素的文本。属性匹配需要精确,并且关联标签元素的文本可以是精确匹配或子串匹配,具体取决于几个选项的设置。

在Capybara的当前版本中,Capybara.exact默认为:smart,当查找关联的标签文本匹配时,将首先尝试完全匹配,如果未找到,则尝试进行子串匹配。在您的情况下,您的两个字段的标签文本为*Password*Password confirmation,当检查与Password完全匹配时失败,并且在使用子字符串匹配进行检查时,两者都匹配 - 因此“模糊匹配”错误,因为更多的元素匹配。

要解决此问题(同时仍使用fill_in),您可以执行以下任何操作

fill_in '*Password', with: password # will match exactly on one elements label text

find('div.user_password').fill_in 'Password' with: password # scope fill_in so substring match is unique

fill_in 'user_password', with: password # match on id attribute

fill_in 'user[password]', with: password # match on name attribute