0

I have a JSON Rails 4 API that I'm testing with Rspec. I'm having trouble passing to two parameters in the post :create request.

Here is the current test:

 require 'spec_helper'
  module Api
    module V1
      describe Api::V1::ProductsController, type: :controller do

        before do
          @api_app = FactoryGirl.create(:api_app, request_origin: "0.0.0.0")
          @store = FactoryGirl.create(:store)
        end

        after(:all) do
          Product.all.each {|l| l.destroy}
          ApiApp.all.each {|a| a.destroy}
        end

        describe "POST 'create' " do
          context "Creates a product with the correct parameters" do
            it "returns a successful response string with success message" do
              json = { :format => 'json', product:{first_name:"Hello", last_name:"You", email:"email@email.edu",street1:"103 ABC Street", city:"Pittsburgh", phone:"4125361111", store_id:@store.id, state:"CA", country:"United States", organization:"ABC", organization_type: "Org"}}
              post :create, json, access_token: @api_app.access_token 
              expect(response).to be_success
              expect(response.body).to include("Product created")
            end
          end

          context "Incorrect parameters to create a product" do
            it "returns a failure response when a parameter is missing" do
              json = { :format => 'json', product:{first_name:"Hello", last_name:"You", email:"email@email.edu",street1:"103 ABC Street", city:"Pittsburgh", phone:"4125361111", store_id:@store.id, state:"CA", country:"United States", organization:"ABC"}}
              post :create, json, access_token: @api_app.access_token 
              expect(response).to be_success
              expect(response.body).to include("Product failed to create")
            end
          end
        end
      end
    end
  end

I need both json and access_token on the line:

post :create, json, access_token: @api_app.access_token

but the request ignores the second parameter (I can switch their placement to confirm). How do I word the post so that both parameters are read in?

Brit200313
  • 728
  • 5
  • 20

2 Answers2

2

What you are looking for is Hash.merge(other_hash). You might want to do some reading on the Hash class since about 50% of Ruby programming is about hash manipulation (IMHO).

This is how you would use it in your spec:

require 'spec_helper'

# You don't need to put the spec inside your module! 
# It just makes it harder to read!
describe Api::V1::ProductsController, type: :controller do

  before do
    @api_app = FactoryGirl.create(:api_app, request_origin: "0.0.0.0")
    @store = FactoryGirl.create(:store)
  end

  after(:all) do
    Product.all.each {|l| l.destroy}
    ApiApp.all.each {|a| a.destroy}
  end

  describe "POST 'create' " do

    # DRY up the parameters
    let(:params){
      access_token: @api_app.access_token 
      format: 'json'
    }

    # Even better is to use fixures or factories for this.
    let(:product_params) {
      first_name:"Hello", 
      last_name:"You", 
      email:"email@email.edu",
      street1:"103 ABC Street", 
      city:"Pittsburgh", 
      phone:"4125361111", 
      store_id:@store.id, 
      state:"CA", 
      country:"United States", 
      organization:"ABC"
    }

    context "Creates a product with the correct parameters" do
      it "returns a successful response string with success message" do
        product = product_params.merge(organization_type: "Org")
        post :create, params.merge(product: product)
        expect(response).to be_success
        expect(response.body).to include("Product created")
      end
    end

    context "Incorrect parameters to create a product" do
      it "returns a failure response when a parameter is missing" do
        product = product_params.merge(organization_type: "ABC")
        post :create, params.merge(product: product)
        expect(response).to be_success
        expect(response.body).to include("Product failed to create")
      end
    end
  end
end

However your spec contains an misstake:

context "Incorrect parameters to create a product" do
  it "returns a failure response when a parameter is missing" do
    product = product_params.merge(organization_type: "ABC")
    post :create, params.merge(product: product)
    expect(response).to be_success #! it should not be a success!
  end
end

expect(response).to be_success actually means that the response should have the 200 OK HTTP response code - but you should be returning a 400 Bad Request if there is missing parameter. The correct expectation is:

expect(response).to have_http_status :bad_request
Community
  • 1
  • 1
max
  • 96,212
  • 14
  • 104
  • 165
  • 2
    *50% of Ruby programming is about hash manipulation* - I'd argue that only 10% is hash manipulation, another 10% is figuring out how to write your method on one line, and 80% is bragging about how great Ruby is. :) – zetetic Jun 19 '15 at 20:37
  • Thanks, maxcal. I ended up needing the one liner from another answer. I'm using FactoryGirl already but the point of the test is whether the API creates the record. I'll second that 80%, zetetic! – Brit200313 Jun 19 '15 at 23:52
  • Then you can do `FactoryGirl.attributes_for(:product, organization_type: "ABC")` – max Jun 20 '15 at 02:51
1

I think you should send a single hash in your post. Try the following:

post :create, json.merge!(access_token: @api_app.access_token)
gabrielhilal
  • 10,660
  • 6
  • 54
  • 81