Alert メッセージ確認 shared_example : 小林研 Rails Tips (26)

はじめに

Rails Tips の 26 回目です。今日は create の request_spec における異常系を説明します。

  # describe "POST #create" do
  #   before { object.destroy }
  #   subject { -> { post <%= plural_table_name %>_path, params: {<%= singular_table_name %>: attrs} } }
  #   context "owned object" do
  #     let(:one) { <%= singular_table_name %> }
  #     context "正しいパラメータに対して" do
  #       it_behaves_like "レスポンスコード確認", 302
  #       it_behaves_like "オブジェクトが1増えるか?", <%= class_name %>
  #       it_behaves_like "リダイレクト確認"
  #       it_behaves_like "Notice メッセージ確認", "XXXを登録しました。"
  #     end

  #     context "不正なパラメータに対して" do
  #       before { attrs["name"] = "" }
  #       it_behaves_like "レスポンスコード確認", 422
  #       it_behaves_like "オブジェクト数が変化しない?", <%= class_name %>
  #       it_behaves_like "Alert メッセージ確認", "XXXの登録に失敗しました。"
  #     end
  #   end

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

Alert メッセージ確認

以下はイベント (Event) を作成する create の異常系の spec になります。Event は comment が空白であることを許さないので、save でエラーになります。この時、レスポンスは Unprocessable Content の 422 になります。失敗するのでオブジェクト数が増えないことも確認しています。最後が今回の Alert メッセージ確認です。これは昨日の Notice メッセージ確認と同じですね。雛形には「XXXを登録に失敗しました。」とテンプレートの文字列を用意してあるので、Notice メッセージの時の置換を指定れば、この部分はイベントに書き換わっているはずです。

      context "不正なパラメータに対して" do
        before { attrs["comment"] = "" }
        it_behaves_like "レスポンスコード確認", 422
        it_behaves_like "オブジェクト数が変化しない?", Event
        it_behaves_like "Alert メッセージ確認", "イベントの登録に失敗しました。"
      end

この shared_example は以下のようになります。Notice メッセージ確認と同様、subject.call した後で、Alert メッセージを確認しているだけです。

shared_examples_for "Alert メッセージ確認" do |str|
  it "alert に「#{str}」が出力されること" do
    subject.call
    expect(flash.now[:alert]).to eq str
  end
end

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

create action には以下のように記載しています。ここでも、notice_message, alert_message: 小林研 Rails Tips (17) - hkob’s blog で説明した alert_message(Kurasu) を使っています。これによって、日本語の表記揺れがなくなり、テストも簡単になります。redirect_to と異なり、render action では flash の指定ができないので、事前に flash.now[:alert] に代入しています。また、render action 時に :unprocessable_entity の status を設定するのを忘れないようにします。

def create
    @event = Event.new event_params
    if @event.save
      redirect_to teacher_events_path(date: @event.event_date.to_s), notice: notice_message(Event)
    else
      @date = @event.event_date
      flash.now[:alert] = alert_message Event
      render action: :new, status: :unprocessable_entity
    end
  end

おわりに

ユカスタマスは終わってしまいましたが、まだ全ての shared_example などを紹介しきれていないので、ネタが尽きるまで連続掲載を続けていきます。