Skip to content

Commit

Permalink
test_http_request: support form-urlencoded requests (#43)
Browse files Browse the repository at this point in the history
* test_http_request: support form-urlencoded requests

* Typo

* Add unit tets for mock_odoo_request
  • Loading branch information
ddufresne authored and numigi-robot committed Nov 27, 2019
1 parent 3bd88e5 commit 5bc156d
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 12 deletions.
57 changes: 45 additions & 12 deletions test_http_request/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
from contextlib import contextmanager
from odoo.addons.http_routing.models.ir_http import url_for
from odoo.api import Environment
from odoo.http import HttpRequest, OpenERPSession, _request_stack
from odoo.http import HttpRequest, JsonRequest, OpenERPSession, _request_stack
from odoo.tools import config
from typing import Optional
from werkzeug.contrib.sessions import FilesystemSessionStore
from werkzeug.test import EnvironBuilder
from werkzeug.wrappers import Request


class _MockOdooHttpRequest(HttpRequest):
class _MockOdooRequestMixin:

@staticmethod
def redirect(url, code=302):
Expand Down Expand Up @@ -46,12 +46,42 @@ def __exit__(self, exc_type, exc_value, traceback):
_request_stack.pop()


class _MockOdooHttpRequest(_MockOdooRequestMixin, HttpRequest):
pass


class _MockOdooJsonRequest(_MockOdooRequestMixin, JsonRequest):
pass


def _make_environ(
method: str = 'POST',
headers: Optional[dict] = None,
data: Optional[dict] = None,
routing_type: str = 'http',
):
"""Make an environ for the given request parameters."""
assert routing_type in ('http', 'json')
environ_builder = EnvironBuilder(
method=method,
data=json.dumps(data or {}) if routing_type == 'json' else data,
headers=headers,
)
environ_builder.content_type = (
'application/json' if routing_type == 'json' else
'application/x-www-form-urlencoded'
)
environ = environ_builder.get_environ()
return environ


@contextmanager
def mock_odoo_request(
env: Environment,
method: str ='POST',
headers: Optional[dict]=None,
data: Optional[dict]=None,
method: str = 'POST',
headers: Optional[dict] = None,
data: Optional[dict] = None,
routing_type: str = 'http',
):
"""Mock an Odoo HTTP request.
Expand All @@ -65,23 +95,26 @@ def mock_odoo_request(
:param env: the odoo environment to bind with the request.
:param method: the HTTP method called during the request.
:param headers: the request headers.
:param data: an optional dict to be serialized as json data.
:param data: an optional dict to be serialized as json or url-encoded data.
:param routing_type: whether to use an http (x-www-form-urlencoded) or json request.
"""
environ = _make_environ(method, headers, data, routing_type)
httprequest = Request(environ)

session_store = FilesystemSessionStore(
config.session_dir, session_class=OpenERPSession, renew_missing=True)
session = session_store.new()
session.db = env.cr.dbname
session.uid = env.uid
session.context = env.context

json_data = json.dumps(data or {})

environ_builder = EnvironBuilder(method=method, data=json_data, headers=headers)
environ = environ_builder.get_environ()
httprequest = Request(environ)
httprequest.session = session

odoo_http_request = _MockOdooHttpRequest(httprequest)
odoo_http_request_cls = (
_MockOdooJsonRequest if routing_type == 'json' else
_MockOdooHttpRequest
)
odoo_http_request = odoo_http_request_cls(httprequest)
odoo_http_request._env = env
odoo_http_request._cr = env.cr
odoo_http_request._uid = env.uid
Expand Down
2 changes: 2 additions & 0 deletions test_http_request/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
59 changes: 59 additions & 0 deletions test_http_request/tests/test_mock_http_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# © 2019 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

import json
from collections import OrderedDict
from ddt import data, ddt, unpack
from odoo.http import request
from odoo.tests import common
from werkzeug.datastructures import ImmutableMultiDict
from ..common import mock_odoo_request


@ddt
class TestMockHttpRequest(common.TransactionCase):

def setUp(self):
super().setUp()
self.data = OrderedDict([
('firstname', 'John'),
('lastname', 'Doe'),
])

def test_env_propagated_to_request(self):
with mock_odoo_request(self.env, data=self.data):
assert request.env == self.env

def test_method_propagated_to_request(self):
method = 'PATCH'
with mock_odoo_request(self.env, data=self.data, method=method):
assert request.httprequest.method == method

def test_headers_propagated_to_request(self):
header_key = 'Some-Header'
header_value = 'some value'
headers = {
header_key: header_value,
}
with mock_odoo_request(self.env, data=self.data, headers=headers):
assert request.httprequest.headers[header_key] == header_value

@data(
('http', 'application/x-www-form-urlencoded'),
('json', 'application/json'),
)
@unpack
def test_content_type(self, routing_type, content_type):
with mock_odoo_request(self.env, data=self.data, routing_type=routing_type):
assert request.httprequest.content_type == content_type

def test_if_http_routing__data_contained_in_request_form(self):
with mock_odoo_request(self.env, data=self.data):
assert request.httprequest.form == ImmutableMultiDict(self.data)
assert not request.httprequest.data

def test_if_json_routing__data_contained_in_request_data(self):
json_data = json.dumps(self.data).encode()
with mock_odoo_request(self.env, data=self.data, routing_type='json'):
assert not request.httprequest.form
assert request.httprequest.data == json_data

0 comments on commit 5bc156d

Please sign in to comment.