Commit d575b87b authored by Titouan Soulard's avatar Titouan Soulard

erp5_api_style: add test on errors

parent c98f5f0a
...@@ -27,11 +27,41 @@ ...@@ -27,11 +27,41 @@
from DateTime import DateTime from DateTime import DateTime
from ZPublisher.HTTPRequest import HTTPRequest
from ZPublisher.HTTPResponse import HTTPResponse
import httplib
import json import json
import ssl
import transaction
import urlparse
import urllib
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.utils import createZODBPythonScript from Products.ERP5Type.tests.utils import createZODBPythonScript
class TemporaryAPIScript(object):
"""
Context manager for temporary alarm python scripts
"""
def __init__(self, portal, script_name, content):
self.script_name = script_name
self.portal = portal
self.content = content
def __enter__(self):
if self.script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % self.script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
self.script_name,
'*args, **kwargs',
'# Script body\n' + self.content)
transaction.commit()
def __exit__(self, exc_type, exc_value, traceback):
if self.script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(self.script_name)
transaction.commit()
class TestjIOApiStyle(ERP5TypeTestCase): class TestjIOApiStyle(ERP5TypeTestCase):
""" """
...@@ -124,6 +154,46 @@ class TestjIOApiStyle(ERP5TypeTestCase): ...@@ -124,6 +154,46 @@ class TestjIOApiStyle(ERP5TypeTestCase):
id=action_type, id=action_type,
) )
def fakeRequestToApi(self, request_method, headers=None, data=()):
__version__ = "0.1"
if (headers is None):
headers = {}
env={}
env['SERVER_NAME']='bobo.server'
env['SERVER_PORT']='80'
env['REQUEST_METHOD']=request_method
env['REMOTE_ADDR']='204.183.226.81 '
env['REMOTE_HOST']='bobo.remote.host'
env['HTTP_USER_AGENT']='Bobo/%s' % __version__
env['HTTP_HOST']='127.0.0.1'
env['SERVER_SOFTWARE']='Bobo/%s' % __version__
env['SERVER_PROTOCOL']='HTTP/1.0 '
env['HTTP_ACCEPT']='image/gif, image/x-xbitmap, image/jpeg, */* '
env['SERVER_HOSTNAME']='bobo.server.host'
env['GATEWAY_INTERFACE']='CGI/1.1 '
env['SCRIPT_NAME']='Main'
env.update(headers)
# for some mysterious reason QUERY_STRING does not get parsed into data fields
if data and request_method.upper() == 'GET':
# see: GET http://www.cgi101.com/book/ch3/text.html
env['QUERY_STRING'] = '&'.join(
'{}={}'.format(urllib.quote_plus(key), urllib.quote(value))
for key, value in data
)
if data and request_method.upper() == 'POST':
env['CONTENT_TYPE'] = 'application/json'
request = HTTPRequest(None, env, HTTPResponse())
if data and request_method.upper() == 'POST':
request.set("BODY", json.dumps(data))
self.portal.REQUEST = request
def getToApi(self, json_data): def getToApi(self, json_data):
self.portal.REQUEST.set("BODY", json_data) self.portal.REQUEST.set("BODY", json_data)
return self.web_site.api.get() return self.web_site.api.get()
...@@ -213,6 +283,59 @@ class TestjIOApiStyle(ERP5TypeTestCase): ...@@ -213,6 +283,59 @@ class TestjIOApiStyle(ERP5TypeTestCase):
action_list = self.web_site.api.ERP5Site_getAllActionListForAPIAllDocs() action_list = self.web_site.api.ERP5Site_getAllActionListForAPIAllDocs()
self.assertEqual(len(action_list), 0) self.assertEqual(len(action_list), 0)
def test_tmp(self):
"""
XXX: example to be deleted
"""
self.createUpdateScriptPersonAsBasicJSON()
self.updateCreateAction(
"Person", "%sperson_get_basic_json" % self.id_template,
self.action_type_dict["get"], "string:${object_url}/Person_asBasicJSON"
)
person = self.portal.person_module.newContent(
id="%s_person" % self.id_template,
portal_type="Person",
title=self.id_template,
)
self.tic()
self.fakeRequestToApi("POST", data={
"portal_type": "Person",
"id": "person_module/%s_person" % self.id_template
})
result = self.web_site.api.get()
self.assertEqual(result, json.dumps({
"id": person.getRelativeUrl(),
"title": person.getTitle()
}, indent=2))
def test_invalid_endpoint(self):
"""
Test that an invalid endpoint yields JSON data
"""
endpoint_url = "/".join([self.web_site.absolute_url(), "api", "getget"])
endpoint_scheme, endpoint_netloc, _, _, _ = urlparse.urlsplit(endpoint_url)
if endpoint_scheme == 'https':
connection = httplib.HTTPSConnection(endpoint_netloc, context=ssl._create_unverified_context(), timeout=10)
else:
connection = httplib.HTTPConnection(endpoint_netloc, timeout=10)
connection.request(
method="POST",
url=endpoint_url
)
response = connection.getresponse()
response_body = response.read()
connection.close()
isJson = True
try:
json.loads(response_body)
except ValueError:
isJson = False
self.assertTrue(isJson)
def test_json_api_hyperschema(self): def test_json_api_hyperschema(self):
""" """
Test a basic json hyper schema Test a basic json hyper schema
...@@ -351,7 +474,7 @@ class TestjIOApiStyle(ERP5TypeTestCase): ...@@ -351,7 +474,7 @@ class TestjIOApiStyle(ERP5TypeTestCase):
self.assertEqual(error_record.getTextContent(), json_payload) self.assertEqual(error_record.getTextContent(), json_payload)
def createUpdateScriptPersonAsBasicJSON(self): def createUpdateScriptPersonAsBasicJSON(self):
createZODBPythonScript( script = createZODBPythonScript(
self.portal.portal_skins.custom, self.portal.portal_skins.custom,
"Person_asBasicJSON", "Person_asBasicJSON",
"text_data, list_error", "text_data, list_error",
...@@ -363,6 +486,7 @@ return json.dumps({ ...@@ -363,6 +486,7 @@ return json.dumps({
}, indent=2) }, indent=2)
""" """
) )
script.manage_proxy(roles=["Manager"])
def test_action_get_success(self): def test_action_get_success(self):
""" """
...@@ -666,6 +790,55 @@ return json.dumps({ ...@@ -666,6 +790,55 @@ return json.dumps({
person = self.portal.restrictedTraverse(response['id'].encode()) person = self.portal.restrictedTraverse(response['id'].encode())
self.assertEqual(person.getTitle(), self.id_template) self.assertEqual(person.getTitle(), self.id_template)
def test_action_post_internal_error(self):
"""
Test POST action internal error case
"""
createZODBPythonScript(
self.portal.portal_skins.custom,
"jIOWebSection_createPersonFromJSONError",
"data, list_error",
"""
import json
person = context.getPortalObject().person_module.newContent(
portal_type="Person",
title=data["title"],
id=data["id"]
)
raise NotImplementedError
""")
self.updateCreateAction(
"jIO Web Section", "%sperson_post_basic_json" % self.id_template,
self.action_type_dict["post"], "string:${object_url}/jIOWebSection_createPersonFromJSONError"
)
self.tic()
throwed = False
try:
self.postToApi(
"""{
"portal_type": "Person",
"title": "%s",
"id": "%s"
}""" % (self.id_template, self.id_template)
)
except NotImplementedError:
throwed = True
person = self.portal.restrictedTraverse(self.id_template, None)
response_body = json.loads(self.portal.REQUEST.RESPONSE.getBody())
debug_id = response_body["debug_id"]
recorded_error = self.portal.restrictedTraverse(debug_id, None)
self.assertTrue(throwed)
self.assertEqual(self.portal.REQUEST.RESPONSE.getStatus(), 500)
self.assertEqual(response_body["status"], "500")
self.assertEqual(person, None)
self.assertEqual(recorded_error, None)
# Force fail because scenario is incorrect:
# 1. an Error Record is created with the error (see `ERP5Site_logApiErrorAndReturn`);
# 2. we now roll-back changes made to the ZODB on error (see except/raise in `document.erp5.jIOWebSection`);
# 3. therefore, the Error Record module is made useless. Either we want to delete it or log the error back.
self.assertTrue(False)
def test_action_post_no_action_matches(self): def test_action_post_no_action_matches(self):
""" """
Test POST action, doesn't find matching action Test POST action, doesn't find matching action
......
...@@ -39,7 +39,9 @@ ...@@ -39,7 +39,9 @@
<item> <item>
<key> <string>text_content_warning_message</string> </key> <key> <string>text_content_warning_message</string> </key>
<value> <value>
<tuple/> <tuple>
<string>W:840, 4: Redundant use of assertTrue with constant value False (redundant-unittest-assert)</string>
</tuple>
</value> </value>
</item> </item>
<item> <item>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment