<!-- ## フィーチャースペック編 microposts_spec 7/7 -->
テスト対象
該当するコントローラ | 該当するアクション |
---|---|
MicropostsController | create, destroy |
環境
フォルダ、使用ファイル
種類 | ファイル名 |
---|---|
スペック | spec/features/microposts_pages_spec.rb |
スペック | spec/features/authorization_spec.rb |
サポートモジュール | spec/support/support_module.rb |
shared_context | spec/support/shared_context.rb |
shared_examples | spec/support/shared_examples.rb |
ファクトリ(ユーザ) | spec/support/factories/users.rb |
ファクトリ(マイクロポスト) | spec/support/factories/microposts.rb |
アウトラインの作成
- マイクロポストの作成/削除
他人のマイクロポストは削除できない
※ 未ログインの場合(ページ保護)のテストは
authorization_spec.rb
(別ファイル)にて作成
フィーチャスペック編 authorization_spec
# spec/features/microposts_pages_spec.rb
RSpec.feature "MicropostsPages", type: :feature do
# 未ログイン場合のスペックは、
# authorization_spec.rb にて(別ファイル)作成
# マイクロポストの作成(create)
describe "create"
# valid な情報の場合
context "valid info"
# 成功 (increment: 1)
it_behaves_like "success create micropost"
# 成功メッセージ
scenario "have success messages"
# invalid な情報の場合
context "invalid info"
it_behaves_like "fail create micropost"
# 失敗メッセージ
scenario "have error messages"
# マイクロポストの削除(delete)
describe "destroy"
# 自分のマイクロポストの場合
context "attempt to delete my microposts"
# 成功 (decrement: -1)
it_behaves_like "success delete micropost"
# successメッセージが出力されること
scenario "have success messages"
# 他人のマイクロポストの場合
context "attempt to delete other user's microposts"
# 失敗 (decrement: 0)
it_behaves_like "fail delete micropost"
end
スペック作成
# spec/features/microposts_pages_spec.rb
require 'rails_helper'
RSpec.feature "MicropostsPages", type: :feature do
include SupportModule
include_context "setup"
subject { page }
# マイクロポストの作成(create)
describe "create" do
before { login_as(user) }
# valid な情報の場合
context "valid info" do
# 成功 (increment: 1)
it_behaves_like "success create micropost"
end
# invalid な情報の場合
context "invalid info" do
it_behaves_like "fail create micropost"
end
end
# マイクロポストの削除(delete)
describe "destroy", type: :request do
before { login_as(user) }
# 自分のマイクロポストの場合
context "attempt to delete my microposts" do
it_behaves_like "success delete micropost"
end
# 他人のマイクロポストの場合
context "attempt to delete other user's microposts" do
it_behaves_like "fail delete micropost"
end
end
end
shared_examples の作成
it_behaves_like "success create micropost"
it_behaves_like "fail create micropost"
it_behaves_like "success delete micropost"
it_behaves_like "fail delete micropost"
# spec/support/shared_examples.rb
# マイクロポストの作成/削除
# microposts#create
# 成功
shared_examples_for "success create micropost" do
scenario "micropost increment 1" do
expect {
visit root_path
params = post_params
fill_in "micropost_content", with: params[:content]
click_button "Post"
}.to change(Micropost, :count).by(1)
# 成功メッセージ
expect(page).to have_css("div.alert.alert-success", text: "Micropost created")
end
end
# 失敗
shared_examples_for "fail create micropost" do
scenario "micropost increment 0" do
expect {
visit root_path
fill_in "micropost_content", with: ""
click_button "Post"
}.to change(Micropost, :count).by(0)
# 失敗メッセージ
expect(page).to have_css("div.alert.alert-danger")
end
end
# microposts#destroy
# 成功
shared_examples_for "success delete micropost" do
before { my_posts }
scenario "micropost descrement -1" do
expect {
visit root_path
click_link "delete", match: :first
}.to change(Micropost, :count).by(-1)
# 成功メッセージ
expect(page).to have_css("div.alert.alert-success", text: "Micropost deleted")
end
end
# 失敗
shared_examples_for "fail delete micropost" do
before { other_posts }
scenario "micropost descrement 0" do
expect {
# リンクが無いので、直接 HTTPリクエストを発行
delete micropost_path(other_posts.first.id)
}.to change(User, :count).by(0)
end
end
実行結果
$ bin/rspec spec/features/microposts_pages_spec.rb
MicropostPages
create
valid info
behaves like success create micropost
micropost increment 1
invalid info
behaves like fail create micropost
micropost increment 0
destroy
attempt to delete my microposts
behaves like success delete micropost
micropost descrement -1
attempt to delete other user's microposts
behaves like fail delete micropost
micropost descrement 0
Finished in 7.13 seconds (files took 2.15 seconds to load)
4 examples, 0 failures
未ログインの場合(ページ保護)のスペック
アウトラインの作成
# spec/features/authorization_spec.rb
RSpec.feature "Authorization", type: :feature do
# ページ保護(アクセス権限)
describe "in MicropostsController"
# マイクロポスト 投稿(作成)/削除
describe "authorization of create/destroy micropost"
context "when non-login"
describe "create"
describe "destroy"
end
shared_examples の作成
-
ログインメッセージ出力・ログインページへリダイレクトは、一般化して使い回せるようにしてみる
spec側でブロックをオブジェクト化(
Proc.new { }
)してsubject { }
に定義し、shared_examples側で、subject.call
して呼び出す
# spec/support/shared_examples.rb
# 成功メッセージ
# flash[:success]
shared_examples_for "success message" do |msg|
it { subject.call; expect(flash[:success]).to eq msg }
end
# 失敗メッセージ
# flash[:danger]
shared_examples_for "error message" do |msg|
it { subject.call; expect(flash[:danger]).to eq msg }
end
# リダイレクト
# redirect to path
shared_examples_for "redirect to path" do |path|
it { subject.call; expect(response).to redirect_to path }
end
スペック作成
# spec/features/authorization_spec.rb
require 'rails_helper'
RSpec.feature "Authorization", type: :feature do
include SupportModule
include_context "setup"
# アクセス権限
describe "in MicropostsController", type: :request do
# マイクロポスト 投稿(作成)/削除
describe "authorization of create/destroy micropost" do
context "when non-login" do
describe "create" do
subject { Proc.new { post microposts_path, params: post_params } }
it_behaves_like "error flash", "Please log in"
it_behaves_like "redirect to path", "/login"
end
describe "destroy" do
subject { Proc.new { delete micropost_path(my_post.id) } }
it_behaves_like "error flash", "Please log in"
it_behaves_like "redirect to path", "/login"
end
end
end
end
end
実行結果
$ bin/rspec spec/features/authorization_spec.rb -e "authorization of create/destroy micropost"
Authorization
in MicropostsController
authorization of create/destroy micropost
when non-login
create
behaves like error flash
should eq "Please log in"
behaves like redirect to path
should redirect to "/login"
destroy
behaves like error flash
should eq "Please log in"
behaves like redirect to path
should redirect to "/login"
Finished in 4.68 seconds (files took 2.33 seconds to load)
4 examples, 0 failures