相似按钮未通过的RSpec Ajax测试

时间:2017-02-08 20:55:55

标签: ruby-on-rails ajax rspec capybara

我有一个RSpec控制器规格,简直不会通过。我正在尝试测试一个类似按钮,这是一个AJAX帖子请求,用于更新帖子下显示页面上的喜欢数量。当我在localhost上进行物理测试时,我可以按照预期点击帖子下方的“喜欢”按钮,并将喜欢的数量增加1。当我运行我的控制器规范时,它始终失败:

PostsController POST #vote a user can vote on a post increments the number of votes

Failure/Error: expect { post1.votes }.to change{post1.votes}.by(1)
           expected result to have changed by 1, but was changed by 0
         # ./spec/controllers/posts_controller_spec.rb:17:in `block (4 levels) in <top (required)>'

以上来自:

/spec/controllers/posts_controller_spec.rb

require 'rails_helper'
require 'capybara/rails'

RSpec.describe PostsController, :type => :controller do

  describe "POST #vote" do

    let(:post1) {Post.create!(content: "The Content created", votes: 1, story: "My story", author: "Authors Name")}

    context "a user can vote on a post" do
      it "increments the number of votes" do

        post :vote, post1: { votes: post1.votes }, 
          params: { id: post1.id },
          xhr: true

        expect { post1.votes }.to change{post1.votes}.by(1)

      end
    end
  end
end

我尝试了expect { post1.votes }.to change{post1.votes}.by(1)的一些变体,包括但不限于:expect { post1.votes }.to change{post1.votes}.from(1).to(2),但它仍未通过。require 'rails_helper' RSpec.feature "Like feature" do let!(:post) {Post.create!(content: "The Content created", votes: 1, story: "My story", author: "Authors Name")} scenario "users can like quotes" do visit root_path click_link "Motivation" click_link post.author expect(page).to have_button "Like" expect(page).to have_current_path post_path(post.id) click_button "Like" expect { post.votes }.to change{post.votes}.by(1) end end 。我不知道我在哪里出错了。我还制作了一个类似的功能规范:

/spec/features/liking_spec.rb

"use strict";

$(document).ready(function(){

  // On click increments likes by 1. 
  $("#liking").click(function() {
    console.log('clicked');
    var id = $(this).data("id");
    $.ajax({
        url: '/posts/vote',
        type: 'POST',
        data: {
          id: id,
          increment: true
        },
        success: function() {
          var like_counter = $('#likeit');
          var current_count = parseInt($('#likeit').html());
          like_counter.html(current_count + 1); 
          $("#liking").hide();
        }
    });
  });
});

这也会失败并显示与上述相同的消息。

这是我的AJAX请求,点击&#34;喜欢&#34;和喜欢的数量增加1。

应用程序/资产/ Javascript角/ like.js

class PostsController < ApplicationController

  def index
    @posts = Post.all
  end

  def show
    @post = Post.find(params[:id])
  end

  def vote
    @post = Post.find(params[:id])
    @post.update(votes: @post.votes + 1)
  end
end

在我的帖子控制器中:

应用程序/控制器/ posts_controller.rb

<center>
  <strong>Likes:</strong>
</center>
<center>
  <p id='likeit'><%= @post.votes %></p>
</center>
<center>
  <button id="liking" type="submit" data-id="<%= @post.id %>">Like</button>
</center>

最后,这是我的show.html.erb,其中like按钮是。

{{1}}

如果您需要其他信息,请与我们联系。

1 个答案:

答案 0 :(得分:2)

您未正确使用expect {}.to change ...

它应该是expect { the action that causes the change }.to change { the value that will change }.by(1)

在您的控制器规范示例中,类似于

expect do
  post :vote, post1: { votes: post1.votes }, 
     params: { id: post1.id },
     xhr: true
end.to change { post1.reload.votes }.by(1)

注意post1上的reload调用,当匹配器在执行对象更新的帖子后重新评估投票值时就是这样。

您遇到的第二个问题是您的功能规格。即使您更新了更正以正确使用更改匹配器(expect { click_button "Like"}.to change...),您的测试很可能仍会失败,因为当click_button "Like"返回时实际上未更新投票计数。这是因为click_button异步触发行为然后返回。你真的不应该在功能测试中测试数据库值的更新,而应该检查页面上的可见值是否有变化,但是如果你坚持在那里检查数据库值,你将需要使用某种类型的等待匹配器(https://github.com/abotalov/waiting_rspec_matchers)或点击按钮后休眠。