2

I am writing Request specs, and having trouble with to test api respond in json formate. I am using capybara and fabricator, here is my code which i trying...

    context 'discounts in api' do
      let(:user) { Fabricate(:user, activated: true) }
      let(:api_token) { user.api_token }

      before { visit api_url_for('/v1/discount_coupons', api_token) }

      it 'returns coupons collection' do
        Fabricate(:discount_coupon, code: 'Discount One', global: true)

        save_screenshot("tmp/capybara/screenshot-#{Time::now.strftime('%Y%m%d%H%M%S%N')}.png")
        save_and_open_page


        expect(json_response['total_records']).to eq 1
        expect(json_response['total_pages']).to eq 1
        expect(json_response['page']).to eq 0
        expect(json_response['discount_coupons'].size).to eq 1
        expect(json_response['discount_coupons'][0]['code']).to eq 'Discount One'
      end
end

the responce i getting is this

{"discount_coupons":[{"id":11,"code":"Discount One","type":"DiscountPercentage","amount_off":1.5,"global":true,"expires_on":null,"vendors":[]}],"page":0,"total_pages":1,"total_records":1}

and error goes to stop me for run a successful test,

Failure/Error: expect(json_response['total_pages']).to eq 1
             NoMethodError:
               undefined method `body' for nil:NilClass 

I think my expect to json_response is wrong or something missing, can somone help me to do it handsome way please, hint to that how can i test using key and value.

Awais
  • 1,803
  • 22
  • 26
  • why do you use capybara for testing API?! Capybara for integration tests. I think you should use controller tests for testing API. – gotva Jun 25 '14 at 11:48
  • Integration tests can be done with rspec if you are creating an API as long as capybara is a Behaviour tester, and you want to test requests content. – Jorge de los Santos Jun 25 '14 at 12:08

2 Answers2

2

Best way to test an API is use rspec as you just need to do this:

it "should return the expected information" do
  get "/url"

  parsed_response = JSON.parse(response.body)
  expect(parsed_response["key"]).to eq(whatever)
end

it "should update the expected entity" do
  post "/url", body, headers

  parsed_response = JSON.parse(response.body)
  expect(parsed_response["key"]).to eq(whatever)
end

And your tests are failing because you are trying to parse a response that is empty. The Fabric can be failing or the call might be wrong.

Jorge de los Santos
  • 4,583
  • 1
  • 17
  • 35
  • Then the problem is that the API is not returning anything. Do "puts response" and you will see that is empty. – Jorge de los Santos Jun 25 '14 at 12:06
  • still getting error Failure/Error: parsed_response = JSON.parse(response.body) NoMethodError: undefined method `body' for nil:NilClass – Awais Jun 25 '14 at 12:06
  • Empty response means you have no body. Check routes and fabric for this request. – Jorge de los Santos Jun 25 '14 at 12:07
  • ok i go in deep but can you tell me if this is so then why i getting this respond in screenshot {"discount_coupons":[{"id":11,"code":"Discount One","type":"DiscountPercentage","amount_off":1.5,"global":true,"expires_on":null,"vendors":[]}],"page":0,"total_pages":1,"total_records":1} – Awais Jun 25 '14 at 12:11
  • do: puts response before the JSON.parse – Jorge de los Santos Jun 25 '14 at 12:17
  • @ Jorge de los Santos i am sure about your answer and closer to problem, i have to parse the respond to JSOn, but i fail to way the implementation, when i use your answer error goes to this line, get "/url", body, headers wrong number of argument(3 for 1), can u please help me dude.?? – Awais Jun 26 '14 at 13:47
  • in headers you have to puth whatever the api is needing: usertoken, format. And in body, whatever you are sending in the body request. replace /url with the url you are testing. But just if you do put, patch post. Get doesn't need anything just get "/url". – Jorge de los Santos Jun 26 '14 at 13:50
0

I think the issue may be that you are visiting the page in the before block and then generating the discount coupon later on in the assertion block. Try moving the code around like this and see if it yields a better result.

context 'discounts in api' do
  let(:user) { Fabricate(:user, activated: true) }
  let(:api_token) { user.api_token }

  before do
    Fabricate(:discount_coupon, code: 'Discount One', global: true)
    visit api_url_for('/v1/discount_coupons', api_token)
  end

  it 'returns coupons collection' do
    save_screenshot("tmp/capybara/screenshot-#{Time::now.strftime('%Y%m%d%H%M%S%N')}.png")
    save_and_open_page

    expect(json_response['total_records']).to eq 1
    expect(json_response['total_pages']).to eq 1
    expect(json_response['page']).to eq 0
    expect(json_response['discount_coupons'].size).to eq 1
    expect(json_response['discount_coupons'][0]['code']).to eq 'Discount One'
  end
Paul Elliott
  • 1,174
  • 8
  • 9