test/controllers/controller_test.rb in jsonapi-resources-0.1.1 vs test/controllers/controller_test.rb in jsonapi-resources-0.2.0
- old
+ new
@@ -7,202 +7,215 @@
class PostsControllerTest < ActionController::TestCase
def test_index
get :index
assert_response :success
- assert json_response['posts'].is_a?(Array)
+ assert json_response['data'].is_a?(Array)
end
def test_index_filter_with_empty_result
- get :index, {title: 'post that does not exist'}
+ get :index, {filter: {title: 'post that does not exist'}}
assert_response :success
- assert json_response['posts'].is_a?(Array)
- assert_equal 0, json_response['posts'].size
+ assert json_response['data'].is_a?(Array)
+ assert_equal 0, json_response['data'].size
end
def test_index_filter_by_id
- get :index, {id: '1'}
+ get :index, {filter: {id: '1'}}
assert_response :success
- assert json_response['posts'].is_a?(Array)
+ assert json_response['data'].is_a?(Array)
+ assert_equal 1, json_response['data'].size
end
def test_index_filter_by_title
- get :index, {title: 'New post'}
+ get :index, {filter: {title: 'New post'}}
assert_response :success
- assert json_response['posts'].is_a?(Array)
+ assert json_response['data'].is_a?(Array)
+ assert_equal 1, json_response['data'].size
end
def test_index_filter_by_ids
- get :index, {ids: '1,2'}
+ get :index, {filter: {ids: '1,2'}}
assert_response :success
- assert json_response['posts'].is_a?(Array)
- assert_equal 2, json_response['posts'].size
+ assert json_response['data'].is_a?(Array)
+ assert_equal 2, json_response['data'].size
end
def test_index_filter_by_ids_and_include_related
- get :index, ids: '2', include: 'comments'
+ get :index, {filter: {id: '2'}, include: 'comments'}
assert_response :success
- assert_equal 1, json_response['posts'].size
- assert_equal 1, json_response['linked']['comments'].size
+ assert_equal 1, json_response['data'].size
+ assert_equal 1, json_response['linked'].size
end
def test_index_filter_by_ids_and_include_related_different_type
- get :index, {ids: '1,2', include: 'author'}
+ get :index, {filter: {id: '1,2'}, include: 'author'}
assert_response :success
- assert_equal 2, json_response['posts'].size
- assert_equal 1, json_response['linked']['people'].size
+ assert_equal 2, json_response['data'].size
+ assert_equal 1, json_response['linked'].size
end
def test_index_filter_by_ids_and_fields
- get :index, {ids: '1,2', 'fields' => 'id,title,author'}
+ get :index, {filter: {id: '1,2'}, 'fields' => 'id,title,author'}
assert_response :success
- assert_equal 2, json_response['posts'].size
+ assert_equal 2, json_response['data'].size
- # id, title, links
- assert_equal 3, json_response['posts'][0].size
- assert json_response['posts'][0].has_key?('id')
- assert json_response['posts'][0].has_key?('title')
- assert json_response['posts'][0].has_key?('links')
+ # type, id, title, links
+ assert_equal 4, json_response['data'][0].size
+ assert json_response['data'][0].has_key?('type')
+ assert json_response['data'][0].has_key?('id')
+ assert json_response['data'][0].has_key?('title')
+ assert json_response['data'][0].has_key?('links')
end
def test_index_filter_by_ids_and_fields_specify_type
- get :index, {ids: '1,2', 'fields' => {'posts' => 'id,title,author'}}
+ get :index, {filter: {id: '1,2'}, 'fields' => {'posts' => 'id,title,author'}}
assert_response :success
- assert_equal 2, json_response['posts'].size
+ assert_equal 2, json_response['data'].size
- # id, title, links
- assert_equal 3, json_response['posts'][0].size
- assert json_response['posts'][0].has_key?('id')
- assert json_response['posts'][0].has_key?('title')
- assert json_response['posts'][0].has_key?('links')
+ # type, id, title, links
+ assert_equal 4, json_response['data'][0].size
+ assert json_response['data'][0].has_key?('type')
+ assert json_response['data'][0].has_key?('id')
+ assert json_response['data'][0].has_key?('title')
+ assert json_response['data'][0].has_key?('links')
end
def test_index_filter_by_ids_and_fields_specify_unrelated_type
- get :index, {ids: '1,2', 'fields' => {'currencies' => 'code'}}
+ get :index, {filter: {id: '1,2'}, 'fields' => {'currencies' => 'code'}}
assert_response :bad_request
assert_match /currencies is not a valid resource./, json_response['errors'][0]['detail']
end
def test_index_filter_by_ids_and_fields_2
- get :index, {ids: '1,2', 'fields' => 'author'}
+ get :index, {filter: {id: '1,2'}, 'fields' => 'author'}
assert_response :success
- assert_equal 2, json_response['posts'].size
+ assert_equal 2, json_response['data'].size
- # links
- assert_equal 1, json_response['posts'][0].size
- assert json_response['posts'][0].has_key?('links')
+ # links, id, type
+ assert_equal 3, json_response['data'][0].size
+ assert json_response['data'][0].has_key?('type')
+ assert json_response['data'][0].has_key?('id')
+ assert json_response['data'][0]['links'].has_key?('author')
end
def test_filter_association_single
- get :index, {tags: '5,1'}
+ get :index, {filter: {tags: '5,1'}}
assert_response :success
- assert_equal 3, json_response['posts'].size
+ assert_equal 3, json_response['data'].size
assert_match /New post/, response.body
assert_match /JR Solves your serialization woes!/, response.body
assert_match /JR How To/, response.body
end
def test_filter_associations_multiple
- get :index, {tags: '5,1', comments: '3'}
+ get :index, {filter: {tags: '5,1', comments: '3'}}
assert_response :success
- assert_equal 1, json_response['posts'].size
+ assert_equal 1, json_response['data'].size
assert_match /JR Solves your serialization woes!/, response.body
end
def test_filter_associations_multiple_not_found
- get :index, {tags: '1', comments: '3'}
+ get :index, {filter: {tags: '1', comments: '3'}}
assert_response :success
- assert_equal 0, json_response['posts'].size
+ assert_equal 0, json_response['data'].size
end
def test_bad_filter
- get :index, {post_ids: '1,2'}
+ get :index, {filter: {post_ids: '1,2'}}
assert_response :bad_request
assert_match /post_ids is not allowed/, response.body
end
def test_bad_filter_value_not_integer_array
- get :index, {ids: 'asdfg'}
+ get :index, {filter: {id: 'asdfg'}}
assert_response :bad_request
assert_match /asdfg is not a valid value for id/, response.body
end
def test_bad_filter_value_not_integer
- get :index, {id: 'asdfg'}
+ get :index, {filter: {id: 'asdfg'}}
assert_response :bad_request
assert_match /asdfg is not a valid value for id/, response.body
end
def test_bad_filter_value_not_found_array
- get :index, {ids: '5412333'}
+ get :index, {filter: {id: '5412333'}}
assert_response :not_found
assert_match /5412333 could not be found/, response.body
end
def test_bad_filter_value_not_found
- get :index, {id: '5412333'}
+ get :index, {filter: {id: '5412333'}}
assert_response :not_found
assert_match /5412333 could not be found/, json_response['errors'][0]['detail']
end
def test_index_malformed_fields
- get :index, {ids: '1,2', 'fields' => 'posts'}
+ get :index, {filter: {id: '1,2'}, 'fields' => 'posts'}
assert_response :bad_request
assert_match /posts is not a valid field for posts./, json_response['errors'][0]['detail']
end
def test_field_not_supported
- get :index, {ids: '1,2', 'fields' => {'posts' => 'id,title,rank,author'}}
+ get :index, {filter: {id: '1,2'}, 'fields' => {'posts' => 'id,title,rank,author'}}
assert_response :bad_request
assert_match /rank is not a valid field for posts./, json_response['errors'][0]['detail']
end
def test_resource_not_supported
- get :index, {ids: '1,2', 'fields' => {'posters' => 'id,title'}}
+ get :index, {filter: {id: '1,2'}, 'fields' => {'posters' => 'id,title'}}
assert_response :bad_request
assert_match /posters is not a valid resource./, json_response['errors'][0]['detail']
end
def test_index_filter_on_association
- get :index, {author: '1'}
+ get :index, {filter: {author: '1'}}
assert_response :success
- assert_equal 3, json_response['posts'].size
+ assert_equal 3, json_response['data'].size
end
def test_sorting_asc
- get :index, {sort: 'title'}
+ get :index, {sort: '+title'}
assert_response :success
- assert_equal "Delete This Later - Multiple2-1", json_response['posts'][0]['title']
+ assert_equal "Delete This Later - Multiple2-1", json_response['data'][0]['title']
end
def test_sorting_desc
get :index, {sort: '-title'}
assert_response :success
- assert_equal "Update This Later - Multiple", json_response['posts'][0]['title']
+ assert_equal "Update This Later - Multiple", json_response['data'][0]['title']
end
def test_sorting_by_multiple_fields
- get :index, {sort: 'title,body'}
+ get :index, {sort: '+title,+body'}
assert_response :success
- assert_equal '8', json_response['posts'][0]['id']
+ assert_equal '8', json_response['data'][0]['id']
end
def test_invalid_sort_param
- get :index, {sort: 'asdfg'}
+ get :index, {sort: '+asdfg'}
assert_response :bad_request
- assert_match /asdfg is not a valid sort param for post/, response.body
+ assert_match /asdfg is not a valid sort criteria for post/, response.body
end
+ def test_invalid_sort_param_missing_direction
+ get :index, {sort: 'title'}
+
+ assert_response :bad_request
+ assert_match /title must start with a direction/, response.body
+ end
+
def test_excluded_sort_param
- get :index, {sort: 'id'}
+ get :index, {sort: '+id'}
assert_response :bad_request
- assert_match /id is not a valid sort param for post/, response.body
+ assert_match /id is not a valid sort criteria for post/, response.body
end
# ToDo: test validating the parameter values
# def test_index_invalid_filter_value
# get :index, {ids: [1,'asdfg1']}
@@ -210,37 +223,34 @@
# end
def test_show_single
get :show, {id: '1'}
assert_response :success
- assert json_response['posts'].is_a?(Hash)
- assert_equal 'New post', json_response['posts']['title']
- assert_equal 'A body!!!', json_response['posts']['body']
- assert_equal ['1', '2', '3'], json_response['posts']['links']['tags']
- assert_equal ['1', '2'], json_response['posts']['links']['comments']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal 'New post', json_response['data']['title']
+ assert_equal 'A body!!!', json_response['data']['body']
assert_nil json_response['linked']
end
def test_show_single_with_includes
get :show, {id: '1', include: 'comments'}
assert_response :success
- assert json_response['posts'].is_a?(Hash)
- assert_equal 'New post', json_response['posts']['title']
- assert_equal 'A body!!!', json_response['posts']['body']
- assert_equal ['1', '2', '3'], json_response['posts']['links']['tags']
- assert_equal ['1', '2'], json_response['posts']['links']['comments']
- assert_equal 2, json_response['linked']['comments'].size
- assert_nil json_response['linked']['tags']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal 'New post', json_response['data']['title']
+ assert_equal 'A body!!!', json_response['data']['body']
+ assert_nil json_response['data']['links']['tags']['ids']
+ assert_equal ['1', '2'], json_response['data']['links']['comments']['ids']
+ assert_equal 2, json_response['linked'].size
end
def test_show_single_with_fields
get :show, {id: '1', fields: 'author'}
assert_response :success
- assert json_response['posts'].is_a?(Hash)
- assert_nil json_response['posts']['title']
- assert_nil json_response['posts']['body']
- assert_equal '1', json_response['posts']['links']['author']
+ assert json_response['data'].is_a?(Hash)
+ assert_nil json_response['data']['title']
+ assert_nil json_response['data']['body']
+ assert_equal '1', json_response['data']['links']['author']['id']
end
def test_show_single_invalid_id_format
get :show, {id: 'asdfg'}
assert_response :bad_request
@@ -267,35 +277,37 @@
def test_create_simple
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
title: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
}
}
assert_response :created
- assert json_response['posts'].is_a?(Hash)
- assert_equal '3', json_response['posts']['links']['author']
- assert_equal 'JR is Great', json_response['posts']['title']
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['posts']['body']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['author']['id']
+ assert_equal 'JR is Great', json_response['data']['title']
+ assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['body']
end
def test_create_link_to_missing_object
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
title: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 304567
+ author: {type: 'people', id: '304567'}
}
}
}
assert_response :unprocessable_entity
@@ -305,16 +317,17 @@
def test_create_extra_param
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
asdfg: 'aaaa',
title: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
}
}
assert_response :bad_request
@@ -323,11 +336,12 @@
def test_create_with_invalid_data
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
title: 'JSONAPIResources is the greatest thing...',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
author: nil
}
@@ -347,53 +361,57 @@
def test_create_multiple
set_content_type_header!
post :create,
{
- posts: [
+ data: [
{
+ type: 'posts',
title: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
},
{
+ type: 'posts',
title: 'Ember is Great',
body: 'Ember is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
}
]
}
assert_response :created
- assert json_response['posts'].is_a?(Array)
- assert_equal json_response['posts'].size, 2
- assert_equal json_response['posts'][0]['links']['author'], '3'
+ assert json_response['data'].is_a?(Array)
+ assert_equal json_response['data'].size, 2
+ assert_equal json_response['data'][0]['links']['author']['id'], '3'
assert_match /JR is Great/, response.body
assert_match /Ember is Great/, response.body
end
def test_create_multiple_wrong_case
set_content_type_header!
post :create,
{
- posts: [
+ data: [
{
+ type: 'posts',
Title: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
},
{
+ type: 'posts',
title: 'Ember is Great',
BODY: 'Ember is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
}
]
}
@@ -403,311 +421,448 @@
def test_create_simple_missing_posts
set_content_type_header!
post :create,
{
- posts_spelled_wrong: {
+ data_spelled_wrong: {
+ type: 'posts',
title: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
}
}
assert_response :bad_request
- assert_match /The required parameter, posts, is missing./, json_response['errors'][0]['detail']
+ assert_match /The required parameter, data, is missing./, json_response['errors'][0]['detail']
end
+ def test_create_simple_wrong_type
+ set_content_type_header!
+ post :create,
+ {
+ data: {
+ type: 'posts_spelled_wrong',
+ title: 'JR is Great',
+ body: 'JSONAPIResources is the greatest thing since unsliced bread.',
+ links: {
+ author: {type: 'people', id: '3'}
+ }
+ }
+ }
+
+ assert_response :bad_request
+ assert_match /posts_spelled_wrong is not a valid resource./, json_response['errors'][0]['detail']
+ end
+
+ def test_create_simple_missing_type
+ set_content_type_header!
+ post :create,
+ {
+ data: {
+ title: 'JR is Great',
+ body: 'JSONAPIResources is the greatest thing since unsliced bread.',
+ links: {
+ author: {type: 'people', id: '3'}
+ }
+ }
+ }
+
+ assert_response :bad_request
+ assert_match /The required parameter, type, is missing./, json_response['errors'][0]['detail']
+ end
+
def test_create_simple_unpermitted_attributes
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
subject: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 3
+ author: {type: 'people', id: '3'}
}
}
}
assert_response :bad_request
assert_match /subject/, json_response['errors'][0]['detail']
end
- def test_create_with_links
+ def test_create_with_links_has_many_type_ids
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
title: 'JR is Great',
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
links: {
- author: 3,
- tags: [3, 4]
+ author: {type: 'people', id: '3'},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
}
assert_response :created
- assert json_response['posts'].is_a?(Hash)
- assert_equal '3', json_response['posts']['links']['author']
- assert_equal 'JR is Great', json_response['posts']['title']
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['posts']['body']
- assert_equal ['3', '4'], json_response['posts']['links']['tags']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['author']['id']
+ assert_equal 'JR is Great', json_response['data']['title']
+ assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['body']
end
+ def test_create_with_links_has_many_array
+ set_content_type_header!
+ post :create,
+ {
+ data: {
+ type: 'posts',
+ title: 'JR is Great',
+ body: 'JSONAPIResources is the greatest thing since unsliced bread.',
+ links: {
+ author: {type: 'people', id: '3'},
+ tags: [{type: 'tags', id: '3'}, {type: 'tags', id: '4'}]
+ }
+ }
+ }
+
+ assert_response :created
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['author']['id']
+ assert_equal 'JR is Great', json_response['data']['title']
+ assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['body']
+ end
+
def test_create_with_links_include_and_fields
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
title: 'JR is Great!',
body: 'JSONAPIResources is the greatest thing since unsliced bread!',
links: {
- author: 3,
- tags: [3, 4]
+ author: {type: 'people', id: '3'},
+ tags: {type: 'tags', ids: [3, 4]}
}
},
include: 'author,author.posts',
fields: 'id,title,author'
}
assert_response :created
- assert json_response['posts'].is_a?(Hash)
- assert_equal '3', json_response['posts']['links']['author']
- assert_equal 'JR is Great!', json_response['posts']['title']
- assert_equal nil, json_response['posts']['body']
- assert_equal nil, json_response['posts']['links']['tags']
- assert_not_nil json_response['linked']['posts']
- assert_not_nil json_response['linked']['people']
- assert_nil json_response['linked']['tags']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['author']['id']
+ assert_equal 'JR is Great!', json_response['data']['title']
+ assert_not_nil json_response['linked'].size
end
def test_update_with_links
set_content_type_header!
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: 3,
- posts: {
+ data: {
+ id: '3',
+ type: 'posts',
title: 'A great new Post',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
- }
+ },
+ include: 'tags'
}
assert_response :success
- assert json_response['posts'].is_a?(Hash)
- assert_equal '3', json_response['posts']['links']['author']
- assert_equal javascript.id.to_s, json_response['posts']['links']['section']
- assert_equal 'A great new Post', json_response['posts']['title']
- assert_equal 'AAAA', json_response['posts']['body']
- assert matches_array?(['3', '4'], json_response['posts']['links']['tags'])
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['author']['id']
+ assert_equal javascript.id.to_s, json_response['data']['links']['section']['id']
+ assert_equal 'A great new Post', json_response['data']['title']
+ assert_equal 'AAAA', json_response['data']['body']
+ assert matches_array?(['3', '4'], json_response['data']['links']['tags']['ids'])
end
def test_update_remove_links
set_content_type_header!
put :update,
{
id: 3,
- posts: {
+ data: {
+ type: 'posts',
+ id: 3,
title: 'A great new Post',
links: {
section: nil,
tags: []
}
- }
+ },
+ include: 'tags'
}
assert_response :success
- assert json_response['posts'].is_a?(Hash)
- assert_equal '3', json_response['posts']['links']['author']
- assert_equal nil, json_response['posts']['links']['section']
- assert_equal 'A great new Post', json_response['posts']['title']
- assert_equal 'AAAA', json_response['posts']['body']
- assert matches_array?([], json_response['posts']['links']['tags'])
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['author']['id']
+ assert_equal nil, json_response['data']['links']['section']['id']
+ assert_equal 'A great new Post', json_response['data']['title']
+ assert_equal 'AAAA', json_response['data']['body']
+ assert matches_array?([], json_response['data']['links']['tags']['ids'])
end
def test_update_relationship_has_one
set_content_type_header!
ruby = Section.find_by(name: 'ruby')
post_object = Post.find(3)
assert_not_equal ruby.id, post_object.section_id
- put :update_association, {post_id: 3, association: 'section', sections: ruby.id}
+ put :update_association, {post_id: 3, association: 'section', data: {type: 'sections', id: "#{ruby.id}"}}
assert_response :no_content
post_object = Post.find(3)
assert_equal ruby.id, post_object.section_id
end
- def test_update_relationship_has_one_singular_param
+ def test_update_relationship_has_one_invalid_links_hash_keys_ids
set_content_type_header!
- ruby = Section.find_by(name: 'ruby')
- post_object = Post.find(3)
+ put :update_association, {post_id: 3, association: 'section', data: {types: 'sections', ids: 'foo'}}
- put :update_association, {post_id: 3, association: 'section', section: ruby.id}
+ assert_response :bad_request
+ assert_match /Invalid Links Object/, response.body
+ end
+ def test_update_relationship_has_one_invalid_links_hash_count
+ set_content_type_header!
+ put :update_association, {post_id: 3, association: 'section', data: {types: 'sections'}}
+
assert_response :bad_request
+ assert_match /Invalid Links Object/, response.body
end
- def test_update_relationship_has_one_singular_param_relation_nil
+ def test_update_relationship_has_one_invalid_links_hash_keys_type_mismatch
set_content_type_header!
+ put :update_association, {post_id: 3, association: 'section', data: {type: 'comment', id: '3'}}
+
+ assert_response :bad_request
+ assert_match /Type Mismatch/, response.body
+ end
+
+ def test_update_nil_has_many_links
+ set_content_type_header!
+ put :update,
+ {
+ id: 3,
+ data: {
+ type: 'posts',
+ id: 3,
+ links: {
+ tags: nil
+ }
+ }
+ }
+
+ assert_response :bad_request
+ assert_match /Invalid Links Object/, response.body
+ end
+
+ def test_update_bad_hash_has_many_links
+ set_content_type_header!
+ put :update,
+ {
+ id: 3,
+ data: {
+ type: 'posts',
+ id: 3,
+ links: {
+ tags: {typ: 'bad link', idd: 'as'}
+ }
+ }
+ }
+
+ assert_response :bad_request
+ assert_match /Invalid Links Object/, response.body
+ end
+
+ def test_update_other_has_many_links
+ set_content_type_header!
+ put :update,
+ {
+ id: 3,
+ data: {
+ type: 'posts',
+ id: 3,
+ links: {
+ tags: 'bad link'
+ }
+ }
+ }
+
+ assert_response :bad_request
+ assert_match /Invalid Links Object/, response.body
+ end
+
+ def test_update_relationship_has_one_singular_param_id_nil
+ set_content_type_header!
ruby = Section.find_by(name: 'ruby')
post_object = Post.find(3)
- post_object.section_id = nil
+ post_object.section_id = ruby.id
post_object.save!
- put :update_association, {post_id: 3, association: 'section', sections: ruby.id}
+ put :update_association, {post_id: 3, association: 'section', data: {type: 'sections', id: nil}}
assert_response :no_content
post_object = Post.find(3)
- assert_equal ruby.id, post_object.section_id
+ assert_equal nil, post_object.section_id
end
- def test_create_relationship_has_one_singular_param_relation_nil
+ def test_remove_relationship_has_one
set_content_type_header!
ruby = Section.find_by(name: 'ruby')
post_object = Post.find(3)
- post_object.section_id = nil
+ post_object.section_id = ruby.id
post_object.save!
- post :create_association, {post_id: 3, association: 'section', sections: ruby.id}
+ put :destroy_association, {post_id: 3, association: 'section'}
assert_response :no_content
post_object = Post.find(3)
- assert_equal ruby.id, post_object.section_id
+ assert_equal nil, post_object.section_id
end
- def test_create_relationship_has_one_singular_param_relation_not_nil
+ def test_update_relationship_has_one_singular_param
set_content_type_header!
ruby = Section.find_by(name: 'ruby')
- js = Section.find_by(name: 'javascript')
post_object = Post.find(3)
- post_object.section_id = js.id
+ post_object.section_id = nil
post_object.save!
- post :create_association, {post_id: 3, association: 'section', sections: ruby.id}
+ put :update_association, {post_id: 3, association: 'section', data: {type: 'sections', id: "#{ruby.id}"}}
- assert_response :bad_request
- assert_match /The relation already exists./, response.body
+ assert_response :no_content
post_object = Post.find(3)
- assert_equal js.id, post_object.section_id
+ assert_equal ruby.id, post_object.section_id
end
def test_update_relationship_has_many_join_table_single
set_content_type_header!
- put :update_association, {post_id: 3, association: 'tags', tags: []}
+ put :update_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: []}}
assert_response :no_content
post_object = Post.find(3)
assert_equal 0, post_object.tags.length
- put :update_association, {post_id: 3, association: 'tags', tags: [2]}
+ put :update_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: [2]}}
assert_response :no_content
post_object = Post.find(3)
assert_equal 1, post_object.tags.length
- put :update_association, {post_id: 3, association: 'tags', tags: 5}
+ put :update_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: [5]}}
assert_response :no_content
post_object = Post.find(3)
tags = post_object.tags.collect { |tag| tag.id }
assert_equal 1, tags.length
assert matches_array? [5], tags
end
- def test_update_relationship_has_many_join_table
+ def test_update_relationship_has_many_join_table_homogenous
set_content_type_header!
- put :update_association, {post_id: 3, association: 'tags', tags: [2, 3]}
+ put :update_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: [2, 3]}}
assert_response :no_content
post_object = Post.find(3)
assert_equal 2, post_object.tags.collect { |tag| tag.id }.length
assert matches_array? [2, 3], post_object.tags.collect { |tag| tag.id }
end
+ def test_update_relationship_has_many_join_table_heterogenous
+ set_content_type_header!
+ put :update_association, {post_id: 3, association: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 3}]}
+
+ assert_response :no_content
+ post_object = Post.find(3)
+ assert_equal 2, post_object.tags.collect { |tag| tag.id }.length
+ assert matches_array? [2, 3], post_object.tags.collect { |tag| tag.id }
+ end
+
def test_create_relationship_has_many_join_table
set_content_type_header!
- put :update_association, {post_id: 3, association: 'tags', tags: [2, 3]}
+ put :update_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: [2, 3]}}
assert_response :no_content
post_object = Post.find(3)
assert_equal 2, post_object.tags.collect { |tag| tag.id }.length
assert matches_array? [2, 3], post_object.tags.collect { |tag| tag.id }
- post :create_association, {post_id: 3, association: 'tags', tags: [5]}
+ post :create_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: [5]}}
assert_response :no_content
post_object = Post.find(3)
assert_equal 3, post_object.tags.collect { |tag| tag.id }.length
assert matches_array? [2, 3, 5], post_object.tags.collect { |tag| tag.id }
end
- def test_create_relationship_has_many_missing_tags
+ def test_create_relationship_has_many_mismatched_type
set_content_type_header!
+ post :create_association, {post_id: 3, association: 'tags', data: {type: 'comments', ids: [5]}}
+
+ assert_response :bad_request
+ assert_match /Type Mismatch/, response.body
+ end
+
+ def test_create_relationship_has_many_missing_id
+ set_content_type_header!
+ post :create_association, {post_id: 3, association: 'tags', data: {type: 'tags', idds: [5]}}
+
+ assert_response :bad_request
+ assert_match /The required parameter, ids, is missing/, response.body
+ end
+
+ def test_create_relationship_has_many_missing_data
+ set_content_type_header!
post :create_association, {post_id: 3, association: 'tags'}
assert_response :bad_request
- assert_match /The required parameter, tags, is missing./, response.body
+ assert_match /The required parameter, data, is missing./, response.body
end
+ def test_create_relationship_has_many_join
+ set_content_type_header!
+ post :create_association, {post_id: 4, association: 'tags', data: {type: 'tags', ids: [1, 2, 3]}}
+ assert_response :no_content
+ end
+
def test_create_relationship_has_many_join_table_record_exists
set_content_type_header!
- put :update_association, {post_id: 3, association: 'tags', tags: [2, 3]}
+ put :update_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: [2, 3]}}
assert_response :no_content
post_object = Post.find(3)
assert_equal 2, post_object.tags.collect { |tag| tag.id }.length
assert matches_array? [2, 3], post_object.tags.collect { |tag| tag.id }
- post :create_association, {post_id: 3, association: 'tags', tags: [5, 2]}
+ post :create_association, {post_id: 3, association: 'tags', data: {type: 'tags', ids: [5, 2]}}
assert_response :bad_request
assert_match /The relation to 2 already exists./, response.body
end
- def test_update_relationship_has_one_mismatch_params
- set_content_type_header!
- post :create_association, {post_id: 3, association: 'section', authors: 1}
-
- assert_response :bad_request
- assert_match /The required parameter, sections, is missing./, response.body
- end
-
def test_update_relationship_has_many_missing_tags
set_content_type_header!
put :update_association, {post_id: 3, association: 'tags'}
assert_response :bad_request
- assert_match /The required parameter, tags, is missing./, response.body
+ assert_match /The required parameter, data, is missing./, response.body
end
- def test_delete_relationship_has_one
- set_content_type_header!
- ruby = Section.find_by(name: 'ruby')
-
- post :create_association, {post_id: 9, association: 'section', sections: ruby.id}
-
- assert_response :no_content
-
- delete :destroy_association, {post_id: 9, association: 'section'}
-
- assert_response :no_content
- post = Post.find(9)
- assert_nil post.section
- end
-
def test_delete_relationship_has_many
set_content_type_header!
- put :update_association, {post_id: 9, association: 'tags', tags: [2, 3]}
+ put :update_association, {post_id: 9, association: 'tags', data: {type: 'tags', ids: [2, 3]}}
assert_response :no_content
p = Post.find(9)
assert_equal [2, 3], p.tag_ids
delete :destroy_association, {post_id: 9, association: 'tags', keys: '3'}
@@ -717,11 +872,11 @@
assert_equal [2], p.tag_ids
end
def test_delete_relationship_has_many_does_not_exist
set_content_type_header!
- put :update_association, {post_id: 9, association: 'tags', tags: [2, 3]}
+ put :update_association, {post_id: 9, association: 'tags', data: {type: 'tags', ids: [2, 3]}}
assert_response :no_content
p = Post.find(9)
assert_equal [2, 3], p.tag_ids
delete :destroy_association, {post_id: 9, association: 'tags', keys: '4'}
@@ -736,16 +891,17 @@
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: 3,
- posts: {
+ data: {
+ type: 'posts',
id: 2,
title: 'A great new Post',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
}
assert_response :bad_request
@@ -757,16 +913,18 @@
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: 3,
- posts: {
+ data: {
+ type: 'posts',
+ id: '3',
asdfg: 'aaaa',
title: 'A great new Post',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
}
assert_response :bad_request
@@ -778,16 +936,18 @@
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: 3,
- posts: {
+ data: {
+ type: 'posts',
+ id: '3',
title: 'A great new Post',
links: {
asdfg: 'aaaa',
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
}
assert_response :bad_request
@@ -799,84 +959,129 @@
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: 3,
- posts_spelled_wrong: {
+ data_spelled_wrong: {
+ type: 'posts',
title: 'A great new Post',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
}
assert_response :bad_request
- assert_match /The required parameter, posts, is missing./, response.body
+ assert_match /The required parameter, data, is missing./, response.body
end
+ def test_update_missing_key
+ set_content_type_header!
+
+ put :update,
+ {
+ id: 3,
+ data: {
+ type: 'posts',
+ title: 'A great new Post'
+ }
+ }
+
+ assert_response :bad_request
+ assert_match /The resource object does not contain a key/, response.body
+ end
+
+ def test_update_missing_type
+ set_content_type_header!
+ javascript = Section.find_by(name: 'javascript')
+
+ put :update,
+ {
+ id: 3,
+ data: {
+ id: '3',
+ type_spelled_wrong: 'posts',
+ title: 'A great new Post',
+ links: {
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
+ }
+ }
+ }
+
+ assert_response :bad_request
+ assert_match /The required parameter, type, is missing./, response.body
+ end
+
def test_update_multiple
set_content_type_header!
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: [3, 9],
- posts: [
+ data: [
{
+ type: 'posts',
id: 3,
title: 'A great new Post QWERTY',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
},
{
+ type: 'posts',
id: 9,
title: 'A great new Post ASDFG',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
- ]}
+ ],
+ include: 'tags'
+ }
assert_response :success
- assert_equal json_response['posts'].size, 2
- assert_equal json_response['posts'][0]['links']['author'], '3'
- assert_equal json_response['posts'][0]['links']['section'], javascript.id.to_s
- assert_equal json_response['posts'][0]['title'], 'A great new Post QWERTY'
- assert_equal json_response['posts'][0]['body'], 'AAAA'
- assert_equal json_response['posts'][0]['links']['tags'], ['3', '4']
+ assert_equal json_response['data'].size, 2
+ assert_equal json_response['data'][0]['links']['author']['id'], '3'
+ assert_equal json_response['data'][0]['links']['section']['id'], javascript.id.to_s
+ assert_equal json_response['data'][0]['title'], 'A great new Post QWERTY'
+ assert_equal json_response['data'][0]['body'], 'AAAA'
+ assert_equal json_response['data'][0]['links']['tags']['ids'], ['3', '4']
- assert_equal json_response['posts'][1]['links']['author'], '3'
- assert_equal json_response['posts'][1]['links']['section'], javascript.id.to_s
- assert_equal json_response['posts'][1]['title'], 'A great new Post ASDFG'
- assert_equal json_response['posts'][1]['body'], 'AAAA'
- assert_equal json_response['posts'][1]['links']['tags'], ['3', '4']
+ assert_equal json_response['data'][1]['links']['author']['id'], '3'
+ assert_equal json_response['data'][1]['links']['section']['id'], javascript.id.to_s
+ assert_equal json_response['data'][1]['title'], 'A great new Post ASDFG'
+ assert_equal json_response['data'][1]['body'], 'AAAA'
+ assert_equal json_response['data'][1]['links']['tags']['ids'], ['3', '4']
end
def test_update_multiple_missing_keys
set_content_type_header!
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: [3, 9],
- posts: [
+ data: [
{
+ type: 'posts',
title: 'A great new Post ASDFG',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
},
{
+ type: 'posts',
title: 'A great new Post QWERTY',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
]}
assert_response :bad_request
@@ -888,25 +1093,27 @@
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: [3, 9],
- posts: [
+ data: [
{
+ type: 'posts',
id: 3,
title: 'A great new Post ASDFG',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
},
{
+ type: 'posts',
id: 8,
title: 'A great new Post QWERTY',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
]}
assert_response :bad_request
@@ -918,25 +1125,27 @@
javascript = Section.find_by(name: 'javascript')
put :update,
{
id: [3, 9, 2],
- posts: [
+ data: [
{
+ type: 'posts',
id: 3,
title: 'A great new Post QWERTY',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
},
{
+ type: 'posts',
id: 9,
title: 'A great new Post ASDFG',
links: {
- section: javascript.id,
- tags: [3, 4]
+ section: {type: 'sections', id: "#{javascript.id}"},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
]}
assert_response :bad_request
@@ -946,15 +1155,17 @@
def test_update_unpermitted_attributes
set_content_type_header!
put :update,
{
id: 3,
- posts: {
+ data: {
+ type: 'posts',
+ id: '3',
subject: 'A great new Post',
links: {
- author: 1,
- tags: [3, 4]
+ author: {type: 'people', id: '1'},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
}
assert_response :bad_request
@@ -965,15 +1176,16 @@
def test_update_bad_attributes
set_content_type_header!
put :update,
{
id: 3,
- posts: {
+ data: {
+ type: 'posts',
subject: 'A great new Post',
linked_objects: {
- author: 1,
- tags: [3, 4]
+ author: {type: 'people', id: '1'},
+ tags: {type: 'tags', ids: [3, 4]}
}
}
}
assert_response :bad_request
@@ -1008,41 +1220,55 @@
end
def test_show_has_one_relationship
get :show_association, {post_id: '1', association: 'author'}
assert_response :success
- assert_equal 1, json_response['author']
+ assert_hash_equals json_response,
+ {data: {
+ type: 'people',
+ id: '1',
+ self: 'http://test.host/posts/1/links/author',
+ resource: 'http://test.host/posts/1/author'
+ }
+ }
end
def test_show_has_many_relationship
get :show_association, {post_id: '1', association: 'tags'}
assert_response :success
- assert_equal [1, 2, 3], json_response['tags']
+ assert_hash_equals json_response,
+ {data: {
+ type: 'tags',
+ ids: ['1', '2', '3'],
+ self: 'http://test.host/posts/1/links/tags',
+ resource: 'http://test.host/posts/1/tags'
+ }
+ }
end
end
class TagsControllerTest < ActionController::TestCase
def test_tags_index
- get :index, {ids: '6,7,8,9', include: 'posts,posts.tags,posts.author.posts'}
+ get :index, {filter: {id: '6,7,8,9'}, include: 'posts,posts.tags,posts.author.posts'}
assert_response :success
- assert_equal 4, json_response['tags'].size
- assert_equal 2, json_response['linked']['posts'].size
+ assert_equal 4, json_response['data'].size
+ assert_equal 2, json_response['linked'].size
end
def test_tags_show_multiple
get :show, {id: '6,7,8,9'}
assert_response :success
- assert json_response['tags'].is_a?(Array)
- assert_equal 4, json_response['tags'].size
+ assert json_response['data'].is_a?(Array)
+ assert_equal 4, json_response['data'].size
end
def test_tags_show_multiple_with_include
get :show, {id: '6,7,8,9', include: 'posts,posts.tags,posts.author.posts'}
assert_response :success
- assert json_response['tags'].is_a?(Array)
- assert_equal 4, json_response['tags'].size
- assert_equal 2, json_response['linked']['posts'].size
+ assert json_response['data'].is_a?(Array)
+ assert_equal 4, json_response['data'].size
+ assert_equal 2, json_response['linked'].size
end
def test_tags_show_multiple_with_nonexistent_ids
get :show, {id: '6,99,9,100'}
assert_response :not_found
@@ -1056,26 +1282,25 @@
end
def test_expense_entries_index
get :index
assert_response :success
- assert json_response['expenseEntries'].is_a?(Array)
- assert_equal 2, json_response['expenseEntries'].size
+ assert json_response['data'].is_a?(Array)
+ assert_equal 2, json_response['data'].size
end
def test_expense_entries_show
get :show, {id: 1}
assert_response :success
- assert json_response['expenseEntries'].is_a?(Hash)
+ assert json_response['data'].is_a?(Hash)
end
def test_expense_entries_show_include
get :show, {id: 1, include: 'isoCurrency,employee'}
assert_response :success
- assert json_response['expenseEntries'].is_a?(Hash)
- assert_equal 1, json_response['linked']['isoCurrencies'].size
- assert_equal 1, json_response['linked']['people'].size
+ assert json_response['data'].is_a?(Hash)
+ assert_equal 2, json_response['linked'].size
end
def test_expense_entries_show_bad_include_missing_association
get :show, {id: 1, include: 'isoCurrencies,employees'}
assert_response :bad_request
@@ -1090,253 +1315,216 @@
end
def test_expense_entries_show_fields
get :show, {id: 1, include: 'isoCurrency,employee', 'fields' => 'transactionDate'}
assert_response :success
- assert json_response['expenseEntries'].is_a?(Hash)
- assert json_response['expenseEntries'].has_key?('transactionDate')
- refute json_response['expenseEntries'].has_key?('id')
- refute json_response['expenseEntries'].has_key?('links')
- assert_equal 1, json_response['linked']['isoCurrencies'].size
- assert_equal 1, json_response['linked']['people'].size
+ assert json_response['data'].is_a?(Hash)
+ assert json_response['data'].has_key?('transactionDate')
end
def test_expense_entries_show_fields_type
get :show, {id: 1, include: 'isoCurrency,employee', 'fields' => {'expenseEntries' => 'transactionDate'}}
assert_response :success
- assert json_response['expenseEntries'].is_a?(Hash)
- assert json_response['expenseEntries'].has_key?('transactionDate')
- refute json_response['expenseEntries'].has_key?('id')
- refute json_response['expenseEntries'].has_key?('links')
- assert_equal 1, json_response['linked']['isoCurrencies'].size
- assert_equal 1, json_response['linked']['people'].size
+ assert json_response['data'].is_a?(Hash)
+ assert json_response['data'].has_key?('transactionDate')
+ assert_equal 2, json_response['linked'].size
end
def test_expense_entries_show_fields_type_many
get :show, {id: 1, include: 'isoCurrency,employee', 'fields' => {'expenseEntries' => 'transactionDate',
'isoCurrencies' => 'id,name'}}
assert_response :success
- assert json_response['expenseEntries'].is_a?(Hash)
- assert json_response['expenseEntries'].has_key?('transactionDate')
- refute json_response['expenseEntries'].has_key?('id')
- refute json_response['expenseEntries'].has_key?('links')
- assert_equal 1, json_response['linked']['isoCurrencies'].size
- assert_equal 1, json_response['linked']['people'].size
- assert json_response['linked']['isoCurrencies'][0].has_key?('id')
- assert json_response['linked']['isoCurrencies'][0].has_key?('name')
- refute json_response['linked']['isoCurrencies'][0].has_key?('countryName')
+ assert json_response['data'].is_a?(Hash)
+ assert json_response['data'].has_key?('transactionDate')
+ assert_equal 2, json_response['linked'].size
end
def test_create_expense_entries_underscored
set_content_type_header!
JSONAPI.configuration.json_key_format = :underscored_key
post :create,
{
- expense_entries: {
+ data: {
+ type: 'expense_entries',
transaction_date: '2014/04/15',
cost: 50.58,
links: {
- employee: 3,
- iso_currency: 'USD'
+ employee: {type: 'people', id: '3'},
+ iso_currency: {type: 'iso_currencies', id: 'USD'}
}
},
include: 'iso_currency',
fields: 'id,transaction_date,iso_currency,cost,employee'
}
assert_response :created
- assert json_response['expense_entries'].is_a?(Hash)
- assert_equal '3', json_response['expense_entries']['links']['employee']
- assert_equal 'USD', json_response['expense_entries']['links']['iso_currency']
- assert_equal 50.58, json_response['expense_entries']['cost']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['employee']['id']
+ assert_equal 'USD', json_response['data']['links']['iso_currency']['id']
+ assert_equal 50.58, json_response['data']['cost']
- delete :destroy, {id: json_response['expense_entries']['id']}
+ delete :destroy, {id: json_response['data']['id']}
assert_response :no_content
end
def test_create_expense_entries_camelized_key
set_content_type_header!
JSONAPI.configuration.json_key_format = :camelized_key
post :create,
{
- expenseEntries: {
+ data: {
+ type: 'expense_entries',
transactionDate: '2014/04/15',
cost: 50.58,
links: {
- employee: 3,
- isoCurrency: 'USD'
+ employee: {type: 'people', id: '3'},
+ isoCurrency: {type: 'iso_currencies', id: 'USD'}
}
},
include: 'isoCurrency',
fields: 'id,transactionDate,isoCurrency,cost,employee'
}
assert_response :created
- assert json_response['expenseEntries'].is_a?(Hash)
- assert_equal '3', json_response['expenseEntries']['links']['employee']
- assert_equal 'USD', json_response['expenseEntries']['links']['isoCurrency']
- assert_equal 50.58, json_response['expenseEntries']['cost']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['employee']['id']
+ assert_equal 'USD', json_response['data']['links']['isoCurrency']['id']
+ assert_equal 50.58, json_response['data']['cost']
- delete :destroy, {id: json_response['expenseEntries']['id']}
+ delete :destroy, {id: json_response['data']['id']}
assert_response :no_content
end
def test_create_expense_entries_dasherized_key
set_content_type_header!
JSONAPI.configuration.json_key_format = :dasherized_key
post :create,
{
- 'expense-entries' => {
+ data: {
+ type: 'expense_entries',
'transaction-date' => '2014/04/15',
cost: 50.58,
links: {
- employee: 3,
- 'iso-currency' => 'USD'
+ employee: {type: 'people', id: '3'},
+ 'iso-currency' => {type: 'iso_currencies', id: 'USD'}
}
},
include: 'iso-currency',
fields: 'id,transaction-date,iso-currency,cost,employee'
}
assert_response :created
- assert json_response['expense-entries'].is_a?(Hash)
- assert_equal '3', json_response['expense-entries']['links']['employee']
- assert_equal 'USD', json_response['expense-entries']['links']['iso-currency']
- assert_equal 50.58, json_response['expense-entries']['cost']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['employee']['id']
+ assert_equal 'USD', json_response['data']['links']['iso-currency']['id']
+ assert_equal 50.58, json_response['data']['cost']
- delete :destroy, {id: json_response['expense-entries']['id']}
+ delete :destroy, {id: json_response['data']['id']}
assert_response :no_content
end
end
class IsoCurrenciesControllerTest < ActionController::TestCase
def after_teardown
JSONAPI.configuration.json_key_format = :camelized_key
end
- def test_currencies_index
- JSONAPI.configuration.json_key_format = :camelized_key
- get :index
- assert_response :success
- assert_equal 3, json_response['isoCurrencies'].size
- end
-
- def test_currencies_json_key_underscored
- JSONAPI.configuration.json_key_format = :underscored_key
- get :index
- assert_response :success
- assert_equal 3, json_response['iso_currencies'].size
- end
-
- def test_currencies_json_key_dasherized
- JSONAPI.configuration.json_key_format = :dasherized_key
- get :index
- assert_response :success
- assert_equal 3, json_response['iso-currencies'].size
- end
-
- def test_currencies_custom_json_key
- JSONAPI.configuration.json_key_format = :upper_camelized_key
- get :index
- assert_response :success
- assert_equal 3, json_response['IsoCurrencies'].size
- end
-
def test_currencies_show
get :show, {code: 'USD'}
assert_response :success
- assert json_response['isoCurrencies'].is_a?(Hash)
+ assert json_response['data'].is_a?(Hash)
end
def test_currencies_json_key_underscored_sort
JSONAPI.configuration.json_key_format = :underscored_key
- get :index, {sort: 'country_name'}
+ get :index, {sort: '+country_name'}
assert_response :success
- assert_equal 3, json_response['iso_currencies'].size
- assert_equal 'Canada', json_response['iso_currencies'][0]['country_name']
- assert_equal 'Euro Member Countries', json_response['iso_currencies'][1]['country_name']
- assert_equal 'United States', json_response['iso_currencies'][2]['country_name']
+ assert_equal 3, json_response['data'].size
+ assert_equal 'Canada', json_response['data'][0]['country_name']
+ assert_equal 'Euro Member Countries', json_response['data'][1]['country_name']
+ assert_equal 'United States', json_response['data'][2]['country_name']
# reverse sort
get :index, {sort: '-country_name'}
assert_response :success
- assert_equal 3, json_response['iso_currencies'].size
- assert_equal 'United States', json_response['iso_currencies'][0]['country_name']
- assert_equal 'Euro Member Countries', json_response['iso_currencies'][1]['country_name']
- assert_equal 'Canada', json_response['iso_currencies'][2]['country_name']
+ assert_equal 3, json_response['data'].size
+ assert_equal 'United States', json_response['data'][0]['country_name']
+ assert_equal 'Euro Member Countries', json_response['data'][1]['country_name']
+ assert_equal 'Canada', json_response['data'][2]['country_name']
end
def test_currencies_json_key_dasherized_sort
JSONAPI.configuration.json_key_format = :dasherized_key
- get :index, {sort: 'country-name'}
+ get :index, {sort: '+country-name'}
assert_response :success
- assert_equal 3, json_response['iso-currencies'].size
- assert_equal 'Canada', json_response['iso-currencies'][0]['country-name']
- assert_equal 'Euro Member Countries', json_response['iso-currencies'][1]['country-name']
- assert_equal 'United States', json_response['iso-currencies'][2]['country-name']
+ assert_equal 3, json_response['data'].size
+ assert_equal 'Canada', json_response['data'][0]['country-name']
+ assert_equal 'Euro Member Countries', json_response['data'][1]['country-name']
+ assert_equal 'United States', json_response['data'][2]['country-name']
# reverse sort
get :index, {sort: '-country-name'}
assert_response :success
- assert_equal 3, json_response['iso-currencies'].size
- assert_equal 'United States', json_response['iso-currencies'][0]['country-name']
- assert_equal 'Euro Member Countries', json_response['iso-currencies'][1]['country-name']
- assert_equal 'Canada', json_response['iso-currencies'][2]['country-name']
+ assert_equal 3, json_response['data'].size
+ assert_equal 'United States', json_response['data'][0]['country-name']
+ assert_equal 'Euro Member Countries', json_response['data'][1]['country-name']
+ assert_equal 'Canada', json_response['data'][2]['country-name']
end
def test_currencies_json_key_custom_json_key_sort
JSONAPI.configuration.json_key_format = :upper_camelized_key
- get :index, {sort: 'CountryName'}
+ get :index, {sort: '+CountryName'}
assert_response :success
- assert_equal 3, json_response['IsoCurrencies'].size
- assert_equal 'Canada', json_response['IsoCurrencies'][0]['CountryName']
- assert_equal 'Euro Member Countries', json_response['IsoCurrencies'][1]['CountryName']
- assert_equal 'United States', json_response['IsoCurrencies'][2]['CountryName']
+ assert_equal 3, json_response['data'].size
+ assert_equal 'Canada', json_response['data'][0]['CountryName']
+ assert_equal 'Euro Member Countries', json_response['data'][1]['CountryName']
+ assert_equal 'United States', json_response['data'][2]['CountryName']
# reverse sort
get :index, {sort: '-CountryName'}
assert_response :success
- assert_equal 3, json_response['IsoCurrencies'].size
- assert_equal 'United States', json_response['IsoCurrencies'][0]['CountryName']
- assert_equal 'Euro Member Countries', json_response['IsoCurrencies'][1]['CountryName']
- assert_equal 'Canada', json_response['IsoCurrencies'][2]['CountryName']
+ assert_equal 3, json_response['data'].size
+ assert_equal 'United States', json_response['data'][0]['CountryName']
+ assert_equal 'Euro Member Countries', json_response['data'][1]['CountryName']
+ assert_equal 'Canada', json_response['data'][2]['CountryName']
end
def test_currencies_json_key_underscored_filter
JSONAPI.configuration.json_key_format = :underscored_key
- get :index, {country_name: 'Canada'}
+ get :index, {filter: {country_name: 'Canada'}}
assert_response :success
- assert_equal 1, json_response['iso_currencies'].size
- assert_equal 'Canada', json_response['iso_currencies'][0]['country_name']
+ assert_equal 1, json_response['data'].size
+ assert_equal 'Canada', json_response['data'][0]['country_name']
end
def test_currencies_json_key_camelized_key_filter
JSONAPI.configuration.json_key_format = :camelized_key
- get :index, {'countryName' => 'Canada'}
+ get :index, {filter: {'countryName' => 'Canada'}}
assert_response :success
- assert_equal 1, json_response['isoCurrencies'].size
- assert_equal 'Canada', json_response['isoCurrencies'][0]['countryName']
+ assert_equal 1, json_response['data'].size
+ assert_equal 'Canada', json_response['data'][0]['countryName']
end
def test_currencies_json_key_custom_json_key_filter
JSONAPI.configuration.json_key_format = :upper_camelized_key
- get :index, {'CountryName' => 'Canada'}
+ get :index, {filter: {'CountryName' => 'Canada'}}
assert_response :success
- assert_equal 1, json_response['IsoCurrencies'].size
- assert_equal 'Canada', json_response['IsoCurrencies'][0]['CountryName']
+ assert_equal 1, json_response['data'].size
+ assert_equal 'Canada', json_response['data'][0]['CountryName']
end
end
class PeopleControllerTest < ActionController::TestCase
def test_create_validations
set_content_type_header!
post :create,
{
- people: {
+ data: {
+ type: 'people',
name: 'Steve Jobs',
email: 'sj@email.zzz',
dateJoined: DateTime.parse('2014-1-30 4:20:00 UTC +00:00')
}
}
@@ -1346,11 +1534,12 @@
def test_create_validations_missing_attribute
set_content_type_header!
post :create,
{
- people: {
+ data: {
+ type: 'people',
email: 'sj@email.zzz'
}
}
assert_response :unprocessable_entity
@@ -1364,11 +1553,13 @@
def test_update_validations_missing_attribute
set_content_type_header!
put :update,
{
id: 3,
- people: {
+ data: {
+ id: '3',
+ type: 'people',
name: ''
}
}
assert_response :unprocessable_entity
@@ -1383,112 +1574,113 @@
assert_response :locked
assert_equal initial_count, Person.count
end
def test_invalid_filter_value
- get :index, {name: 'L'}
+ get :index, {filter: {name: 'L'}}
assert_response :bad_request
end
def test_valid_filter_value
- get :index, {name: 'Joe Author'}
+ get :index, {filter: {name: 'Joe Author'}}
assert_response :success
- assert_equal json_response['people'].size, 1
- assert_equal json_response['people'][0]['id'], '1'
- assert_equal json_response['people'][0]['name'], 'Joe Author'
+ assert_equal json_response['data'].size, 1
+ assert_equal json_response['data'][0]['id'], '1'
+ assert_equal json_response['data'][0]['name'], 'Joe Author'
end
end
class AuthorsControllerTest < ActionController::TestCase
def test_get_person_as_author
- get :index, {id: '1'}
+ get :index, {filter: {id: '1'}}
assert_response :success
- assert_equal 1, json_response['authors'].size
- assert_equal '1', json_response['authors'][0]['id']
- assert_equal 'Joe Author', json_response['authors'][0]['name']
- assert_equal nil, json_response['authors'][0]['email']
- assert_equal 1, json_response['authors'][0]['links'].size
- assert_equal 3, json_response['authors'][0]['links']['posts'].size
+ assert_equal 1, json_response['data'].size
+ assert_equal '1', json_response['data'][0]['id']
+ assert_equal 'authors', json_response['data'][0]['type']
+ assert_equal 'Joe Author', json_response['data'][0]['name']
+ assert_equal nil, json_response['data'][0]['email']
end
def test_get_person_as_author_by_name_filter
- get :index, {name: 'thor'}
+ get :index, {filter: {name: 'thor'}}
assert_response :success
- assert_equal 3, json_response['authors'].size
- assert_equal '1', json_response['authors'][0]['id']
- assert_equal 'Joe Author', json_response['authors'][0]['name']
- assert_equal 1, json_response['authors'][0]['links'].size
- assert_equal 3, json_response['authors'][0]['links']['posts'].size
+ assert_equal 3, json_response['data'].size
+ assert_equal '1', json_response['data'][0]['id']
+ assert_equal 'Joe Author', json_response['data'][0]['name']
end
end
class BreedsControllerTest < ActionController::TestCase
# Note: Breed names go through the TitleValueFormatter
def test_poro_index
get :index
assert_response :success
- assert_equal '0', json_response['breeds'][0]['id']
- assert_equal 'Persian', json_response['breeds'][0]['name']
+ assert_equal '0', json_response['data'][0]['id']
+ assert_equal 'Persian', json_response['data'][0]['name']
end
def test_poro_show
get :show, {id: '0'}
assert_response :success
- assert json_response['breeds'].is_a?(Hash)
- assert_equal '0', json_response['breeds']['id']
- assert_equal 'Persian', json_response['breeds']['name']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '0', json_response['data']['id']
+ assert_equal 'Persian', json_response['data']['name']
end
def test_poro_show_multiple
get :show, {id: '0,2'}
assert_response :success
- assert json_response['breeds'].is_a?(Array)
- assert_equal 2, json_response['breeds'].size
- assert_equal '0', json_response['breeds'][0]['id']
- assert_equal 'Persian', json_response['breeds'][0]['name']
- assert_equal '2', json_response['breeds'][1]['id']
- assert_equal 'Sphinx', json_response['breeds'][1]['name']
+ assert json_response['data'].is_a?(Array)
+ assert_equal 2, json_response['data'].size
+ assert_equal '0', json_response['data'][0]['id']
+ assert_equal 'Persian', json_response['data'][0]['name']
+ assert_equal '2', json_response['data'][1]['id']
+ assert_equal 'Sphinx', json_response['data'][1]['name']
end
def test_poro_create_simple
set_content_type_header!
post :create,
{
- breeds: {
+ data: {
+ type: 'breeds',
name: 'tabby'
}
}
assert_response :created
- assert json_response['breeds'].is_a?(Hash)
- assert_equal 'Tabby', json_response['breeds']['name']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal 'Tabby', json_response['data']['name']
end
def test_poro_create_update
set_content_type_header!
post :create,
{
- breeds: {
+ data: {
+ type: 'breeds',
name: 'CALIC'
}
}
assert_response :created
- assert json_response['breeds'].is_a?(Hash)
- assert_equal 'Calic', json_response['breeds']['name']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal 'Calic', json_response['data']['name']
put :update,
{
- id: json_response['breeds']['id'],
- breeds: {
+ id: json_response['data']['id'],
+ data: {
+ id: json_response['data']['id'],
+ type: 'breeds',
name: 'calico'
}
}
assert_response :success
- assert json_response['breeds'].is_a?(Hash)
- assert_equal 'Calico', json_response['breeds']['name']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal 'Calico', json_response['data']['name']
end
def test_poro_delete
initial_count = $breed_data.breeds.keys.count
delete :destroy, {id: '3'}
@@ -1507,82 +1699,196 @@
class Api::V1::PostsControllerTest < ActionController::TestCase
def test_show_post_namespaced
get :show, {id: '1'}
assert_response :success
- assert_hash_equals(
- {
- posts: {
- id: '1',
- title: 'New post',
- body: 'A body!!!',
- subject: 'New post',
- links: {
- section: nil,
- writer: '1',
- comments: ['1', '2']
- }
- }
- }, json_response
- )
+ assert_equal 'http://test.host/api/v1/posts/1/links/writer', json_response['data']['links']['writer']['self']
end
def test_show_post_namespaced_include
get :show, {id: '1', include: 'writer'}
assert_response :success
- assert_equal '1', json_response['posts']['links']['writer']
- assert_nil json_response['posts']['links']['tags']
- assert_equal '1', json_response['linked']['writers'][0]['id']
- assert_equal 'joe@xyz.fake', json_response['linked']['writers'][0]['email']
+ assert_equal '1', json_response['data']['links']['writer']['id']
+ assert_nil json_response['data']['links']['tags']
+ assert_equal '1', json_response['linked'][0]['id']
+ assert_equal 'writers', json_response['linked'][0]['type']
+ assert_equal 'joe@xyz.fake', json_response['linked'][0]['email']
end
def test_index_filter_on_association_namespaced
- get :index, {writer: '1'}
+ get :index, {filter: {writer: '1'}}
assert_response :success
- assert_equal 3, json_response['posts'].size
+ assert_equal 3, json_response['data'].size
end
def test_sorting_desc_namespaced
get :index, {sort: '-title'}
assert_response :success
- assert_equal "Update This Later - Multiple", json_response['posts'][0]['title']
+ assert_equal "Update This Later - Multiple", json_response['data'][0]['title']
end
def test_create_simple_namespaced
set_content_type_header!
post :create,
{
- posts: {
+ data: {
+ type: 'posts',
title: 'JR - now with Namespacing',
body: 'JSONAPIResources is the greatest thing since unsliced bread now that it has namespaced resources.',
links: {
- writer: '3'
+ writer: {type: 'writers', id: '3'}
}
}
}
assert_response :created
- assert json_response['posts'].is_a?(Hash)
- assert_equal '3', json_response['posts']['links']['writer']
- assert_equal 'JR - now with Namespacing', json_response['posts']['title']
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread now that it has namespaced resources.', json_response['posts']['body']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal '3', json_response['data']['links']['writer']['id']
+ assert_equal 'JR - now with Namespacing', json_response['data']['title']
+ assert_equal 'JSONAPIResources is the greatest thing since unsliced bread now that it has namespaced resources.',
+ json_response['data']['body']
end
end
class FactsControllerTest < ActionController::TestCase
def test_type_formatting
get :show, {id: '1'}
assert_response :success
- assert json_response['facts'].is_a?(Hash)
- assert_equal 'Jane Author', json_response['facts']['spouseName']
- assert_equal 'First man to run across Antartica.', json_response['facts']['bio']
- assert_equal 23.89/45.6, json_response['facts']['qualityRating']
- assert_equal 47000.56, json_response['facts']['salary']
- assert_equal '2013-08-07T20:25:00.000Z', json_response['facts']['dateTimeJoined']
- assert_equal '1965-06-30', json_response['facts']['birthday']
- assert_equal '2000-01-01T20:00:00Z', json_response['facts']['bedtime']
- assert_equal 'abc', json_response['facts']['photo']
- assert_equal false, json_response['facts']['cool']
+ assert json_response['data'].is_a?(Hash)
+ assert_equal 'Jane Author', json_response['data']['spouseName']
+ assert_equal 'First man to run across Antartica.', json_response['data']['bio']
+ assert_equal 23.89/45.6, json_response['data']['qualityRating']
+ assert_equal 47000.56, json_response['data']['salary']
+ assert_equal '2013-08-07T20:25:00.000Z', json_response['data']['dateTimeJoined']
+ assert_equal '1965-06-30', json_response['data']['birthday']
+ assert_equal '2000-01-01T20:00:00Z', json_response['data']['bedtime']
+ assert_equal 'abc', json_response['data']['photo']
+ assert_equal false, json_response['data']['cool']
+ end
+end
+
+class Api::V2::BooksControllerTest < ActionController::TestCase
+ def after_teardown
+ Api::V2::BookResource.paginator :offset
+ end
+
+ def test_books_offset_pagination_no_params
+ Api::V2::BookResource.paginator :offset
+
+ get :index
+ assert_response :success
+ assert_equal 10, json_response['data'].size
+ assert_equal 'Book 0', json_response['data'][0]['title']
+ end
+
+ def test_books_offset_pagination
+ Api::V2::BookResource.paginator :offset
+
+ get :index, {page: {offset: 50, limit: 12}}
+ assert_response :success
+ assert_equal 12, json_response['data'].size
+ assert_equal 'Book 50', json_response['data'][0]['title']
+ end
+
+ def test_books_offset_pagination_bad_page_param
+ Api::V2::BookResource.paginator :offset
+
+ get :index, {page: {offset_bad: 50, limit: 12}}
+ assert_response :bad_request
+ assert_match /offset_bad is not an allowed page parameter./, json_response['errors'][0]['detail']
+ end
+
+ def test_books_offset_pagination_bad_param_value_limit_to_large
+ Api::V2::BookResource.paginator :offset
+
+ get :index, {page: {offset: 50, limit: 1000}}
+ assert_response :bad_request
+ assert_match /Limit exceeds maximum page size of 20./, json_response['errors'][0]['detail']
+ end
+
+ def test_books_offset_pagination_bad_param_value_limit_too_small
+ Api::V2::BookResource.paginator :offset
+
+ get :index, {page: {offset: 50, limit: -1}}
+ assert_response :bad_request
+ assert_match /-1 is not a valid value for limit page parameter./, json_response['errors'][0]['detail']
+ end
+
+ def test_books_offset_pagination_invalid_page_format
+ Api::V2::BookResource.paginator :offset
+
+ get :index, {page: 50}
+ assert_response :bad_request
+ assert_match /Invalid Page Object./, json_response['errors'][0]['detail']
+ end
+
+ def test_books_paged_pagination_no_params
+ Api::V2::BookResource.paginator :paged
+
+ get :index
+ assert_response :success
+ assert_equal 10, json_response['data'].size
+ assert_equal 'Book 0', json_response['data'][0]['title']
+ end
+
+ def test_books_paged_pagination_no_page
+ Api::V2::BookResource.paginator :paged
+
+ get :index, {page: {size: 12}}
+ assert_response :success
+ assert_equal 12, json_response['data'].size
+ assert_equal 'Book 0', json_response['data'][0]['title']
+ end
+
+ def test_books_paged_pagination
+ Api::V2::BookResource.paginator :paged
+
+ get :index, {page: {number: 3, size: 12}}
+ assert_response :success
+ assert_equal 12, json_response['data'].size
+ assert_equal 'Book 24', json_response['data'][0]['title']
+ end
+
+ def test_books_paged_pagination_bad_page_param
+ Api::V2::BookResource.paginator :paged
+
+ get :index, {page: {number_bad: 50, size: 12}}
+ assert_response :bad_request
+ assert_match /number_bad is not an allowed page parameter./, json_response['errors'][0]['detail']
+ end
+
+ def test_books_paged_pagination_bad_param_value_limit_to_large
+ Api::V2::BookResource.paginator :paged
+
+ get :index, {page: {number: 50, size: 1000}}
+ assert_response :bad_request
+ assert_match /size exceeds maximum page size of 20./, json_response['errors'][0]['detail']
+ end
+
+ def test_books_paged_pagination_bad_param_value_limit_too_small
+ Api::V2::BookResource.paginator :paged
+
+ get :index, {page: {number: 50, size: -1}}
+ assert_response :bad_request
+ assert_match /-1 is not a valid value for size page parameter./, json_response['errors'][0]['detail']
+ end
+
+ def test_books_paged_pagination_invalid_page_format_interpret_int_text
+ Api::V2::BookResource.paginator :paged
+
+ get :index, {page: 'qwerty'}
+ assert_response :success
+ assert_equal 10, json_response['data'].size
+ assert_equal 'Book 0', json_response['data'][0]['title']
+ end
+
+ def test_books_paged_pagination_invalid_page_format_interpret_int
+ Api::V2::BookResource.paginator :paged
+
+ get :index, {page: 3}
+ assert_response :success
+ assert_equal 10, json_response['data'].size
+ assert_equal 'Book 20', json_response['data'][0]['title']
end
end