def test_simple(self): incident = self.create_incident(date_started=timezone.now() - timedelta(hours=2), projects=[self.project], query="") snapshot = create_initial_event_stats_snapshot(incident) activities = [ create_incident_activity( incident=incident, activity_type=IncidentActivityType.CREATED, user=self.user, comment="hello", event_stats_snapshot=snapshot, ), create_incident_activity( incident=incident, activity_type=IncidentActivityType.COMMENT, user=self.user, comment="goodbye", ), ] expected = serialize(activities, user=self.user) with self.feature("organizations:incidents"): resp = self.get_valid_response(incident.organization.slug, incident.identifier, desc=0) assert resp.data == expected expected.reverse() with self.feature("organizations:incidents"): resp = self.get_valid_response(incident.organization.slug, incident.identifier) assert resp.data == expected
def test_invalid_types(self): for activity_type in (IncidentActivityType.CREATED, IncidentActivityType.DETECTED): activity = create_incident_activity(self.incident, activity_type) send_subscriber_notifications(activity.id) self.send_async.assert_not_called() # NOQA self.send_async.reset_mock()
def test_simple(self): activity = create_incident_activity(self.incident, IncidentActivityType.COMMENT, user=self.user, comment="hello") recipient = self.create_user() self.run_test( activity, expected_username=activity.user.name, expected_action="left a comment", expected_comment=activity.comment, expected_recipient=recipient, ) activity.type = IncidentActivityType.STATUS_CHANGE activity.value = six.text_type(IncidentStatus.CLOSED.value) activity.previous_value = six.text_type(IncidentStatus.WARNING.value) self.run_test( activity, expected_username=activity.user.name, expected_action="changed status from %s to %s" % (IncidentStatus.WARNING.name.lower(), IncidentStatus.CLOSED.name.lower()), expected_comment=activity.comment, expected_recipient=recipient, )
def test_simple(self): activity = create_incident_activity( self.incident, IncidentActivityType.COMMENT, user=self.user, comment='hello', ) self.run_test( activity, expected_username=activity.user.name, expected_action='left a comment', expected_comment=activity.comment, ) activity.type = IncidentActivityType.STATUS_CHANGE activity.value = six.text_type(IncidentStatus.CLOSED.value) activity.previous_value = six.text_type(IncidentStatus.CREATED.value) self.run_test( activity, expected_username=activity.user.name, expected_action='changed status from %s to %s' % ( IncidentStatus.CREATED.name.lower(), IncidentStatus.CLOSED.name.lower(), ), expected_comment=activity.comment, )
def test_snapshot(self): self.create_event(self.now - timedelta(minutes=2)) self.create_event(self.now - timedelta(minutes=2)) self.create_event(self.now - timedelta(minutes=1)) # Define events outside incident range. Should be included in the # snapshot self.create_event(self.now - timedelta(minutes=20)) self.create_event(self.now - timedelta(minutes=30)) # Too far out, should be excluded self.create_event(self.now - timedelta(minutes=100)) incident = self.create_incident(date_started=self.now - timedelta(minutes=5), query='', projects=[self.project]) event_stats_snapshot = create_initial_event_stats_snapshot(incident) activity = create_incident_activity( incident, IncidentActivityType.CREATED, event_stats_snapshot=event_stats_snapshot, ) assert activity.incident == incident assert activity.type == IncidentActivityType.CREATED.value assert activity.value is None assert activity.previous_value is None assert event_stats_snapshot == activity.event_stats_snapshot self.assert_notifications_sent(activity)
def test_simple(self): activity = create_incident_activity( self.incident, IncidentActivityType.COMMENT, user=self.user, comment='hello', ) send_subscriber_notifications(activity.id) # User shouldn't receive an email for their own activity self.send_async.assert_not_called() # NOQA self.send_async.reset_mock() non_member_user = self.create_user(email='*****@*****.**') subscribe_to_incident(activity.incident, non_member_user) member_user = self.create_user(email='*****@*****.**') self.create_member([self.team], user=member_user, organization=self.organization) subscribe_to_incident(activity.incident, member_user) send_subscriber_notifications(activity.id) self.send_async.assert_called_once_with([member_user.email]) assert not IncidentSubscription.objects.filter( incident=activity.incident, user=non_member_user, ).exists() assert IncidentSubscription.objects.filter( incident=activity.incident, user=member_user, ).exists()
def test_mentioned_user_ids(self): incident = self.create_incident() mentioned_member = self.create_user() comment = 'hello **@%s**' % mentioned_member.username with self.assertChanges( lambda: IncidentSubscription.objects.filter( incident=incident, user=mentioned_member, ).exists(), before=False, after=True, ): activity = create_incident_activity( incident, IncidentActivityType.COMMENT, user=self.user, comment=comment, mentioned_user_ids=[mentioned_member.id], ) assert activity.incident == incident assert activity.type == IncidentActivityType.COMMENT.value assert activity.user == self.user assert activity.comment == comment assert activity.value is None assert activity.previous_value is None self.assert_notifications_sent(activity)
def test_event_stats(self): now = datetime.now() with freeze_time((now - timedelta(days=1)).replace(hour=12, minute=30, second=25)): for _ in range(2): self.store_event( data={ "event_id": uuid4().hex, "fingerprint": ["group1"], "timestamp": iso_format(before_now(seconds=1)), }, project_id=self.project.id, ) incident = self.create_incident( date_started=timezone.now() - timedelta(hours=2), projects=[self.project], query="" ) activity = create_incident_activity( incident=incident, activity_type=IncidentActivityType.COMMENT, user=self.user, comment="hello", ) result = serialize(activity) assert result["id"] == six.text_type(activity.id) assert result["incidentIdentifier"] == six.text_type(activity.incident.identifier) assert result["user"] == serialize(activity.user) assert result["type"] == activity.type assert result["value"] is None assert result["previousValue"] is None assert result["comment"] == activity.comment assert result["dateCreated"] == activity.date_added
def test_event_stats(self): for _ in range(2): self.store_event( data={ "event_id": uuid4().hex, "fingerprint": ["group1"], "timestamp": iso_format(before_now(seconds=1)), }, project_id=self.project.id, ) incident = self.create_incident( date_started=timezone.now() - timedelta(hours=2), projects=[self.project], query="" ) snapshot = create_initial_event_stats_snapshot(incident) activity = create_incident_activity( incident=incident, activity_type=IncidentActivityType.COMMENT, user=self.user, comment="hello", event_stats_snapshot=snapshot, ) result = serialize(activity) assert result["id"] == six.text_type(activity.id) assert result["incidentIdentifier"] == six.text_type(activity.incident.identifier) assert result["user"] == serialize(activity.user) assert result["type"] == activity.type assert result["value"] is None assert result["previousValue"] is None assert result["comment"] == activity.comment event_stats = result["eventStats"]["data"] assert [stat[1] for stat in event_stats[:-1]] == [[]] * len(event_stats[:-1]) assert event_stats[-1][1] == [{"count": 2}] assert result["dateCreated"] == activity.date_added
def test_comment(self): incident = self.create_incident() comment = "hello" with self.assertChanges( lambda: IncidentSubscription.objects.filter( incident=incident, user=self.user).exists(), before=False, after=True, ): self.record_event.reset_mock() activity = create_incident_activity(incident, IncidentActivityType.COMMENT, user=self.user, comment=comment) assert activity.incident == incident assert activity.type == IncidentActivityType.COMMENT.value assert activity.user == self.user assert activity.comment == comment assert activity.value is None assert activity.previous_value is None self.assert_notifications_sent(activity) assert len(self.record_event.call_args_list) == 1 event = self.record_event.call_args[0][0] assert isinstance(event, IncidentCommentCreatedEvent) assert event.data == { "organization_id": six.text_type(self.organization.id), "incident_id": six.text_type(incident.id), "incident_type": six.text_type(incident.type), "user_id": six.text_type(self.user.id), "activity_id": six.text_type(activity.id), }
def post(self, request, organization, incident): serializer = CommentSerializer(data=request.DATA) if serializer.is_valid(): activity = create_incident_activity( incident, IncidentActivityType.COMMENT, user=request.user, comment=serializer.object['comment']) return Response(serialize(activity, request.user), status=201) return Response(serializer.errors, status=400)
def test_simple(self): activity = create_incident_activity( self.incident, IncidentActivityType.COMMENT, user=self.user, comment="hello" ) incident = activity.incident recipient = self.create_user() message = generate_incident_activity_email(activity, recipient) assert message.subject == f"Activity on Alert {incident.title} (#{incident.identifier})" assert message.type == "incident.activity" assert message.context == build_activity_context(activity, recipient)
def test_no_snapshot(self): incident = self.create_incident() activity = create_incident_activity( incident, IncidentActivityType.STATUS_CHANGE, user=self.user, value=six.text_type(IncidentStatus.CLOSED.value), previous_value=six.text_type(IncidentStatus.CREATED.value), ) assert activity.incident == incident assert activity.type == IncidentActivityType.STATUS_CHANGE.value assert activity.user == self.user assert activity.value == six.text_type(IncidentStatus.CLOSED.value) assert activity.previous_value == six.text_type(IncidentStatus.CREATED.value)
def test_simple(self): activity = create_incident_activity( self.incident, IncidentActivityType.COMMENT, user=self.user, comment='hello', ) incident = activity.incident message = generate_incident_activity_email(activity) assert message.subject == 'Activity on Incident {} (#{})'.format( incident.title, incident.identifier, ) assert message.type == 'incident.activity' assert message.context == build_activity_context(activity)
def test_simple(self): activity = create_incident_activity( incident=self.create_incident(), activity_type=IncidentActivityType.COMMENT, user=self.user, comment='hello', ) result = serialize(activity) assert result['id'] == six.text_type(activity.id) assert result['incidentIdentifier'] == six.text_type( activity.incident.identifier) assert result['userId'] == six.text_type(activity.user_id) assert result['type'] == activity.type assert result['value'] is None assert result['previousValue'] is None assert result['comment'] == activity.comment
def test_no_snapshot(self): incident = self.create_incident() self.record_event.reset_mock() activity = create_incident_activity( incident, IncidentActivityType.STATUS_CHANGE, user=self.user, value=six.text_type(IncidentStatus.CLOSED.value), previous_value=six.text_type(IncidentStatus.OPEN.value), ) assert activity.incident == incident assert activity.type == IncidentActivityType.STATUS_CHANGE.value assert activity.user == self.user assert activity.value == six.text_type(IncidentStatus.CLOSED.value) assert activity.previous_value == six.text_type(IncidentStatus.OPEN.value) self.assert_notifications_sent(activity) assert not self.record_event.called
def test_no_user(self): activity = create_incident_activity( incident=self.create_incident(), activity_type=IncidentActivityType.COMMENT, user=None, comment="hello", ) result = serialize(activity) assert result["id"] == six.text_type(activity.id) assert result["incidentIdentifier"] == six.text_type(activity.incident.identifier) assert result["user"] is None assert result["type"] == activity.type assert result["value"] is None assert result["previousValue"] is None assert result["comment"] == activity.comment assert result["dateCreated"] == activity.date_added
def test_mentioned_user_ids(self): incident = self.create_incident() mentioned_member = self.create_user() subscribed_mentioned_member = self.create_user() IncidentSubscription.objects.create(incident=incident, user=subscribed_mentioned_member) comment = 'hello **@%s** and **@%s**' % ( mentioned_member.username, subscribed_mentioned_member.username, ) with self.assertChanges( lambda: IncidentSubscription.objects.filter( incident=incident, user=mentioned_member, ).exists(), before=False, after=True, ): self.record_event.reset_mock() activity = create_incident_activity( incident, IncidentActivityType.COMMENT, user=self.user, comment=comment, mentioned_user_ids=[ mentioned_member.id, subscribed_mentioned_member.id ], ) assert activity.incident == incident assert activity.type == IncidentActivityType.COMMENT.value assert activity.user == self.user assert activity.comment == comment assert activity.value is None assert activity.previous_value is None self.assert_notifications_sent(activity) assert len(self.record_event.call_args_list) == 1 event = self.record_event.call_args[0][0] assert isinstance(event, IncidentCommentCreatedEvent) assert event.data == { 'organization_id': six.text_type(self.organization.id), 'incident_id': six.text_type(incident.id), 'incident_type': six.text_type(incident.type), 'user_id': six.text_type(self.user.id), 'activity_id': six.text_type(activity.id), }
def post(self, request, organization, incident): serializer = CommentSerializer( data=request.data, context={"projects": incident.projects.all(), "organization_id": organization.id}, ) if serializer.is_valid(): mentions = extract_user_ids_from_mentions( organization.id, serializer.validated_data.get("mentions", []) ) mentioned_user_ids = mentions["users"] | mentions["team_users"] activity = create_incident_activity( incident, IncidentActivityType.COMMENT, user=request.user, comment=serializer.validated_data["comment"], mentioned_user_ids=mentioned_user_ids, ) return Response(serialize(activity, request.user), status=201) return Response(serializer.errors, status=400)
def test_event_stats(self): for _ in range(2): self.store_event( data={ 'event_id': uuid4().hex, 'fingerprint': ['group1'], 'timestamp': (timezone.now() - timedelta(seconds=1)).isoformat()[:19] }, project_id=self.project.id, ) incident = self.create_incident( date_started=timezone.now() - timedelta(hours=2), projects=[self.project], query='', ) snapshot = create_initial_event_stats_snapshot(incident) activity = create_incident_activity( incident=incident, activity_type=IncidentActivityType.COMMENT, user=self.user, comment='hello', event_stats_snapshot=snapshot, ) result = serialize(activity) assert result['id'] == six.text_type(activity.id) assert result['incidentIdentifier'] == six.text_type( activity.incident.identifier) assert result['user'] == serialize(activity.user) assert result['type'] == activity.type assert result['value'] is None assert result['previousValue'] is None assert result['comment'] == activity.comment event_stats = result['eventStats']['data'] assert [stat[1] for stat in event_stats[:-1]] == [[]] * len(event_stats[:-1]) assert event_stats[-1][1] == [{'count': 2}] assert result['dateCreated'] == activity.date_added
def post(self, request, organization, incident): serializer = CommentSerializer( data=request.DATA, context={ 'projects': incident.projects.all(), 'organization_id': organization.id }, ) if serializer.is_valid(): mentions = extract_user_ids_from_mentions( organization.id, serializer.object.get('mentions', []), ) mentioned_user_ids = mentions['users'] | mentions['team_users'] activity = create_incident_activity( incident, IncidentActivityType.COMMENT, user=request.user, comment=serializer.object['comment'], mentioned_user_ids=mentioned_user_ids, ) return Response(serialize(activity, request.user), status=201) return Response(serializer.errors, status=400)
def test_comment(self): incident = self.create_incident() comment = 'hello' with self.assertChanges( lambda: IncidentSubscription.objects.filter( incident=incident, user=self.user, ).exists(), before=False, after=True, ): activity = create_incident_activity( incident, IncidentActivityType.COMMENT, user=self.user, comment=comment, ) assert activity.incident == incident assert activity.type == IncidentActivityType.COMMENT.value assert activity.user == self.user assert activity.comment == comment assert activity.value is None assert activity.previous_value is None