简体   繁体   English

如何使JavaScript在Rspec Capybara测试中运行

[英]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.

相关问题 RSpec 和 Capybara:如何获取元素的水平和垂直位置 - RSpec and Capybara: How to get the horizontal and vertical position of an element 使用Capybara和Minitest来测试JavaScript - Using Capybara and Minitest to test JavaScript 重构水豚javascript dropzone测试 - refactor capybara javascript dropzone test 无法通过我的JavaScript click事件的Rspec测试 - Can't get my Rspec test of a JavaScript click event to pass Rails / Rspec / Capybara:执行脚本的JavaScript字符串的引号 - Rails/Rspec/Capybara: Interpreting quotes for javascript string for execute script 有没有办法用Rspec / Capybara / Selenium将javascript console.errors打印到终端? - Is there a way to print javascript console.errors to the terminal with Rspec/Capybara/Selenium? 使用JavaScript驱动程序运行RSpec / Capybara时数据库超时 - Database timeout when running RSpec/Capybara with javascript driver 创建插件时,如何使Capybara在插件目录中查看Javascript? - How to get Capybara to see Javascript in plugin directory when creating plugins? PhantomJS + Capybara + RSpec获取默认的PhantomJs示例域 - PhantomJS+Capybara+RSpec get default PhantomJs Example Domain Rails 3.1 capybara javascript测试访问被拒绝 - Rails 3.1 capybara javascript test access denied
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM