RSpec Ajax 点赞按钮测试未通过
RSpec Ajax Test for Like Button Not Passing
我有一个 RSpec 控制器规格,根本不会通过。我正在尝试测试一个点赞按钮,它是一个 AJAX post 请求,它会更新 post 下显示页面上的点赞数量。当我在 localhost 上进行物理测试时,我可以单击 post 下的赞按钮,并且赞的数量按预期增加 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)
,但仍然没有通过。我不确定我哪里出了问题。我还制作了一个功能规范,内容如下:
/spec/features/liking_spec.rb
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
这也失败并显示与上面相同的消息。
这是我的 AJAX 点击 "like" 请求,点赞数增加 1。
app/assets/javascripts/like.js
"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();
}
});
});
});
在我的 post 控制器中:
app/controllers/posts_controller.rb
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
最后,这是我的 show.html.erb 点赞按钮所在的位置。
<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>
如果您需要更多信息,请告诉我。
您没有正确使用 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
调用,即当匹配器 re-evaluates 执行 post 后对象得到更新的投票值时。
您遇到的第二个问题是在您的功能规范中。即使您更新它以正确使用更改匹配器 (expect { click_button "Like"}.to change...
),您的测试很可能仍然会失败,因为在 click_button "Like"
returns 时投票计数实际上并未更新。这是因为 click_button
异步触发行为然后 returns。您真的不应该在功能测试中测试数据库值更新,而应该检查页面上发生变化的可见值,但是如果您坚持在那里检查数据库值,您将需要使用某种类型的等待匹配器(https://github.com/abotalov/waiting_rspec_matchers) 或点击按钮后休眠。
我有一个 RSpec 控制器规格,根本不会通过。我正在尝试测试一个点赞按钮,它是一个 AJAX post 请求,它会更新 post 下显示页面上的点赞数量。当我在 localhost 上进行物理测试时,我可以单击 post 下的赞按钮,并且赞的数量按预期增加 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)
,但仍然没有通过。我不确定我哪里出了问题。我还制作了一个功能规范,内容如下:
/spec/features/liking_spec.rb
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
这也失败并显示与上面相同的消息。
这是我的 AJAX 点击 "like" 请求,点赞数增加 1。
app/assets/javascripts/like.js
"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();
}
});
});
});
在我的 post 控制器中:
app/controllers/posts_controller.rb
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
最后,这是我的 show.html.erb 点赞按钮所在的位置。
<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>
如果您需要更多信息,请告诉我。
您没有正确使用 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
调用,即当匹配器 re-evaluates 执行 post 后对象得到更新的投票值时。
您遇到的第二个问题是在您的功能规范中。即使您更新它以正确使用更改匹配器 (expect { click_button "Like"}.to change...
),您的测试很可能仍然会失败,因为在 click_button "Like"
returns 时投票计数实际上并未更新。这是因为 click_button
异步触发行为然后 returns。您真的不应该在功能测试中测试数据库值更新,而应该检查页面上发生变化的可见值,但是如果您坚持在那里检查数据库值,您将需要使用某种类型的等待匹配器(https://github.com/abotalov/waiting_rspec_matchers) 或点击按钮后休眠。