Source code for nereid.testing

# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
import inspect
import os
import unittest

from contextlib import contextmanager

import jinja2

from flask.globals import _request_ctx_stack
from secure_cookie.session import FilesystemSessionStore
from werkzeug.exceptions import abort

from trytond import backend
from trytond.exceptions import UserError
from trytond.pool import Pool
from trytond.tests.test_tryton import ModuleTestCase
from trytond.transaction import Transaction

from nereid import Nereid, current_app
from nereid.contrib.locale import Babel
from nereid.sessions import Session

from .templating import LazyRenderer

Pool.start()
DB_NAME = os.environ['DB_NAME']
DB = backend.Database(DB_NAME)
Pool.test = True
POOL = Pool(DB_NAME)


[docs]class NereidTestApp(Nereid): """ A Nereid app which works by removing transaction handling around the wsgi app """ # Setting to run specific functions defined in test cases as methods dispatch_function_as_method = False def __init__(self, **config): super(NereidTestApp, self).__init__(**config) self.config['WTF_CSRF_ENABLED'] = False @property def root_transaction(self): """ There is no need of a separate root transaction as everything could be loaded in the transaction context provided in the test case """ @contextmanager def do_nothing(): yield return do_nothing()
[docs] def load_backend(self): """ Use the global pool """ global DB, POOL self._database = DB.connect() self._pool = POOL
[docs] def dispatch_request(self): """ Skip the transaction handling and call the _dispatch_request """ req = _request_ctx_stack.top.request if req.routing_exception is not None: self.raise_routing_exception(req) rule = req.url_rule # if we provide automatic options for this URL and the # request came with the OPTIONS method, reply automatically if getattr(rule, 'provide_automatic_options', False) \ and req.method == 'OPTIONS': return self.make_default_options_response() Website = current_app.pool.get('nereid.website') website = Website.get_from_host(req.host) locale = website.get_current_locale(req) _request_ctx_stack.top.website = website.id _request_ctx_stack.top.locale = locale.id # pop locale if specified in the view_args req.view_args.pop('locale', None) active_id = req.view_args.pop('active_id', None) return self._dispatch_request(req, locale.language.code, active_id)
def _dispatch_request(self, req, language, active_id): """ Implement the nereid specific testing _dispatch """ with Transaction().set_context(language=language): # otherwise dispatch to the handler for that endpoint if req.url_rule.endpoint in self.view_functions: meth = self.view_functions[req.url_rule.endpoint] else: model, method = req.url_rule.endpoint.rsplit('.', 1) meth = getattr(Pool().get(model), method) # Provide the ability to run specific functions # in test cases as methods if not inspect.isfunction(meth) or self.dispatch_function_as_method: # static or class method result = meth(**req.view_args) else: # instance method, extract active_id from the url # arguments and pass the model instance as first argument model = Pool().get(req.url_rule.endpoint.rsplit('.', 1)[0]) i = model(active_id) try: i.rec_name except UserError: # The record may not exist anymore which results in # a read error current_app.logger.debug( "Record %s doesn't exist anymore." % i) abort(404) result = meth(i, **req.view_args) if isinstance(result, LazyRenderer): result = (str(result), result.status, result.headers) return result
def get_app(**options): app = NereidTestApp() if 'SECRET_KEY' not in options: options['SECRET_KEY'] = 'secret-key' app.config.update(options) app.config['DATABASE_NAME'] = DB_NAME app.config['DEBUG'] = True app.session_interface.session_store = \ FilesystemSessionStore('/tmp', session_class=Session) # loaders is usually lazy loaded # Pre-fetch it so that the instance attribute _loaders will exist app.jinja_loader.loaders # Initialise the app now app.initialise() # Load babel as its a required extension anyway Babel(app) return app
[docs]class NereidTestCase(unittest.TestCase): @property def _templates(self): if hasattr(self, 'templates'): return self.templates return {} def get_app(self, **options): app = get_app(**options) app.jinja_loader._loaders.insert(0, jinja2.DictLoader(self._templates)) return app
[docs]class NereidModuleTestCase(NereidTestCase, ModuleTestCase): ''' Provide a simple Mixin for usage in module tests ''' pass