我正在使用Rails项目中的Mobvious gem来确定用于访问页面的设备类型。我遇到问题的用户故事是:
desktop
值,以确保记录他们在移动设备上查看桌面版网站的偏好(当移动用户首次访问移动设备上的主页时,他们会自动重新访问指向移动网站)使用Mobvious实现条件渲染的代码很简单:
应用/视图/欢迎/ index.html.haml
- for_device_type :mobile do
.switch-to-mobile-site-banner
# code for banner
代码本身按预期工作:问题是我想为此编写RSpec feature test,但我想我似乎无法在RSpec功能测试场景中正确模拟移动用户代理无法直接访问 request
对象。我的理由是,在我测试页面上是否存在特定内容时,功能规范比request spec更合适。
到目前为止,从helper specs of the Mobvious gem获取提示,我在我的功能规范中删除了一个request
对象,根据需要将device_type
设置为:mobile
,但是我似乎无法将.switch-to-mobile-site-banner
中的内容显示为:
规格/特征/ mobile_navigation_features_spec.rb
feature 'Switch to mobile site banner' do
include Mobvious::Rails::Helper
given(:env) { double('env') }
given(:request) { double('request') }
background do
allow(env).to receive(:[]).with('mobvious.device_type').and_return(:mobile)
allow(request).to receive(:env).and_return(env)
end
scenario 'mobile user prefers using the desktop site' do
visit root_url(desktop: 1)
puts "Device type is #{device_type}" # => correctly returns :mobile
expect(page).to have_selector('.switch-to-mobile-site-banner') # fails
end
end
期望失败,并使用save_and_open_page
查看页面上的呈现显示没有横幅,我不知道为什么。当代码通过Mobvious'for_device_type
方法运行时,我似乎没有得到任何错误,所以我想也许我在request
对象模拟(?)中缺少某些东西。 / p>
我没有专门针对任何实现/测试类型,因此我对如何测试我想要的功能有任何其他想法。我最初认为rack_session_access
gem可以提供帮助,但除非我使用它错了,否则我无法用它做我想做的事。
澄清:我正在使用Poltergeist作为Capybara的javascript驱动程序。
我认为真正让我误解的是,在mobvious-rails宝石中,当你想要获得device_type
时,它calls the request
object directly并且我想我需要嘲笑这个为了让助手在我的规格中正常工作。正如答案中所指出的那样,高级功能规范中的这种低级别模拟是一种代码(spec?)气味,事后我应该听到代码实际告诉我我做错了。此外,出于某种原因,在这种情况下添加js: true
甚至没有在我脑海中浮现,无论是否在我的其他测试中使用它。
我最终使用Billy Chan和Kaleidoscope的答案部分来制定我喜欢的解决方案更简单,更清洁:
规格/特征/ mobile_navigation_features_spec.rb
feature 'Switch to mobile site banner' do
background do
page.driver.headers = { "User-Agent" => "mobile" }
end
scenario 'mobile user prefers using the desktop site', js: true do
visit root_path(desktop: 1)
expect(page).to have_selector('.switch-to-mobile-site-banner')
end
end
由于Kaleidoscope是第一个提出一系列工作规格的人,我大部分时间都在考虑他,但是我会接受Billy Chan的答案是正确的,因为我觉得它是一个更“规范”的解决方案,我将指导其他人在将来参考。
答案 0 :(得分:4)
首先,您需要在此功能中启用Javascript,因为移动检测是通过此gem中的Javascript以及许多其他类似解决方案完成的。
feature 'Switch to mobile site banner', js: true do
更新:根据Andrey的评论,Mobivious不会使用JS来检测移动设备,所以你不需要启用JS。
其次,我建议你尽可能在集成测试中使用低级模拟。您需要做的是完全像移动用户一样,看看他将体验什么。你甚至不需要低水平的Mobvious助手。
我四处搜寻,发现这颗宝石可能有所帮助:https://github.com/mururu/capybara-user_agent
虽然我之前没有使用过那个宝石,但语法看起来很简单
feature 'Switch to mobile site banner', js: true do
background do
set_user_agent(:iphone)
end
scenario 'mobile user prefers using the desktop site' do
visit root_url(desktop: 1)
expect(page).to have_selector('.switch-to-mobile-site-banner')
end
end
OP评论的补充答案
关于到达'example.com'。修复方法是在root_path
行使用root_url
代替visit
。建议您删除对域设置的依赖。
关于用户代理设置。我检查了宝石,语法与Poltergeist可以做的不同。所以,尽量不要使用gem而是根据Poltergeist的问题设置标题
page.driver.headers = {"User-Agent:" => "iphone"}
参考:https://github.com/jonleighton/poltergeist/issues/127
如果这仍然不起作用,您可以在此测试中暂时使用Webkit。毕竟他们都是无头司机。我总是安装这两个宝石,并使用Poltergeist作为主要宝石。安装宝石后,只需将其设置如下。
在测试中
require 'spec_helper'
require 'capybara-webkit'
feature 'Switch to mobile site banner', js: true do
capybara.javascript_driver = :webkit
答案 1 :(得分:2)
在你的规范中启用js并且在你请求你正在指定的页面之前立即坚持这个(它只需要在你关心的请求之前去,但是先试试这个):
page.driver.headers = { "User-Agent" => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Safari/7534.48.3" }
更新:这是我工作规范的代码:
root标记:
<% for_device_type :mobile do %>
HAHA LOL MOBILE
<% end %>
规格:
require 'spec_helper'
feature 'Switch to mobile site banner' do
scenario 'desktop content', js: true do
visit "/"
expect(page).to_not have_content('LOL')
end
scenario 'mobile content', js: true do
page.driver.headers = { "User-Agent" => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Safari/7534.48.3" }
visit "/"
expect(page).to have_content('LOL')
end
end
更新2 至于为什么你的原始规格不起作用,你实际上并没有嘲笑env afaik。如果功能规格允许您轻松访问env或请求对象,我会感到惊讶。您应该使用浏览器的POV工作,因此设置用户代理似乎是要走的路。