diff --git a/spec/factories/users.rb b/spec/factories/users.rb new file mode 100644 index 0000000..054b03c --- /dev/null +++ b/spec/factories/users.rb @@ -0,0 +1,9 @@ +FactoryBot.define do + factory :user do + email { Faker::Internet.unique.email } + password { 'password' } + password_confirmation { 'password' } + first_name { Faker::Name.first_name } + last_name { Faker::Name.last_name } + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 00345af..7fa16d7 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -61,4 +61,5 @@ config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") + config.include FactoryBot::Syntax::Methods end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ce33d66..d10f957 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -46,14 +46,14 @@ # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. -=begin + # This allows you to limit a spec run to individual examples or groups # you care about by tagging them with `:focus` metadata. When nothing # is tagged with `:focus`, all examples get run. RSpec also provides # aliases for `it`, `describe`, and `context` that include `:focus` # metadata: `fit`, `fdescribe` and `fcontext`, respectively. config.filter_run_when_matching :focus - +=begin # Allows RSpec to persist some state between runs in order to support # the `--only-failures` and `--next-failure` CLI options. We recommend # you configure your source control system to ignore this file. @@ -93,4 +93,9 @@ # as the one that triggered the failure. Kernel.srand config.seed =end + + config.before(:each, type: :system) do + driven_by :selenium, using: :headless_chrome, screen_size: [1920, 1080] + # driven_by :selenium, using: :chrome, screen_size: [1080, 1080] # ローカルでの確認用 + end end diff --git a/spec/system/posts_spec.rb b/spec/system/posts_spec.rb new file mode 100644 index 0000000..91ca0a9 --- /dev/null +++ b/spec/system/posts_spec.rb @@ -0,0 +1,92 @@ +require 'rails_helper' + +RSpec.describe "Posts", type: :system do + describe '確認観点4:投稿機能' do + let!(:user){ create(:user) } + let(:another_user){ create(:user) } + + before do + # 確認対象の画面に移動 + visit '/login' + + # labelの存在確認 + expect(page).to have_selector('label',text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ログイン用ボタンの存在確認 + expect(page).to have_button('Login'), 'ログイン用のボタンが表示されていることを確認してください' + + # ユーザーログイン処理 + fill_in 'Email', with: user.email + fill_in 'Password', with: 'password' + click_button 'Login' + end + + it '4-1:自分の投稿を編集することができる' do + create(:post, user: user) + + # 確認対象の画面に移動 + visit '/posts' + + # 編集リンクの存在確認 + expect(page).to have_content('Edit'), '自分の投稿に編集用のリンクが表示されているかを確認してください' + click_on 'Edit' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Title'), 'Title というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Content'), 'Content というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='post_title']"), 'Title というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='post_content']"), 'Content というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # 更新ボタンの存在確認 + expect(page).to have_button('Update Post'), '編集画面に更新用のボタンが表示されているかを確認してください' + + # 投稿編集と更新処理 + fill_in 'Title', with: 'edited_title' + fill_in 'Content', with: 'edited_content' + click_on 'Update Post' + + # 処理結果の確認 + expect(current_path).to eq(post_path(Post.find_by(title: 'edited_title'))), '投稿編集後に投稿詳細画面に遷移できていません' + expect(page).to have_content('edited_title'), '編集した投稿のタイトルが表示されていません' + expect(page).to have_content('edited_content'), '編集した投稿の本文が表示されていません' + end + + it '4-2:自分の投稿を削除することができる' do + post = create(:post, user: user) + + # 確認対象の画面に移動 + visit '/posts' + + # 削除リンクの存在確認 + expect(page).to have_content('Destroy'), '自分の投稿に削除用のリンクが表示されているかを確認してください' + page.accept_confirm { click_on 'Destroy' } + + # 処理結果の確認 + expect(current_path).to eq('/posts'), '投稿削除後に投稿一覧画面に遷移できていません' + expect(page).not_to have_content(post.title), '投稿が削除できているかを確認してください' + end + + it '4-3:他人の投稿に編集リンクが表示されない' do + create(:post, user: another_user) + + # 確認対象の画面に移動 + visit '/posts' + expect(page).not_to have_link('Edit'), '他人の投稿に編集リンクが表示されています' + end + + it '4-4:他人の投稿に削除リンクが表示されない' do + create(:post, user: another_user) + + # 確認対象の画面に移動 + visit '/posts' + expect(page).not_to have_link('Destroy'), '他人の投稿に削除リンクが表示されています' + end + end +end diff --git a/spec/system/user_sessions_spec.rb b/spec/system/user_sessions_spec.rb new file mode 100644 index 0000000..107f3b2 --- /dev/null +++ b/spec/system/user_sessions_spec.rb @@ -0,0 +1,197 @@ + +require 'rails_helper' + +RSpec.describe "UserSessions", type: :system do + describe '確認観点2:ユーザーログイン' do + it '2-1:ユーザーのログインができる' do + # テストデータの用意 + user = create(:user) # describe使わないので、let!を使わずに記載 + + # 確認対象の画面に移動 + visit '/login' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ログイン用ボタンの存在確認 + expect(page).to have_button('Login'), 'ログイン用のボタンが表示されていることを確認してください' + + # ユーザーログイン処理 + fill_in 'Email', with: user.email + fill_in 'Password', with: 'password' + click_button 'Login' + + # 処理結果の確認 + expect(current_path).not_to eq('/login'), 'ログイン処理が正しく行えるかを確認してください' + expect(current_path).to eq('/posts'), 'ログイン後に投稿一覧画面に遷移できていません' + end + + it '2-2:入力項目が不足している場合にログインができない' do + # テストデータの用意 + user = create(:user) # describe使わないので、let!を使わずに記載 + + # 確認対象の画面に移動 + visit '/login' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ログイン用ボタンの存在確認 + expect(page).to have_button('Login'), 'ログイン用のボタンが表示されていることを確認してください' + + # ユーザーログイン処理 + fill_in 'Email', with: nil + fill_in 'Password', with: nil + click_button 'Login' + + # 処理結果の確認 + expect(current_path).not_to eq('/posts'), '入力項目が不足している場合にログインできていないかを確認してください' + expect(current_path).to eq('/login'), 'ログインの失敗時に別の画面の遷移していないかを確認してください' + end + + it '2-3:存在しないユーザーでログインができない' do + # テストデータの用意 + user = create(:user) # describe使わないので、let!を使わずに記載 + + # 確認対象の画面に移動 + visit '/login' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ログイン用ボタンの存在確認 + expect(page).to have_button('Login'), 'ログイン用のボタンが表示されていることを確認してください' + + # ユーザーログイン処理 + fill_in 'Email', with: 'another_user@example.com' + fill_in 'Password', with: 'password' + click_button 'Login' + + # 処理結果の確認 + expect(current_path).not_to eq('/posts'), '存在しないユーザーでログインできていないかを確認してください' + expect(current_path).to eq('/login'), 'ログインの失敗時に別の画面の遷移していないかを確認してください' + end + + it '2-4:パスワードが間違っている場合にログインができない' do + # テストデータの用意 + user = create(:user) # describe使わないので、let!を使わずに記載 + + # 確認対象の画面に移動 + visit '/login' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ログイン用ボタンの存在確認 + expect(page).to have_button('Login'), 'ログイン用のボタンが表示されていることを確認してください' + + # ユーザーログイン処理 + fill_in 'Email', with: user.email + fill_in 'Password', with: 'wrong_password' + click_button 'Login' + + # 処理結果の確認 + expect(current_path).not_to eq('/posts'), 'パスワードが間違っている場合にログインできていないかを確認してください' + expect(current_path).to eq('/login'), 'ログインの失敗時に別の画面の遷移していないかを確認してください' + end + + it '2-5:複数ユーザー登録時に問題なくログインができる' do + # テストデータの用意 + first_user = create(:user) # describe使わないので、let!を使わずに記載 + second_user = create(:user) # describe使わないので、let!を使わずに記載 + third_user = create(:user) # describe使わないので、let!を使わずに記載 + + # 確認対象の画面に移動 + visit '/login' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ログイン用ボタンの存在確認 + expect(page).to have_button('Login'), 'ログイン用のボタンが表示されていることを確認してください' + + # ユーザーログイン処理 + fill_in 'Email', with: second_user.email + fill_in 'Password', with: 'password' + click_button 'Login' + + # 処理結果の確認 + expect(current_path).not_to eq('/login'), 'ログイン処理が正しく行えるかを確認してください' + + find('#header-profile').click + expect(page).not_to have_content("#{first_user.last_name} #{first_user.first_name}"), '最初に登録されたユーザーでログインされています。ログイン時のロジックを確認してください' + expect(page).to have_content("#{second_user.last_name} #{second_user.first_name}"), '複数のユーザーを作成した状態で、正しくログインができるかを確認してください' + expect(page).not_to have_content("#{third_user.last_name} #{third_user.first_name}"), '最後に登録されたユーザーでログインされています。ログイン時のロジックを確認してください' + end + end + + describe '確認観点3:ユーザーログアウト' do + it '3-1:ユーザーのログアウトができる' do + # テストデータの用意 + user = create(:user) # describe使わないので、let!を使わずに記載 + + # 確認対象の画面に移動 + visit '/login' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ログイン用ボタンの存在確認 + expect(page).to have_button('Login'), 'ログイン用のボタンが表示されていることを確認してください' + + # ユーザーログイン処理 + fill_in 'Email', with: user.email + fill_in 'Password', with: 'password' + click_button 'Login' + + # ユーザーログアウト処理 + find('#header-profile').click + + # ログアウト用ボタンの存在確認 + expect(page).to have_link('Logout'), 'ログアウトのボタンが表示されていることを確認してください' + + click_on 'Logout' + + # 処理結果の確認 + expect(page).to have_button('Login'), 'ログアウトができているかを確認してください' + end + + it '3-2:ログインしていない場合、ユーザーのログアウトリンクが表示されない' do + # 確認対象の画面に移動 + visit '/login' + + # 処理結果の確認 + expect(page).not_to have_link('Logout'), 'ログインしていない場合でも、ログアウトリンクが表示されています' + end + end +end diff --git a/spec/system/users_spec.rb b/spec/system/users_spec.rb new file mode 100644 index 0000000..01eb89b --- /dev/null +++ b/spec/system/users_spec.rb @@ -0,0 +1,108 @@ + +require 'rails_helper' + +RSpec.describe "Users", type: :system do + let(:user) { create(:user) } + + describe '確認観点1:ユーザー新規作成' do + it '1-1:ユーザーの新規作成ができる' do + # 確認対象の画面に移動 + visit 'users/new' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Last name'), 'Last name というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'First name'), 'First name というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password confirmation'), 'Password confirmation というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='user_last_name']"), 'Last name というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_first_name']"), 'First name というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_password_confirmation']"), 'Password confirmation というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ユーザー作成用ボタンの存在確認 + expect(page).to have_button('Create User'), 'ユーザー作成用のボタンが表示されていることを確認してください' + + # ユーザー新規作成用の処理 + expect { + fill_in 'Last name', with: 'test01' + fill_in 'First name', with: 'test01' + fill_in 'Email', with: 'test01@example.com' + fill_in 'Password', with: 'password' + fill_in 'Password confirmation', with: 'password' + click_on 'Create User' + }.to change { User.count }.by(1) # 処理結果の確認 + expect(current_path).to eq('/login'), 'ユーザー作成後にログイン画面に遷移できていません' + end + + it '1-2:同じメールアドレスのユーザーは新規作成できない' do + # テストデータの用意 + user = create(:user) # describe使わないので、let!を使わずに記載 + + # 確認対象の画面に移動 + visit 'users/new' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Last name'), 'Last name というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'First name'), 'First name というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password confirmation'), 'Password confirmation というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='user_last_name']"), 'Last name というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_first_name']"), 'First name というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_password_confirmation']"), 'Password confirmation というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ユーザー作成用ボタンの存在確認 + expect(page).to have_button('Create User'), 'ユーザー作成用のボタンが表示されていることを確認してください' + + # ユーザー新規作成用の処理 + expect { + fill_in 'Last name', with: 'test01' + fill_in 'First name', with: 'test01' + fill_in 'Email', with: user.email + fill_in 'Password', with: 'password' + fill_in 'Password confirmation', with: 'password' + click_on 'Create User' + }.to change { User.count }.by(0) # 処理結果の確認 + end + + it '1-3:入力項目が不足している場合に新規作成ができない' do + # 確認対象の画面に移動 + visit 'users/new' + + # labelの存在確認 + expect(page).to have_selector('label', text: 'Last name'), 'Last name というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'First name'), 'First name というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Email'), 'Email というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password'), 'Password というラベルが表示されていることを確認してください' + expect(page).to have_selector('label', text: 'Password confirmation'), 'Password confirmation というラベルが表示されていることを確認してください' + + # labelとフィールドの対応付け確認 + expect(page).to have_css("label[for='user_last_name']"), 'Last name というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_first_name']"), 'First name というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_email']"), 'Email というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_password']"), 'Password というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + expect(page).to have_css("label[for='user_password_confirmation']"), 'Password confirmation というラベルをクリックすると対応するフィールドにフォーカスすることを確認してください' + + # ユーザー作成用ボタンの存在確認 + expect(page).to have_button('Create User'), 'ユーザー作成用のボタンが表示されていることを確認してください' + + # ユーザー新規作成用の処理 + expect { + fill_in 'Last name', with: nil + fill_in 'First name', with: nil + fill_in 'Email', with: nil + fill_in 'Password', with: nil + fill_in 'Password confirmation', with: nil + click_on 'Create User' + }.to change { User.count }.by(0) # 処理結果の確認 + end + end +end