実現したいこと
・パスワード再設定のメールを送信し、メール内のリンクから新たなパスワードを再設定できるようにしたい
・その機能を実装するために、まずはRspecでコントローラのテストをしたい
発生している問題
ブラウザ上でパスワードが再設定できることを確認したのですが、
その流れを再現したコントローラのテストでエラーが出ました。
エラー内容
パスワードの変更を試みたが実際は反映されておらず、
期待した値を返していないという内容(だと思います)。
Failure/Error: expect(user.valid_password?("12345678")).to eq(true) expected: true got: false (compared using ==) Diff: @@ -1 +1 @@ -true +false # ./spec/controllers/passwords_controller_spec.rb:43:in `block (4 levels) in <main>'
テストの内容と試してみたこと
テスト内容とテストデータは下記のとおりです。
user.reload の下に binding.pry を差し込んだところ、変更が反映されていなかったので、
その前の put :update に問題があると思ったのですが、原因を特定できませんでした。
Ruby
1require 'rails_helper' 2 3RSpec.describe Users::PasswordsController, type: :controller do 4 let(:user) { create(:user) } 5 6 describe "updateアクション" do 7 context "パスワード再設定に成功する場合" do 8 it "ルートにリダイレクトする" do 9 @request.env["devise.mapping"] = Devise.mappings[:user] 10 user.confirm 11 put :update, params: { id: user.id, user: { password: "12345678", password_confirmation: "12345678" } } 12 user.reload 13 # ここに binding.pry を入れました 14 expect(user.valid_password?("12345678")).to eq(true) 15 expect(response).to have_http_status "302" 16 expect(response).to redirect_to root_path 17 end 18 end 19 end 20 21end
Ruby
1FactoryBot.define do 2 3 factory :user, class: User do 4 name { 'user' } 5 email { 'user@example.com' } 6 password { '1234567' } 7 end 8 9end
pryで user.password と入力すると、変更前のパスワードである "1234567" が返ってくる状態です。
routes.rb
Ruby
1 Prefix Verb URI Pattern Controller#Action 2 root GET / static_pages#home 3 help GET /help(.:format) static_pages#help 4 about GET /about(.:format) static_pages#about 5 contact GET /contact(.:format) static_pages#contact 6 new_user_session GET /users/sign_in(.:format) users/sessions#new 7 user_session POST /users/sign_in(.:format) users/sessions#create 8 destroy_user_session DELETE /users/sign_out(.:format) users/sessions#destroy 9 new_user_password GET /users/password/new(.:format) users/passwords#new 10 edit_user_password GET /users/password/edit(.:format) users/passwords#edit 11 user_password PATCH /users/password(.:format) users/passwords#update 12 PUT /users/password(.:format) users/passwords#update 13 POST /users/password(.:format) users/passwords#create 14 cancel_user_registration GET /users/cancel(.:format) users/registrations#cancel 15 new_user_registration GET /users/sign_up(.:format) users/registrations#new 16 edit_user_registration GET /users/edit(.:format) users/registrations#edit 17 user_registration PATCH /users(.:format) users/registrations#update 18 PUT /users(.:format) users/registrations#update 19 DELETE /users(.:format) users/registrations#destroy 20 POST /users(.:format) users/registrations#create 21 new_user_confirmation GET /users/confirmation/new(.:format) users/confirmations#new 22 user_confirmation GET /users/confirmation(.:format) users/confirmations#show 23 POST /users/confirmation(.:format) users/confirmations#create 24 sign_in GET /sign_in(.:format) users/sessions#new 25 sign_out DELETE /sign_out(.:format) users/sessions#destroy 26
該当のcontroller
Ruby
1# frozen_string_literal: true 2 3class Users::PasswordsController < Devise::PasswordsController 4 5 def new 6 super 7 end 8 9 def create 10 super 11 end 12 13 def edit 14 super 15 end 16 17 def update 18 super 19 end 20 21 protected 22 23 def after_sending_reset_password_instructions_path_for(resource_name) 24 super(resource_name) 25 end 26 27 def after_resetting_password_path_for(resource) 28 super(resource) 29 end 30 31end 32
該当のview
<% provide(:title, "パスワード再設定") %> <h3>新しいパスワードを設定してください</h3> <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> <%= render "devise/shared/error_messages", resource: resource %> <%= f.hidden_field :reset_password_token %> <div class="field"> <%= f.label :password, "新しいパスワード" %><br /> <% if @minimum_password_length %> <em>パスワードは<%= @minimum_password_length %>文字以上です</em><br /> <% end %> <%= f.password_field :password, autofocus: true, autocomplete: "new-password" %> </div> <div class="field"> <%= f.label :password_confirmation, "確認用パスワード" %><br /> <%= f.password_field :password_confirmation, autocomplete: "new-password" %> </div> <div class="actions"> <%= f.submit "保存" %> </div> <% end %> <%= render "devise/shared/links" %>
確認したこと
controllerとviewはデフォルトで使用しており、またブラウザでは正常に作動したので
単にテストの update アクションで値を正しく渡せていないだけだと思ったのですが、
本当の原因がわかりませんでした。
テストの書き方は、こちらのサイトを参考にしています。
質問に不備がある場合は遠慮なく伝えていただけると幸いです。
どうぞよろしくお願いします。
補足情報(FW/ツールのバージョンなど)
ruby 2.7.1
Rails 6.0.3.2
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。