Search code examples
ruby-on-railsrspechttp-postrspec-rails

rails request spec post syntax


I can't seem to get my head over how to make post requests for testing a url in request spec tests, here's the test code

RSpec.describe "Certifications", type: :request do
  describe "denies public access" do

    it "for new certification form" do
        get new_certification_path
        expect(response).to redirect_to new_user_session_path
    end

    it "for creating certification" do
        certification_attributes = FactoryGirl.attributes_for :certification 

        expect {
            post "/certifications", { certification: certification_attributes }
        }.to_not change(Certification, :count)

        expect(response).to redirect_to new_user_session_path
    end
  end
end

Which gives the error

  1) Certifications denies public access for creating certification
     Failure/Error: post "/certifications", { certification: certification_attributes }

 ArgumentError:
   unknown keyword: certification

I've tried the :certifications => certification_attributes, basically can't get my head over on how to pass params.

The controller under test is, adding only relevant methods to this post.

class CertificationsController < ApplicationController
  skip_before_action :authenticate_user!, if: :skip_user_authentication
  before_action :set_certification, only: [:show, :edit, :update, :destroy]

  # GET /certifications
  # GET /certifications.json
  def index
    @certifications = Certification.all
  end

  # GET /certifications/1
  # GET /certifications/1.json
  def show
  end

  # GET /certifications/new
  def new
    @certification = Certification.new
  end

  # POST /certifications
  # POST /certifications.json
  def create
    @certification = Certification.new(certification_params)

    respond_to do |format|
      if @certification.save
        format.html { redirect_to @certification, notice: 'Certification was successfully created.' }
        format.json { render :show, status: :created, location: @certification }
      else
        format.html { render :new }
        format.json { render json: @certification.errors, status: :unprocessable_entity }
      end
    end
  end

  protected
    def skip_user_authentication
        request.format.json? && (action_name.eql?('show') || (action_name.eql?('index'))) 
    end 
end

I am trying to assert the behaviour of allowing all methods except certifications.json or certifications/1.json to not require authentication, there are other tests which access these URLs and they pass. The part of ensuring it does not allow any other request is where I am stuck. I am using Devise with Omnitauth Google OAuth2 for authentication in this application.

certification_attributes

{
 :name=>"Foundation Certification", 
 :description=>"Foundation Certification", 
 :terms=>"Foundation Certification", 
 :seo_meta_keywords=>["laaa", "lalala certifications"],
 :seo_meta_description=>"Foundation Certifications"
}

Solution

  • Send request parameters under :params keyword:

    post "/certifications", params: { certification: certification_attributes }
                            ^^^^^^