summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRomain Derie <rde@odoo.com>2019-06-26 13:48:56 +0000
committerRomain Derie <rde@odoo.com>2019-06-26 17:08:09 +0000
commit6ebcb1db80eeb37ab7ac2f5a27a8c616f12b95b3 (patch)
treee5b099e61983f969a205d593cdd31b557306b722
parentbb81e4ccd7b0044bbe1ad45842a3f799ceac0838 (diff)
[IMP] tool, website, website_sale: move test utils functions
We have multiple ways of simulating a frontend context while running python tests (mainly during TransactionCase): - `MockObject` class from 8557bcfa30 - `simulate_frontend_context` method from a5a5a57e48 - `DotDict` from f8efc9a957c28 This commit moves `MockObject` to misc to be reusable and adapt it to be accessible by dot notation with `DotDict`. Part of #34396
-rw-r--r--addons/website/tests/test_qweb.py53
-rw-r--r--addons/website/tools.py60
-rw-r--r--addons/website_sale/tests/test_website_sale_pricelist.py8
-rw-r--r--odoo/tools/misc.py11
4 files changed, 80 insertions, 52 deletions
diff --git a/addons/website/tests/test_qweb.py b/addons/website/tests/test_qweb.py
index 8cba2d150c0..b752d641f40 100644
--- a/addons/website/tests/test_qweb.py
+++ b/addons/website/tests/test_qweb.py
@@ -2,10 +2,9 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import re
-import werkzeug
-import odoo
from odoo import tools
+from odoo.addons.website.tools import MockRequest
from odoo.modules.module import get_module_resource
from odoo.tests.common import TransactionCase
@@ -66,42 +65,6 @@ class TestQweb(TransactionCase):
"user_id": demo.id,
}).encode('utf8'))
-class MockObject(object):
- _log_call = []
- def __init__(self, *args, **kwargs):
- self.__dict__ = kwargs
- def __call__(self, *args, **kwargs):
- self._log_call.append((args, kwargs))
- return self
- def __getitem__(self, index):
- return self
-
-def werkzeugRaiseNotFound(*args, **kwargs):
- raise werkzeug.exceptions.NotFound()
-
-class MockRequest(object):
- """ Class with context manager mocking odoo.http.request for tests """
- def __init__(self, env, website=None, context=None, multilang=True, routing=True):
- app = MockObject(routing={
- 'type': 'http',
- 'website': True,
- 'multilang': multilang,
- })
- app.get_db_router = app.bind = app.match = app
- if not routing:
- app.match = werkzeugRaiseNotFound
- self.request = MockObject(
- env=env, context=context or {}, db=None, debug=False,
- website=website, httprequest=MockObject(
- path='/hello/',
- app=app
- )
- )
- odoo.http._request_stack.push(self.request)
- def __enter__(self):
- return self.request
- def __exit__(self, exc_type, exc_value, traceback):
- odoo.http._request_stack.pop()
class TestQwebProcessAtt(TransactionCase):
def setUp(self):
@@ -128,7 +91,7 @@ class TestQwebProcessAtt(TransactionCase):
self._test_att('/a', {'href': '/a'})
def test_process_att_no_website(self):
- with MockRequest(self.env) as request:
+ with MockRequest(self.env):
# no website so URL rewriting
self._test_att('/', {'href': '/'})
self._test_att('/en_US/', {'href': '/en_US/'})
@@ -137,7 +100,7 @@ class TestQwebProcessAtt(TransactionCase):
self._test_att('/a', {'href': '/a'})
def test_process_att_monolang_route(self):
- with MockRequest(self.env, website=self.website, multilang=False) as request:
+ with MockRequest(self.env, website=self.website, multilang=False):
# lang not changed in URL but CDN enabled
self._test_att('/a', {'href': 'http://test.cdn/a'})
self._test_att('/en_US/a', {'href': 'http://test.cdn/en_US/a'})
@@ -145,19 +108,19 @@ class TestQwebProcessAtt(TransactionCase):
self._test_att('/en_US/b', {'href': '/en_US/b'})
def test_process_att_no_request_lang(self):
- with MockRequest(self.env, self.website) as request:
+ with MockRequest(self.env, website=self.website):
self._test_att('/', {'href': '/'})
self._test_att('/en_US/', {'href': '/'})
self._test_att('/fr_FR/', {'href': '/fr_FR/'})
def test_process_att_with_request_lang(self):
- with MockRequest(self.env, self.website, context={'lang': 'fr_FR'}) as request:
+ with MockRequest(self.env, website=self.website, context={'lang': 'fr_FR'}):
self._test_att('/', {'href': '/fr_FR/'})
self._test_att('/en_US/', {'href': '/'})
self._test_att('/fr_FR/', {'href': '/fr_FR/'})
def test_process_att_matching_cdn_and_lang(self):
- with MockRequest(self.env, self.website) as request:
+ with MockRequest(self.env, website=self.website):
# lang prefix is added before CDN
self._test_att('/a', {'href': 'http://test.cdn/a'})
self._test_att('/en_US/a', {'href': 'http://test.cdn/a'})
@@ -167,13 +130,13 @@ class TestQwebProcessAtt(TransactionCase):
self._test_att('/fr_FR/b', {'href': '/fr_FR/b'})
def test_process_att_no_route(self):
- with MockRequest(self.env, self.website, context={'lang': 'fr_FR'}, routing=False) as request:
+ with MockRequest(self.env, website=self.website, context={'lang': 'fr_FR'}, routing=False):
# default on multilang=True if route is not /{module}/static/
self._test_att('/web/static/hi', {'href': '/web/static/hi'})
self._test_att('/my-page', {'href': '/fr_FR/my-page'})
def test_process_att_url_crap(self):
- with MockRequest(self.env, self.website) as request:
+ with MockRequest(self.env, website=self.website) as request:
# #{fragment} is stripped from URL when testing route
self._test_att('/x#y?z', {'href': '/x#y?z'})
self.assertEqual(
diff --git a/addons/website/tools.py b/addons/website/tools.py
new file mode 100644
index 00000000000..fde1e94651d
--- /dev/null
+++ b/addons/website/tools.py
@@ -0,0 +1,60 @@
+# -*- encoding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import odoo
+import werkzeug
+
+from odoo.tools import DotDict
+
+
+class MockObject(object):
+ _log_call = []
+
+ def __init__(self, *args, **kwargs):
+ self.__dict__ = kwargs
+
+ def __call__(self, *args, **kwargs):
+ self._log_call.append((args, kwargs))
+ return self
+
+ def __getitem__(self, index):
+ return self
+
+
+def werkzeugRaiseNotFound(*args, **kwargs):
+ raise werkzeug.exceptions.NotFound()
+
+
+class MockRequest(object):
+ """ Class with context manager mocking odoo.http.request for tests """
+ def __init__(self, env, **kw):
+ app = MockObject(routing={
+ 'type': 'http',
+ 'website': True,
+ 'multilang': kw.get('multilang', True),
+ })
+ app.get_db_router = app.bind = app.match = app
+ if not kw.get('routing', True):
+ app.match = werkzeugRaiseNotFound
+ self.request = DotDict({
+ 'context': kw.get('context', {}),
+ 'db': None,
+ 'debug': False,
+ 'env': env,
+ 'httprequest': {
+ 'path': '/hello/',
+ 'app': app,
+ },
+ 'redirect': werkzeug.utils.redirect,
+ 'session': {
+ 'sale_order_id': kw.get('sale_order_id'),
+ },
+ 'website': kw.get('website'),
+ })
+ odoo.http._request_stack.push(self.request)
+
+ def __enter__(self):
+ return self.request
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ odoo.http._request_stack.pop()
diff --git a/addons/website_sale/tests/test_website_sale_pricelist.py b/addons/website_sale/tests/test_website_sale_pricelist.py
index eb3b9d5d1f6..9190ebc7dc5 100644
--- a/addons/website_sale/tests/test_website_sale_pricelist.py
+++ b/addons/website_sale/tests/test_website_sale_pricelist.py
@@ -5,6 +5,7 @@ try:
except ImportError:
from mock import patch
from odoo.tests.common import HttpCase, TransactionCase
+from odoo.tools import DotDict
''' /!\/!\
Calling `get_pricelist_available` after setting `property_product_pricelist` on
@@ -154,13 +155,6 @@ def simulate_frontend_context(self, website_id=1):
self.addCleanup(patcher.stop)
-class DotDict(dict):
- """dot.notation access to dictionary attributes"""
- def __getattr__(*args):
- val = dict.get(*args)
- return DotDict(val) if type(val) is dict else val
-
-
class TestWebsitePriceListAvailable(TransactionCase):
# This is enough to avoid a mock (request.session/website do not exist during test)
def get_pricelist_available(self, show_visible=False, website_id=1, country_code=None, website_sale_current_pl=None):
diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py
index 762c07e535c..7d465356e10 100644
--- a/odoo/tools/misc.py
+++ b/odoo/tools/misc.py
@@ -1242,3 +1242,14 @@ def wrap_module(module, attr_list):
raise AttributeError(attrib)
# module and attr_list are in the closure
return WrappedModule()
+
+
+class DotDict(dict):
+ """Helper for dot.notation access to dictionary attributes
+ E.g.
+ foo = DotDict({'bar': False})
+ return foo.bar
+ """
+ def __getattr__(self, attrib):
+ val = self.get(attrib)
+ return DotDict(val) if type(val) is dict else val