[英]How to get javascript to run in Rspec Capybara test
I'm building a simple Reddit Clone for practice, and would like to test to see if the ajax works and that a value on the screen is properly updated with the javascript response. 我正在构建一个简单的Reddit Clone进行练习,并想测试一下ajax是否有效以及屏幕上的值是否已使用javascript响应正确更新。 Here is the test:
这是测试:
RSpec.describe "User voting", type: :system, js: true do # Rails 5 uses describe, Rails < 5 feature
it "updates the downvote count" do
user = create(:user)
login_as(user)
link = create(:link)
visit root_path
expect(page).to have_css('#upvotes-1', text: '0')
click_on(id: 'upvoter-1')
wait_for_ajax
expect(page).to have_css('#upvotes-1', text: '1')
end
end
wait_for_ajax: (in /spec/support/wait_for_ajax.rb) wait_for_ajax :(在/spec/support/wait_for_ajax.rb中)
module WaitForAjax
def wait_for_ajax
Timeout.timeout(Capybara.default_max_wait_time) do
loop until finished_all_ajax_requests?
end
end
def finished_all_ajax_requests?
page.evaluate_script('jQuery.active').zero?
end
end
Relative code from index.html.erb: 来自index.html.erb的相对代码:
<%= button_tag(class: "btn btn-secondary btn-sm", id: "upvoter-#{link.id}") do %>
<span class="fa fa-chevron-up"></span>
Upvote
<%= content_tag(:span, link.upvotes(), id: "upvotes-#{link.id}") %>
<% end %>
Controller code: 控制器代码:
def create
@vote = current_user.votes.new(link_params)
if @vote.vote_value == 1
@new_value = @vote.link.upvotes
@id_name = "#upvotes-" + @vote.link.id.to_s
else
@new_value = @vote.link.downvotes
@id_name = "#downvotes-" + @vote.link.id.to_s
end
respond_to do |format|
if @vote.save
format.js { }
else
format.html { render :new }
end
end
end
And finally create.js.erb: 最后是create.js.erb:
console.log("create.js.erb file");
$("<%= j @id_name %>").html("<%= j @new_value.to_s %>");
Gemfile: 的Gemfile:
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
gem 'rspec-rails'
gem 'guard-rspec', require: false
gem 'factory_bot_rails', '~> 4.0'
gem 'database_cleaner'
gem 'rails-controller-testing'
gem 'capybara', '~> 2.13'
gem 'selenium-webdriver'
gem 'chromedriver-helper'
gem 'puma'
gem 'poltergeist'
end
If I load the site myself and click on the button the tally updates correctly. 如果我自己加载网站并单击按钮,则提示会正确更新。 However, the test fails on the second expect.
但是,测试失败的第二个期望。 If I reload the page, the tally will update so the database is updated and #create works as expected.
如果我重新加载页面,则提示将更新,因此数据库将更新,并且#create可以按预期工作。 The javascript doesn't get executed for some reason.
javascript由于某种原因未执行。 And I've tried putting a sleep after the click_on as well.
而且我也尝试在click_on之后入睡。 It still fails.
它仍然失败。 There seems to be something simple I'm missing here.
我在这里似乎缺少一些简单的东西。
Switching to Selenium helped me see the problem more clearly. 切换到Selenium帮助我更清楚地了解了问题。 Here is a pretty good tutorial that tells you how to get setup with Rails 5 / latest (late 2018) versions of things:
这是一个非常不错的教程,告诉您如何使用Rails 5 /最新(2018年末)版本进行设置:
A Quick Guide to Rails System Tests in RSpec RSpec中的Rails系统测试快速指南
In the end, I used .new to create the model, but hadn't saved it, so the new vote count wasn't showing. 最后,我使用.new来创建模型,但没有保存它,因此没有显示新的投票数。 Moving the logic that pulled the count after the save solved the problem.
保存后移动拉动计数的逻辑即可解决问题。
In votes_controller.rb: 在tickets_controller.rb中:
def create
@vote = current_user.votes.new(link_params)
respond_to do |format|
if @vote.save
format.js {
if @vote.vote_value == 1
@new_value = @vote.link.upvotes
@id_name = "#upvotes-" + @vote.link.id.to_s
else
@new_value = @vote.link.downvotes
@id_name = "#downvotes-" + @vote.link.id.to_s
end
}
else
format.html { render :new }
end
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.