Skip to content

Commit

Permalink
pair programming and test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
Alicia Matsumoto committed Jan 3, 2025
1 parent 9f95d24 commit 0d2615b
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 8 deletions.
13 changes: 8 additions & 5 deletions src/dispatch/signal/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,17 @@ def signal_instance_create_flow(
oncall_service = signal_instance.oncall_service
elif signal_instance.signal.oncall_service:
oncall_service = signal_instance.signal.oncall_service
elif signal_instance.case_type.oncall_service:
oncall_service = signal_instance.case_type.oncall_service
elif case_type.oncall_service:
oncall_service = case_type.oncall_service
else:
oncall_service = None

if signal_instance.conversation_target:
conversation_target = signal_instance.conversation_target
elif signal_instance.signal.conversation_target:
conversation_target = signal_instance.signal.conversation_target
elif signal_instance.case_type.conversation_target:
conversation_target = signal_instance.case_type.conversation_target
elif case_type.conversation_target:
conversation_target = case_type.conversation_target
else:
conversation_target = None

Expand Down Expand Up @@ -176,7 +176,10 @@ def create_signal_instance(
raise DispatchException("Signal definition is not enabled.")

signal_instance_in = SignalInstanceCreate(
raw=signal_instance_data, signal=signal, project=signal.project
**signal_instance_data,
raw=signal_instance_data,
signal=signal,
project=signal.project,
)

signal_instance = signal_service.create_instance(
Expand Down
4 changes: 2 additions & 2 deletions src/dispatch/signal/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
TimeStampMixin,
)
from dispatch.project.models import ProjectRead
from dispatch.service.models import Service
from dispatch.service.models import Service, ServiceRead
from dispatch.tag.models import TagRead
from dispatch.workflow.models import WorkflowRead

Expand Down Expand Up @@ -391,7 +391,7 @@ class SignalInstanceCreate(SignalInstanceBase):
case_priority: Optional[CasePriorityRead]
case_type: Optional[CaseTypeRead]
conversation_target: Optional[str]
oncall_service: Optional[Service]
oncall_service: Optional[ServiceRead]


class SignalInstanceRead(SignalInstanceBase):
Expand Down
16 changes: 15 additions & 1 deletion src/dispatch/signal/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,11 @@ def create_instance(

signal = get(db_session=db_session, signal_id=signal_instance_in.signal.id)

# remove non-serializable entities from the raw JSON:
signal_instance_in_raw = signal_instance_in.raw.copy()
if signal_instance_in.oncall_service:
signal_instance_in_raw.pop('oncall_service')

# we round trip the raw data to json-ify date strings
signal_instance = SignalInstance(
**signal_instance_in.dict(
Expand All @@ -580,12 +585,13 @@ def create_instance(
"case_type",
"entities",
"external_id",
"oncall_service",
"project",
"raw",
"signal",
}
),
raw=json.loads(json.dumps(signal_instance_in.raw)),
raw=json.loads(json.dumps(signal_instance_in_raw)),
project=project,
signal=signal,
)
Expand Down Expand Up @@ -619,6 +625,14 @@ def create_instance(
)
signal_instance.case_type = case_type

if signal_instance_in.oncall_service:
oncall_service = service_service.get_by_name(
db_session=db_session,
project_id=project.id,
name=signal_instance_in.oncall_service.name,
)
signal_instance.oncall_service = oncall_service

db_session.add(signal_instance)
db_session.commit()
return signal_instance
Expand Down
180 changes: 180 additions & 0 deletions tests/signal/test_signal_flow.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from unittest import mock
from unittest.mock import MagicMock

import pytest

from dispatch.exceptions import DispatchException
Expand Down Expand Up @@ -59,3 +62,180 @@ def test_create_signal_instance_not_enabled(session, signal, case_severity, case
signal_instance_data=instance_data,
current_user=user,
)

def test_create_signal_instance_custom_conversation_target(session, signal, case_severity, case_priority, user, case_type):
from dispatch.signal.flows import create_signal_instance

case_priority.default = True
case_priority.project_id = signal.project_id

case_severity.default = True
case_severity.project_id = signal.project_id

instance_data = {"variant": signal.variant, "conversation_target": "instance-conversation-target"}
signal.conversation_target = "signal-conversation-target"

signal_instance = create_signal_instance(
db_session=session,
project=signal.project,
signal_instance_data=instance_data,
current_user=user,
)
assert signal_instance.conversation_target == 'instance-conversation-target'


def test_create_signal_instance_custom_oncall_service(session, signal, case_severity, case_priority, user, services):
from dispatch.signal.flows import create_signal_instance

case_priority.default = True
case_priority.project_id = signal.project_id

case_severity.default = True
case_severity.project_id = signal.project_id

service_0, service_1 = services
service_0.project_id = signal.project_id
service_1.project_id = signal.project_id

signal.oncall_service = service_0
instance_data = {"variant": signal.variant, "oncall_service": service_1}

signal_instance = create_signal_instance(
db_session=session,
project=signal.project,
signal_instance_data=instance_data,
current_user=user,
)
assert signal_instance.oncall_service.id == service_1.id

def test_signal_instance_create_flow_custom_attributes(session, signal, case_severity, case_priority, user, services, signal_instance, oncall_plugin, case_type, case):
from dispatch.signal.flows import signal_instance_create_flow
from dispatch.service import flows as service_flows
from dispatch.case import service as case_service

case_priority.default = True
case_priority.project_id = signal.project_id

case_severity.default = True
case_severity.project_id = signal.project_id

service_0, service_1 = services
service_0.project_id = signal.project_id
service_1.project_id = signal.project_id

signal_instance.oncall_service = service_0
signal_instance.signal.oncall_service = service_1
signal_instance.conversation_target = "instance-conversation-target"
signal_instance.signal.conversation_target = "signal-conversation-target"

with mock.patch.object(service_flows, "resolve_oncall") as mock_resolve_oncall, \
mock.patch.object(case_service, "create") as mock_case_create, \
mock.patch("dispatch.case.flows.case_new_create_flow") as mock_case_new_create_flow:
mock_resolve_oncall.side_effect = lambda service, db_session: "[email protected]" if service.id == service_0.id else None
mock_case_create.return_value = case

post_flow_instance = signal_instance_create_flow(
signal_instance_id=signal_instance.id,
db_session=session,
current_user=user
)
case_in_arg = mock_case_create.call_args[1]['case_in']
assert case_in_arg.assignee.individual.email == "[email protected]"
mock_case_new_create_flow.assert_called_once_with(
db_session=session,
organization_slug=None,
service_id=None,
conversation_target="instance-conversation-target",
case_id=post_flow_instance.case.id,
create_all_resources=False
)

def test_signal_instance_create_flow_use_signal_attributes(session, signal, case_severity, case_priority, user, services, signal_instance,
case_type, case):
"""
If the signal instance does not specify a conversation target or on-call service, use the signal's configurations
before the case type's configurations.
"""
from dispatch.signal.flows import signal_instance_create_flow
from dispatch.service import flows as service_flows
from dispatch.case import service as case_service

case_priority.default = True
case_priority.project_id = signal.project_id

case_severity.default = True
case_severity.project_id = signal.project_id

service_0, service_1 = services
service_0.project_id = signal.project_id
service_1.project_id = signal.project_id

signal_instance.signal.oncall_service = service_0
signal_instance.signal.conversation_target = "signal-conversation-target"
case_type.oncall_service = service_1
case_type.conversation_target = "case-type-conversation-target"
signal_instance.signal.case_type = case_type

with mock.patch.object(service_flows, "resolve_oncall") as mock_resolve_oncall, \
mock.patch.object(case_service, "create") as mock_case_create, \
mock.patch("dispatch.case.flows.case_new_create_flow") as mock_case_new_create_flow:

mock_resolve_oncall.side_effect = lambda service, db_session: "[email protected]" if service.id == service_0.id else None
mock_case_create.return_value = case

post_flow_instance = signal_instance_create_flow(
signal_instance_id=signal_instance.id,
db_session=session,
current_user=user
)
case_in_arg = mock_case_create.call_args[1]['case_in']
assert case_in_arg.assignee.individual.email == "[email protected]"
mock_case_new_create_flow.assert_called_once_with(
db_session=session,
organization_slug=None,
service_id=None,
conversation_target="signal-conversation-target",
case_id=post_flow_instance.case.id,
create_all_resources=False
)


def test_signal_instance_create_flow_use_case_type_attributes(session, signal, case_severity, case_priority, user, service, case, signal_instance, case_type):
"""
If the signal instance and the signal both do not specify conversation targets or on-call services, use the case type's configurations.
"""
from dispatch.signal.flows import signal_instance_create_flow
from dispatch.service import flows as service_flows
from dispatch.case import service as case_service

case_priority.default = True
case_priority.project_id = signal.project_id

case_severity.default = True
case_severity.project_id = signal.project_id

case_type.oncall_service = service
case_type.conversation_target = "case-type-conversation-target"
signal_instance.signal.case_type = case_type

with mock.patch.object(service_flows, "resolve_oncall") as mock_resolve_oncall, \
mock.patch.object(case_service, "create") as mock_case_create, \
mock.patch("dispatch.case.flows.case_new_create_flow") as mock_case_new_create_flow:
mock_resolve_oncall.side_effect = lambda service, db_session: "[email protected]"
mock_case_create.return_value = case

post_flow_instance = signal_instance_create_flow(
signal_instance_id=signal_instance.id,
db_session=session,
current_user=user
)
case_in_arg = mock_case_create.call_args[1]['case_in']
assert case_in_arg.assignee.individual.email == "[email protected]"
mock_case_new_create_flow.assert_called_once_with(
db_session=session,
organization_slug=None,
service_id=None,
conversation_target="case-type-conversation-target",
case_id=post_flow_instance.case.id,
create_all_resources=False
)

0 comments on commit 0d2615b

Please sign in to comment.