1
0

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 3 years have passed since last update.

【RSpec】Railsチュートリアル第6版 第10章

Last updated at Posted at 2021-11-04

#はじめに
Railsチュートリアル第6版のテストをRSpecで書き直していく。

###目次

#Minitest

###編集に対するテスト

test/integration/users_edit_test.rb
require 'test_helper'

class UsersEditTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "unsuccessful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
    assert_template 'users/edit'
    patch user_path(@user), params: { user: { name:  "",
                                              email: "foo@invalid",
                                              password:              "foo",
                                              password_confirmation: "bar" } }

    assert_template 'users/edit'
  end

  test "successful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
    assert_template 'users/edit'
    name  = "Foo Bar"
    email = "foo@bar.com"
    patch user_path(@user), params: { user: { name:  name,
                                              email: email,
                                              password:              "",
                                              password_confirmation: "" } }
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name,  @user.name
    assert_equal email, @user.email
  end

  test "successful edit with friendly forwarding" do
    get edit_user_path(@user)
    log_in_as(@user)
    assert_redirected_to edit_user_url(@user)
    name  = "Foo Bar"
    email = "foo@bar.com"
    patch user_path(@user), params: { user: { name:  name,
                                              email: email,
                                              password:              "",
                                              password_confirmation: "" } }
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name,  @user.name
    assert_equal email, @user.email
  end
end

###editとupdateアクションの保護に対するテスト

test/controllers/users_controller_test.rb
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest

  def setup
    @user       = users(:michael)
    @other_user = users(:archer)
  end

  test "should get new" do
    get signup_path
    assert_response :success
  end

  test "should redirect index when not logged in" do
    get users_path
    assert_redirected_to login_url
  end
  
  test "should redirect edit when not logged in" do
    get edit_user_path(@user)
    assert_not flash.empty?
    assert_redirected_to login_url
  end

  test "should redirect update when not logged in" do
    patch user_path(@user), params: { user: { name: @user.name,
                                              email: @user.email } }
    assert_not flash.empty?
    assert_redirected_to login_url
  end

  test "should redirect edit when logged in as wrong user" do
    log_in_as(@other_user)
    get edit_user_path(@user)
    assert flash.empty?
    assert_redirected_to root_url
  end

  test "should redirect update when logged in as wrong user" do
    log_in_as(@other_user)
    patch user_path(@user), params: { user: { name: @user.name,
                                              email: @user.email } }
    assert flash.empty?
    assert_redirected_to root_url
  end

  test "should redirect destroy when not logged in" do
    assert_no_difference 'User.count' do
      delete user_path(@user)
    end
    assert_redirected_to login_url
  end

  test "should redirect destroy when logged in as a non-admin" do
    log_in_as(@other_user)
    assert_no_difference 'User.count' do
      delete user_path(@user)
    end
    assert_redirected_to root_url
  end

end

###fixture

test/fixtures/users.yml
michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>
  admin: true

archer:
  name: Sterling Archer
  email: duchess@example.gov
  password_digest: <%= User.digest('password') %>

lana:
  name: Lana Kane
  email: hands@example.gov
  password_digest: <%= User.digest('password') %>

malory:
  name: Malory Archer
  email: boss@example.gov
  password_digest: <%= User.digest('password') %>

<% 30.times do |n| %>
user_<%= n %>:
  name:  <%= "User #{n}" %>
  email: <%= "user-#{n}@example.com" %>
  password_digest: <%= User.digest('password') %>
<% end %>

###UsersIndexのテスト

test/integration/users_index_test.rb
require 'test_helper'

class UsersIndexTest < ActionDispatch::IntegrationTest

  def setup
    @admin     = users(:michael)
    @non_admin = users(:archer)
  end

  test "index as admin including pagination and delete links" do
    log_in_as(@admin)
    get users_path
    assert_template 'users/index'
    assert_select 'div.pagination'
    first_page_of_users = User.paginate(page: 1)
    first_page_of_users.each do |user|
      assert_select 'a[href=?]', user_path(user), text: user.name
      unless user == @admin
        assert_select 'a[href=?]', user_path(user), text: 'delete'
      end
    end
    assert_difference 'User.count', -1 do
      delete user_path(@non_admin)
    end
  end

  test "index as non-admin" do
    log_in_as(@non_admin)
    get users_path
    assert_select 'a', text: 'delete', count: 0
  end
end

#RSpec

###編集に対するテスト

spec/system/users_edit_spec.rb
require 'rails_helper'

RSpec.describe "UsersEdits", type: :system do

  let(:user) {FactoryBot.create(:user)}

  it "unsuccessful edit" do
    visit login_path
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Log in"
    click_on "Setting"
    expect(page).to have_current_path edit_user_path(user)
    fill_in "Name", with: ""
    fill_in "Email", with: "user@invalid"
    fill_in "Password", with: "foo"
    fill_in "Confirmation", with: "bar"
    click_on "Save changes"
    expect(page).to have_current_path user_path(user)
  end

  it "successful edit" do
    visit login_path
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Log in"
    click_on "Setting"
    expect(page).to have_current_path edit_user_path(user)
    fill_in "Name", with: "Foo Bar"
    fill_in "Email", with: "foo@bar.com"
    fill_in "Password", with: ""
    fill_in "Confirmation", with: ""
    click_on "Save changes"
    expect(page).to have_content("Profile updated")
    expect(page).to have_current_path user_path(user)
    user.reload
    expect(user.name).to eq "Foo Bar"
    expect(user.email).to eq "foo@bar.com"
  end

  it "successful edit with friendly forwarding" do
    visit edit_user_path(user)
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Log in"
    expect(page).to have_current_path edit_user_path(user)
    fill_in "Name", with: "Foo Bar"
    fill_in "Email", with: "foo@bar.com"
    fill_in "Password", with: ""
    fill_in "Confirmation", with: ""
    click_on "Save changes"
    expect(page).to have_content("Profile updated")
    expect(page).to have_current_path user_path(user)
    user.reload
    expect(user.name).to eq "Foo Bar"
    expect(user.email).to eq "foo@bar.com"
  end

end

###editとupdateアクションの保護に対するテスト

spec/requests/users_spec.rb
require 'rails_helper'

RSpec.describe "Users", type: :request do

  before do
  @user = FactoryBot.create(:user)
  @noadmin_user = FactoryBot.create(:user, :noadmin)
  end

  it "returns http success" do
    get signup_path
    expect(response).to have_http_status(:success)
  end

  it "should redirect index when not logged in" do
    get users_path
    expect(response).to redirect_to login_path
  end

  it "should redirect edit when not logged in" do
    get edit_user_path(@user)
    expect(flash[:danger]).to eq "Please log in."
    expect(response).to redirect_to login_url
  end

  it "should redirect update when not logged in" do
    patch user_path(@user), params: { user: { name: @user.name,
    email: @user.email } }
    expect(flash[:danger]).to eq "Please log in."
    expect(response).to redirect_to login_url
  end

  it "should redirect edit when logged in as wrong user" do
    log_in_as(@noadmin_user)
    get edit_user_path(@user)
    expect(flash[:danger]).to eq nil
    expect(response).to redirect_to root_url
  end

  it "should redirect update when logged in as wrong user" do
    log_in_as(@noadmin_user)
    patch user_path(@user), params: { user: { name: @user.name,
    email: @user.email } }
    expect(flash[:danger]).to eq nil
    expect(response).to redirect_to root_url
  end

  it"should redirect destroy when not logged in" do
    expect {
      delete user_path(@user)
    }.to_not change(User, :count)
    expect(response).to redirect_to login_url
  end

  it "should redirect destroy when logged in as a non-admin" do
    log_in_as(@noadmin_user)
    expect {
      delete user_path(@user)
    }.to_not change(User, :count)
    expect(response).to redirect_to root_url
  end

end

letを使用してユーザーを遅延読み込みしてしまうと、最後の二つのテスト内のexpect {delete user_path(@user)}.to_not change(User, :count)において結果的にユーザー数が変わってしまいエラーになるため今回はbeforeで代用。

###factory

spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name {"Michael Example"}
    sequence(:email) { |n| "test#{n}@example.com" } 
    password {"password"}
    password_confirmation  {"password"}
    admin {true}

    trait :noadmin do
      admin {false}
    end

    trait :users do
      sequence(:name) { |n| "User#{n}" } 
      sequence(:email) { |n| "testusers#{n}@example.com" }
      admin {false}
    end

  end
end

traitを使用し、adminがfalseである非管理者のnoadmin、シーケンスを用いたnameとemailを持ち非管理者のusersを作成。

###UsersIndexのテスト

spec/requests/users_index_spec.rb
require 'rails_helper'

RSpec.describe "UsersIndex", type: :request do

  before do
    30.times {FactoryBot.create(:user, :users)}
    @admin_user = FactoryBot.create(:user)
    @noadmin_user = FactoryBot.create(:user, :noadmin)
  end

  it "index as admin including pagination and delete links" do
    log_in_as(@admin_user)
    get users_path
    expect(response).to have_http_status(200)
    assert_select "div.pagination"
    first_page_of_users = User.paginate(page: 1)
    first_page_of_users.each do |user|
      assert_select "a[href=?]", user_path(user), text: "delete"
      unless user == @admin_user
        assert_select "a[href=?]", user_path(user), text: "delete"
      end
    end
    expect {
      delete user_path(@noadmin_user)
    }.to change(User, :count).by(-1)
  end

  it "index as non-admin" do
    log_in_as(@noadmin_user)
    get users_path
    assert_select "a", text: "delete", count: 0
  end

end

editとupdateアクションの保護に対するテストと同理由で、letbeforeで代用。before do内において、factoryで作成したusersを三十人分複製し、ページネーションのテストに使用する。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?