2014-02-07 22:47:30 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from django.test import TestCase
|
|
|
|
|
|
|
|
from zerver.decorator import \
|
2014-02-14 19:56:55 +01:00
|
|
|
REQ, has_request_variables, RequestVariableMissingError, \
|
2014-02-07 22:47:30 +01:00
|
|
|
RequestVariableConversionError, JsonableError
|
2014-02-14 19:56:55 +01:00
|
|
|
from zerver.lib.validator import (
|
|
|
|
check_string, check_dict, check_bool, check_int, check_list
|
|
|
|
)
|
2014-02-07 22:47:30 +01:00
|
|
|
|
|
|
|
import ujson
|
|
|
|
|
|
|
|
class DecoratorTestCase(TestCase):
|
|
|
|
def test_REQ_converter(self):
|
|
|
|
|
2014-02-11 16:37:56 +01:00
|
|
|
def my_converter(data):
|
2014-02-14 19:56:55 +01:00
|
|
|
lst = ujson.loads(data)
|
|
|
|
if not isinstance(lst, list):
|
|
|
|
raise ValueError('not a list')
|
2014-02-11 16:37:56 +01:00
|
|
|
if 13 in lst:
|
|
|
|
raise JsonableError('13 is an unlucky number!')
|
|
|
|
return lst
|
|
|
|
|
2014-02-07 22:47:30 +01:00
|
|
|
@has_request_variables
|
2014-02-11 16:37:56 +01:00
|
|
|
def get_total(request, numbers=REQ(converter=my_converter)):
|
2014-02-07 22:47:30 +01:00
|
|
|
return sum(numbers)
|
|
|
|
|
|
|
|
class Request:
|
|
|
|
pass
|
|
|
|
|
|
|
|
request = Request()
|
|
|
|
request.REQUEST = {}
|
|
|
|
|
|
|
|
with self.assertRaises(RequestVariableMissingError):
|
|
|
|
get_total(request)
|
|
|
|
|
|
|
|
request.REQUEST['numbers'] = 'bad_value'
|
|
|
|
with self.assertRaises(RequestVariableConversionError) as cm:
|
|
|
|
get_total(request)
|
|
|
|
self.assertEqual(str(cm.exception), "Bad value for 'numbers': bad_value")
|
|
|
|
|
2014-02-11 16:37:56 +01:00
|
|
|
request.REQUEST['numbers'] = ujson.dumps([2,3,5,8,13,21])
|
|
|
|
with self.assertRaises(JsonableError) as cm:
|
|
|
|
get_total(request)
|
|
|
|
self.assertEqual(str(cm.exception), "13 is an unlucky number!")
|
|
|
|
|
2014-02-07 22:47:30 +01:00
|
|
|
request.REQUEST['numbers'] = ujson.dumps([1,2,3,4,5,6])
|
|
|
|
result = get_total(request)
|
|
|
|
self.assertEqual(result, 21)
|
|
|
|
|
|
|
|
def test_REQ_validator(self):
|
|
|
|
|
|
|
|
@has_request_variables
|
|
|
|
def get_total(request, numbers=REQ(validator=check_list(check_int))):
|
|
|
|
return sum(numbers)
|
|
|
|
|
|
|
|
class Request:
|
|
|
|
pass
|
|
|
|
|
|
|
|
request = Request()
|
|
|
|
request.REQUEST = {}
|
|
|
|
|
|
|
|
with self.assertRaises(RequestVariableMissingError):
|
|
|
|
get_total(request)
|
|
|
|
|
|
|
|
request.REQUEST['numbers'] = 'bad_value'
|
|
|
|
with self.assertRaises(JsonableError) as cm:
|
|
|
|
get_total(request)
|
|
|
|
self.assertEqual(str(cm.exception), 'argument "numbers" is not valid json.')
|
|
|
|
|
|
|
|
request.REQUEST['numbers'] = ujson.dumps([1,2,"what?",4,5,6])
|
|
|
|
with self.assertRaises(JsonableError) as cm:
|
|
|
|
get_total(request)
|
|
|
|
self.assertEqual(str(cm.exception), 'numbers[2] is not an integer')
|
|
|
|
|
|
|
|
request.REQUEST['numbers'] = ujson.dumps([1,2,3,4,5,6])
|
|
|
|
result = get_total(request)
|
|
|
|
self.assertEqual(result, 21)
|
|
|
|
|
|
|
|
class ValidatorTestCase(TestCase):
|
|
|
|
def test_check_string(self):
|
|
|
|
x = "hello"
|
|
|
|
self.assertEqual(check_string('x', x), None)
|
|
|
|
|
|
|
|
x = 4
|
|
|
|
self.assertEqual(check_string('x', x), 'x is not a string')
|
|
|
|
|
|
|
|
def test_check_bool(self):
|
|
|
|
x = True
|
|
|
|
self.assertEqual(check_bool('x', x), None)
|
|
|
|
|
|
|
|
x = 4
|
|
|
|
self.assertEqual(check_bool('x', x), 'x is not a boolean')
|
|
|
|
|
|
|
|
def test_check_int(self):
|
|
|
|
x = 5
|
|
|
|
self.assertEqual(check_int('x', x), None)
|
|
|
|
|
|
|
|
x = [{}]
|
|
|
|
self.assertEqual(check_int('x', x), 'x is not an integer')
|
|
|
|
|
|
|
|
def test_check_list(self):
|
|
|
|
x = 999
|
|
|
|
error = check_list(check_string)('x', x)
|
|
|
|
self.assertEqual(error, 'x is not a list')
|
|
|
|
|
|
|
|
x = ["hello", 5]
|
|
|
|
error = check_list(check_string)('x', x)
|
|
|
|
self.assertEqual(error, 'x[1] is not a string')
|
|
|
|
|
|
|
|
x = [["yo"], ["hello", "goodbye", 5]]
|
|
|
|
error = check_list(check_list(check_string))('x', x)
|
|
|
|
self.assertEqual(error, 'x[1][2] is not a string')
|
|
|
|
|
|
|
|
x = ["hello", "goodbye", "hello again"]
|
|
|
|
error = check_list(check_string, length=2)('x', x)
|
|
|
|
self.assertEqual(error, 'x should have exactly 2 items')
|
|
|
|
|
|
|
|
def test_check_dict(self):
|
|
|
|
keys = [
|
|
|
|
('names', check_list(check_string)),
|
|
|
|
('city', check_string),
|
|
|
|
]
|
|
|
|
|
|
|
|
x = {
|
|
|
|
'names': ['alice', 'bob'],
|
|
|
|
'city': 'Boston',
|
|
|
|
}
|
|
|
|
error = check_dict(keys)('x', x)
|
|
|
|
self.assertEqual(error, None)
|
|
|
|
|
|
|
|
x = 999
|
|
|
|
error = check_dict(keys)('x', x)
|
|
|
|
self.assertEqual(error, 'x is not a dict')
|
|
|
|
|
|
|
|
x = {}
|
|
|
|
error = check_dict(keys)('x', x)
|
|
|
|
self.assertEqual(error, 'names key is missing from x')
|
|
|
|
|
|
|
|
x = {
|
|
|
|
'names': ['alice', 'bob', {}]
|
|
|
|
}
|
|
|
|
error = check_dict(keys)('x', x)
|
|
|
|
self.assertEqual(error, 'x["names"][2] is not a string')
|
|
|
|
|
|
|
|
x = {
|
|
|
|
'names': ['alice', 'bob'],
|
|
|
|
'city': 5
|
|
|
|
}
|
|
|
|
error = check_dict(keys)('x', x)
|
|
|
|
self.assertEqual(error, 'x["city"] is not a string')
|
|
|
|
|
|
|
|
def test_encapsulation(self):
|
|
|
|
# There might be situations where we want deep
|
|
|
|
# validation, but the error message should be customized.
|
|
|
|
# This is an example.
|
|
|
|
def check_person(val):
|
|
|
|
error = check_dict([
|
|
|
|
['name', check_string],
|
|
|
|
['age', check_int],
|
|
|
|
])('_', val)
|
|
|
|
if error:
|
|
|
|
return 'This is not a valid person'
|
|
|
|
|
|
|
|
person = {'name': 'King Lear', 'age': 42}
|
|
|
|
self.assertEqual(check_person(person), None)
|
|
|
|
|
|
|
|
person = 'misconfigured data'
|
|
|
|
self.assertEqual(check_person(person), 'This is not a valid person')
|
|
|
|
|