def test_args_contain_error_message(self, mock): fakefunc(1, None, False) try: faux(mock).args_contain(True) except AssertionError as e: assert e.message == 'Expected args to contain True. Received (1, None, False).'
def test_kwarg_equals_error_message(self, mock): fakefunc(foo=1, bar=2) try: faux(mock).kwarg_equals("bar", True) except AssertionError as e: assert str(e) == "Expected kwargs[bar] to equal True. Received 2."
def test_called_with_error_message(self, mock): fakefunc(1) try: faux(mock).called_with(False) except AssertionError as e: assert e.message == "Expected to be called with (False). Received (1)."
def test_args_equal_error_message(self, mock): fakefunc(1, False) try: faux(mock).args_equals(['beep']) except AssertionError as e: assert e.message == 'Expected args to equal ([\'beep\']). Received (1, False).'
def test_kwargs_contain_error_message(self, mock): fakefunc(foo=1) try: faux(mock).kwargs_contain("bar") except AssertionError as e: assert e.message == "Expected kwargs to contain key 'bar'. Received (foo=1)."
def test_kwarg_equals_error_message(self, mock): fakefunc(foo=1, bar=2) try: faux(mock).kwarg_equals('bar', True) except AssertionError as e: assert e.message == 'Expected kwargs[bar] to equal True. Received 2.'
def test_args_contain_error_message(self, mock): fakefunc(1, None, False) try: faux(mock).args_contain(True) except AssertionError as e: assert e.message == "Expected args to contain True. Received (1, None, False)."
def test_kwargs_contain_error_message(self, mock): fakefunc(foo=1) try: faux(mock).kwargs_contain('bar') except AssertionError as e: assert e.message == 'Expected kwargs to contain key \'bar\'. Received (foo=1).'
def test_called_with_error_message(self, mock): fakefunc(1) try: faux(mock).called_with(False) except AssertionError as e: assert e.message == 'Expected to be called with (False). Received (1).'
def test_args_equal_error_message(self, mock): fakefunc(1, False) try: faux(mock).args_equals(["beep"]) except AssertionError as e: assert e.message == "Expected args to equal (['beep']). Received (1, False)."
def test_uninstallation_enqueued(self, safe_urlopen): InstallationNotifier.run(install=self.install, user=self.user, action="deleted") data = faux(safe_urlopen).kwargs["data"] assert data == json.dumps( { "action": "deleted", "installation": {"uuid": self.install.uuid}, "data": { "installation": { "app": {"uuid": self.sentry_app.uuid, "slug": self.sentry_app.slug}, "organization": {"slug": self.org.slug}, "uuid": self.install.uuid, "code": self.install.api_grant.code, "status": "pending", } }, "actor": {"id": self.user.id, "name": self.user.name, "type": "user"}, } ) assert faux(safe_urlopen).kwarg_equals( "headers", DictContaining( "Content-Type", "Request-ID", "Sentry-Hook-Resource", "Sentry-Hook-Timestamp", "Sentry-Hook-Signature", ), )
def test_send_alert_event(self, safe_urlopen): group = self.create_group(project=self.project) event = self.create_event(group=group) rule_future = RuleFuture( rule=self.rule, kwargs={'sentry_app': self.sentry_app}, ) with self.tasks(): notify_sentry_app(event, [rule_future]) data = json.loads(faux(safe_urlopen).kwargs['data']) assert data == { 'action': 'triggered', 'installation': { 'uuid': self.install.uuid, }, 'data': { 'event': DictContaining( event_id=event.event_id, url=absolute_uri( reverse('sentry-api-0-project-event-details', args=[ self.organization.slug, self.project.slug, event.id, ])), web_url=absolute_uri( reverse('sentry-group-event', args=[ self.organization.slug, self.project.slug, group.id, event.id, ])), issue_url=absolute_uri( '/api/0/issues/{}/'.format(group.id), ), ), 'triggered_rule': self.rule.label, }, 'actor': { 'type': 'application', 'id': 'sentry', 'name': 'Sentry', } } assert faux(safe_urlopen).kwarg_equals( 'headers', DictContaining( 'Content-Type', 'Request-ID', 'Sentry-Hook-Resource', 'Sentry-Hook-Timestamp', 'Sentry-Hook-Signature', ))
def test_send_alert_event(self, safe_urlopen): group = self.create_group(project=self.project) event = self.create_event(group=group) rule_future = RuleFuture(rule=self.rule, kwargs={"sentry_app": self.sentry_app}) with self.tasks(): notify_sentry_app(event, [rule_future]) data = json.loads(faux(safe_urlopen).kwargs["data"]) assert data == { "action": "triggered", "installation": { "uuid": self.install.uuid }, "data": { "event": DictContaining( event_id=event.event_id, url=absolute_uri( reverse( "sentry-api-0-project-event-details", args=[ self.organization.slug, self.project.slug, event.event_id ], )), web_url=absolute_uri( reverse( "sentry-organization-event-detail", args=[ self.organization.slug, group.id, event.event_id ], )), issue_url=absolute_uri("/api/0/issues/{}/".format( group.id)), ), "triggered_rule": self.rule.label, }, "actor": { "type": "application", "id": "sentry", "name": "Sentry" }, } assert faux(safe_urlopen).kwarg_equals( "headers", DictContaining( "Content-Type", "Request-ID", "Sentry-Hook-Resource", "Sentry-Hook-Timestamp", "Sentry-Hook-Signature", ), )
def test_called_with_error_message(self, mock): fakefunc(1) try: faux(mock).called_with(False) except AssertionError as e: assert six.text_type( e) == 'Expected to be called with (False). Received (1).'
def test_kwarg_equals_error_message(self, mock): fakefunc(foo=1, bar=2) try: faux(mock).kwarg_equals('bar', True) except AssertionError as e: assert six.text_type( e) == 'Expected kwargs[bar] to equal True. Received 2.'
def test_sends_resolved_webhook(self, safe_urlopen): workflow_notification(self.install.id, self.issue.id, 'resolved', self.user.id) assert faux(safe_urlopen).kwarg_equals('url', self.sentry_app.webhook_url) assert faux(safe_urlopen).kwarg_equals('data.action', 'resolved', format='json') assert faux(safe_urlopen).kwarg_equals('headers.Sentry-Hook-Resource', 'issue') assert faux(safe_urlopen).kwarg_equals( 'data.data.issue.id', six.binary_type( self.issue.id), format='json')
def test_sends_resolved_webhook(self, safe_urlopen): workflow_notification(self.install.id, self.issue.id, "resolved", self.user.id) assert faux(safe_urlopen).kwarg_equals("url", self.sentry_app.webhook_url) assert faux(safe_urlopen).kwarg_equals("data.action", "resolved", format="json") assert faux(safe_urlopen).kwarg_equals("headers.Sentry-Hook-Resource", "issue") assert faux(safe_urlopen).kwarg_equals( "data.data.issue.id", str(self.issue.id), format="json" )
def test_args_equal_error_message(self, mock): fakefunc(1, False) try: faux(mock).args_equals(['beep']) except AssertionError as e: assert six.text_type( e ) == 'Expected args to equal ([\'beep\']). Received (1, False).'
def test_kwargs_contain_error_message(self, mock): fakefunc(foo=1) try: faux(mock).kwargs_contain('bar') except AssertionError as e: assert six.text_type( e ) == 'Expected kwargs to contain key \'bar\'. Received (foo=1).'
def test_sends_resolved_webhook_as_Sentry_without_user(self, safe_urlopen): workflow_notification(self.install.id, self.issue.id, "resolved", None) assert faux(safe_urlopen).kwarg_equals("data.actor.type", "application", format="json") assert faux(safe_urlopen).kwarg_equals("data.actor.id", "sentry", format="json") assert faux(safe_urlopen).kwarg_equals("data.actor.name", "Sentry", format="json")
def test_sends_resolved_webhook_as_Sentry_without_user(self, safe_urlopen): workflow_notification(self.install.id, self.issue.id, 'resolved', None) assert faux(safe_urlopen).kwarg_equals('data.actor.type', 'application', format='json') assert faux(safe_urlopen).kwarg_equals('data.actor.id', 'sentry', format='json') assert faux(safe_urlopen).kwarg_equals('data.actor.name', 'Sentry', format='json')
def test_send_alert_event(self, safe_urlopen): group = self.create_group(project=self.project) event = self.create_event(group=group) rule_future = RuleFuture( rule=self.rule, kwargs={'sentry_app': self.sentry_app}, ) with self.feature('organizations:sentry10'): with self.tasks(): notify_sentry_app(event, [rule_future]) data = json.loads(faux(safe_urlopen).kwargs['data']) assert data == { 'action': 'triggered', 'installation': { 'uuid': self.install.uuid, }, 'data': { 'event': DictContaining( event_id=event.event_id, url=absolute_uri(reverse('sentry-api-0-project-event-details', args=[ self.organization.slug, self.project.slug, event.id, ])), web_url=absolute_uri(reverse('sentry-organization-event-detail', args=[ self.organization.slug, group.id, event.id, ])), issue_url=absolute_uri( '/api/0/issues/{}/'.format(group.id), ), ), 'triggered_rule': self.rule.label, }, 'actor': { 'type': 'application', 'id': 'sentry', 'name': 'Sentry', } } assert faux(safe_urlopen).kwarg_equals('headers', DictContaining( 'Content-Type', 'Request-ID', 'Sentry-Hook-Resource', 'Sentry-Hook-Timestamp', 'Sentry-Hook-Signature', ))
def test_send_alert_event(self, safe_urlopen): event = self.store_event(data={}, project_id=self.project.id) group = event.group rule_future = RuleFuture(rule=self.rule, kwargs={"sentry_app": self.sentry_app}) with self.tasks(): notify_sentry_app(event, [rule_future]) data = json.loads(faux(safe_urlopen).kwargs["data"]) assert data == { "action": "triggered", "installation": {"uuid": self.install.uuid}, "data": { "event": DictContaining( event_id=event.event_id, url=absolute_uri( reverse( "sentry-api-0-project-event-details", args=[self.organization.slug, self.project.slug, event.event_id], ) ), web_url=absolute_uri( reverse( "sentry-organization-event-detail", args=[self.organization.slug, group.id, event.event_id], ) ), issue_url=absolute_uri(f"/api/0/issues/{group.id}/"), ), "triggered_rule": self.rule.label, }, "actor": {"type": "application", "id": "sentry", "name": "Sentry"}, } assert faux(safe_urlopen).kwarg_equals( "headers", DictContaining( "Content-Type", "Request-ID", "Sentry-Hook-Resource", "Sentry-Hook-Timestamp", "Sentry-Hook-Signature", ), ) buffer = SentryAppWebhookRequestsBuffer(self.sentry_app) requests = buffer.get_requests() assert len(requests) == 1 assert requests[0]["response_code"] == 200 assert requests[0]["event_type"] == "event_alert.triggered"
def test_group_created_sends_service_hook(self, safe_urlopen): with self.tasks(): issue = self.create_group(project=self.project) data = json.loads(faux(safe_urlopen).kwargs['data']) assert data['action'] == 'issue.created' assert data['installation']['uuid'] == self.install.uuid assert data['data']['id'] == six.text_type(issue.id) assert faux(safe_urlopen).kwarg_equals('headers', DictContaining( 'Content-Type', 'X-ServiceHook-Timestamp', 'X-ServiceHook-GUID', 'X-ServiceHook-Signature', ))
def test_log_exception(self): def call(self): with self.log(): raise TypeError setattr(self.mediator, "call", types.MethodType(call, self.mediator)) with patch.object(self.logger, "info") as mock: try: self.mediator.call() except Exception: pass assert faux(mock).kwarg_equals("extra.at", "exception") assert faux(mock).kwargs_contain("extra.elapsed")
def test_verify_sentry_hook_signature(self, safe_urlopen): import hmac from hashlib import sha256 with self.tasks(): self.create_group(project=self.project) secret = self.install.sentry_app.application.client_secret body = json.dumps(faux(safe_urlopen).kwargs['data']) expected = hmac.new( key=secret.encode('utf-8'), msg=body, digestmod=sha256, ).hexdigest() assert expected == faux(safe_urlopen).kwargs['headers']['Sentry-Hook-Signature']
def test_log_exception(self): def call(self): with self.log(): raise TypeError setattr(self.mediator, 'call', types.MethodType(call, self.mediator)) # noqa: B010 with patch.object(self.logger, 'info') as mock: try: self.mediator.call() except Exception: pass assert faux(mock).kwarg_equals('extra.at', 'exception') assert faux(mock).kwargs_contain('extra.elapsed')
def test_group_created_sends_service_hook(self, safe_urlopen): with self.tasks(): issue = self.create_group(project=self.project) data = faux(safe_urlopen).kwargs['data'] assert data['action'] == 'created' assert data['installation']['uuid'] == self.install.uuid assert data['data']['id'] == six.text_type(issue.id) assert faux(safe_urlopen).kwarg_equals('headers', DictContaining( 'Content-Type', 'Request-ID', 'Sentry-Hook-Resource', 'Sentry-Hook-Timestamp', 'Sentry-Hook-Signature', ))
def test_process_resource_change_bound_passes_retry_object(self, process, safe_urlopen): group = self.create_group(project=self.project) process_resource_change_bound('created', 'Group', group.id) task = faux(process).kwargs['retryer'] assert isinstance(task, Task)
def test_send_alert_event_with_additional_payload(self, safe_urlopen): event = self.store_event(data={}, project_id=self.project.id) settings = { "alert_prefix": "[Not Good]", "channel": "#ignored-errors", "best_emoji": ":fire:", } rule_future = RuleFuture( rule=self.rule, kwargs={"sentry_app": self.sentry_app, "schema_defined_settings": settings}, ) with self.tasks(): notify_sentry_app(event, [rule_future]) payload = json.loads(faux(safe_urlopen).kwargs["data"]) assert payload["action"] == "triggered" assert payload["data"]["triggered_rule"] == self.rule.label assert payload["data"]["issue_alert"] == { "id": self.rule.id, "title": self.rule.label, "sentry_app_id": self.sentry_app.id, "settings": settings, } buffer = SentryAppWebhookRequestsBuffer(self.sentry_app) requests = buffer.get_requests() assert len(requests) == 1 assert requests[0]["response_code"] == 200 assert requests[0]["event_type"] == "event_alert.triggered"
def test_processes_created_issues(self, delay): issue = self.create_group() assert faux(delay).called_with( action='created', sender='Group', instance_id=issue.id, )
def test_after_issue_assigned_with_enhanced_privacy(self, delay): org = self.issue.project.organization org.flags.enhanced_privacy = True org.save() GroupAssignee.objects.assign( self.issue, self.assignee, self.user, ) assert faux(delay).called_with( installation_id=self.install.id, issue_id=self.issue.id, type='assigned', user_id=self.user.id, data={ # Excludes email address 'assignee': { 'type': 'user', 'name': self.assignee.name, 'id': self.assignee.id, }, }, )
def test_redacted_symbol_source_secrets(self, create_audit_entry): with Feature( {"organizations:symbol-sources": True, "organizations:custom-symbol-sources": True} ): config = { "id": "honk", "name": "honk source", "layout": { "type": "native", }, "filetypes": ["pe"], "type": "http", "url": "http://honk.beep", "username": "******", "password": "******", } self.get_valid_response( self.org_slug, self.proj_slug, symbolSources=json.dumps([config]) ) assert self.project.get_option("sentry:symbol_sources") == json.dumps([config]) # redact password redacted_source = config.copy() redacted_source["password"] = {"hidden-secret": True} # check that audit entry was created with redacted password assert create_audit_entry.called call = faux.faux(create_audit_entry) assert call.kwarg_equals("data", {"sentry:symbol_sources": [redacted_source]}) self.get_valid_response( self.org_slug, self.proj_slug, symbolSources=json.dumps([redacted_source]) ) # on save the magic object should be replaced with the previously set password assert self.project.get_option("sentry:symbol_sources") == json.dumps([config])
def test_event_created_sends_service_hook(self, safe_urlopen): self.hook.update(events=['event.created', 'event.alert']) event = self.create_event(project=self.project) process_service_hook(self.hook.id, event) data = json.loads(faux(safe_urlopen).kwargs['data']) assert faux(safe_urlopen).kwarg_equals('url', self.hook.url) assert data == json.loads(json.dumps(get_payload_v0(event))) assert faux(safe_urlopen).kwarg_equals('headers', DictContaining( 'Content-Type', 'X-ServiceHook-Timestamp', 'X-ServiceHook-GUID', 'X-ServiceHook-Signature', ))
def test_sends_comment_created_webhook(self, safe_urlopen): build_comment_webhook(self.install.id, self.issue.id, "comment.created", self.user.id, data=self.data) assert faux(safe_urlopen).kwarg_equals("url", self.sentry_app.webhook_url) assert faux(safe_urlopen).kwarg_equals("data.action", "created", format="json") assert faux(safe_urlopen).kwarg_equals("headers.Sentry-Hook-Resource", "comment") assert faux(safe_urlopen).kwarg_equals("data.data.issue_id", self.issue.id, format="json")
def test_records_analytics(self, create_audit_entry, record): sentry_app = InternalCreator.run( name="nulldb", user=self.user, author="Sentry", organization=self.org, scopes=("project:read", ), webhook_url="http://example.com", schema={"elements": [self.create_issue_link_schema()]}, request=MagicMock(), ) assert faux(record).args_equals("internal_integration.created") assert faux(record).kwargs == { "user_id": self.user.id, "organization_id": self.org.id, "sentry_app": sentry_app.slug, }
def test_records_analytics(self, create_audit_entry, record): sentry_app = InternalCreator.run( name='nulldb', user=self.user, author='Sentry', organization=self.org, scopes=('project:read',), webhook_url='http://example.com', schema={'elements': [self.create_issue_link_schema()]}, request=MagicMock(), ) assert faux(record).args_equals('internal_integration.created') assert faux(record).kwargs == { 'user_id': self.user.id, 'organization_id': self.org.id, 'sentry_app': sentry_app.slug, }
def test_notify_after_basic_resolved(self, delay): self.update_issue() assert faux(delay).called_with( installation_id=self.install.id, issue_id=self.issue.id, type='resolved', user_id=self.user.id, data={'resolution_type': 'now'}, )
def test_notify_after_issue_ignored(self, delay): self.update_issue({'status': 'ignored'}) assert faux(delay).called_with( installation_id=self.install.id, issue_id=self.issue.id, type='ignored', user_id=self.user.id, data={}, )
def test_task_enqueued(self, safe_urlopen): InstallationNotifier.run( install=self.install, user=self.user, ) data = faux(safe_urlopen).kwargs['data'] assert data == { 'action': 'created', 'installation': { 'uuid': self.install.uuid, }, 'data': { 'app': { 'uuid': self.sentry_app.uuid, 'slug': self.sentry_app.slug, }, 'organization': { 'slug': self.org.slug, }, 'uuid': self.install.uuid, 'code': self.install.api_grant.code, }, 'actor': { 'id': self.user.id, 'name': self.user.name, 'type': 'user', }, } assert faux(safe_urlopen).kwarg_equals('headers', DictContaining( 'Content-Type', 'Request-ID', 'Sentry-Hook-Resource', 'Sentry-Hook-Timestamp', 'Sentry-Hook-Signature', ))
def test_send_alert_event(self, safe_urlopen): group = self.create_group(project=self.project) event = self.create_event(group=group) rule_future = RuleFuture( rule=self.rule, kwargs={'sentry_app': self.sentry_app}, ) event_data = self._get_event_data(event) with self.tasks(): notify_sentry_app(event, [rule_future]) data = faux(safe_urlopen).kwargs['data'] assert data == { 'action': 'triggered', 'installation': { 'uuid': self.install.uuid, }, 'data': { 'event': event_data, 'triggered_rule': self.rule.label, }, 'actor': { 'type': 'application', 'id': 'sentry', 'name': 'Sentry', } } assert faux(safe_urlopen).kwarg_equals('headers', DictContaining( 'Content-Type', 'Request-ID', 'Sentry-Hook-Resource', 'Sentry-Hook-Timestamp', 'Sentry-Hook-Signature', ))
def test_notify_after_resolve_in_latest_release(self, delay): self.create_release(project=self.project) self.update_issue({ 'statusDetails': { 'inRelease': 'latest', }, }) assert faux(delay).called_with( installation_id=self.install.id, issue_id=self.issue.id, type='resolved', user_id=self.user.id, data={'resolution_type': 'in_release'}, )
def test_verify_sentry_hook_signature(self, safe_urlopen): import hmac from hashlib import sha256 event = self.create_event(project=self.project) process_service_hook(self.hook.id, event) body = json.dumps(get_payload_v0(event)) expected = hmac.new( key=self.hook.secret.encode('utf-8'), msg=body.encode('utf-8'), digestmod=sha256, ).hexdigest() assert expected == faux(safe_urlopen).kwargs['headers']['X-ServiceHook-Signature']
def test_notify_after_resolve_from_set_commits(self, delay): repo = Repository.objects.create( organization_id=self.organization.id, name='test/repo', ) release = Release.objects.create( version='abcabc', organization=self.organization, ) commit = Commit.objects.create( repository_id=repo.id, organization_id=self.organization.id, key='b' * 40, ) GroupLink.objects.create( group_id=self.issue.id, project_id=self.project.id, linked_type=GroupLink.LinkedType.commit, linked_id=commit.id, ) release.add_project(self.project) release.set_commits( [ { 'id': 'b' * 40, 'repository': repo.name, 'author_email': '*****@*****.**', 'author_name': 'Foo Bar', 'message': u'FIXES {}'.format(self.issue.qualified_short_id), } ] ) assert faux(delay).called_with( installation_id=self.install.id, issue_id=self.issue.id, type='resolved', user_id=None, data={'resolution_type': 'with_commit'}, )
def test_notify_after_resolve_in_commit(self, delay): repo = self.create_repo(project=self.project) commit = self.create_commit(repo=repo) self.update_issue({ 'statusDetails': { 'inCommit': { 'repository': repo.name, 'commit': commit.key, } } }) assert faux(delay).called_with( installation_id=self.install.id, issue_id=self.issue.id, type='resolved', user_id=self.user.id, data={'resolution_type': 'in_commit'}, )
def test_after_issue_assigned(self, delay): GroupAssignee.objects.assign( self.issue, self.assignee, self.user, ) assert faux(delay).called_with( installation_id=self.install.id, issue_id=self.issue.id, type='assigned', user_id=self.user.id, data={ 'assignee': { 'type': 'user', 'name': self.assignee.name, 'email': self.assignee.email, 'id': self.assignee.id, }, }, )
def test_group_created_sends_webhook(self, safe_urlopen): issue = self.create_group(project=self.project) event = self.create_event(group=issue) with self.tasks(): post_process_group( event=event, is_new=True, is_regression=False, is_sample=False, is_new_group_environment=False, ) data = json.loads(faux(safe_urlopen).kwargs['data']) assert data['action'] == 'created' assert data['installation']['uuid'] == self.install.uuid assert data['data']['issue']['id'] == six.text_type(issue.id) assert faux(safe_urlopen).kwargs_contain('headers.Content-Type') assert faux(safe_urlopen).kwargs_contain('headers.Request-ID') assert faux(safe_urlopen).kwargs_contain('headers.Sentry-Hook-Resource') assert faux(safe_urlopen).kwargs_contain('headers.Sentry-Hook-Timestamp') assert faux(safe_urlopen).kwargs_contain('headers.Sentry-Hook-Signature')
def test_kwargs(self, mock): fakefunc(foo=1) assert faux(mock).kwargs == {'foo': 1}
def test_args_and_kwargs(self, mock): fakefunc(True, foo=1) assert faux(mock).args == (True,) assert faux(mock).kwargs == {'foo': 1}
def test_called_with(self, mock): fakefunc(True, foo=1) assert faux(mock).called_with(True, foo=1)
def test_kwargs_contain(self, mock): fakefunc(foo=1) assert faux(mock).kwargs_contain('foo')
def test_kwarg_equals(self, mock): fakefunc(foo=1, bar=2) assert faux(mock).kwarg_equals('bar', 2)
def test_args_contain(self, mock): fakefunc(1, False, None) assert faux(mock).args_contain(False)
def test_args_equal(self, mock): fakefunc(1, False, None) assert faux(mock).args_equals(1, False, None)