Added unittests for caching of file links.
Also converted test_auth.py to use the new AbstractPillarTest class. This class ensures that we test against the testing database, which is dropped at every setUp()/tearDown().
This commit is contained in:
parent
cb4b0f1e4d
commit
adb4f5b39e
82
tests/common_test_stuff.py
Normal file
82
tests/common_test_stuff.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import json
|
||||||
|
import copy
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from eve.tests import TestMinimal
|
||||||
|
import pymongo.collection
|
||||||
|
from flask.testing import FlaskClient
|
||||||
|
import httpretty
|
||||||
|
|
||||||
|
from test_data import EXAMPLE_PROJECT, EXAMPLE_FILE
|
||||||
|
|
||||||
|
BLENDER_ID_ENDPOINT = 'http://127.0.0.1:8001' # nonexistant server, no trailing slash!
|
||||||
|
MY_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
TEST_EMAIL_USER = 'koro'
|
||||||
|
TEST_EMAIL_ADDRESS = '%s@testing.blender.org' % TEST_EMAIL_USER
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG,
|
||||||
|
format='%(asctime)-15s %(levelname)8s %(name)s %(message)s')
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractPillarTest(TestMinimal):
|
||||||
|
def setUp(self, **kwargs):
|
||||||
|
settings_file = os.path.join(MY_PATH, 'test_settings.py')
|
||||||
|
kwargs['settings_file'] = settings_file
|
||||||
|
os.environ['EVE_SETTINGS'] = settings_file
|
||||||
|
super(AbstractPillarTest, self).setUp(**kwargs)
|
||||||
|
|
||||||
|
from application import app
|
||||||
|
|
||||||
|
app.config['BLENDER_ID_ENDPOINT'] = BLENDER_ID_ENDPOINT
|
||||||
|
logging.getLogger('application').setLevel(logging.DEBUG)
|
||||||
|
logging.getLogger('werkzeug').setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
self.app = app
|
||||||
|
self.client = app.test_client()
|
||||||
|
assert isinstance(self.client, FlaskClient)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(AbstractPillarTest, self).tearDown()
|
||||||
|
|
||||||
|
# Not only delete self.app (like the superclass does),
|
||||||
|
# but also un-import the application.
|
||||||
|
del sys.modules['application']
|
||||||
|
|
||||||
|
def _ensure_file_exists(self, file_overrides=None):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
files_collection = self.app.data.driver.db['files']
|
||||||
|
projects_collection = self.app.data.driver.db['projects']
|
||||||
|
assert isinstance(files_collection, pymongo.collection.Collection)
|
||||||
|
|
||||||
|
file = copy.deepcopy(EXAMPLE_FILE)
|
||||||
|
if file_overrides is not None:
|
||||||
|
file.update(file_overrides)
|
||||||
|
|
||||||
|
projects_collection.insert_one(EXAMPLE_PROJECT)
|
||||||
|
result = files_collection.insert_one(file)
|
||||||
|
file_id = result.inserted_id
|
||||||
|
return file_id, EXAMPLE_FILE
|
||||||
|
|
||||||
|
def htp_blenderid_validate_unhappy(self):
|
||||||
|
"""Sets up HTTPretty to mock unhappy validation flow."""
|
||||||
|
|
||||||
|
httpretty.register_uri(httpretty.POST,
|
||||||
|
'%s/u/validate_token' % BLENDER_ID_ENDPOINT,
|
||||||
|
body=json.dumps(
|
||||||
|
{'data': {'token': 'Token is invalid'}, 'status': 'fail'}),
|
||||||
|
content_type="application/json")
|
||||||
|
|
||||||
|
def htp_blenderid_validate_happy(self):
|
||||||
|
"""Sets up HTTPretty to mock happy validation flow."""
|
||||||
|
|
||||||
|
httpretty.register_uri(httpretty.POST,
|
||||||
|
'%s/u/validate_token' % BLENDER_ID_ENDPOINT,
|
||||||
|
body=json.dumps(
|
||||||
|
{'data': {'user': {'email': TEST_EMAIL_ADDRESS, 'id': 5123}},
|
||||||
|
'status': 'success'}),
|
||||||
|
content_type="application/json")
|
||||||
|
|
@ -1,23 +1,7 @@
|
|||||||
import unittest
|
|
||||||
import os
|
|
||||||
import base64
|
import base64
|
||||||
import httpretty
|
import httpretty
|
||||||
import json
|
|
||||||
|
|
||||||
BLENDER_ID_ENDPOINT = 'http://127.0.0.1:8001' # nonexistant server, no trailing slash!
|
from common_test_stuff import AbstractPillarTest, TEST_EMAIL_USER, TEST_EMAIL_ADDRESS
|
||||||
TEST_EMAIL_USER = 'koro'
|
|
||||||
TEST_EMAIL_ADDRESS = '%s@testing.blender.org' % TEST_EMAIL_USER
|
|
||||||
|
|
||||||
os.environ['BLENDER_ID_ENDPOINT'] = BLENDER_ID_ENDPOINT
|
|
||||||
os.environ['MONGO_DBNAME'] = 'unittest'
|
|
||||||
os.environ['EVE_SETTINGS'] = os.path.join(
|
|
||||||
os.path.dirname(os.path.dirname(__file__)),
|
|
||||||
'pillar', 'settings.py')
|
|
||||||
|
|
||||||
from application import app
|
|
||||||
from application.utils import authentication as auth
|
|
||||||
|
|
||||||
app.config['BLENDER_ID_ENDPOINT'] = BLENDER_ID_ENDPOINT
|
|
||||||
|
|
||||||
|
|
||||||
def make_header(username, password=''):
|
def make_header(username, password=''):
|
||||||
@ -26,19 +10,11 @@ def make_header(username, password=''):
|
|||||||
return 'basic ' + base64.b64encode('%s:%s' % (username, password))
|
return 'basic ' + base64.b64encode('%s:%s' % (username, password))
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationTests(unittest.TestCase):
|
class AuthenticationTests(AbstractPillarTest):
|
||||||
def setUp(self):
|
|
||||||
self.app = app.test_client()
|
|
||||||
with app.test_request_context():
|
|
||||||
self.delete_test_data()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
with app.test_request_context():
|
|
||||||
self.delete_test_data()
|
|
||||||
|
|
||||||
def test_make_unique_username(self):
|
def test_make_unique_username(self):
|
||||||
|
from application.utils import authentication as auth
|
||||||
|
|
||||||
with app.test_request_context():
|
with self.app.test_request_context():
|
||||||
# This user shouldn't exist yet.
|
# This user shouldn't exist yet.
|
||||||
self.assertEqual(TEST_EMAIL_USER, auth.make_unique_username(TEST_EMAIL_ADDRESS))
|
self.assertEqual(TEST_EMAIL_USER, auth.make_unique_username(TEST_EMAIL_ADDRESS))
|
||||||
|
|
||||||
@ -46,44 +22,29 @@ class AuthenticationTests(unittest.TestCase):
|
|||||||
auth.create_new_user(TEST_EMAIL_ADDRESS, TEST_EMAIL_USER, 'test1234')
|
auth.create_new_user(TEST_EMAIL_ADDRESS, TEST_EMAIL_USER, 'test1234')
|
||||||
self.assertEqual('%s1' % TEST_EMAIL_USER, auth.make_unique_username(TEST_EMAIL_ADDRESS))
|
self.assertEqual('%s1' % TEST_EMAIL_USER, auth.make_unique_username(TEST_EMAIL_ADDRESS))
|
||||||
|
|
||||||
def delete_test_data(self):
|
|
||||||
app.data.driver.db.drop_collection('users')
|
|
||||||
app.data.driver.db.drop_collection('tokens')
|
|
||||||
|
|
||||||
def blenderid_validate_unhappy(self):
|
|
||||||
"""Sets up HTTPretty to mock unhappy validation flow."""
|
|
||||||
|
|
||||||
httpretty.register_uri(httpretty.POST,
|
|
||||||
'%s/u/validate_token' % BLENDER_ID_ENDPOINT,
|
|
||||||
body=json.dumps({'data': {'token': 'Token is invalid'}, 'status': 'fail'}),
|
|
||||||
content_type="application/json")
|
|
||||||
|
|
||||||
def blenderid_validate_happy(self):
|
|
||||||
"""Sets up HTTPretty to mock happy validation flow."""
|
|
||||||
|
|
||||||
httpretty.register_uri(httpretty.POST,
|
|
||||||
'%s/u/validate_token' % BLENDER_ID_ENDPOINT,
|
|
||||||
body=json.dumps({'data': {'user': {'email': TEST_EMAIL_ADDRESS, 'id': 5123}},
|
|
||||||
'status': 'success'}),
|
|
||||||
content_type="application/json")
|
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_validate_token__not_logged_in(self):
|
def test_validate_token__not_logged_in(self):
|
||||||
with app.test_request_context():
|
from application.utils import authentication as auth
|
||||||
|
|
||||||
|
with self.app.test_request_context():
|
||||||
self.assertFalse(auth.validate_token())
|
self.assertFalse(auth.validate_token())
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_validate_token__unknown_token(self):
|
def test_validate_token__unknown_token(self):
|
||||||
"""Test validating of invalid token, unknown both to us and Blender ID."""
|
"""Test validating of invalid token, unknown both to us and Blender ID."""
|
||||||
|
|
||||||
self.blenderid_validate_unhappy()
|
from application.utils import authentication as auth
|
||||||
with app.test_request_context(headers={'Authorization': make_header('unknowntoken')}):
|
|
||||||
|
self.htp_blenderid_validate_unhappy()
|
||||||
|
with self.app.test_request_context(headers={'Authorization': make_header('unknowntoken')}):
|
||||||
self.assertFalse(auth.validate_token())
|
self.assertFalse(auth.validate_token())
|
||||||
|
|
||||||
@httpretty.activate
|
@httpretty.activate
|
||||||
def test_validate_token__unknown_but_valid_token(self):
|
def test_validate_token__unknown_but_valid_token(self):
|
||||||
"""Test validating of valid token, unknown to us but known to Blender ID."""
|
"""Test validating of valid token, unknown to us but known to Blender ID."""
|
||||||
|
|
||||||
self.blenderid_validate_happy()
|
from application.utils import authentication as auth
|
||||||
with app.test_request_context(headers={'Authorization': make_header('knowntoken')}):
|
|
||||||
|
self.htp_blenderid_validate_happy()
|
||||||
|
with self.app.test_request_context(headers={'Authorization': make_header('knowntoken')}):
|
||||||
self.assertTrue(auth.validate_token())
|
self.assertTrue(auth.validate_token())
|
||||||
|
282
tests/test_data.py
Normal file
282
tests/test_data.py
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from bson import tz_util, ObjectId
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLE_FILE = {u'_id': ObjectId('5672e2c1c379cf0007b31995'),
|
||||||
|
u'_updated': datetime.datetime(2016, 3, 25, 10, 28, 24, tzinfo=tz_util.utc),
|
||||||
|
u'height': 2048,
|
||||||
|
u'name': 'c2a5c897769ce1ef0eb10f8fa1c472bcb8e2d5a4.png', u'format': 'png',
|
||||||
|
u'variations': [
|
||||||
|
{u'format': 'jpg', u'height': 160, u'width': 160, u'length': 8558,
|
||||||
|
u'link': 'http://localhost:8002/file-variant-h', u'content_type': 'image/jpeg',
|
||||||
|
u'md5': '--', u'file_path': 'c2a5c897769ce1ef0eb10f8fa1c472bcb8e2d5a4-b.jpg',
|
||||||
|
u'size': 'b'},
|
||||||
|
{u'format': 'jpg', u'height': 2048, u'width': 2048, u'length': 819569,
|
||||||
|
u'link': 'http://localhost:8002/file-variant-h', u'content_type': 'image/jpeg',
|
||||||
|
u'md5': '--', u'file_path': 'c2a5c897769ce1ef0eb10f8fa1c472bcb8e2d5a4-h.jpg',
|
||||||
|
u'size': 'h'}, ],
|
||||||
|
u'filename': 'brick_dutch_soft_bump.png',
|
||||||
|
u'project': ObjectId('5672beecc0261b2005ed1a33'),
|
||||||
|
u'width': 2048, u'length': 6227670, u'user': ObjectId('56264fc4fa3a250344bd10c5'),
|
||||||
|
u'content_type': 'image/png', u'_etag': '044ce3aede2e123e261c0d8bd77212f264d4f7b0',
|
||||||
|
u'_created': datetime.datetime(2015, 12, 17, 16, 28, 49, tzinfo=tz_util.utc),
|
||||||
|
u'md5': '',
|
||||||
|
u'file_path': 'c2a5c897769ce1ef0eb10f8fa1c472bcb8e2d5a4.png', u'backend': 'gcs',
|
||||||
|
u'link': 'http://localhost:8002/file',
|
||||||
|
u'link_expires': datetime.datetime(2016, 3, 22, 9, 28, 22, tzinfo=tz_util.utc)}
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLE_PROJECT = {
|
||||||
|
u'_created': datetime.datetime(2015, 12, 17, 13, 22, 56, tzinfo=tz_util.utc),
|
||||||
|
u'_etag': u'cc4643e98d3606f87bbfaaa200bfbae941b642f3',
|
||||||
|
u'_id': ObjectId('5672beecc0261b2005ed1a33'),
|
||||||
|
u'_updated': datetime.datetime(2016, 1, 7, 18, 59, 4, tzinfo=tz_util.utc),
|
||||||
|
u'category': u'assets',
|
||||||
|
u'description': u'Welcome to this curated collection of Blender Institute textures and image resources. This collection is an on-going project, as with each project we create a number of textures based on our own resources (photographs, scans, etc.) or made completely from scratch. At the moment you can find all the textures from the past Open Projects that were deemed re-usable. \r\n\r\nPeople who have contributed to these textures:\r\n\r\nAndrea Weikert, Andy Goralczyk, Basse Salmela, Ben Dansie, Campbell Barton, Enrico Valenza, Ian Hubert, Kjartan Tysdal, Manu J\xe4rvinen, Massimiliana Pulieso, Matt Ebb, Pablo Vazquez, Rob Tuytel, Roland Hess, Sarah Feldlaufer, S\xf6nke M\xe4ter',
|
||||||
|
u'is_private': False,
|
||||||
|
u'name': u'Textures',
|
||||||
|
u'node_types': [{u'description': u'Group for texture node type',
|
||||||
|
u'dyn_schema': {u'order': {u'type': u'integer'},
|
||||||
|
u'status': {u'allowed': [u'published', u'pending', u'deleted'],
|
||||||
|
u'type': u'string'},
|
||||||
|
u'url': {u'type': u'string'}},
|
||||||
|
u'form_schema': {u'order': {}, u'status': {}, u'url': {}},
|
||||||
|
u'name': u'group_texture',
|
||||||
|
u'parent': [u'group_texture', u'project'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']},
|
||||||
|
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||||
|
u'methods': [u'GET']},
|
||||||
|
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||||
|
u'methods': [u'GET']},
|
||||||
|
{u'group': ObjectId('564c52b96dcaf85da2faef00'),
|
||||||
|
u'methods': [u'GET', u'POST']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']}},
|
||||||
|
{u'description': u'Generic group node type edited',
|
||||||
|
u'dyn_schema': {u'notes': {u'maxlength': 256, u'type': u'string'},
|
||||||
|
u'order': {u'type': u'integer'},
|
||||||
|
u'status': {u'allowed': [u'published', u'pending', u'deleted'],
|
||||||
|
u'type': u'string'},
|
||||||
|
u'url': {u'type': u'string'}},
|
||||||
|
u'form_schema': {u'notes': {}, u'order': {}, u'status': {}, u'url': {}},
|
||||||
|
u'name': u'group',
|
||||||
|
u'parent': [u'group', u'project'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']},
|
||||||
|
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||||
|
u'methods': [u'GET']},
|
||||||
|
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||||
|
u'methods': [u'GET']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']}},
|
||||||
|
{u'description': u'Basic Asset Type',
|
||||||
|
u'dyn_schema': {
|
||||||
|
u'attachments': {u'schema': {u'schema': {u'field': {u'type': u'string'},
|
||||||
|
u'files': {u'schema': {
|
||||||
|
u'schema': {u'file': {
|
||||||
|
u'data_relation': {
|
||||||
|
u'embeddable': True,
|
||||||
|
u'field': u'_id',
|
||||||
|
u'resource': u'files'},
|
||||||
|
u'type': u'objectid'},
|
||||||
|
u'size': {
|
||||||
|
u'type': u'string'},
|
||||||
|
u'slug': {
|
||||||
|
u'minlength': 1,
|
||||||
|
u'type': u'string'}},
|
||||||
|
u'type': u'dict'},
|
||||||
|
u'type': u'list'}},
|
||||||
|
u'type': u'dict'},
|
||||||
|
u'type': u'list'},
|
||||||
|
u'categories': {u'type': u'string'},
|
||||||
|
u'content_type': {u'type': u'string'},
|
||||||
|
u'file': {u'data_relation': {u'embeddable': True,
|
||||||
|
u'field': u'_id',
|
||||||
|
u'resource': u'files'},
|
||||||
|
u'type': u'objectid'},
|
||||||
|
u'order': {u'type': u'integer'},
|
||||||
|
u'status': {u'allowed': [u'published',
|
||||||
|
u'pending',
|
||||||
|
u'processing',
|
||||||
|
u'deleted'],
|
||||||
|
u'type': u'string'},
|
||||||
|
u'tags': {u'schema': {u'type': u'string'}, u'type': u'list'}},
|
||||||
|
u'form_schema': {u'attachments': {u'visible': False},
|
||||||
|
u'categories': {},
|
||||||
|
u'content_type': {u'visible': False},
|
||||||
|
u'file': {u'visible': False},
|
||||||
|
u'order': {},
|
||||||
|
u'status': {},
|
||||||
|
u'tags': {}},
|
||||||
|
u'name': u'asset',
|
||||||
|
u'parent': [u'group'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']},
|
||||||
|
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||||
|
u'methods': [u'GET']},
|
||||||
|
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||||
|
u'methods': [u'GET']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']}},
|
||||||
|
{u'description': u'Entrypoint to a remote or local storage solution',
|
||||||
|
u'dyn_schema': {u'backend': {u'type': u'string'},
|
||||||
|
u'subdir': {u'type': u'string'}},
|
||||||
|
u'form_schema': {u'backend': {}, u'subdir': {}},
|
||||||
|
u'name': u'storage',
|
||||||
|
u'parent': [u'group', u'project'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']},
|
||||||
|
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||||
|
u'methods': [u'GET']},
|
||||||
|
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||||
|
u'methods': [u'GET']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': []}},
|
||||||
|
{u'description': u'Comments for asset nodes, pages, etc.',
|
||||||
|
u'dyn_schema': {u'confidence': {u'type': u'float'},
|
||||||
|
u'content': {u'minlength': 5, u'type': u'string'},
|
||||||
|
u'is_reply': {u'type': u'boolean'},
|
||||||
|
u'rating_negative': {u'type': u'integer'},
|
||||||
|
u'rating_positive': {u'type': u'integer'},
|
||||||
|
u'ratings': {u'schema': {
|
||||||
|
u'schema': {u'is_positive': {u'type': u'boolean'},
|
||||||
|
u'user': {u'type': u'objectid'},
|
||||||
|
u'weight': {u'type': u'integer'}},
|
||||||
|
u'type': u'dict'},
|
||||||
|
u'type': u'list'},
|
||||||
|
u'status': {u'allowed': [u'published', u'deleted', u'flagged',
|
||||||
|
u'edited'],
|
||||||
|
u'type': u'string'}},
|
||||||
|
u'form_schema': {u'confidence': {},
|
||||||
|
u'content': {},
|
||||||
|
u'is_reply': {},
|
||||||
|
u'rating_negative': {},
|
||||||
|
u'rating_positive': {},
|
||||||
|
u'ratings': {},
|
||||||
|
u'status': {}},
|
||||||
|
u'name': u'comment',
|
||||||
|
u'parent': [u'asset', u'comment'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']},
|
||||||
|
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||||
|
u'methods': [u'GET', u'POST']},
|
||||||
|
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||||
|
u'methods': [u'GET', u'POST']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']}},
|
||||||
|
{u'description': u'Container for node_type post.',
|
||||||
|
u'dyn_schema': {u'categories': {u'schema': {u'type': u'string'},
|
||||||
|
u'type': u'list'},
|
||||||
|
u'template': {u'type': u'string'}},
|
||||||
|
u'form_schema': {u'categories': {}, u'template': {}},
|
||||||
|
u'name': u'blog',
|
||||||
|
u'parent': [u'project'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']}},
|
||||||
|
{u'description': u'A blog post, for any project',
|
||||||
|
u'dyn_schema': {
|
||||||
|
u'attachments': {u'schema': {u'schema': {u'field': {u'type': u'string'},
|
||||||
|
u'files': {u'schema': {
|
||||||
|
u'schema': {u'file': {
|
||||||
|
u'data_relation': {
|
||||||
|
u'embeddable': True,
|
||||||
|
u'field': u'_id',
|
||||||
|
u'resource': u'files'},
|
||||||
|
u'type': u'objectid'},
|
||||||
|
u'size': {
|
||||||
|
u'type': u'string'},
|
||||||
|
u'slug': {
|
||||||
|
u'minlength': 1,
|
||||||
|
u'type': u'string'}},
|
||||||
|
u'type': u'dict'},
|
||||||
|
u'type': u'list'}},
|
||||||
|
u'type': u'dict'},
|
||||||
|
u'type': u'list'},
|
||||||
|
u'category': {u'type': u'string'},
|
||||||
|
u'content': {u'maxlength': 90000,
|
||||||
|
u'minlength': 5,
|
||||||
|
u'required': True,
|
||||||
|
u'type': u'string'},
|
||||||
|
u'status': {u'allowed': [u'published', u'deleted', u'pending'],
|
||||||
|
u'default': u'pending',
|
||||||
|
u'type': u'string'},
|
||||||
|
u'url': {u'type': u'string'}},
|
||||||
|
u'form_schema': {u'attachments': {u'visible': False},
|
||||||
|
u'category': {},
|
||||||
|
u'content': {},
|
||||||
|
u'status': {},
|
||||||
|
u'url': {}},
|
||||||
|
u'name': u'post',
|
||||||
|
u'parent': [u'blog'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']}},
|
||||||
|
{u'description': u'Image Texture',
|
||||||
|
u'dyn_schema': {u'aspect_ratio': {u'type': u'float'},
|
||||||
|
u'categories': {u'type': u'string'},
|
||||||
|
u'files': {u'schema': {u'schema': {
|
||||||
|
u'file': {u'data_relation': {u'embeddable': True,
|
||||||
|
u'field': u'_id',
|
||||||
|
u'resource': u'files'},
|
||||||
|
u'type': u'objectid'},
|
||||||
|
u'is_tileable': {u'type': u'boolean'},
|
||||||
|
u'map_type': {u'allowed': [u'spec',
|
||||||
|
u'bump',
|
||||||
|
u'nor',
|
||||||
|
u'col',
|
||||||
|
u'translucency',
|
||||||
|
u'emission',
|
||||||
|
u'alpha'],
|
||||||
|
u'type': u'string'}},
|
||||||
|
u'type': u'dict'},
|
||||||
|
u'type': u'list'},
|
||||||
|
u'is_landscape': {u'type': u'boolean'},
|
||||||
|
u'is_tileable': {u'type': u'boolean'},
|
||||||
|
u'order': {u'type': u'integer'},
|
||||||
|
u'resolution': {u'type': u'string'},
|
||||||
|
u'status': {u'allowed': [u'published',
|
||||||
|
u'pending',
|
||||||
|
u'processing',
|
||||||
|
u'deleted'],
|
||||||
|
u'type': u'string'},
|
||||||
|
u'tags': {u'schema': {u'type': u'string'}, u'type': u'list'}},
|
||||||
|
u'form_schema': {u'aspect_ratio': {},
|
||||||
|
u'categories': {},
|
||||||
|
u'content_type': {u'visible': False},
|
||||||
|
u'files': {u'visible': False},
|
||||||
|
u'is_landscape': {},
|
||||||
|
u'is_tileable': {},
|
||||||
|
u'order': {},
|
||||||
|
u'resolution': {},
|
||||||
|
u'status': {},
|
||||||
|
u'tags': {}},
|
||||||
|
u'name': u'texture',
|
||||||
|
u'parent': [u'group'],
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']},
|
||||||
|
{u'group': ObjectId('5596e975ea893b269af85c0f'),
|
||||||
|
u'methods': [u'GET']},
|
||||||
|
{u'group': ObjectId('564733b56dcaf85da2faee8a'),
|
||||||
|
u'methods': [u'GET']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']}}],
|
||||||
|
u'nodes_blog': [],
|
||||||
|
u'nodes_featured': [],
|
||||||
|
u'nodes_latest': [],
|
||||||
|
u'organization': ObjectId('55a99fb43004867fb9934f01'),
|
||||||
|
u'owners': {u'groups': [], u'users': []},
|
||||||
|
u'permissions': {u'groups': [{u'group': ObjectId('5596e975ea893b269af85c0e'),
|
||||||
|
u'methods': [u'GET', u'PUT', u'POST']}],
|
||||||
|
u'users': [],
|
||||||
|
u'world': [u'GET']},
|
||||||
|
u'picture_header': ObjectId('5673f260c379cf0007b31bc4'),
|
||||||
|
u'picture_square': ObjectId('5673f256c379cf0007b31bc3'),
|
||||||
|
u'status': u'published',
|
||||||
|
u'summary': u'Texture collection from all Blender Institute open projects.',
|
||||||
|
u'url': u'textures',
|
||||||
|
u'user': ObjectId('552b066b41acdf5dec4436f2')}
|
58
tests/test_file_caching.py
Normal file
58
tests/test_file_caching.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
"""Test cases for the /files/{id} entrypoint, testing cache behaviour."""
|
||||||
|
|
||||||
|
import bson.tz_util
|
||||||
|
import datetime
|
||||||
|
from eve import RFC1123_DATE_FORMAT
|
||||||
|
|
||||||
|
from common_test_stuff import AbstractPillarTest
|
||||||
|
|
||||||
|
|
||||||
|
class FileCachingTest(AbstractPillarTest):
|
||||||
|
|
||||||
|
def test_nonexistant_file(self):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
resp = self.client.get('/files/12345')
|
||||||
|
self.assertEqual(404, resp.status_code)
|
||||||
|
|
||||||
|
def test_existing_file(self):
|
||||||
|
file_id, _ = self._ensure_file_exists()
|
||||||
|
|
||||||
|
resp = self.client.get('/files/%s' % file_id)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
|
def test_if_modified_304(self):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
# Make sure the file link has not expired.
|
||||||
|
expires = datetime.datetime.now(tz=bson.tz_util.utc) + datetime.timedelta(minutes=1)
|
||||||
|
file_id, file_doc = self._ensure_file_exists(file_overrides={
|
||||||
|
u'link_expires': expires
|
||||||
|
})
|
||||||
|
|
||||||
|
updated = file_doc['_updated'].strftime(RFC1123_DATE_FORMAT)
|
||||||
|
resp = self.client.get('/files/%s' % file_id,
|
||||||
|
headers={'if_modified_since': updated})
|
||||||
|
self.assertEqual(304, resp.status_code)
|
||||||
|
|
||||||
|
def test_if_modified_200(self):
|
||||||
|
file_id, file_doc = self._ensure_file_exists()
|
||||||
|
|
||||||
|
delta = datetime.timedelta(days=-1)
|
||||||
|
|
||||||
|
with self.app.test_request_context():
|
||||||
|
updated = (file_doc['_updated'] + delta).strftime(RFC1123_DATE_FORMAT)
|
||||||
|
resp = self.client.get('/files/%s' % file_id,
|
||||||
|
headers={'if_modified_since': updated})
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
|
def test_if_modified_link_expired(self):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
# Make sure the file link has expired.
|
||||||
|
expires = datetime.datetime.now(tz=bson.tz_util.utc) - datetime.timedelta(seconds=1)
|
||||||
|
file_id, file_doc = self._ensure_file_exists(file_overrides={
|
||||||
|
u'link_expires': expires
|
||||||
|
})
|
||||||
|
|
||||||
|
updated = file_doc['_updated'].strftime(RFC1123_DATE_FORMAT)
|
||||||
|
resp = self.client.get('/files/%s' % file_id,
|
||||||
|
headers={'if_modified_since': updated})
|
||||||
|
self.assertEqual(200, resp.status_code)
|
3
tests/test_settings.py
Normal file
3
tests/test_settings.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from settings import *
|
||||||
|
|
||||||
|
from eve.tests.test_settings import MONGO_DBNAME
|
Loading…
x
Reference in New Issue
Block a user