Skip to content

Commit

Permalink
Enable submitting values with a JSON body and refactor test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
amol- committed May 26, 2013
1 parent 309e4aa commit 854c4e1
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 2 deletions.
66 changes: 66 additions & 0 deletions tests/test_rest_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import transaction

class TestRestJsonEditCreateDelete(CrudTest):
"""Basic tests for POST, PUT & DELETE using urlencoded parameters and requesting for JSON responses"""

def controller_factory(self):
class MovieController(EasyCrudRestController):
model = Movie
Expand Down Expand Up @@ -128,6 +130,8 @@ def test_delete_nofilter(self):
assert movie is not None

class TestRestJsonRead(CrudTest):
"""Basic tests for GET requests with JSON responses"""

def controller_factory(self):
class MovieController(EasyCrudRestController):
model = Movie
Expand Down Expand Up @@ -311,3 +315,65 @@ def test_get_one___json__(self):
assert result['model'] == 'Actor', result
assert result['value']['name'] == actor.name
assert result['value']['movie_title'] == movie_title

class TestRestJsonEditCreateJsonBody(CrudTest):
def controller_factory(self):
class MovieController(EasyCrudRestController):
model = Movie

class RestJsonController(TGController):
movies = MovieController(DBSession)

return RestJsonController()

def test_post(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})

movie = DBSession.query(Movie).first()
assert movie is not None, result

assert movie.movie_id == result.json['value']['movie_id']

def test_post_validation(self):
result = self.app.post_json('/movies.json', params={'title':''}, status=400)
assert result.json['title'] is not None #there is an error for required title
assert result.json['description'] is None #there isn't any error for optional description

assert DBSession.query(Movie).first() is None

def test_put(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})
movie = result.json['value']

result = self.app.put_json('/movies/%s.json' % movie['movie_id'],
params={'title':'New Title'})
assert result.json['value']['title'] == 'New Title'

def test_put_validation(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})
movie = result.json['value']

result = self.app.put_json('/movies/%s.json' % movie['movie_id'],
params={'title':''}, status=400)
assert result.json['title'] is not None #there is an error for required title
assert result.json['description'] is None #there isn't any error for optional description

movie = DBSession.query(Movie).first()
assert movie.title == 'Movie Test'

def test_put_relationship(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})
movie = result.json['value']

actors = [Actor(name='James Who'), Actor(name='John Doe'), Actor(name='Man Alone')]
map(DBSession.add, actors)
DBSession.flush()
actor_ids = [actor.actor_id for actor in actors[:2]]
transaction.commit()

result = self.app.put_json('/movies/%s.json' % movie['movie_id'],
params={'title':'Movie Test',
'actors':actor_ids})
assert len(result.json['value']['actors']) == 2, result

assert DBSession.query(Actor).filter_by(movie_id=movie['movie_id']).count() == 2
70 changes: 70 additions & 0 deletions tests/test_rest_json_body.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from tg import TGController
from tgext.crud import EasyCrudRestController
from .base import CrudTest, Movie, DBSession, metadata, Genre, Actor

import transaction


class TestRestJsonEditCreateJsonBody(CrudTest):
"""Tests for submitting POST & PUT values through a JSON body instead of parameters"""

def controller_factory(self):
class MovieController(EasyCrudRestController):
model = Movie

class RestJsonController(TGController):
movies = MovieController(DBSession)

return RestJsonController()

def test_post(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})

movie = DBSession.query(Movie).first()
assert movie is not None, result

assert movie.movie_id == result.json['value']['movie_id']

def test_post_validation(self):
result = self.app.post_json('/movies.json', params={'title':''}, status=400)
assert result.json['title'] is not None #there is an error for required title
assert result.json['description'] is None #there isn't any error for optional description

assert DBSession.query(Movie).first() is None

def test_put(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})
movie = result.json['value']

result = self.app.put_json('/movies/%s.json' % movie['movie_id'],
params={'title':'New Title'})
assert result.json['value']['title'] == 'New Title'

def test_put_validation(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})
movie = result.json['value']

result = self.app.put_json('/movies/%s.json' % movie['movie_id'],
params={'title':''}, status=400)
assert result.json['title'] is not None #there is an error for required title
assert result.json['description'] is None #there isn't any error for optional description

movie = DBSession.query(Movie).first()
assert movie.title == 'Movie Test'

def test_put_relationship(self):
result = self.app.post_json('/movies.json', params={'title':'Movie Test'})
movie = result.json['value']

actors = [Actor(name='James Who'), Actor(name='John Doe'), Actor(name='Man Alone')]
map(DBSession.add, actors)
DBSession.flush()
actor_ids = [actor.actor_id for actor in actors[:2]]
transaction.commit()

result = self.app.put_json('/movies/%s.json' % movie['movie_id'],
params={'title':'Movie Test',
'actors':actor_ids})
assert len(result.json['value']['actors']) == 2, result

assert DBSession.query(Actor).filter_by(movie_id=movie['movie_id']).count() == 2
98 changes: 98 additions & 0 deletions tests/test_rest_json_dictified.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from tg import TGController
from tgext.crud import EasyCrudRestController
from .base import CrudTest, Movie, DBSession, metadata, Genre, Actor

import transaction


class TestRestJsonReadDictified(CrudTest):
"""
Tests for GET requests that enabled dictification, this will rely on
sprox provider dictify function to resolve also relationships.
"""

def controller_factory(self):
class MovieController(EasyCrudRestController):
model = Movie
pagination = {'items_per_page': 3}
json_dictify = True

class ActorController(EasyCrudRestController):
model = Actor
json_dictify = True

class RestJsonController(TGController):
movies = MovieController(DBSession)
actors = ActorController(DBSession)

return RestJsonController()

def setUp(self):
super(TestRestJsonReadDictified, self).setUp()
genre = Genre(name='action')
DBSession.add(genre)

actors = [Actor(name='James Who'), Actor(name='John Doe'), Actor(name='Man Alone')]
map(DBSession.add, actors)

DBSession.add(Movie(title='First Movie', genre=genre, actors=actors[:2]))
DBSession.add(Movie(title='Second Movie', genre=genre))
DBSession.add(Movie(title='Third Movie', genre=genre))
DBSession.add(Movie(title='Fourth Movie', genre=genre))
DBSession.add(Movie(title='Fifth Movie'))
DBSession.add(Movie(title='Sixth Movie'))
DBSession.flush()
transaction.commit()

def test_get_all(self):
result = self.app.get('/movies.json?order_by=movie_id')
result = result.json['value_list']
assert result['total'] == 6, result
assert result['page'] == 1, result
assert result['entries'][0]['title'] == 'First Movie', result
assert len(result['entries'][0]['actors']) == 2, result

result = self.app.get('/movies.json?page=2&order_by=movie_id')
result = result.json['value_list']
assert result['total'] == 6, result
assert result['page'] == 2, result
assert result['entries'][0]['title'] == 'Fourth Movie', result

def test_get_all_filter(self):
actor = DBSession.query(Actor).first()

result = self.app.get('/actors.json?movie_id=%s' % actor.movie_id)
result = result.json['value_list']
assert result['total'] == 2, result

def test_get_all___json__(self):
actor = DBSession.query(Actor).filter(Actor.movie_id!=None).first()
movie_title = actor.movie.title

result = self.app.get('/actors.json?movie_id=%s' % actor.movie_id)
result = result.json['value_list']
assert result['total'] > 0, result

for entry in result['entries']:
assert entry['movie_title'] == movie_title

def test_get_one(self):
movie = DBSession.query(Movie).first()
movie_actors_count = len(movie.actors)

result = self.app.get('/movies/%s.json' % movie.movie_id)
result = result.json
assert result['model'] == 'Movie', result
assert result['value']['title'] == movie.title
assert result['value']['movie_id'] == movie.movie_id
assert len(result['value']['actors']) == movie_actors_count

def test_get_one___json__(self):
actor = DBSession.query(Actor).filter(Actor.movie_id!=None).first()
movie_title = actor.movie.title

result = self.app.get('/actors/%s.json' % actor.actor_id)
result = result.json
assert result['model'] == 'Actor', result
assert result['value']['name'] == actor.name
assert result['value']['movie_title'] == movie_title
4 changes: 3 additions & 1 deletion tgext/crud/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
optional_paginate)
from tgext.crud.utils import (SmartPaginationCollection, RequestLocalTableFiller, create_setter,
set_table_filler_getter, SortableTableBase, map_args_to_pks,
adapt_params_for_pagination)
adapt_params_for_pagination, allow_json_parameters)
from sprox.providerselector import ProviderTypeSelector
from sprox.fillerbase import TableFiller
from sprox.formbase import AddRecordForm, EditableForm
Expand Down Expand Up @@ -337,6 +337,7 @@ def new(self, *args, **kw):

@expose(content_type='text/html')
@expose('json:', content_type='application/json')
@before_validate(allow_json_parameters)
@catch_errors(errors, error_handler=new)
@registered_validate(error_handler=new)
def post(self, *args, **kw):
Expand All @@ -350,6 +351,7 @@ def post(self, *args, **kw):

@expose(content_type='text/html')
@expose('json:', content_type='application/json')
@before_validate(allow_json_parameters)
@before_validate(map_args_to_pks)
@registered_validate(error_handler=edit)
@catch_errors(errors, error_handler=edit)
Expand Down
6 changes: 5 additions & 1 deletion tgext/crud/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,8 @@ def adapt_params_for_pagination(params, pagination_enabled=True):
page = paginator.paginate_page - 1

params['offset'] = page*paginator.paginate_items_per_page
params['limit'] = paginator.paginate_items_per_page
params['limit'] = paginator.paginate_items_per_page

def allow_json_parameters(remainder, params):
if request.content_type == 'application/json':
params.update(request.json_body)

0 comments on commit 854c4e1

Please sign in to comment.