mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 16:37:23 +00:00
refactor: Parse JSON from bots in one place.
We move the JSON parsing step into the higher level function: process_success_response(). In the unlikely event that we'll start integrating with a solution that doesn't use JSON, we can deal with that, and for now doing the parsing in one place will help us make error reporting more consistent. In a subsequent commit we'll introduce better error handling for malformed JSON.
This commit is contained in:
@@ -45,7 +45,7 @@ class OutgoingWebhookServiceInterface:
|
|||||||
# The main use case for this function is to massage data from
|
# The main use case for this function is to massage data from
|
||||||
# various APIs to have similar data structures.
|
# various APIs to have similar data structures.
|
||||||
# It also allows bots to explictly set response_not_required.
|
# It also allows bots to explictly set response_not_required.
|
||||||
def process_success(self, response: Response,
|
def process_success(self, response_json: Dict[str, Any],
|
||||||
event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@@ -63,10 +63,8 @@ class GenericOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
|||||||
"trigger": event['trigger']}
|
"trigger": event['trigger']}
|
||||||
return rest_operation, json.dumps(request_data)
|
return rest_operation, json.dumps(request_data)
|
||||||
|
|
||||||
def process_success(self, response: Response,
|
def process_success(self, response_json: Dict[str, Any],
|
||||||
event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||||
response_json = json.loads(response.text)
|
|
||||||
|
|
||||||
if "response_not_required" in response_json and response_json['response_not_required']:
|
if "response_not_required" in response_json and response_json['response_not_required']:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -111,10 +109,8 @@ class SlackOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
|||||||
|
|
||||||
return rest_operation, request_data
|
return rest_operation, request_data
|
||||||
|
|
||||||
def process_success(self, response: Response,
|
def process_success(self, response_json: Dict[str, Any],
|
||||||
event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||||
response_json = json.loads(response.text)
|
|
||||||
|
|
||||||
if "text" in response_json:
|
if "text" in response_json:
|
||||||
content = response_json['text']
|
content = response_json['text']
|
||||||
success_data = dict(content=content)
|
success_data = dict(content=content)
|
||||||
@@ -258,7 +254,8 @@ def request_retry(event: Dict[str, Any],
|
|||||||
def process_success_response(event: Dict[str, Any],
|
def process_success_response(event: Dict[str, Any],
|
||||||
service_handler: Any,
|
service_handler: Any,
|
||||||
response: Response) -> None:
|
response: Response) -> None:
|
||||||
success_data = service_handler.process_success(response, event)
|
response_json = json.loads(response.text)
|
||||||
|
success_data = service_handler.process_success(response_json, event)
|
||||||
|
|
||||||
if success_data is None:
|
if success_data is None:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from typing import Any
|
from typing import Any, Dict
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from requests.models import Response
|
|
||||||
from zerver.lib.outgoing_webhook import GenericOutgoingWebhookService, \
|
from zerver.lib.outgoing_webhook import GenericOutgoingWebhookService, \
|
||||||
SlackOutgoingWebhookService
|
SlackOutgoingWebhookService
|
||||||
from zerver.lib.test_classes import ZulipTestCase
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
@@ -36,16 +35,15 @@ class TestGenericOutgoingWebhookService(ZulipTestCase):
|
|||||||
self.assertEqual(request_data['message'], self.event['message'])
|
self.assertEqual(request_data['message'], self.event['message'])
|
||||||
|
|
||||||
def test_process_success(self) -> None:
|
def test_process_success(self) -> None:
|
||||||
response = mock.Mock(spec=Response)
|
response = dict(response_not_required=True) # type: Dict[str, Any]
|
||||||
response.text = json.dumps({"response_not_required": True})
|
|
||||||
success_response = self.handler.process_success(response, self.event)
|
success_response = self.handler.process_success(response, self.event)
|
||||||
self.assertEqual(success_response, None)
|
self.assertEqual(success_response, None)
|
||||||
|
|
||||||
response.text = json.dumps({"response_string": 'test_content'})
|
response = dict(response_string='test_content')
|
||||||
success_response = self.handler.process_success(response, self.event)
|
success_response = self.handler.process_success(response, self.event)
|
||||||
self.assertEqual(success_response, dict(content='test_content'))
|
self.assertEqual(success_response, dict(content='test_content'))
|
||||||
|
|
||||||
response.text = json.dumps({})
|
response = dict()
|
||||||
success_response = self.handler.process_success(response, self.event)
|
success_response = self.handler.process_success(response, self.event)
|
||||||
self.assertEqual(success_response, None)
|
self.assertEqual(success_response, None)
|
||||||
|
|
||||||
@@ -123,11 +121,10 @@ class TestSlackOutgoingWebhookService(ZulipTestCase):
|
|||||||
self.assertTrue(mock_fail_with_message.called)
|
self.assertTrue(mock_fail_with_message.called)
|
||||||
|
|
||||||
def test_process_success(self) -> None:
|
def test_process_success(self) -> None:
|
||||||
response = mock.Mock(spec=Response)
|
response = dict(response_not_required=True) # type: Dict[str, Any]
|
||||||
response.text = json.dumps({"response_not_required": True})
|
|
||||||
success_response = self.handler.process_success(response, self.stream_message_event)
|
success_response = self.handler.process_success(response, self.stream_message_event)
|
||||||
self.assertEqual(success_response, None)
|
self.assertEqual(success_response, None)
|
||||||
|
|
||||||
response.text = json.dumps({"text": 'test_content'})
|
response = dict(text='test_content')
|
||||||
success_response = self.handler.process_success(response, self.stream_message_event)
|
success_response = self.handler.process_success(response, self.stream_message_event)
|
||||||
self.assertEqual(success_response, dict(content='test_content'))
|
self.assertEqual(success_response, dict(content='test_content'))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ def timeout_error(http_method: Any, final_url: Any, data: Any, **request_kwargs:
|
|||||||
raise requests.exceptions.Timeout("Time is up!")
|
raise requests.exceptions.Timeout("Time is up!")
|
||||||
|
|
||||||
class MockServiceHandler(OutgoingWebhookServiceInterface):
|
class MockServiceHandler(OutgoingWebhookServiceInterface):
|
||||||
def process_success(self, response: Response, event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
def process_success(self, response_json: Dict[str, Any], event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||||
# Our tests don't really look at the content yet.
|
# Our tests don't really look at the content yet.
|
||||||
# They just ensure we use the "success" codepath.
|
# They just ensure we use the "success" codepath.
|
||||||
success_data = dict(
|
success_data = dict(
|
||||||
|
|||||||
Reference in New Issue
Block a user