前提・実現したいこと
Railsでtwitterのようなアプリを作成しています。
ユーザーの投稿に「いいね」ボタンを実装し、ボタンを押すとajaxでjs.erb
ファイルを読み込むことでボタン(赤いハート、灰色のハート)が非同期で切り替わるように実装しています。
このテンプレートが切り替わったかどうかを検証するテストを書こうと思い、
assert_select
を用いてボタン部分の要素が存在するか確認したところ、
(1)非同期通信 => 該当する要素を見つけられずテストが失敗
(2)同期通信 => テスト成功
という結果になりました。
そこで、代わりにassert_match
を用いると、非同期通信でもテストが通るようになりました。
なぜassert_select
だと、非同期通信において指定した要素を検知できなかったのでしょうか。
該当のソースコード
いいねボタンのテンプレート(app/views/likes/_like_form.html.erb)
<% if logged_in? %> <%# いいね済みの場合 %> <% if current_user.liked_micropost?(micropost.id) %> <td> <%= link_to destroy_like_path(micropost), method: :POST, remote: true do %> <i class="fa fa-heart unlike-btn"></i> <% end %> <%= micropost.likes.count %> </td> <%# いいねしてない場合 %> <% else %> <td> <%= link_to create_like_path(micropost), method: :POST, remote: true do %> <i class="fa fa-heart like-btn"></i> <% end %> <%= object.likes.count %> </td> <% end %> <% end %>
app/controllers/likes_controller.rb
class LikesController < ApplicationController before_action :micropost_params def create @like = Like.new(user_id: current_user.id, micropost_id: params[:micropost_id]) @like.save respond_to do |format| format.html { redirect_back(fallback_location: root_url) } # jsをオフにしている人向け format.js # => /app/views/likes/create.js.erb end end def destroy @like = Like.find_by(user_id: current_user.id, micropost_id: params[:micropost_id]) @like.destroy respond_to do |format| format.html { redirect_back(fallback_location: root_url) } format.js # => /app/views/likes/create.js.erb end end private # いいねボタンを押した投稿情報を、インスタンス変数に保持してビューへ def micropost_params @micropost = Micropost.find(params[:micropost_id]) end end
app/views/likes/create.js.erb
$('#like_<%= @micropost.id %>').html("<%= j(render partial: 'likes/like_form', locals: {micropost: @micropost}) %>");
app/views/likes/destroy.js.erb
$('#like_<%= @micropost.id %>').html("<%= j(render partial: 'likes/like_form', locals: {micropost: @micropost}) %>");
テストコード
test/integration/likes_interface_test.rb
require 'test_helper' class LikesInterfaceTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) # feed: 自身とフォロー中ユーザーの全投稿 @micropost = @user.feed.paginate(page: 1).first log_in_as(@user) get root_url end # いいねボタンの描画の切り替わり(通常リクエスト) => テスト成功 test "like-btn should change on standard way" do assert_select 'i.like-btn' post create_like_path(@micropost) follow_redirect! assert_select 'i.unlike-btn' post destroy_like_path(@micropost) follow_redirect! assert_select 'i.like-btn' end # いいねボタンの描画の切り替わり(ajaxリクエスト) => テスト失敗 test "like-btn should change with ajax " do assert_select 'i.like-btn' post create_like_path(@micropost), xhr: true assert_select 'i.unlike-btn' post destroy_like_path(@micropost), xhr: true assert_select 'i.like-btn' end # 以下略 end
発生している問題・エラーメッセージ
Expected at least 1 element matching "i.unlike-btn", found 0.. Expected 0 to be >= 1.
試したこと
① assert_match
を用いてrespose.body
の中から調べる形で書くとテストが通る。
# いいねボタンの描画の切り替わり(ajaxリクエスト) test "like-btn should change with ajax when pusshed " do assert_select 'i.like-btn' post create_like_path(@micropost), xhr: true assert_match 'unlike-btn', response.body post destroy_like_path(@micropost), xhr: true assert_match 'like-btn', response.body end
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/29 07:48
2021/11/29 10:16
2021/11/29 14:20
2021/12/01 06:59
2021/12/05 02:37 編集