Reputation: 8451
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
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
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