def test_get_fixture_http_headers_for_error_handling( self, import_module_mock: MagicMock) -> None: fake_module = SimpleNamespace() import_module_mock.return_value = fake_module with self.assertRaises(AttributeError): get_fixture_http_headers("some_integration", "simple_fixture")
def send_all_webhook_fixture_messages( request: HttpRequest, url: str = REQ(), integration_name: str = REQ() ) -> HttpResponse: fixtures_dir = os.path.join( ZULIP_PATH, "zerver/webhooks/{integration_name}/fixtures".format( integration_name=integration_name)) if not os.path.exists(fixtures_dir): msg = ("The integration \"{integration_name}\" does not have fixtures." ).format(integration_name=integration_name) return json_error(msg, status=404) responses = [] for fixture in os.listdir(fixtures_dir): fixture_path = os.path.join(fixtures_dir, fixture) with open(fixture_path, 'r') as f: content = f.read() x = fixture.split(".") fixture_name, fixture_format = "".join(_ for _ in x[:-1]), x[-1] headers = get_fixture_http_headers(integration_name, fixture_name) if fixture_format == "json": is_json = True else: is_json = False response = send_webhook_fixture_message(url, content, is_json, headers) responses.append({ "status_code": response.status_code, "fixture_name": fixture, "message": response.content }) return json_success({"responses": responses})
def send_and_test_private_message( self, fixture_name: str, expected_topic: Optional[str] = None, expected_message: Optional[str] = None, content_type: Optional[str] = "application/json", **kwargs: Any, ) -> Message: payload = self.get_body(fixture_name) if content_type is not None: kwargs['content_type'] = content_type if self.FIXTURE_DIR_NAME is not None: headers = get_fixture_http_headers(self.FIXTURE_DIR_NAME, fixture_name) headers = standardize_headers(headers) kwargs.update(headers) # The sender profile shouldn't be passed any further in kwargs, so we pop it. sender = kwargs.pop('sender', self.test_user) msg = self.send_json_payload(sender, self.url, payload, stream_name=None, **kwargs) self.do_test_message(msg, expected_message) return msg
def send_and_test_private_message( self, fixture_name: str, expected_message: str, content_type: str = "application/json", **kwargs: Any, ) -> Message: """ For the rare cases that you are testing a webhook that sends private messages, use this function. Most webhooks send to streams, and you will want to look at check_webhook. """ payload = self.get_payload(fixture_name) kwargs['content_type'] = content_type if self.FIXTURE_DIR_NAME is not None: headers = get_fixture_http_headers(self.FIXTURE_DIR_NAME, fixture_name) headers = standardize_headers(headers) kwargs.update(headers) # The sender profile shouldn't be passed any further in kwargs, so we pop it. sender = kwargs.pop('sender', self.test_user) msg = self.send_webhook_payload( sender, self.url, payload, **kwargs, ) self.assertEqual(msg.content, expected_message) return msg
def get_fixtures(request: HttpResponse, integration_name: str=REQ()) -> HttpResponse: integrations = get_webhook_integrations() if integration_name not in integrations: return json_error("\"{integration_name}\" is not a valid webhook integration.".format( integration_name=integration_name), status=404) fixtures = {} fixtures_dir = os.path.join(ZULIP_PATH, "zerver/webhooks/{integration_name}/fixtures".format( integration_name=integration_name)) if not os.path.exists(fixtures_dir): msg = ("The integration \"{integration_name}\" does not have fixtures.").format( integration_name=integration_name) return json_error(msg, status=404) for fixture in os.listdir(fixtures_dir): fixture_path = os.path.join(fixtures_dir, fixture) body = open(fixture_path).read() try: body = ujson.loads(body) except ValueError: pass # The file extension will be used to determine the type. headers_raw = get_fixture_http_headers(integration_name, "".join(fixture.split(".")[:-1])) headers = {} for header in headers_raw: if header.startswith("HTTP_"): # HTTP_ is a prefix intended for Django. headers[header.lstrip("HTTP_")] = headers_raw[header] else: headers[header] = headers_raw[header] fixtures[fixture] = {"body": body, "headers": headers} return json_success({"fixtures": fixtures})
def get_fixtures(request: HttpResponse, integration_name: str=REQ()) -> HttpResponse: valid_integration_name = get_valid_integration_name(integration_name) if not valid_integration_name: return json_error(f"\"{integration_name}\" is not a valid webhook integration.", status=404) fixtures = {} fixtures_dir = os.path.join(ZULIP_PATH, f"zerver/webhooks/{valid_integration_name}/fixtures") if not os.path.exists(fixtures_dir): msg = ("The integration \"{valid_integration_name}\" does not have fixtures.").format( valid_integration_name=valid_integration_name) return json_error(msg, status=404) for fixture in os.listdir(fixtures_dir): fixture_path = os.path.join(fixtures_dir, fixture) with open(fixture_path) as f: body = f.read() try: body = orjson.loads(body) except orjson.JSONDecodeError: pass # The file extension will be used to determine the type. headers_raw = get_fixture_http_headers(valid_integration_name, "".join(fixture.split(".")[:-1])) def fix_name(header: str) -> str: if header.startswith("HTTP_"): # HTTP_ is a prefix intended for Django. return header[len("HTTP_"):] return header headers = {fix_name(k): v for k, v in headers_raw.items()} fixtures[fixture] = {"body": body, "headers": headers} return json_success({"fixtures": fixtures})
def test_get_fixture_http_headers_with_no_fixtures_to_headers_function( self, import_module_mock: MagicMock) -> None: fake_module = SimpleNamespace() import_module_mock.return_value = fake_module self.assertEqual( get_fixture_http_headers("some_integration", "simple_fixture"), {})
def test_get_fixture_http_headers_for_success(self, import_module_mock: MagicMock) -> None: def fixture_to_headers(fixture_name: str) -> Dict[str, str]: # A sample function which would normally perform some # extra operations before returning a dictionary # corresponding to the fixture name passed. For this test, # we just return a fixed dictionary. return {"key": "value"} fake_module = SimpleNamespace(fixture_to_headers=fixture_to_headers) import_module_mock.return_value = fake_module headers = get_fixture_http_headers("some_integration", "complex_fixture") self.assertEqual(headers, {"key": "value"})
def check_webhook( self, fixture_name: str, expected_topic: str, expected_message: str, content_type: Optional[str] = "application/json", **kwargs: Any, ) -> None: """ check_webhook is the main way to test "normal" webhooks that work by receiving a payload from a third party and then writing some message to a Zulip stream. We use `fixture_name` to find the payload data in of our test fixtures. Then we verify that a message gets sent to a stream: self.STREAM_NAME: stream name expected_topic: topic expected_message: content We simulate the delivery of the payload with `content_type`, and you can pass other headers via `kwargs`. For the rare cases of webhooks actually sending private messages, see send_and_test_private_message. """ assert self.STREAM_NAME is not None self.subscribe(self.test_user, self.STREAM_NAME) payload = self.get_payload(fixture_name) if content_type is not None: kwargs['content_type'] = content_type if self.FIXTURE_DIR_NAME is not None: headers = get_fixture_http_headers(self.FIXTURE_DIR_NAME, fixture_name) headers = standardize_headers(headers) kwargs.update(headers) msg = self.send_webhook_payload( self.test_user, self.url, payload, **kwargs, ) self.assert_stream_message( message=msg, stream_name=self.STREAM_NAME, topic_name=expected_topic, content=expected_message, )
def send_and_test_stream_message(self, fixture_name: str, expected_topic: Optional[str]=None, expected_message: Optional[str]=None, content_type: Optional[str]="application/json", **kwargs: Any) -> Message: payload = self.get_body(fixture_name) if content_type is not None: kwargs['content_type'] = content_type headers = get_fixture_http_headers(self.FIXTURE_DIR_NAME, fixture_name) headers = standardize_headers(headers) kwargs.update(headers) msg = self.send_json_payload(self.test_user, self.url, payload, self.STREAM_NAME, **kwargs) self.do_test_topic(msg, expected_topic) self.do_test_message(msg, expected_message) return msg
def send_and_test_private_message(self, fixture_name: str, expected_topic: str = None, expected_message: str = None, content_type: str = "application/json", **kwargs: Any) -> Message: payload = self.get_body(fixture_name) if content_type is not None: kwargs['content_type'] = content_type headers = get_fixture_http_headers(self.FIXTURE_DIR_NAME, fixture_name) headers = parse_headers_dict(headers) kwargs.update(headers) sender = kwargs.get('sender', self.test_user) msg = self.send_json_payload(sender, self.url, payload, stream_name=None, **kwargs) self.do_test_message(msg, expected_message) return msg
def send_all_webhook_fixture_messages( request: HttpRequest, url: str = REQ(), integration_name: str = REQ() ) -> HttpResponse: valid_integration_name = get_valid_integration_name(integration_name) if not valid_integration_name: raise ResourceNotFoundError( f'"{integration_name}" is not a valid webhook integration.') fixtures_dir = os.path.join( ZULIP_PATH, f"zerver/webhooks/{valid_integration_name}/fixtures") if not os.path.exists(fixtures_dir): msg = ( 'The integration "{valid_integration_name}" does not have fixtures.' ).format(valid_integration_name=valid_integration_name) raise ResourceNotFoundError(msg) responses = [] for fixture in os.listdir(fixtures_dir): fixture_path = os.path.join(fixtures_dir, fixture) with open(fixture_path) as f: content = f.read() x = fixture.split(".") fixture_name, fixture_format = "".join(_ for _ in x[:-1]), x[-1] headers = get_fixture_http_headers(valid_integration_name, fixture_name) if fixture_format == "json": is_json = True else: is_json = False response = send_webhook_fixture_message(url, content, is_json, headers) responses.append({ "status_code": response.status_code, "fixture_name": fixture, "message": response.content.decode(), }) return json_success({"responses": responses})
def test_get_fixture_http_headers_for_non_existent_integration( self) -> None: headers = get_fixture_http_headers( "some_random_nonexistent_integration", "fixture_name") self.assertEqual(headers, {})