rootリダイレクト確認 shared_example : 小林研 Rails Tips (22)

はじめに

Rails Tips の 22 回目です。昨日から request_spec に使う shared_example を紹介しています。request_spec の index のテストまでの雛形は以下のようになっています。ここで使われているものを順に紹介しています。

# rubocop:disable all
require "rails_helper"

RSpec.describe "<%= class_name.pluralize %>", type: :request do
  # let!(:<%= singular_table_name %>) { <%= plural_table_name %> :<%= singular_table_name %> }
  # let!(:object) { <%= singular_table_name %> }
  # let!(:attrs) { object.attributes }
  # let(:not_mine) { <%= plural_table_name %> :not_mine }

  # let(:return_path) { <%= plural_table_name %>_path }
  # context "login by hkob" do
  #   kyouin_server_user_login :hkob

  #   describe "GET #index" do
  #     subject { -> { get <%= plural_table_name %>_path } }
  #     context "owned object" do
  #       let(:one) { <%= singular_table_name %> }
  #       it_behaves_like "レスポンスコード確認", 200
  #       it_behaves_like "描画結果に文字列が含まれている?", %w[XXX一覧]
  #       it_behaves_like "描画結果に文字列が含まれていない?", "XXXの追加"
  #     end
      
  #     context "not owned object" do
  #       let(:one) { not_mine }
  #       it_behaves_like "レスポンスコード確認", 302
  #       it_behaves_like "rootリダイレクト確認"
  #     end
  #   end

rootリダイレクト確認

gnumber_ktannis_path は学生の単位確認するためのページです。gnumbers/:gnumber_id/ktannis#index というアクションになるので、学生ごとに異なる URL になります。当然他人の成績を勝手に見られては困りますから、自分のものではないページを表示しようとしたらエラーとしてトップページに戻るようにします。

この RSpec は以下のようになります。subject では gnumber の部分を one と設定しています。owned object および not owned object のそれぞれの context において、この one を let で遅延評価しています。自分の学生番号の場合には結果が表示されることを確認しますが、他人の学生番号を開こうとしたら root ページにリダイレクトすることを確認します。新しいのは rootリダイレクト確認 だけになります。

    describe "GET #index" do
      subject { -> { get gnumber_ktannis_path(one) } }
      context "owned object" do
        let(:one) { gnumber }
        it_behaves_like "レスポンスコード確認", 200
        it_behaves_like "描画結果に文字列が含まれている?", %w[履修計画シート]
      end

      context "not owned object" do
        let(:one) { not_mine }
        it_behaves_like "レスポンスコード確認", 302
        it_behaves_like "rootリダイレクト確認"
      end
    end

この shared_example は以下のようになります。subject.call した後の response.body をチェックしているだけです。

shared_examples_for "rootリダイレクト確認" do
  it do
    subject.call
    expect(response).to redirect_to(root_path)
  end
end

正しく動作させるための実装

権限確認は実装によって様々なのでここでは細かくは解説しません。校務支援システムでは、最近自作の権限管理システムを作成しました。ページに権限を細かく設定し、その権限を見ながらリンクなども自動設定するようになり、非常にコードが書きやすくなりました。その辺りも今後紹介できたらとは思っています。

おわりに

とりあえず index は完了しました。show, new, edit は単体表示なので index とほぼ同じです。index よりもさらに権限管理テストが重要になるくらいだと思います。