why is my response.body empty - ruby-on-rails

Below is test class. I am getting response.body as empty when finding an account.
require 'spec_helper'
describe ProjectController, :type => :controller do
before(:all) do
#acc = FactoryGirl.create(:project, name: "test",
description: "Something about test");
user = User.login(FactoryGirl.create(:user, email: "test#test.com",
password: "test", code: 0));
if user
#auth = user['auth_token']
end
end
it "can find an account" do
Account.find(id: 2055, authorization: #auth);
hashed_response = {
"#type" => "test",
"createdAt" => "2014-07-24T15:26:49",
"description" => "Something about test",
"disabled" => false
}
expect(response.status).to eq 200
expect(response.body).to eq(hashed_response.to_json);
end
end
When i try to find Account, it gets me result but why is my response.body empty. Below is the response i get in log/test for Account.find
{
"#type": "res",
"createdAt": "2014-07-24T15:26:49",
"description": "test",
"disabled": false
}

Account.find(id: 2055, authorization: #auth) is going to return an Account object, not a response, as it is an ORM request rather than a web request. If you want to test for a web request response, you'll need to make a request first.
I think your test should look something like this:
it "can find an account" do
Account.should_receive(:find, with: {id: 2055, authorization: #auth}
get :show, id: 2055 # you might need to pass in some auth details also
hashed_response = {
"#type" => "test",
"createdAt" => "2014-07-24T15:26:49",
"description" => "Something about test",
"disabled" => false
}
expect(response.status).to eq 200
expect(response.body).to eq(hashed_response.to_json);
end

Related

RSpec request spec for post action that includes headers results in parms being dropped

I am trying to figure out why I can't use use both params and headers in an request spec.
What works:
RSpec.describe Api::V1::UsersController, :type => :request do
before { host! 'api.localhost:3000'}
let(:params) {
{
"user": {
"identifier_for_vendor": "BD43813E"
}
}
}
describe 'Post /users' do
context 'when request is valid' do
before {
post api_users_path,
params: params
}
it "is successful" do
expect(response).to be_successful
end
end
end
end
What does not:
RSpec.describe Api::V1::UsersController, :type => :request do
let(:params) {
{
"user": {
"identifier_for_vendor": "BD43813E"
}
}
}
let(:headers) {
{
"host": "api.localhost:3000",
"Accept": "application/vnd.domain_name.v1",
"Content-Type": "application/vnd.api+json",
"X-API-Key": "fake087uakey"
}
}
describe 'Post /users' do
context 'when request is valid' do
before {
post api_users_path,
params: params,
headers: headers
}
it "successful" do
expect(response).to be_successful
end
end
end
end
The above fails, returning the error:
1) Api::V1::UsersController Post /users when request is valid is successful
Failure/Error: params.require(:user).permit(:identifier_for_vendor)
ActionController::ParameterMissing:
param is missing or the value is empty: user
The headers are needed due to having to ensure that valid api-keys are included in the request.
Would appreciate feedback on what I am missing. Thank you
Versions:
Ruby version: 2.6.3
Rails version: 6.0.3.4
RSpec 3.10
So issue had to do with how params and headers objects are created.
Params:
I passed in:
{"user": {"identifier_for_vendor": "OFJPJ"} }
the correct object is:
{:params=>{:user=>{:identifier_for_vendor=>"OFJPJ"}}}
Headers:
I passed in:
{
"host": "api.localhost:3000",
"Accept": "application/vnd.domain_name.v1",
"Content-Type": "application/vnd.api+json",
"X-API-Key": "fake087uakey"
}
the correct object is:
{
"headers" => {
"host" => "api.localhost:3000",
"Accept" => "application/vnd.domain_name.v1",
"X-API-Key" => "api_key"
}
}
Final solution looks like this:
RSpec.describe Api::V1::UsersController, :type => :request do
describe 'Post /users' do
context 'when request is valid' do
before do
post api_users_path,
:params => params,
:headers => headers
end
it "is successful" do
expect(response).to be_successful
end
it "returns a data of type user" do
expect(json_data["type"]).to eq("user")
end
end
end
end
The key to figuring this out was reading the documentation and realizing the my formatting was wrong.

Issue with apipie gem and rspec in rails 4

i'm writing the code to get my Rspec tests to pass on my api. I'm using the apipie gem to generate documentation and it seems that my tests are failing because thy are expecting a number and it's funny because this is exactly what I want to test.
The page fails when the :bpm parameter is not a number. is there any way of going around this ?
context "when is not created" do
before(:each) do
user = FactoryGirl.create :user
#invalid_lesson_attributes = { title: "California Dreamin",
bpm: "Hello"
}
request.headers['Authorization'] = user.auth_token
post :create, { user_id: user.id, lesson: #invalid_lesson_attributes }
end
it "renders an errors json" do
lesson_response = json_response
expect(lesson_response).to have_key(:errors)
end
it "renders the json errors on why the user could not be created" do
lesson_response = json_response
expect(lesson_response[:errors][:bpm]).to include "is not a number"
end
it { should respond_with 422 }
end
end
Update spec:
context "when is not updated" do
before(:each) do
patch :update, { user_id: #user.id, id: #lesson.id,
lesson: { bpm: "ten" }, format: :json }
end
it "renders an errors json" do
lesson_response = json_response
expect(lesson_response).to have_key(:errors)
end
it "renders the json errors on why the user could not be updated" do
lesson_response = json_response
expect(lesson_response[:errors][:bpm]).to include "is not a number"
end
it { should respond_with 422 }
end
in my users_controller:
api :POST, '/teachers/:user_id/lessons/', "Create lesson"
param :lesson, Hash, desc: 'Lesson information', :required => true do
param :title, String, desc: 'Title of the lesson', :required => true
param :bpm, :number, desc: 'tempo of the lesson (beats per second)', :required => true
end
error :code => 422, :desc => "Unprocessable Entity"
my error when I run my rspec tests :
Apipie::ParamInvalid: Invalid parameter 'bpm' value "Hello": Must be a number.
Adds format json to post request
post :create, { user_id: user.id, lesson: #invalid_lesson_attributes, format: :json }
That worked for me.

How do you test authentication in API controllers

I'm writing a Rails API and am stuck trying to write controllers that will test the authentication. For instance, I have in my PostController before_action :authenticate which is
def authenticate
authenticate_or_request_with_http_token do |token, options|
User.find_by(:auth_token => token)
end
end
And this is my PostsController test:
require 'rails_helper'
RSpec.describe Api::PostsController, type: :controller do
let(:valid_attributes) {
{
"title" => "Post title",
"content" => "Post content",
"status" => "published"
}
}
let(:invalid_attributes) {
{
"title" => "",
"content" => "",
"status" => ""
}
}
let(:valid_session) { {} }
before do
params = { session: { email: 'wagner.matos#mac.com', password: 'foobar' } }
SessionsController.create params
#post = Post.new({
title: "Some title",
content: 'Some content',
status: "published"
})
end
it "creates a new post" do
post :create, post: #post
expect(Post.count).to eq(1)
end
end
Yet the above is failing with the following error:
1) Api::PostsController creates a new post
Failure/Error: SessionsController.create params
NoMethodError:
undefined method `create' for SessionsController:Class
Any suggestions?
You can not invoke create action of SessionsController with class. Better you create user object and assign to request.env the same token. like below sample code -
require 'rails_helper'
RSpec.describe Api::PostsController, type: :controller do
before do
user = User.create( :auth_token => 'token' )
request.env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Token.encode_credentials("token")
end
end

Checking whether the json response is right or not

I get a json response from my server.
{
"#type": "res",
"createdAt": "2014-07-24T15:26:49",
"description": "test",
"disabled": false
}
How can i test whether the response is right or wrong. Below is my test case.
it "can find an account that this user belongs to" do
Account.find(id: #acc.id, authorization: #token);
expect(response.status).to eq 200
expect(response.body).to eq({
"#type": "res",
"createdAt": "2014-07-24T15:26:49",
"description": "test",
"disabled": false
})
end
When i try to execute the test, it throws me a lot of syntax error.
You should parse JSON.parse(response.body), because body as string:
it "can find an account that this user belongs to" do
Account.find(id: #acc.id, authorization: #token)
valid_hash = {
"#type" => "res",
"createdAt" => "2014-07-24T15:26:49",
"description" => "test",
"disabled" => false
}
expect(response.status).to eq 200
expect(JSON.parse(response.body)).to eq(valid_hash)
end
Or without parsing:
it "can find an account that this user belongs to" do
Account.find(id: #acc.id, authorization: #token)
valid_hash = {
"#type" => "res",
"createdAt" => "2014-07-24T15:26:49",
"description" => "test",
"disabled" => false
}
expect(response.status).to eq 200
expect(response.body).to eq(valid_hash.to_json)
end
Update, you hash syntax invalid instead:
valid_hash = {
"#type": "res",
"createdAt": "2014-07-24T15:26:49",
"description": "test",
"disabled": false
}
use:
valid_hash = {
"#type" => "res",
"createdAt" => "2014-07-24T15:26:49",
"description" => "test",
"disabled" => false
}

Getting html instead of json respone

I am getting a html instead of json response when i test. Below is code.
require 'spec_helper'
describe AccController, :type => :controller do
before(:all) do
user = User.login(FactoryGirl.create(:user, email: "test#test.com", password: "test", code: 0));
if user
#auth = user['token']
end
end
it "can find an account that this user belongs to" do
Account.should_receive(:find, with: {id: 2055, authorization: #auth})
get :show, id:2055
hashed_response = {
"#type" => "test",
"createdAt" => "2014-08-07T14:31:58.198",
"createdBy" => 2,
"updatedAt" => "2014-08-07T14:31:58.247",
"updatedBy" => 2,
"accountid" => 2055,
"name" => "test",
"description" => "Something about test",
"disabled" => false
}
expect(response.status).to eq 200
expect(response.body).to eq(hashed_response.to_json);
end
end
Below is what my rspec is failure message.
Failure/Error: expect(response.body).to eq(hashed_response.to_json);
expected: "{\"#type\":\"test\",\"createdAt\":\"2014-08-07T14:31:58.198\",\"createdBy\":2,\"updatedAt\":\"2014-08-07T14:31:58.247\",\"updatedBy\":2,\"accountid\":2055,\"name\":\"test\",\"description\":\"Something about test\",\"disabled\":false}"
got: "<html><body>You are being redirected.</body></html>"
I want to check whether my find method yeilds the right response by comparing.
You need to set what type of data you want, otherwise it will return HTML.
before :each do
request.env["HTTP_ACCEPT"] = 'application/json'
end
Try to change the request to
xhr(:get, :show, id: "2055", format: "json")

Resources