模拟下载 link / 检查 link 使用 Capybara 针对控制器方法生成
Mocking download link / checking link generation against controller methods with Capybara
在某个页面的 Capybara 功能规范中,我有一个下载 link:
download_link = find_link(expected_link_text)
我想检查生成的 link 是否是下载文件的正确文件,即它会使用正确的模型对象在我的 FileController
上调用 download()
。
RSpec-Rails 似乎有很多方法可以得到我想要的东西。例如,在 controller spec 中,我可以在控制器上使用普通的 RSpec 断言:
expect(controller).to receive(:download).with(expected_id)
# download_link = find_link(expected_link_text) # can't do this in a controller spec
# visit(download_link) # can't do this in a controller spec
在路由规范中,我可以使用 route_to()
:
# download_link = find_link(expected_link_text) # can't do this in a routing spec
expect(get: download_link[href]).to route_to(controller: 'file', action: 'download', id: expected_id)
但是在功能规范中,controller
和 route_to()
都不可用。
通过以下恶作剧和调试器中的大量探索,我能够将 route_to()
包含在我的测试中:
describe 'the page' do
it 'should let the user download a file' do
self.class.send(:include, RSpec::Rails::Matchers::RoutingMatchers) # hack to get routing matchers into feature test
self.class.send(:include, ActionDispatch::Assertions::RoutingAssertions) # RoutingMatchers uses this internally
self.class.send(:define_method, :message) { |msg, _| msg } # RoutingAssertions expects message() to be included from somewhere
@routes = Rails.application.routes # RoutingAssertions needs @routes
download_link = find_link(expected_link_text)
expect(get: download_link[href]).to route_to(controller: 'file', action: 'download', id: expected_id) # works!
end
end
这确实有效,但它是香蕉。有没有现成的方法可以将 Capybara 混合到其他类型的规范中,或者将其他类型的规范混合到功能规范中?或者只是一种更简洁的 Rails-y(可能不是 RSpec)获取路线的方式?
注意: 路由没有命名,所以我不能使用 URL 助手(我不认为);由于历史原因,URL 路径本身是不连贯的噪音,所以我不只是想以字符串形式断言 href。
正如您所说,如果您想检查正在调用的特定控制器方法,那将是控制器规范,如果您想验证路由,那将是路由规范。对于 Capybara,您应该编写功能 specs/system 测试——这意味着没有 mocking/stubbing 而是 运行 端到端测试。配置您用于下载文件的任何驱动程序,然后单击 link,下载文件,并验证是否下载了正确的文件。另一种选择是只使用 url_for
而不是试图包含所有额外的东西而只做
expect(download_link[href]).to eq url_for(controller: 'file', action: 'download', id: expected_id)
或更好
expect(page).to have_link(expected_link_text, href: url_for(controller: 'file', action: 'download', id: expected_id))
但是如果您要测试文件下载,您真的应该只下载文件。
如果您必须处理编码问题,您可以使用过滤器块重写预期并解析 paths/urls 以规范化
expect(page).to have_link(expected_link_text) do |link|
Addressable::URI.parse(link[:href]) == Addressable::URI.parse(url_for(controller: 'file', action: 'download', id: expected_id))
end
在某个页面的 Capybara 功能规范中,我有一个下载 link:
download_link = find_link(expected_link_text)
我想检查生成的 link 是否是下载文件的正确文件,即它会使用正确的模型对象在我的 FileController
上调用 download()
。
RSpec-Rails 似乎有很多方法可以得到我想要的东西。例如,在 controller spec 中,我可以在控制器上使用普通的 RSpec 断言:
expect(controller).to receive(:download).with(expected_id)
# download_link = find_link(expected_link_text) # can't do this in a controller spec
# visit(download_link) # can't do this in a controller spec
在路由规范中,我可以使用 route_to()
:
# download_link = find_link(expected_link_text) # can't do this in a routing spec
expect(get: download_link[href]).to route_to(controller: 'file', action: 'download', id: expected_id)
但是在功能规范中,controller
和 route_to()
都不可用。
通过以下恶作剧和调试器中的大量探索,我能够将 route_to()
包含在我的测试中:
describe 'the page' do
it 'should let the user download a file' do
self.class.send(:include, RSpec::Rails::Matchers::RoutingMatchers) # hack to get routing matchers into feature test
self.class.send(:include, ActionDispatch::Assertions::RoutingAssertions) # RoutingMatchers uses this internally
self.class.send(:define_method, :message) { |msg, _| msg } # RoutingAssertions expects message() to be included from somewhere
@routes = Rails.application.routes # RoutingAssertions needs @routes
download_link = find_link(expected_link_text)
expect(get: download_link[href]).to route_to(controller: 'file', action: 'download', id: expected_id) # works!
end
end
这确实有效,但它是香蕉。有没有现成的方法可以将 Capybara 混合到其他类型的规范中,或者将其他类型的规范混合到功能规范中?或者只是一种更简洁的 Rails-y(可能不是 RSpec)获取路线的方式?
注意: 路由没有命名,所以我不能使用 URL 助手(我不认为);由于历史原因,URL 路径本身是不连贯的噪音,所以我不只是想以字符串形式断言 href。
正如您所说,如果您想检查正在调用的特定控制器方法,那将是控制器规范,如果您想验证路由,那将是路由规范。对于 Capybara,您应该编写功能 specs/system 测试——这意味着没有 mocking/stubbing 而是 运行 端到端测试。配置您用于下载文件的任何驱动程序,然后单击 link,下载文件,并验证是否下载了正确的文件。另一种选择是只使用 url_for
而不是试图包含所有额外的东西而只做
expect(download_link[href]).to eq url_for(controller: 'file', action: 'download', id: expected_id)
或更好
expect(page).to have_link(expected_link_text, href: url_for(controller: 'file', action: 'download', id: expected_id))
但是如果您要测试文件下载,您真的应该只下载文件。
如果您必须处理编码问题,您可以使用过滤器块重写预期并解析 paths/urls 以规范化
expect(page).to have_link(expected_link_text) do |link|
Addressable::URI.parse(link[:href]) == Addressable::URI.parse(url_for(controller: 'file', action: 'download', id: expected_id))
end