devise_token_auth でログアウトのテストコード作成時、エラー解決の情報が少なかったのでまとめます。
※ user の新規登録、ログイン、ログアウト機能を実装しているものとします。
※ FactoryBot を導入してます。
headers にログインに必要な情報が入っていないため、エラー発生
エラー発生時のコード
describe "DELETE /v1/auth/user/sign_out" do
subject { delete(destroy_v1_user_session_path) }
context "トレーナーログアウト時" do
let(:user) { create(:user) }
it "トークンを無くし、ログアウトできる" do
subject
expect(response).to have_http_status(200)
end
end
end
エラー内容
Failure/Error: expect(response).to have_http_status(200)
expected the response to have status code 200 but it was 404
正常なレスポンス(200)ではなく、リクエストが存在しない(404)エラーが出てます。との内容。
subject の下に binding.pry を入れ、デバック画面にしuser
を実行
#<Trainer id: 532, provider: "email", uid: "6_hannah@emmerich.name", allow_password_change: false, name: "松本 七海", nickname: nil, email: "6_hannah@emmerich.name", address: nil, birthday: nil, created_at: "2020-07-26 06:10:35", updated_at: "2020-07-26 06:10:35">
user の中にデータがあることを確認できました。
次に headers 情報を確認するため、response.headers
を実行。
{"X-Frame-Options"=>"SAMEORIGIN",
"X-XSS-Protection"=>"1; mode=block",
"X-Content-Type-Options"=>"nosniff",
"X-Download-Options"=>"noopen",
"X-Permitted-Cross-Domain-Policies"=>"none",
"Referrer-Policy"=>"strict-origin-when-cross-origin",
"Content-Type"=>"application/json; charset=utf-8",
"Cache-Control"=>"no-cache",
"X-Request-Id"=>"a2ad39e6-d2b2-4ae8-93c1-5ddcd2ea22d1",
"X-Runtime"=>"0.010570",
"Content-Length"=>"71"}
headers の情報は返ってきましたが、ログアウトに必要な情報
access-token
、client
、uid
が入ってないことが分かります。
headers にログアウトに必要な情報が入ってないから、404の異常系のエラーが発生している。
新規作成時、ログイン時にトークン情報が発行され、その情報をもとにログアウトの処理を行うのですが、現状のコードでは user の情報は作成されても、トークン情報は作成されていない状況です。
なので、トークン情報を入れてあげましょう。
describe "DELETE /v1/auth/user/sign_out" do
subject { delete(destroy_v1_user_session_path, headers: headers) }
context "トレーナーログアウト時" do
let(:user) { create(:user) }
let(:headers) { user.create_new_auth_token }
it "トークンを無くし、ログアウトできる" do
subject
expect(response).to have_http_status(200)
end
end
end
create_new_auth_token
メソッドで、必要なメタデータ全てを含む新しい認証トークンを作成します。
subject の下に binding.pry を入れheaders
を実行し、データが入っていればオッケーです。
ログアウト時にトークン情報が残ったままのため、エラー発生
ログアウトは、「有効なトークン情報がなくなる」なので、先ほどのコードにトークン情報の有無を確認するテストコードを追記しました。
describe "DELETE /v1/auth/user/sign_out" do
subject { delete(destroy_v1_user_session_path, headers: headers) }
context "トレーナーログアウト時" do
let(:user) { create(:user) }
let(:headers) { user.create_new_auth_token }
it "トークンを無くし、ログアウトできる" do
subject
+ expect(user.tokens).to be_blank
expect(response).to have_http_status(200)
end
end
end
エラー内容
Failure/Error: expect(trainer.tokens).to be_blank
expected `{"LT4SdlN2czyzNnwTfLGjTw"=>{"expiry"=>1596957557, "token"=>"$2a$10$BgZ4YItos1hQRTp4y1JvZ.mIsreaIxD1NC3ckRk0euxsk8IBkoM7K", "updated_at"=>"2020-07-26 07:19:17 UTC"}}.blank?` to return true, got false
トークン情報が残ったままとのエラーです。
ログアウトに必要な情報を user に入れ、ログアウトの処理はできても、user の値は更新されないので残ったままになっています。
user の値を更新するためには、user.reload.token
と記述してあげる必要があります。
describe "DELETE /v1/auth/user/sign_out" do
subject { delete(destroy_v1_user_session_path, headers: headers) }
context "トレーナーログアウト時" do
let(:user) { create(:user) }
let(:headers) { user.create_new_auth_token }
it "トークンを無くし、ログアウトできる" do
subject
expect(user.reload.tokens).to be_blank
expect(response).to have_http_status(200)
end
end
end
以上の内容にすれば、ログアウト後の user の値が更新されるため、user にトークン情報がなくなります。