2021年10月4日 現場Rails Chapter5-9 他のユーザーが作成したタスクが表示されないことの確認
前回はユーザーAが作成したタスクがページに表示されていることを確認するテストを書きました。 今回はユーザーBがログインした際にユーザーAのタスクは表示されていないことを確認するテストを書いていきます。
require 'rails_helper' describe 'タスク管理機能', type: :system do describe '一覧表示機能' do before do # user_aを名前とメールを指定して、新たに作成する user_a = FactoryBot.create(:user, name: 'ユーザーA', email: 'a@example.com') # user_aに紐づくタスクをタスク名を指定して作成する FactoryBot.create(:task, name: '最初のタスク', user: user_a) end context 'ユーザーAがログインしているとき' do before do # ログインページへアクセスする visit login_path # メールアドレスとパスワードをログインフォームに入力する fill_in 'メールアドレス', with: 'a@example.com' fill_in 'パスワード', with: 'password' # ログインボタンを押す click_button 'ログインする' end it 'ユーザーAが作成したタスクが表示される' do # pageに最初のタスクという内容があることを期待する。 expect(page).to have_content '最初のタスク' end ーーーーーーーーーーーーーーーーーーーーーーー # ここからが今回学んだ内容になります。 context 'ユーザーBがログインしているとき' do before do Factorybot.create(:task, name: 'ユーザーB', email: 'a@example.com', user: user_a) visit login_path fill_in 'メールアドレス', with: login_user.email fill_in 'パスワード', with: login_user.password # ログインボタンを押す click_button 'ログイン' end context 'ユーザーAがログインしているとき' do let(:login_user){ user_a } it 'ユーザーAが作成したタスクが表示される' expect(page).to have_content '最初のタスク' end end # ユーザーBとしてログインしている為、ユーザーAが作成した最初のタスクが表示されないようにする it 'ユーザーAが作成したタスクが表示されない' do # '最初のタスク'が表示されない。 expect(page).to have_no_content '最初のタスク' end end end end
beforeを利用した共通化
コード自体の共通点が多い時、似たコードをまとめて、共通化することができます。今回は、beforeを使って共通化していきます。
describe 'タスク管理機能', type: :system do describe '一覧表示機能' do let(:user_a){ FactoryBot.create(:user, name: 'ユーザーA', email: 'a@example.com')} let(:user_b){ FactoryBot.create(:user, name: 'ユーザーB', email: 'b@example.com')} before do FactoryBot.create(:task, name: '最初のタスク', user: user_a) # ここでletのユーザーAが実際にデータベースに登録されます。 visit login_path fill_in 'メールアドレス', with: login_user.email fill_in 'パスワード', with: login_user.password click_button 'ログインする' end context 'ユーザーAがログインしている時' do let(:login_user) { user_a } it 'ユーザーAが作成したタスクが表示される' do expect(page).to have_content '最初のタスク' end end context 'ユーザーBがログインしている時' do let(:login_user) { user_b } it 'ユーザーAが作成したタスクが表示されない' do expect(page).to have_no_content '最初のタスク' end end end end
否定系の書き方
以下の3種類がありますがどれを使用しても大丈夫です。
expect(page).to have_no_content '最初のタスク' expect(page).not_to have_content '最初のタスク' expect(page).to_not have_content '最初のタスク'
伊藤淳一さんはこちらのツイートで to_not
が書きやすいとおっしゃっているので参考にしてみても良いかも知れません。
上記のコード(否定系の書き方の上)のように、同じ階層にあるすべてのcontext~end内で共通する処理は、一つ上の階層内で、beforeを定義して、共通処理を書くことが出来ます。
この場合は、context処理前にbeforeブロック内の処理が実行されます。ここで実行される処理は、パスワードやメールなどの値は実際に入っておらず、箱のような状態になっています。実際にcontext処理内のletで、before処理内のパスワードやメールの値が入ります。
letとlet!
現場Rails P.213~P.214に詳しく記載されてるので、以下に引用します。
letは呼び出されたタイミングで実行され、一度も呼び出されないときは実行されずじまいとなります。
そのため、例えばlogin_userというletを定義したとしても、以下の例のようにlogin_userを一度も呼び出さずにログインすると、ユーザーが作られることがありません。そのため、ログインが失敗してしまいます。
describe '一覧表示機能' do let(:login_user) { FactoryBot.create(:user, name: 'ユーザーA, email: 'a@exaple.com)} before do # let(:login_user)の定義を一度も呼び出さずにログインする visit login_path fill_in 'メールアドレス', with: 'a@example.com' fill_in 'パスワード', with: 'password' click_button 'ログインする' #=> ユーザーAが作られていないためにログイン失敗する end ... end
このような場合は、letの代わりにlet!を利用すれば、beforeの前にユーザーが登録されるため、意図通りにログインできるようになります(参照しないのであればlet!にもせずにbeforeに記述しても良いという考え方もできますが、let!を使う方が読みやすくなる場合があります。また「呼び出されるケースと呼び出されないケースがあるが、データは常に作りたい」といった場合にも便利に利用できます)
参照
現場Rails(p.205~214)
RSpecで「~ではないこと」を検証するときは expect(x).to_not 、または expect(x).not_to のどちらを使うべきか?