stub_request must return array in body - ruby-on-rails

I would like test my service with rspec but i got a error in my return body undefined method 'each' for "invoices":String because in my original method i parse an array in the response
I would like know how can i test this method and send a array in return body
My method in service:
def generate_invoices
invoices_ids = []
response = HTTParty.get('https://books.zoho.com/api/v3/invoices?organization_id='\
"#{ENV['ZOHO_ORGANISATION_ID']}&cf_lc_contract_id_startswith=#{#contract_id}&"\
'cf_facture_final=true', headers: { 'Authorization' => "Zoho-oauthtoken #{#access_token}" })
response.code == 200 ? response : raise_error(response.body)
response['invoices'].each do |invoice|
invoices_ids.push invoice['invoice_id']
end
invoices_ids.join(',')
end
stub request i tried:
stub_request(:get, 'https://books.zoho.com/api/v3/invoices?cf_facture_final=true'\
"&cf_lc_contract_id_startswith=123&organization_id=#{ENV['ZOHO_ORGANISATION_ID']}")
.with(headers: { 'Authorization' => 'Zoho-oauthtoken access_token' })
.to_return(status: 200, body: { 'invoices' => [{ "invoice_id": '123' }] }.to_json,
headers: {})

Try this at the end of your call:
.to_return(status: 200, body: '{"invoices" => [{ "invoice_id": "123"}]}', headers: {})

Related

Rails WebMock error on the second request try ::NetConnectNotAllowedError

I want to mock custom devise strategies to authenticate user in my feature specs. To stub request to 3th party app I'm using WebMock with the implementation below:
spec/utility/stub_methods.rb
def stub_aware_auth(creds, returns_token, _valid)
stub_request(:post, "http://example.com/oauth/token").
with(body: {"grant_type" => "password", "password" => creds.password, "username" => creds.email},
headers: {'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/x-www-form-urlencoded'}).
to_return(status: 200, body: {'access_token' => returns_token, 'token_type' => 'bearer', 'expires_in' => 1200}.to_json, headers: {})
end
Which is called in the spec by:
context 'AWARxE authenticated user' do
before do
stub_aware_auth(creds, return_token, valid)
end
let(:creds) do
OpenStruct.new(email: 'physiciansreallyshouldonlyautoauth#example.com', password: "Ican'tb3li3v3itsn0tbutt3r")
end
let(:return_token) { SecureRandom.hex(32) }
let(:valid) { true }
# other logic (...)
end
spec_helper.rb
WebMock.disable_net_connect!(allow_localhost: true)
Which works quite surprisingly wired because if in one test example it has to use stub_aware_auth twice, the first request returns the defined result but the second throws an error:
WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: POST http://example.com/oauth/token with body 'grant_type=password&password=Ican%27tb3li3v3itsn0tbutt3r&username=PHYSICIANSREALLYSHOULDONLYAUTOAUTH%40EXAMPLE.COM' with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Faraday v0.12.1'}
You can stub this request with the following snippet:
stub_request(:post, "http://example.com/oauth/token").
with(body: {"grant_type"=>"password", "password"=>"Ican'tb3li3v3itsn0tbutt3r", "username"=>"PHYSICIANSREALLYSHOULDONLYAUTOAUTH#EXAMPLE.COM"},
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Faraday v0.12.1'}).
to_return(status: 200, body: "", headers: {})
registered request stubs:
stub_request(:get, "http://example.com/api/v1/user").
with(headers: {'Authorization'=>'Bearer dc2dcf4c5b47ffcfea28c26490ed2a0e2580f152dfb18dbfc97670028d24ecaa'})
stub_request(:post, "http://example.com/oauth/token").
with(body: {"grant_type"=>"password", "password"=>"Ican'tb3li3v3itsn0tbutt3r", "username"=>"physiciansreallyshouldonlyautoauth#example.com"},
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded'})
Which is surprised because WebMock.disable_net_connect!(allow_localhost: true) is defined in spec_helper.
[EDIT]
Full failed example if it helps:
spec/features/login_strategies_spec.rb
context 'AWARxE authenticated user' do
before do
stub_aware_auth(creds, return_token, valid)
end
let(:return_token) { SecureRandom.hex(32) }
let(:valid) { true }
context 'physician' do
let(:creds) do
OpenStruct.new(email: 'physiciansreallyshouldonlyautoauth#example.com', password: "Ican'tb3li3v3itsn0tbutt3r")
end
let(:user) { build(:physician) }
before do
stub_aware_user_info(user, 'Physician (MD, DO)', return_token, valid, 1)
end
# some other it block (...)
context 'case insensitive' do
let(:valid) { true }
let(:uppercase_email_creds) {
OpenStruct.new(email: creds.email.upcase, password: creds.password)
}
scenario 'logging in with upper case email' do
expect { subject }.to change(Login, :count)
logout
expect {
login(uppercase_email_creds)
}.to_not change(Login, :count)
expect(page).to have_current_path(name_search_registrants_url, url: true)
end
end
end
The stub you are creating is still on the original creds with the lowercase email. There is no possibility for webmock to mock the call unless you actually call something like
stub_aware_auth(uppercase_email_creds, return_token, valid)
If you actualy expect the app to call out with lowercase email in body, then the test fails because it should fail, it is calling out with the email in uppercase:
You can stub this request with the following snippet:
stub_request(:post, "http://example.com/oauth/token").
with(body: {..., "username"=>"PHYSICIANSREALLYSHOULDONLYAUTOAUTH#EXAMPLE.COM"},
...).
to_return(status: 200, body: "", headers: {})

Error SENDING POST in rails and HTTPPARTY semantic error my request

this is my error when I lanunched my method {"errors"=>{"users"=>["Missing data for required field."]}, "msg"=>"The request was well-formed but was unable to be followed due to semantic errors."}
class BookingNotifier
include HTTParty
def initialize(booking_id)
#booking = Booking.find booking_id
#venue = #booking.event.service.venue
#body = { "users" => [] }
#headers = {
"Accept" => "application/json",
"Authorization" => "ENV_KEY",
"Content-Type" => "application/json"
}
end
def send_venue_notification
venues_objects = []
if #venue.notifications_enabled
venues_objects << { "cellphone" => #booking.event.service.venue.phone,
"country_code" => "+57",
"user_session_keys" => [{ "key" => "Nombre", "value" => #booking.profile.name },
{ "key" => "Centro", "value" => #booking.event.service.venue.name },
{ "key" => "Cupos", "value" => #booking.quantity },
{ "key" => "Horarios", "value" => #booking.time.strftime("%I:%M %p el %d/%m/%Y") }] }.to_json
#body["users"] = venues_objects
make_request_venue
end
end
def make_request_venue
HTTParty.post("http://api.treble.ai/api/poll/49/deploy", headers: #header, body: #body)
end
The problem is caused by to_json called in the wrong place.
The whole request body should be sent as a JSON. In your code, you call to_json for a hash that is later pushed into #body["users"] array.
Please remove to_json from send_venue_notification and call it for the #body when sending the request:
HTTParty.post("http://api.treble.ai/api/poll/49/deploy", headers: #headers, body: #body.to_json)

How to verify the response from api while writing test with Cucumber

I am working on a Rails project where I have to test the API with Cucumber. I have to test a POST type API and I need to verify its response. I have tried something like:
When(/^I make abc API call$/) do
#url = 'http://example.com/api/abc'
#params = '{
data: {
type: "abc",
attributes: {
title: "example",
all_day: "0",
start_date: "1409175049",
end_date: "1409175049"
}
}
}'
#login_token = 'pHufpGplLTYJnmWh5cqKoA'
end
Then(/^It should return success for abc$/) do
post 'http://example.com/api/abc', body: #params,
headers: { 'Accept' => 'application/json',
'login_token' => #login_token,
'Content-Type' => 'application/json' }
end
But I am not sure how to verify the status code from the response and any attributes from the response. Something like:
Then(/^It should return success for abc$/) do
post 'http://example.com/api/abc', body: #params,
headers: { 'Accept' => 'application/json',
'login_token' => #login_token,
'Content-Type' => 'application/json' }
.to_return(status: 200, body: '{ title: "abc" }')
end
How can I achieve it?
If you are using Capybara this should work for you:
Then /^I should get a response with status (\d+)$/ do |status|
response = post 'http://example.com/api/abc', body: #params,
headers: { 'Accept' => 'application/json',
'login_token' => #login_token,
'Content-Type' => 'application/json' }
response.status_code.should include(status.to_i)
end

Stubbing a HTTP Party request to run Specs

I need to stub my HTTP Party request to run my spec and I have to store the transaction Id i get from the parsed_response.Here is my stub
stub_request(:post, {MYURL).to_return(status: 200, body: "{'Success': { 'TransactionId' => '123456789' }}", headers: {})
I get my response to the request as
#<HTTParty::Response:0x5d51240 parsed_response="{'Success': { 'TransactionId' => '123456789' }}", #response=#<Net::HTTPOK 200 readbody=true>, #headers={}>
i need to store transactionid from the field
response.parsed_response['Success']["perfiosTransactionId"]
by i am getting null from there.Can any one help me modify my stub response so that i could get the transactionid saved
PS: If I check the fileds of response i get
response.success? ----> true
response.parsed_response --> "{'Success': { 'TransactionId' => '123456789' }}"
response.parsed_response['Success'] ---> "Success"
You're sending the payload in wrong format:
stub_request(
:post,
{MYURL}
).to_return(
status: 200,
body: '{"Success": { "TransactionId": "123456789" }}', # valid json string
headers: {"Content-Type" => "application/json"}
)
It's must be a valid json object, not a ruby hash.
Here is another way:
stub_request(
:post,
{MYURL}
).to_return(
status: 200,
body: {
"Success": { "TransactionId" => "123456789" }
}.to_json, # valid json string
headers: {"Content-Type" => "application/json"}
)

How to properly format json to send over using RestClient

I am trying to implement this javascript code
var token = "<page_access_token>";
function sendTextMessage(sender, text) {
messageData = {
text:text
}
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
}
into ruby on rails code
def reply_back(sender, text)
page_token = "*****"
base_uri = "https://graph.facebook.com/v2.6/me/messages"
messageData = {
text: text
}
qs = {
access_token: page_token
}
json = {
recipient: {
id: sender
},
message: messageData
}
response = RestClient.post base_uri, qs.to_json, json.to_json, :content_type => :json, :accept => :json
p "this is the response #{response}"
end
but obviously i am doing something wrong, i am getting this in console
(wrong number of arguments (4 for 2..3))
on line
response = RestClient.post base_uri, qs.to_json, json.to_json, :content_type => :json, :accept => :json
any insight?
You should put all your params in one params hash like this:
params = {
recipient: { id: sender },
message: { text: text },
access_token: page_token
}
response = RestClient.post base_uri, params.to_json, content_type: 'application/json', accept: 'application/json'
p "this is the response #{response}"
According to documentation, you should merge you params and pass it in method as one object:
params = qs.merge(json)
response = RestClient.post(base_uri,
params.to_json,
content_type: :json, accept: :json)
This method expects 2 or 3 arguments. In this case the third argument is a hash { content_type: :json, accept: :json }. Since it is a last argument, you can omit curly braces.

Resources