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
}
Related
I have 3 model user, post and comment.
the user can have multiple post and comments.
I need to produce the JSON for last 50 post only.
I am not using rails convention, so i have to write that in neewsfeed_controller.
Thank for the support.
class NewsfeedsController < ApplicationController
respond_to :json
def build
#posts = Post.all.order("created_at DESC")
render json: {:event => #posts}
end
def data
#posts = Post.all.order("created_at DESC")
render :partial => "newsfeeds/data.json"
end
private
def post_params
params.require(:post).permit(:content)
end
def find_post
#post = Post.find(params[:id])
end
end
In View: data.json.erb
<%= res = {
:posts => #posts.map do |post|
end
} %>
<% res.to_json.html_safe %>
Routes:
get 'build' => 'newsfeeds#build'
get 'data' => 'newsfeeds#data', :defaults => { :format => 'json' }
Form build i am getting data.
but i want custom json format from data.json,
Response Format which i want :
[
{
"type": "Post",
"content": "First post",
"user": {
"type": "User",
"name": "Luke"
},
"comments": [
{
"type": "Comment",
"user": {
"type": "User",
"name": "Leia"
},
"content": "First comment"
},
{
"type": "Comment",
"user": {
"type": "User",
"name": "Han"
},
"content": "Second comment"
},
]
},
{
"type": "Post",
"content": "Second post",
"user": {
"type": "User",
"name": "Darth Vader"
},
"comments": [
{
"type": "Comment",
"user": {
"type": "User",
"name": "Boba Fett"
},
"content": "Third comment"
},
{
"type": "Comment",
"user": {
"type": "User",
"name": "Jabba"
},
"content": "Fourth comment"
},
]
}
]
Please guide.
Currently, I am not able to get that format.
First, you'll need to override the to_json in your models:
app/models/post.rb
def to_json
return {
type: 'Post',
content: self.content,
user: self.user ? self.user.to_json : nil,
comments: self.comments.map(&:to_json)
}
end
app/models/user.rb
def to_json
return {
type: 'User',
name: self.name
}
end
app/models/comment.rb
def to_json
return {
type: 'Comment',
content: self.content,
user: self.user ? self.user.to_json : nil,
}
end
Then in your controller, do something like:
def data
#posts = Post.all.order("created_at DESC")
render json: #posts.map(&:to_json), status: :ok
end
I'm trying to setup RSpec tests for my Rails 5 API server. The server uses active_model_serializers (0.10.5) with the JSON API adapter.
From what I can tell, the server is serving valid JSON:
{
"data": [{
"id": "1",
"type": "categories",
"attributes": {
"name": "Language"
}
}, {
"id": "2",
"type": "categories",
"attributes": {
"name": "Ruby"
}
}, {
"id": "3",
"type": "categories",
"attributes": {
"name": "HTML"
}
}]
}
Here is my setup:
app/controllers/categories_controller.rb
def index
#categories = Category.all
render json: #categories
end
app/serializers/category_serializer.rb
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
end
spec/requests/categories_spec.rb
describe 'GET /categories' do
before do
#category1 = FactoryGirl.create(:category)
#category2 = FactoryGirl.create(:category)
get '/categories'
json = ActiveModelSerializers::Deserialization.jsonapi_parse!(response.body)
#category_ids = json.collect { |category| category['id'] }
end
it 'returns all resources in the response body' do
expect(#category_ids).to eq([#category1.id, #category2.id])
end
it 'returns HTTP status ok' do
expect(response).to have_http_status(:ok)
end
end
Following is the error I get when running bundle exec spec:
ActiveModelSerializers::Adapter::JsonApi::Deserialization::InvalidDocument:
Invalid payload (Expected hash): {"data":
[{"id":"55","type":"categories","attributes":{"name":"feed"}},
{"id":"56","type":"categories","attributes":{"name":"bus"}}]}
What am I missing to get the deserializer working?
You don't need to use the ActiveModel deserializer in this context. For your tests, just do something like this:
parsed_response = JSON.parse(response.body)
expect(parsed_response['data'].size).to eq(2)
expect(parsed_response['data'].map { |category| category['id'].to_i })
.to eq(Category.all.map(&:id))
expect(response.status).to eq(200)
I'm witnessing an odd behavior in Rails, when sending a post request, with the following body:
If you check is a Hash (converted to JSON when sending). But ODDLY when being read by params in controller, is recognized like this:
If you check carefully, the attributes of :first_name and :email are moved to the previous item in the array.
I'd thought if you have an array with certain attributes on the first item, but some different attributes on the following items, the array would be respecting the positions of which the attributes are set for.
I know most likely the answer would be "just put a nil or empty value of those attributes on the first item of the array", but I'm more interested in the reason of why this is happening.
Thank you.
UPDATE
Thanks to a question, I replicated the scenario form a browser (I was originally doing the request from the test feature of rails), and checking the Network from the browser, this is what is being sent:
{
"name": "un nombre",
"team_members": [
{
"user_id": 1,
"team_member_role_id": 4
},
{
"email": "cpamerica#avengers.com",
"first_name": "Cap America",
"team_member_role_id": 4,
"admin": true
},
{
"email": "hulk#avenrgers.com",
"first_name": "Bruce Banner",
"team_member_role_id": 1,
"admin": false
},
{
"email": "ironman#avengers.com",
"first_name": "Tony Stark",
"team_member_role_id": 1,
"admin": false
},
{
"email": "thor#avengers.com",
"first_name": "Thor Hijo de Odín",
"team_member_role_id": 2,
"admin": false
}
]
}
And it works. So I focused on how I was sending the info from the test environment, this is the actual code:
team = {
:name => 'un nombre',
:team_members => [
{
:user_id => 1,
:team_member_role_id => TeamMemberRole.role_communicator_id
},
{
:email => 'cpamerica#avengers.com',
:first_name => 'Cap America',
:team_member_role_id => TeamMemberRole.role_communicator_id,
:admin => true
},
{
:email => 'hulk#avenrgers.com',
:first_name => 'Bruce Banner',
:team_member_role_id => TeamMemberRole.role_visionary_id,
:admin => false
},
{
:email => 'ironman#avengers.com',
:first_name => 'Tony Stark',
:team_member_role_id => TeamMemberRole.role_visionary_id,
:admin => false
},
{
:email => 'thor#avengers.com',
:first_name => 'Thor Hijo de Odín',
:team_member_role_id => TeamMemberRole.role_developer_id,
:admin => false
}
]
}
post create_team_path, :team => team, :format => :json
And what is being read in the controller by request.raw, this is what is getting (using the debugger):
team[name]=un+nombre&
team[team_members][][user_id]=1&
team[team_members][][team_member_role_id]=4&
team[team_members][][email]=cpamerica%40avengers.com&
team[team_members][][first_name]=Cap+America&
team[team_members][][team_member_role_id]=4&
team[team_members][][admin]=true&
team[team_members][][email]=hulk%40avenrgers.com&
team[team_members][][first_name]=Bruce+Banner&
team[team_members][][team_member_role_id]=1&
team[team_members][][admin]=false&
team[team_members][][email]=ironman%40avengers.com&
team[team_members][][first_name]=Tony+Stark&
team[team_members][][team_member_role_id]=1&
team[team_members][][admin]=false&
team[team_members][][email]=thor%40avengers.com&
team[team_members][][first_name]=Thor+Hijo+de+Od%C3%ADn&
team[team_members][][team_member_role_id]=2&
team[team_members][][admin]=false&
format=json
Any idea on why the index of each team_member is missing? Am I sending the array wrong?
To send an acceptable json request you need to send as a formed String instead the hash, also add the headers
your code must look something like this:
post create_team_path, {:team => team}.to_json, 'CONTENT_TYPE' => 'application/json;charset=utf-8'
Note the problem is within the parser hash to form-request not adding the index of each object
Source: How to post JSON data in rails 3 functional test
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
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")