Skip to content
This repository has been archived by the owner on Jan 5, 2019. It is now read-only.

Commit

Permalink
Merge pull request #7 from rbw0/branch-0.1.4
Browse files Browse the repository at this point in the history
Branch 0.1.4
  • Loading branch information
rbw committed Mar 12, 2018
2 parents b9f97ca + 3499f99 commit 0fdbdc3
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 9 deletions.
4 changes: 2 additions & 2 deletions examples/full/README.rst
Expand Up @@ -9,7 +9,7 @@ This example shows how a structured Flask application can utilize the Flask-Jour
- Marshalling


Note that the `routes` endpoint uses the regular ``route`` decorator from ``flask.Blueprint``. This is intentional to show that Flask-Journey works seamlessly with vanilla Flask blueprints.
Note that the **routes** endpoint uses the regular ``route`` decorator from ``flask.Blueprint``. This is intentional to show that Flask-Journey works seamlessly with vanilla Flask blueprints.


Preparations
Expand All @@ -33,7 +33,7 @@ Test it out *now* with a user-agent!
============================== ============== ================
Name Default value Description
============================== ============== ================
list routes with details GET http://127.0.0.1:5000/api/v1/routes
list routes with details GET http://127.0.0.1:5000/server-info/routes
planes with 3 or more wings GET http://127.0.0.1:5000/api/v1/planes?min_wings=3
get pilot by id GET http://127.0.0.1:5000/api/v1/pilots/1
update plane #3 PUT http://127.0.0.1:5000/api/v1/planes/3
Expand Down
3 changes: 2 additions & 1 deletion examples/full/app/api/__init__.py
Expand Up @@ -3,13 +3,14 @@
from app import factory
from app.core import journey

from .bundles import v1
from .bundles import v1, server_info


def create_app():
app = factory.create_app(__name__)

journey.attach_bundle(v1)
journey.attach_bundle(server_info)
journey.init_app(app)

return app
5 changes: 4 additions & 1 deletion examples/full/app/api/bundles.py
Expand Up @@ -6,8 +6,11 @@
from .pilots import bp as pilots
from .routes import bp as routes

server_info = BlueprintBundle(path='/server-info')
server_info.attach_bp(routes)

v1 = BlueprintBundle(path='/api/v1')
v1.attach_bp(planes, description='Planes API, CRUD')
v1.attach_bp(pilots, description='Info about pilots')
v1.attach_bp(routes)


2 changes: 1 addition & 1 deletion examples/full/app/api/pilots/views.py
Expand Up @@ -17,7 +17,7 @@ def get_one(pilot_id):


@route(bp, '/', methods=['GET'], _query=query, marshal_with=pilots, validate=False)
def get_many(_query=None):
def get_many(_query):
pilot_name = _query.data.get('name', None)
return get_pilots(pilot_name)

6 changes: 3 additions & 3 deletions examples/full/app/api/planes/views.py
Expand Up @@ -17,7 +17,7 @@ def get_one(plane_id):


@route(bp, '/<plane_id>', methods=['PUT'], _body=plane, marshal_with=plane)
def update(plane_id, _body=None):
def update(plane_id, _body):
return update_plane(plane_id, _body.data)


Expand All @@ -27,12 +27,12 @@ def delete(plane_id):


@route(bp, '/', methods=['GET'], _query=query, marshal_with=planes)
def get_many(_query=None):
def get_many(_query):
return get_planes(_query.data['min_wings'])


@route(bp, '/', methods=['POST'], _body=plane, marshal_with=plane)
def create(_body=None):
def create(_body):
return create_plane(_body.data)


2 changes: 1 addition & 1 deletion flask_journey/__init__.py
Expand Up @@ -8,7 +8,7 @@
"""

__author__ = "Robert Wikman <rbw@vault13.org>"
__version__ = "0.1.3"
__version__ = "0.1.4"

from .exceptions import (
IncompatibleBundle, InvalidPath, IncompatibleSchema,
Expand Down
5 changes: 5 additions & 0 deletions flask_journey/utils.py
Expand Up @@ -86,6 +86,11 @@ def wrapper(*inner_args, **inner_kwargs):
if body is not None:
body.strict = validate
json_data = request.get_json()

if json_data is None:
# Set json_data to empty dict if body is empty, so it gets picked up by the validator
json_data = {}

inner_kwargs['_body'] = body.load(data=json_data)

except ValidationError as err:
Expand Down
38 changes: 38 additions & 0 deletions tests/test_route.py
Expand Up @@ -36,6 +36,8 @@ def setUp(self):
self.blueprint = Blueprint('test', __name__)

def test_query_schema(self):
"""Passing a query with the required keys should work"""

app = self.app
bp = Blueprint('test', __name__)

Expand All @@ -62,6 +64,8 @@ def get_with_query(**kwargs):
self.assertEqual(data, expected_output)

def test_query_missing_required(self):
"""Required keys missing in query should cause validation to fail"""

app = self.app
bp = Blueprint('test', __name__)

Expand All @@ -81,6 +85,8 @@ def get_with_query(**kwargs):
self.assertTrue(response_has_key)

def test_body_schema(self):
"""Passing the expected body should work"""

app = self.app
bp = Blueprint('test', __name__)

Expand Down Expand Up @@ -108,6 +114,8 @@ def get_with_query(**kwargs):
self.assertEqual(data, expected_output)

def test_body_missing_required(self):
"""Validation should let the user know which keys are missing"""

app = self.app
bp = Blueprint('test', __name__)

Expand Down Expand Up @@ -135,6 +143,8 @@ def get_with_query(**kwargs):
self.assertTrue(response_has_key)

def test_without_schemas(self):
"""Not using a schema should fall back to default Blueprint.route mode"""

app = self.app
bp = Blueprint('test', __name__)

Expand All @@ -154,19 +164,47 @@ def get_with_query():

self.assertEqual(data, expected_output)

def test_empty_json_body(self):
"""Empty json body should cause validation to fail"""

app = self.app
bp = Blueprint('test', __name__)

@route(bp, '/test', methods=['POST'], _body=BodySchema(), marshal_with=OutputSchema())
def get_with_query(**kwargs):
return json.dumps({})

app.register_blueprint(bp)

response = self.client.post('/test')

data = json.loads(response.get_data(as_text=True))

response_contains_p1 = 'p1' in data
response_contains_p2 = 'p2' in data

self.assertTrue(response_contains_p1)
self.assertTrue(response_contains_p2)

def test_invalid_body_schema(self):
"""Passing an non-compatible schema in _body should raise IncompatibleSchema"""

bp = Blueprint('test', __name__)
kwargs = {'_body': dict()}

self.assertRaises(IncompatibleSchema, route, bp, '/test', **kwargs)

def test_invalid_query_schema(self):
"""Passing an non-compatible schema in _query should raise IncompatibleSchema"""

bp = Blueprint('test', __name__)
kwargs = {'_query': dict()}

self.assertRaises(IncompatibleSchema, route, bp, '/test', **kwargs)

def test_invalid_marshal_with_schema(self):
"""Passing an non-compatible schema in _marshal_with should raise IncompatibleSchema"""

bp = Blueprint('test', __name__)
kwargs = {'marshal_with': dict()}

Expand Down

0 comments on commit 0fdbdc3

Please sign in to comment.