Capybara HaveSelector
没有像我期望的那样使用RSpec expect
。我是Capybara和RSpec的新手所以我这可能是对RSpec或Capybara的误解,或者它可能是Capybara(版本2.0.2)的缺陷。请帮助我理解我的错误或制作错误报告/功能请求。
在我的RSpec中,我写道:
expect { click('.special-div .submit') }.to have_css('.submitted')
我预计这在功能上等同于
click('.special-div .submit')
page.should have_css('.submitted')
但事实并非如此。相反,匹配器have_css
尝试匹配proc对象的字符串转换,而不是调用proc对象的结果。 (换句话说,永远不会执行click('.special-div .submit')
。)
Capybara的行为:
另外,我显然可以通过使用上面的2行版本来做我想要的,但我们的团队正试图在expect {}
上进行标准化,那么有没有办法使用expect {}
形式和得到它做我想要的?
修改
我继承了我正在使用的代码所以我没有意识到,正如Andrey Botalov指出的那样,click
不是Capybara的标准部分。看起来应该是这样,但是click
已经被大量用于其他事情,所以Capybara没有添加另一个定义可能会更好。
由于有些人似乎持怀疑态度,请允许我向您保证此代码工作正常:
click('.special-div .submit')
page.should have_css('.submitted')
对于那些对have_css()
感到疑惑的人,这是has_css?
的RSpec魔术。对于那些想知道click
的人,在我的项目中,有人方便地创建了click
函数,如下所示:
def click(css)
page.execute_script("$('#{css}').first().trigger('click');")
end
为什么呢?因为没有明显的替代方案可行。
click_on('.special-div .submit') # Fails because click_on does not take CSS
# Cannot use click_button() because we are clicking on a <div>
find('.special-div .submit').click # Raises exception because there are more than one
first('.special-div .submit').click # Fails because the div is not visible
继续前进,@ zetetic问是否
expect(click('.special-div .submit')).to have_css('.submitted')
会奏效。不,它对我们不起作用,因为我们仍然使用RSpec 2.9并且语法是在2.11中引入的,但即使我们升级它仍然无法工作,因为click
没有返回一个对象。如果我们升级到2.11并将click
更改为返回page
,则可能会有效。
答案 0 :(得分:2)
expect { click('.special-div .submit') }.to have_css('.submitted')
有几个问题,这就是为什么我这么困惑。
最令我困惑的是RSpec的expect {...}.to ...
语法。我认为这种语法会导致匹配器在{}
中运行代码并将匹配器应用于结果或类似的东西。在the example:
expect { something }.to raise_error(SomeError)
事实证明这通常不正确。只有某些匹配者期望“实际”('expect'和'.to'之间的内容)为Proc
然后调用它。大多数匹配者都希望“实际”成为一个对象。所以:
expect { 1 + 1 }.to eq(2)
尝试将Proc
与Fixnum
进行比较时引发异常。
所以Capybara的has_css?
匹配器完全合理地期望“实际”成为响应has_selector?
而不是Proc
的对象。这真的是我的主要问题,因此,Capybara已经摆脱困境。
让我感到困惑的是,Capybara帮助提供了一个DSL,因此在我的示例中has_css?
等同于page.has_css?
,这使我期望have_css(css)
将继续神奇地对抗{{1} 1}}。
开始编写测试的更好方法。 @deviousdodo大多是正确的,这就是我为这个答案授予奖金的原因。我想要的是
page
实际上,虽然它超出了原始问题的范围,但我真正想要的是
expect {
click('.special-div .submit')
}.to change { page.has_css?('.submitted') }.from(false).to(true)
我想要这个的原因是因为我最想检查的是点击记录在数据库中(expect {
click('.special-div .submit')
page.should have_css('.submitted')
}.to change { Click.count }.by 1
增量)但是我必须等待点击触发的AJAX调用才能完成,由Click.count
完成。
答案 1 :(得分:1)
编辑:答案的第一部分是错误的,所以我改变了它。
我最初说的是这段代码
expect { click('.special-div .submit') }.to have_css('.submitted')
相当于:
click('.special-div .submit').should have_css('.submitted')
但这不是真的,因为传递给expect
的proc实际上不会被评估(你可以阅读@ OldPro的答案以获取更多细节)。
解决方案是expect change
:
expect {
click_button('Button label')
}.to change { page.has_css?('.submitted') }.from(false).to(true)
您可以在rspec website找到更多详细信息。