Ruby on Rails チュートリアルの第4版を学習し、Everyday Rails - RSpecによるRailsテスト入門でRSpecを学習したので、Ruby on Rails チュートリアルをRSpecでテストしてみました。
今回は第10章のテストを書きます。
第3章~第9章のテストは以下。
- Railsチュートリアルの第4版をRSpecでテスト-1(第3章~第6章)
- Railsチュートリアルの第4版をRSpecでテスト-2(第7章~第8章)
- Railsチュートリアルの第4版をRSpecでテスト-3(第9章)
ユーザーの編集・更新のテスト
初めにユーザーコントローラのeditアクション、updateアクションをテストします。
リクエストスペックに以下のテストを追加します。
require 'rails_helper'
RSpec.describe "User pages", type: :request do
let(:user) { FactoryBot.create(:user) }
let(:other_user) { FactoryBot.create(:user) }
describe "GET #new" do
# 中身は省略
end
describe "GET #show" do
# 中身は省略
end
describe "#edit" do
# 認可されたユーザーとして
context "as an authorized user" do
it "responds successfully" do
sign_in_as user
get edit_user_path(user)
expect(response).to be_success
expect(response).to have_http_status "200"
end
end
# ログインしていないユーザーの場合
context "as a guest" do
# ログイン画面にリダイレクトすること
it "redirects to the login page" do
get edit_user_path(user)
expect(response).to have_http_status "302"
expect(response).to redirect_to login_path
end
end
# アカウントが違うユーザーの場合
context "as other user" do
# ホーム画面にリダイレクトすること
it "redirects to the login page" do
sign_in_as other_user
get edit_user_path(user)
expect(response).to redirect_to root_path
end
end
end
describe "#update" do
# 認可されたユーザーとして
context "as an authorized user" do
# ユーザーを更新できること
it "updates a user" do
user_params = FactoryBot.attributes_for(:user, name: "NewName")
sign_in_as user
patch user_path(user), params: { id: user.id, user: user_params }
expect(user.reload.name).to eq "NewName"
end
end
# ログインしていないユーザーの場合
context "as a guest" do
# ログイン画面にリダイレクトすること
it "redirects to the login page" do
user_params = FactoryBot.attributes_for(:user, name: "NewName")
patch user_path(user), params: { id: user.id, user: user_params }
expect(response).to have_http_status "302"
expect(response).to redirect_to login_path
end
end
# アカウントが違うユーザーの場合
context "as other user" do
# ユーザーを更新できないこと
it "does not update the user" do
user_params = FactoryBot.attributes_for(:user, name: "NewName")
sign_in_as other_user
patch user_path(user), params: { id: user.id, user: user_params }
expect(user.reload.name).to eq other_user.name
end
# ホーム画面にリダイレクトすること
it "redirects to the login page" do
user_params = FactoryBot.attributes_for(:user, name: "NewName")
sign_in_as other_user
patch user_path(user), params: { id: user.id, user: user_params }
expect(response).to redirect_to root_path
end
end
end
end
editアクションは基本的にshowアクションと同じですが、updateアクションはPATCHリクエストを使っています。
テストを実行しパスするのを確認します。
続いて、編集の失敗・成功のテストをフィーチャースペックに書いていきます。
ただし、パスワードの更新が上手くいかなかったのでとりあえずコメントアウトしてあります。
require 'rails_helper'
RSpec.feature "Edit", type: :feature do
let(:user) { FactoryBot.create(:user) }
# ユーザーは編集に成功する
scenario "successful edit" do
valid_login(user) # spec/support/login_support.rbに定義済み
visit user_path(user)
click_link "プロフィール編集"
fill_in "メールアドレス", with: "edit@example.com"
# fill_in "パスワード", with: user.password, match: :first
# fill_in "新しいパスワード", with: "test123", match: :first
# fill_in "新しいパスワード確認", with: "test123"
click_button "変更する"
expect(current_path).to eq user_path(user)
expect(user.reload.email).to eq "edit@example.com"
# expect(user.reload.password).to eq "test123"
end
# ユーザーは編集に失敗する
scenario "unsuccessful edit" do
valid_login(user) # spec/support/login_support.rbに定義済み
visit user_path(user)
click_link "プロフィール編集"
fill_in "メールアドレス", with: "foo@invalid"
fill_in "新しいパスワード", with: "foo", match: :first
fill_in "新しいパスワード確認", with: "bar"
click_button "変更する"
expect(user.reload.email).to_not eq "foo@invalid"
end
end
実行しテストがパスするのを確認します。
フレンドリーフォーワーディングのテスト
フレンドリーフォーワーディングのテストでは、ログインしていないユーザーが編集ページにアクセスしようとした際、ユーザーがログインした後にはその編集ページにリダイレクトされることをテストします。
このテストは、先程作成したユーザー編集のフィーチャースペックを少し変えるだけです。
require 'rails_helper'
RSpec.feature "Edit", type: :feature do
let(:user) { FactoryBot.create(:user) }
# ユーザーは編集に成功する
scenario "successful edit" do
visit user_path(user) # 順序を入れ替えただけ
valid_login(user) # 順序を入れ替えただけ
# ・・・以下省略
ユーザーの削除のテスト
リクエストスペックにユーザー削除のテストを追加します。
require 'rails_helper'
RSpec.describe "User pages", type: :request do
let(:user) { FactoryBot.create(:user) }
let(:other_user) { FactoryBot.create(:user) }
# 他のアクションのテストは省略
describe "#destroy" do
# 認可されたユーザーとして
context "as an authorized user" do
# ユーザーを削除できること
it "deletes a user" do
sign_in_as user
expect {
delete user_path(user), params: { id: user.id }
}.to change(User, :count).by(-1)
end
end
# アカウントの違うユーザーの場合
context "as au unauthorized user" do
# ホーム画面にリダイレクトすること
it "redirects to the dashboard" do
sign_in_as other_user
delete user_path(user), params: { id: user.id }
expect(response).to redirect_to root_path
end
end
# ゲストとして
context "as a guest" do
it "returns a 302 response" do
delete user_path(user), params: { id: user.id }
expect(response).to have_http_status "302"
end
it "redirects to the sign-in page" do
delete user_path(user), params: { id: user.id }
expect(response).to redirect_to login_path
end
end
end
end
実行しテストがパスするのを確認します。
今回は以上です。
11章以降は完成し次第書いていきます。
#追記
第11章以降のテストを書きました。