0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

devise_token_authのメール認証済みでないとログインできない機能をRSpecでテストする方法

Posted at

はじめに

devise_token_authのログイン機能が開発し終わったので現在RSpecでテストを書いているのですが、"メール認証済みでないとログインできない"というテストを書くことができたので、備忘録として残そうと思います。

sessions_spec.rbで何をテストするか

devise_token_authで設定をすればアカウント作成時にメールで本認証を行わないとログインができない機能を実装することができます。
この"sessions_spec.rb"は、ログイン機能を担当しているので"メールが送信できているか?"などのテストではなくシンプルに、

・認証が済んでいればそのアカウントはログインできる
・認証ができていなければそのアカウントはログインできない

という2点が問題なく動作していることをテストで確認できればOKという考えになりました。
アカウントを作成する箇所のテストについては、registrations_spec.rbで記述します。
(その他パスワードやメールアドレスが間違っている場合はログインできない等のテストは書いていますが、認証とは関係ないので省略しています)

どうやって認証の状態を制御するか

結論から述べると"confirmed_at"に日付を入れることにより、認証済みか未認証かを制御することができます。
メール認証が完了(認証メール内にあるリンクを開くこと)でconfirmed_atに値が入り、認証済みかどうか判断しているようです。

最初に作成されるDBテーブルのカラム内にもちゃんとありますね。

class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[6.1]
  def change
    
    create_table(:users) do |t|
      ## Required
      t.string :provider, :null => false, :default => "email"
      t.string :uid, :null => false, :default => ""

      #省略
  
      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at #=>これ!!
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      #省略

  end
end

結論

そのため下記のように、confirmed_atに値がある場合/ない場合のuserデータを作成してそれぞれテストを行えばOKです。

RSpec.describe "Api::V1::Auth::Sessions", type: :request do
  let(:current_user) { create(:user, confirmed_at: Date.today) }

  describe "POST /api/v1/auth/sign_in" do
    context "認証時みでメールアドレス、パスワードが正しい場合" do
      let(:params) { { email: current_user.email, password: current_user.password } }

      it "ログインが成功すること" do
        post api_v1_user_session_path, params: params
        expect(response.headers["uid"]).to be_present
        expect(response.headers["access-token"]).to be_present
        expect(response.headers["client"]).to be_present
        expect(response).to have_http_status(200)
      end
    end

    context "未認証でメールアドレス、パスワードが正しい場合" do
      let(:no_confirmed_current_user) { create(:user, confirmed_at: "") }
      let(:params) { { email: no_confirmed_current_user.email, password: no_confirmed_current_user.password } }

      it "ログインが失敗すること" do
        post api_v1_user_session_path, params: params
        res = JSON.parse(response.body)
        expect(res["errors"]).to include("A confirmation email was sent to your account at '#{no_confirmed_current_user.email}'. You must follow the instructions in the email before your account can be activated")
        expect(response).to have_http_status(401)
      end
    end
  end
end

テストも無事通りました。

コンテナ名:/サービス名 # bundle exec rspec ./spec/requests/api/v1/auth/sessions_spec.rb
.....

Finished in 0.57591 seconds (files took 3.55 seconds to load)
5 examples, 0 failures

【余談】エラーメッセージはどこにあるのか

いろんなrspecを参考にしながらも、response.bodyのエラーメッセージとかどこのこと言ってんねん!と密かに思っていた時期があったので、一応どこにあるか画像に残そうと思います。
(何を写しちゃだめかわからなくて不安なので、一応不要そうな箇所は隠しました。)
スクリーンショット 2022-09-03 0.49.09.png

終わりに

テストを書くために必要な準備は、どんなロジックで実装しているのか、もしくはされているのかの理解だと強く感じました。
gemを使って機能を作ってる時は理解してないとなんとなくで機能が作れちゃったりすると思うので、ちゃんとソースコードを読むことが大事だなぁとも感じました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?