Bitwise
Bitwise

Reputation: 8451

RSpec - Type error - no implicit conversion of String into Integer

I'm trying to make a test green and I'm getting this error. Even when I pry the code it shows that a string is being returned so I have no idea why the test won't green. Here is my test and error for clarification. I'm assuming this is a common error for folks.

Here is my test -

require "rails_helper"

RSpec.describe "/api/retailers" do

describe "GET /api/retailers" do
it "Returns JSON for retailers" do

  location = Location.create!(
    city: "Portland",
    street_1: "Cherry",
    state: "Oregon",
    zip: "49490"
  )

  retailer = Retailer.create!(
    name: "Good Coffee Co.",
    description: "Hipster Good",
    image_url: "http://www.example.com/foo_bar.jpg",
    location: location
  )

  get "/api/retailers.json"

  expect(response).to be_success
  json = JSON.parse(response.body)

  expect(json["name"]).to eql("Good Coffee Co.")
  expect(json["description"]).to eql("Hipster Good")
  expect(json["image_url"]).to eql("http://www.example.com/foo_bar.jpg")
  expect(json["location"]).to eql(location.city)
end
end
end

here is my error message -

/api/retailers GET /api/retailers Returns JSON for retailers
 Failure/Error: expect(json["name"]).to eql("Good Coffee Co.")

 TypeError:
   no implicit conversion of String into Integer
 # ./spec/requests/retailers_spec.rb:28:in `[]'
 # ./spec/requests/retailers_spec.rb:28:in `block (3 levels) in <top (required)>'

Upvotes: 3

Views: 3717

Answers (2)

Tyler Ferraro
Tyler Ferraro

Reputation: 3772

It looks like you're hitting an index endpoint which is returning an array of retailers, in your case an array with a single retailer. To access this you'll need to select the first object in the array and then do your comparisons:

expect(json[0]['name']).to eq('Good Coffee Co.')

On a similar note you should be using let and before to setup your tests. Following the rspec conventions will not only make your code more readable, but easier to maintain. I've made style changes below as to how I typically lay out my tests. These are just suggestions of course and make a couple of assumptions as to the naming and scoping of your controller.

require "rails_helper"

RSpec.describe Api::RetailersController do

  # /api/retailers
  describe '#index' do
    let!(:location) {
      Location.create!(
        city: "Portland",
        street_1: "Cherry",
        state: "Oregon",
        zip: "49490"
      )
    }

    let!(:retailer) {
      Retailer.create!(
        name: "Good Coffee Co.",
        description: "Hipster Good",
        image_url: "http://www.example.com/foo_bar.jpg",
        location: location
    )

    before(:each) do
      get :index, format: :json
      json = JSON.parse(response.body)
    end

    it 'Returns a status 200' do
      expect(response).to be_success
    end
    it 'Returns a JSON list of retailers' do
      expect(json.length).to eq(1)
    end

    # I would probably only check these in the show action
    # unless needing different data on index
    it 'Contains a name attribute' do
      expect(json[0]['name']).to eq('Good Coffee Co.')
    end
    it 'Contains a description attribute' do
      expect(json[0]['description']to eq('Hipster Good')
    end
    it 'contains an image_url attribute' do
      expect(json[0]['image_url']).to eq('http://www.example.com/foo_bar.jpg')
     end
     it 'contains a location attribute' do 
       expect(json[0]['location']).to eq(location.city)
     end
   end
 end

Upvotes: 4

David Meza
David Meza

Reputation: 3180

As mentioned in the comments, the issue was that the JSON object returns an array of objects. So the proper test expectations would be the following:

expect(json.first["name"]).to eq("Good Coffee Co.")
expect(json.first["description"]).to eq("Hipster Good")
expect(json.first["image_url"]).to eq("http://www.example.com/foo_bar.jpg")
expect(json.first["city"]).to eq("Portland")

Upvotes: 3

Related Questions