Techioz Blog

RSpec 3.12 リクエストで属性を連結するにはどうすればよいですか?

概要

アプリケーションの編集ビューは、予期されるデータ フィールドに加えて、注釈や翻訳などのモデルに属さない追加フィールドも提供します。これらは、編集されたレコードを保存する前にコントローラー メソッドによって処理されます。

リクエストのテストを作成するときは、モデル フィールドに加えて、次の追加フィールドを Post メソッドに提供する必要があります。

RSpec.describe "Playgrounds", type: :request do
  include Warden::Test::Helpers 
  # Playground. As you add validations to Playground, be sure to
  # adjust the attributes here as well.

  let(:user) { create(:user, is_admin: true) }
  let(:playground) {FactoryBot.create(:playground)}

  # User login 
  before do
    login_as user, scope: :user
  end

  describe "POST /playgrounds" do
    context "with valid attributes" do
      # Use per context let instead 
      let(:attributes) { attributes_for(:playground) }
      it "creates a playground" do
        expect {
          post '/entities', params: {
            playground: attributes, 
            playground_name_fr: "Donnée de test", 
            playground_name_de: "", 
            playground_name_en: "Test data", 
            playground_name_it: "Dati del test", 
            playground_description_fr: "Ceci n'est qu'un test", 
            playground_description_de: "", 
            playground_description_en: "This is just a test", 
            playground_description_it: "Questo è solo un test"
          }
        }.to change(Playground, :count).by(1)
        expect(response).to have_http_status 302
      end
    end 
  end
end

翻訳に使用されるこれら 8 つのフィールドを 1 回だけ定義するために、ハッシュ変数を定義し、それをプレイグラウンド ハッシュに追加したいと思います。

RSpec.describe "Playgrounds", type: :request do
  include Warden::Test::Helpers 
  # Playground. As you add validations to Playground, be sure to
  # adjust the attributes here as well.

  let(:user) { create(:user, is_admin: true) }
  let(:playground) {FactoryBot.create(:playground)}
  let(:fields) do 
    { 
      playground_name_fr: "Donnée de test", 
      playground_name_de: "", 
      playground_name_en: "Test data", 
      playground_name_it: "Dati del test", 
      playground_description_fr: "Ceci n'est qu'un test", 
      playground_description_de: "", 
      playground_description_en: "This is just a test", 
      playground_description_it: "Questo è solo un test" 
    }
  end

    # User login 
    before do
        login_as user, scope: :user
    end

  describe "POST /playgrounds" do
    context "with valid attributes" do
      # Use per context let instead 
      let(:attributes) { attributes_for(:playground) }
      it "creates a playground" do
        expect {
          post '/entities', params: {
            playground: attributes < fields 
          }
        }.to change(Playground, :count).by(1)
        expect(response).to have_http_status 302
      end
    end 
  end
end 

しかし、次のエラーが表示されます。

 Failure/Error:
   params.require(:playground)
         .permit(:code,
                 :status_id,
                 :logo,
                 :organisation_id,
                 :responsible_id,
                 :deputy_id,
                 :sort_code,
                 name: {},
                 description: {}

 NoMethodError:
   undefined method `permit' for "false":String

最初の構文は期待どおりに機能しますが、2 番目の構文は期待どおりに機能しないため、フィールドを間違った場所またはレベルに挿入した可能性がありますが、これを解決する方法がわかりません。

助けてくれてありがとう!

解決策

ハッシュをマージするには、Hash#merge を使用します。

expect {
  post '/entities', params: {
    playground: attributes.merge(fields)
  }
}.to change(Playground, :count).by(1)

Ruby にはこれを表す演算子の短縮形がありません。 Hash#< は、実際には、ハッシュが別のハッシュのサブセットであるかどうかをテストするために使用され、ブール値を返します。