我是Rails和TDD的新手。 我目前正忙着用Capybara和RSpec测试我的页面。
我在主页(root_path)上有一个表单,它通过post提交给Linkage控制器:
<%= form_for @link, url: linkages_path, method: :post, remote: true do |f| %>
<%= f.labels/text_fields... %>
<%= f.submit "Add Link" %>
<% end %>
进入 Linkages控制器的创建操作和 理想情况下应该使用AJAX(format.js)更改root_path的数据:
def create
@link = Link.new(params[:link])
if @link.save and current_user.linkages.build(link_id: @link.id).save
flash.now[:success] = "Link to \"#{@link.content}\" was successfully added!"
respond_to do |format|
format.html { redirect root_path }
format.js do
@user_linkage = current_user.linkages
render 'users/user_linkage.js.erb'
end
end
else
flash.now[:error] = "..."
error...
end
end
现在成功它应该呈现js文件users / user_linkage.js.erb, 这就是这个(它只是改变了root_path中的userLinkage div):
$('#flash').html("<%= escape_javascript(raw(flash_display)) %>");
$('#userLinkage').html("<%= escape_javascript(render partial: 'users/user_linkage_items',
locals: {user_linkage: @user_linkage }) %>");
它在Chrome / Firefox / IE / Opera中完美运行。 但是当我在 Capybara (下面)中为它编写测试时,它失败了,因为它 重定向回root_path(format.html),而不是渲染 format.js块中指定的页面(更改root_path中的数据)。
describe "test" do
let(:link){'some link'}
let(:text){'some text'}
before do
visit root_path
fill_in 'Text', with: link
fill_in 'Link', with: text
end
it "should work" do
expect do
click_button 'Add Link'
end.to change(Link, :count).by(1)
sleep(5)
should have_content(text) # works until here (root_path has same info)
should have_selector('div.alert-success') # fails on this line(flash message)
end
end
所以我知道Capybara只能执行GET请求,我的表单是POST,但是对于用户模拟,这些东西应该是无关紧要的(?)。
如果我将format.html / format.js上的成功格式更改为以下内容:
respond_to do |format|
format.all do
@user_linkage = current_user.linkages
render 'users/user_linkage.js.erb'
end
end
,然后Capybara最终呈现给我正确的页面,但是如果我打电话给save_and_open_page
在它上面,然后我看到所有转义的javascript和错误呈现的HTML,所以我无法测试
像have_selector()
这样的东西。
我的问题是为什么会发生这种情况? 是因为Capybara使用GET而不是POST,甚至点击链接也不一定在控制器内调用正确的格式?
P.S。使用format.js(排序)切换format.html无法解决问题 - format.html正在调用。
答案 0 :(得分:2)
AFAIK Capybara对POST很好。如果您使用的是capybara-webkit,请添加:js => true
。
在您的js中,您需要.html_safe
:
$('#userLinkage').html("<%= escape_javascript(render partial: 'users/user_linkage_items',
locals: {user_linkage: @user_linkage }).html_safe %>");
还有:
current_user.linkages.build(link_id: @link.id).save
可以更改为:
current_user.linkages.create(link_id: @link.id)
还要遵循一些常量缩进方案(常用2个空格)。