bot tests: Allow raw responses in fixtures.
Previously, the responses set in bot test fixtures where handled as JSON objects. This works fine for most bot tests, because most of the APIs that bots are calling return a JSON-formatted response object. However, some, like Trello, do return raw data. This hasn't been noticed so far, because the respective Trello test needed internet access. Tests shouldn't need internet access. This commit makes that Trello test use a fixture. To work properly, it also adds a way to make http_mock_config parse the response object as raw data. This can now be done by modifying the "is_raw_response" property in a newly introduced "meta" object that can be used to specify how a fixture should be handled.
This commit is contained in:
parent
e638cdd4a9
commit
60c3919deb
15
zulip_bots/zulip_bots/bots/trello/fixtures/invalid_key.json
Normal file
15
zulip_bots/zulip_bots/bots/trello/fixtures/invalid_key.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"is_raw_response": true
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"api_url": "https://api.trello.com/1/members/TEST/",
|
||||||
|
"params": {
|
||||||
|
"key": "TEST",
|
||||||
|
"token": "TEST"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": "invalid key",
|
||||||
|
"response-headers": {
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ class TestTrelloBot(BotTestCase):
|
||||||
|
|
||||||
def test_bot_quit_with_invalid_config(self) -> None:
|
def test_bot_quit_with_invalid_config(self) -> None:
|
||||||
with self.mock_config_info(mock_config), self.assertRaises(StubBotHandler.BotQuitException):
|
with self.mock_config_info(mock_config), self.assertRaises(StubBotHandler.BotQuitException):
|
||||||
|
with self.mock_http_conversation('invalid_key'):
|
||||||
TrelloHandler().initialize(StubBotHandler())
|
TrelloHandler().initialize(StubBotHandler())
|
||||||
|
|
||||||
def test_invalid_command(self) -> None:
|
def test_invalid_command(self) -> None:
|
||||||
|
|
|
@ -18,18 +18,21 @@ def mock_http_conversation(http_data):
|
||||||
http_data should be fixtures data formatted like the data
|
http_data should be fixtures data formatted like the data
|
||||||
in zulip_bots/zulip_bots/bots/giphy/fixtures/test_normal.json
|
in zulip_bots/zulip_bots/bots/giphy/fixtures/test_normal.json
|
||||||
"""
|
"""
|
||||||
def get_response(http_response, http_headers):
|
def get_response(http_response, http_headers, is_raw_response):
|
||||||
# type: (Dict[str, Any], Dict[str, Any]) -> Any
|
# type: (Dict[str, Any], Dict[str, Any], bool) -> Any
|
||||||
"""Creates a fake `requests` Response with a desired HTTP response and
|
"""Creates a fake `requests` Response with a desired HTTP response and
|
||||||
response headers.
|
response headers.
|
||||||
"""
|
"""
|
||||||
mock_result = requests.Response()
|
mock_result = requests.Response()
|
||||||
mock_result._content = json.dumps(http_response).encode() # type: ignore # This modifies a "hidden" attribute.
|
if is_raw_response:
|
||||||
|
mock_result._content = http_response.encode() # type: ignore # This modifies a "hidden" attribute.
|
||||||
|
else:
|
||||||
|
mock_result._content = json.dumps(http_response).encode() # type: ignore # See above.
|
||||||
mock_result.status_code = http_headers.get('status', 200)
|
mock_result.status_code = http_headers.get('status', 200)
|
||||||
return mock_result
|
return mock_result
|
||||||
|
|
||||||
def assert_called_with_fields(mock_result, http_request, fields):
|
def assert_called_with_fields(mock_result, http_request, fields, meta):
|
||||||
# type: (Any, Dict[str, Any], List[str]) -> None
|
# type: (Any, Dict[str, Any], List[str], Dict[str, Any]) -> None
|
||||||
"""Calls `assert_called_with` on a mock object using an HTTP request.
|
"""Calls `assert_called_with` on a mock object using an HTTP request.
|
||||||
Uses `fields` to determine which keys to look for in HTTP request and
|
Uses `fields` to determine which keys to look for in HTTP request and
|
||||||
to test; if a key is in `fields`, e.g., 'headers', it will be used in
|
to test; if a key is in `fields`, e.g., 'headers', it will be used in
|
||||||
|
@ -51,34 +54,40 @@ def mock_http_conversation(http_data):
|
||||||
print("ERROR: Failed to find 'request', 'response' or 'response-headers' fields in fixture")
|
print("ERROR: Failed to find 'request', 'response' or 'response-headers' fields in fixture")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
meta = http_data.get('meta', dict())
|
||||||
|
is_raw_response = meta.get('is_raw_response', False)
|
||||||
|
|
||||||
http_method = http_request.get('method', 'GET')
|
http_method = http_request.get('method', 'GET')
|
||||||
|
|
||||||
if http_method == 'GET':
|
if http_method == 'GET':
|
||||||
with patch('requests.get') as mock_get:
|
with patch('requests.get') as mock_get:
|
||||||
mock_get.return_value = get_response(http_response, http_headers)
|
mock_get.return_value = get_response(http_response, http_headers, is_raw_response)
|
||||||
yield
|
yield
|
||||||
assert_called_with_fields(
|
assert_called_with_fields(
|
||||||
mock_get,
|
mock_get,
|
||||||
http_request,
|
http_request,
|
||||||
['params', 'headers']
|
['params', 'headers'],
|
||||||
|
meta
|
||||||
)
|
)
|
||||||
elif http_method == 'PATCH':
|
elif http_method == 'PATCH':
|
||||||
with patch('requests.patch') as mock_patch:
|
with patch('requests.patch') as mock_patch:
|
||||||
mock_patch.return_value = get_response(http_response, http_headers)
|
mock_patch.return_value = get_response(http_response, http_headers, is_raw_response)
|
||||||
yield
|
yield
|
||||||
assert_called_with_fields(
|
assert_called_with_fields(
|
||||||
mock_patch,
|
mock_patch,
|
||||||
http_request,
|
http_request,
|
||||||
['params', 'headers', 'json', 'data']
|
['params', 'headers', 'json', 'data'],
|
||||||
|
meta
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
with patch('requests.post') as mock_post:
|
with patch('requests.post') as mock_post:
|
||||||
mock_post.return_value = get_response(http_response, http_headers)
|
mock_post.return_value = get_response(http_response, http_headers, is_raw_response)
|
||||||
yield
|
yield
|
||||||
assert_called_with_fields(
|
assert_called_with_fields(
|
||||||
mock_post,
|
mock_post,
|
||||||
http_request,
|
http_request,
|
||||||
['params', 'headers', 'json', 'data']
|
['params', 'headers', 'json', 'data'],
|
||||||
|
meta
|
||||||
)
|
)
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
|
Loading…
Reference in a new issue