Skip to content

Commit

Permalink
Merge pull request #915 from MasoniteFramework/master
Browse files Browse the repository at this point in the history
Next Minor
  • Loading branch information
josephmancuso authored Oct 6, 2019
2 parents d487624 + d90603c commit 6236948
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 53 deletions.
2 changes: 1 addition & 1 deletion masonite/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__title__ = 'masonite'
__description__ = 'The core for the Masonite framework'
__url__ = 'https://github.com/MasoniteFramework/masonite'
__version__ = '2.2.19'
__version__ = '2.2.20'
__author__ = 'Joseph Mancuso'
__author_email__ = 'joe@masoniteproject.com'
__licence__ = 'MIT'
18 changes: 18 additions & 0 deletions masonite/helpers/view_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,21 @@ def back(location=None):

def hidden(value, name='hidden-input'):
return Markup("<input type='hidden' name='{}' value='{}'>".format(name, value))


def old(session_key, default=''):
"""Return the old value submitted by forms validated with Valitators.
Arguments:
session_key {string} -- The key flashed to session.
Returns:
string -- An input string.
"""

from wsgi import container
session_container = container.make('Session')

if session_container.has(session_key):
return session_container.get(session_key)
return default
5 changes: 3 additions & 2 deletions masonite/providers/HelpersProvider.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import os

from masonite.exception_handler import DD
from masonite.helpers.view_helpers import back, set_request_method, hidden
from masonite.helpers.view_helpers import back, set_request_method, hidden, old
from masonite.helpers.sign import sign, unsign, decrypt, encrypt
from masonite.helpers import config, optional
from masonite.provider import ServiceProvider
Expand Down Expand Up @@ -50,6 +50,7 @@ def boot(self, view: View, request: Request):
'hidden': hidden,
'exists': view.exists,
'cookie': request.get_cookie,
'url': lambda name, params={}: request.route(name, params, full=True)
'url': lambda name, params={}: request.route(name, params, full=True),
'old': old
}
)
13 changes: 13 additions & 0 deletions masonite/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,10 @@ def redirect(self, route=None, params={}, name=None, controller=None, status=302
self.status(status)
return self

def with_input(self):
self.flash_inputs_to_session()
return self

def redirect_to(self, route_name, params={}, status=302):
"""Redirect to a named route.
Expand Down Expand Up @@ -785,6 +789,8 @@ def back(self, default=None):
Returns:
self
"""
self.with_input()

redirect_url = self.input('__back')
if not redirect_url and default:
return self.redirect(default)
Expand All @@ -793,6 +799,13 @@ def back(self, default=None):

return self.redirect(redirect_url)

def flash_inputs_to_session(self):
if not hasattr(self, 'session'):
return

for key, value in self.all().items():
self.session.flash(key, value)

def is_named_route(self, name, params={}):
"""Check if the current URI is a specific named route.
Expand Down
82 changes: 82 additions & 0 deletions masonite/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from orator.support.collection import Collection
from orator import Model
from orator import Paginator, LengthAwarePaginator
from masonite.app import App


Expand Down Expand Up @@ -37,6 +38,85 @@ def json(self, payload, status=200):

return self.data()

def paginated_json(self, paginator, status=200):
"""Determine type of paginated instance and return JSON response.
Arguments:
paginator {Paginator|LengthAwarePaginator} --
Either an Orator Paginator or LengthAwarePaginator object
Returns:
string -- Returns a string representation of the data
"""
# configured param types
page_size_parameter = 'page_size'
page_parameter = 'page'

# try to capture request input for page_size and/or page
page_size_input = self.request.input(page_size_parameter)
page_input = self.request.input(page_parameter)
# use try/except here, as int(bool) will return 0 for False above
try:
page_size = (
int(page_size_input)
if page_size_input and int(page_size_input) > 0
else paginator.per_page
)
except Exception:
page_size = paginator.per_page
try:
page = (
int(page_input)
if page_input and int(page_input) > 0
else paginator.current_page
)
except Exception:
page = paginator.current_page

# don't waste time instantiating new paginator if no change
if (
page_size != paginator.per_page
or page != paginator.current_page
):
try:
# try to get class of model
next(type(x) for x in paginator.items)
if isinstance(paginator, Paginator):
paginator = model_class.simple_paginate(
page_size,
page
)
elif isinstance(paginator, LengthAwarePaginator):
paginator = model_class.paginate(page_size, page)
except Exception:
paginator = paginator

payload = {
'total': (
paginator.total
if isinstance(paginator, LengthAwarePaginator)
else None
),
'count': paginator.count(),
'per_page': page_size,
'current_page': page,
'last_page': (
paginator.last_page
if isinstance(paginator, LengthAwarePaginator)
else None
),
'from': (page_size * (page - 1)) + 1,
'to': page_size * page,
'data': paginator.serialize()
}

# remove fields not relevant to Paginator instance
if isinstance(paginator, Paginator):
del payload['total']
del payload['last_page']

return self.json(payload, status)

def make_headers(self, content_type="text/html; charset=utf-8"):
"""Make the appropriate headers based on changes made in controllers or middleware.
Expand Down Expand Up @@ -99,6 +179,8 @@ def view(self, view, status=200):
view = view.rendered_template
elif isinstance(view, self.request.__class__):
view = self.data()
if isinstance(view, (Paginator, LengthAwarePaginator)):
return self.paginated_json(view, status=self.request.get_status())
elif view is None:
raise ResponseError('Responses cannot be of type: None.')

Expand Down
54 changes: 53 additions & 1 deletion masonite/testing/MockRoute.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ def hasController(self, controller):
def contains(self, value):
return value in self.container.make('Response')

def assertContains(self, value):
assert value in self.container.make('Response'), "Response does not contain {}".format(value)
return self

def assertNotFound(self):
return self.assertIsStatus(404)

def ok(self):
return '200 OK' in self.container.make('Request').get_status_code()

Expand All @@ -43,9 +50,38 @@ def hasJson(self, key, value=''):
return True
return Dot().dot(key, response, False)

def assertHasJson(self, key, value):
response = json.loads(self.container.make('Response'))
if isinstance(key, dict):
for item_key, key_value in key.items():
assert Dot().dot(item_key, response, False) == key_value
else:
assert Dot().dot(key, response, False) == value, "Key '{}' with the value of '{}' could not find a match in {}".format(key, value, response)
return self

def assertJsonContains(self, key, value):
response = json.loads(self.container.make('Response'))
if not isinstance(response, list):
raise ValueError("This method can only be used if the response is a list of elements.")

found = False
for element in response:
if Dot().dot(key, element, False):
assert Dot().dot(key, element, False)
found = True

if not found:
raise AssertionError("Could not find a key of: {} that had the value of {}".format(key, value))
return self

def count(self, amount):
return len(json.loads(self.container.make('Response'))) == amount

def assertCount(self, amount):
response_amount = len(json.loads(self.container.make('Response')))
assert response_amount == amount, 'Response has an count of {}. Asserted {}'.format(response_amount, amount)
return self

def amount(self, amount):
return self.count(amount)

Expand All @@ -63,13 +99,17 @@ def assertHasAmount(self, key, amount):
except TypeError:
raise TypeError("The json response key of: {} is not iterable but has the value of {}".format(key, response[key]))

return self

def assertNotHasAmount(self, key, amount):
response = json.loads(self.container.make('Response'))
try:
assert not len(response[key]) == amount, '{} is equal to {} but should not be'.format(len(response[key]), amount)
except TypeError:
raise TypeError("The json response key of: {} is not iterable but has the value of {}".format(key, response[key]))

return self

def user(self, obj):
self._user = obj
self.container.on_resolve(Request, self._bind_user_to_request)
Expand Down Expand Up @@ -111,9 +151,21 @@ def assertParameterIs(self, key, value):

def assertIsStatus(self, status):
request = self.container.make('Request')
if not request.get_status_code() == status:
assert request.is_status(status), AssertionError("{} is not equal to {}".format(request.get_status_code(), status))
if not request.is_status(status):
raise AssertionError("{} is not equal to {}".format(request.get_status_code(), status))

return self

def assertHasHeader(self, key):
pass

def assertHeaderIs(self, key, value):
request = self.container.make('Request')
assert str(request.header(key)) == str(value), AssertionError("{} is not equal to {}".format(request.header(key), value))

return self

def assertPathIs(self, url):
path = self.container.make('Request').path
assert path == url, "Asserting the path is '{}' but it is '{}'".format(url, path)
Expand Down
Loading

0 comments on commit 6236948

Please sign in to comment.