Skip to content

Commit bf92a29

Browse files
author
Anogio
authored
Ticketing PR reviews (jsocol#125)
1 parent 908adbe commit bf92a29

File tree

18 files changed

+179
-56
lines changed

18 files changed

+179
-56
lines changed

tests/adapters/test_message_router_ticket_creator.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import pytest
2+
from requests import Timeout
3+
from requests.exceptions import ConnectionError # pylint: disable=redefined-builtin
4+
from requests.exceptions import RequestException
25

36
from tests import common
47
from use_case_executor import config
@@ -7,7 +10,9 @@
710
)
811
from use_case_executor.domain.errors import ImpossibleTicketCreation
912
from use_case_executor.domain.flow.node_data.create_ticket_data import SystemField
10-
from use_case_executor.domain.message_processing.ticket_creator import SystemFieldValue
13+
from use_case_executor.domain.message_processing.system_field_value import (
14+
SystemFieldValue,
15+
)
1116

1217

1318
def test_creates_ticket_and_returns_response(responses):
@@ -17,16 +22,14 @@ def test_creates_ticket_and_returns_response(responses):
1722
json={"ticket": {"id": 123}},
1823
)
1924

20-
result = MessageRouterTicketCreator().create_ticket(
25+
MessageRouterTicketCreator().create_ticket(
2126
system_field_values=[
2227
SystemFieldValue(
2328
system_field=SystemField.ticket_description, value="a value"
2429
)
2530
]
2631
)
2732

28-
assert result == {"ticket": {"id": 123}}
29-
3033
common.assert_responses_call(
3134
call=responses.calls[0],
3235
method="POST",
@@ -39,11 +42,20 @@ def test_creates_ticket_and_returns_response(responses):
3942
)
4043

4144

42-
def test_raises_if_error(responses):
45+
@pytest.mark.parametrize(
46+
"message_router_mock_params",
47+
[
48+
{"status": 400},
49+
{"body": ConnectionError()},
50+
{"body": Timeout()},
51+
{"body": RequestException()},
52+
],
53+
)
54+
def test_raises_if_error(responses, message_router_mock_params):
4355
responses.add(
4456
responses.POST,
4557
url=f"{config.MESSAGE_ROUTER_URL}/create_ticket",
46-
status=400,
58+
**message_router_mock_params,
4759
)
4860

4961
with pytest.raises(ImpossibleTicketCreation):

tests/domain/execute_flow_from_position/test_answer_node_bubbles_and_plain_text_pieces.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def test_raises_if_no_text_in_language(
9494

9595
with pytest.raises(
9696
InvalidFlowConfiguration,
97-
match="Empty text for answer in language another_language",
97+
match="Empty text for bubble in language another_language",
9898
):
9999
facade.execute_flow_from_position(
100100
flow=flow,

tests/domain/execute_flow_from_position/test_create_ticket_node.py

Lines changed: 117 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
from tests import common
77
from use_case_executor.domain import facade
8+
from use_case_executor.domain.errors import InvalidFlowConfiguration
89
from use_case_executor.domain.flow.edge_data.quick_reply_data import QuickReplyData
9-
from use_case_executor.domain.flow.node_data.bubble import (
10-
PlainTextPieceData,
11-
)
10+
from use_case_executor.domain.flow.node_data.bubble import Bubble
11+
from use_case_executor.domain.flow.node_data.bubble import PlainTextPieceData
1212
from use_case_executor.domain.flow.node_data.bubble import TextPiece
1313
from use_case_executor.domain.flow.node_data.bubble import (
1414
TextPieceDataType,
@@ -30,7 +30,9 @@
3030
from use_case_executor.domain.flow_execution.position import StartPosition
3131
from use_case_executor.domain.flow_execution.position import SubstepPosition
3232
from use_case_executor.domain.flow_execution.substeps.substep_names import SubstepName
33-
from use_case_executor.domain.message_processing.ticket_creator import SystemFieldValue
33+
from use_case_executor.domain.message_processing.system_field_value import (
34+
SystemFieldValue,
35+
)
3436

3537

3638
@pytest.fixture
@@ -141,7 +143,114 @@ def test_creates_ticket_and_returns_success_bubbles(
141143
)
142144

143145

144-
# TODO: discuss with @vincent: the other cases (unknown variable, wrong language, etc) are already tested in
145-
# the answer node tests. This seems to mean we should mock out the "render text piece" and "render bubble"
146-
# here, and maybe have dedicated tests for them rather than test them in the answer. Or maybe even put them in
147-
# the facade ? I'm not sure here, we could also just duplicate the tests but it feels strange
146+
def test_variables_without_value_are_replaced_by_empty_strings(
147+
mocker,
148+
mock_repository,
149+
mock_ticket_creator,
150+
flow,
151+
create_ticket_node_uuid,
152+
execution_environment,
153+
):
154+
ticket_creation_data: CreateTicketData = flow.get_node(
155+
uuid=create_ticket_node_uuid
156+
).data
157+
ticket_creation_data.ticket_creation_success_bubbles = [
158+
Bubble(
159+
delay_seconds=0,
160+
templated_text_translations={
161+
execution_environment.language: [
162+
TextPiece(
163+
type=TextPieceDataType.variable,
164+
data=VariableTextPieceData(variable_uuid=uuid.uuid4()),
165+
),
166+
TextPiece(
167+
type=TextPieceDataType.plain_text,
168+
data=PlainTextPieceData(text="text"),
169+
),
170+
]
171+
},
172+
)
173+
]
174+
175+
mock_ticket_creator.set_create_ticket_mock(mocker=mocker, return_value={})
176+
mock_repository.set_query_variable_value_return_value(
177+
mocker=mocker, return_value=None
178+
)
179+
180+
flow_execution_result = facade.execute_flow_from_position(
181+
flow=flow,
182+
position=NodePosition(
183+
use_case_uuid=execution_environment.use_case_uuid,
184+
node_uuid=create_ticket_node_uuid,
185+
),
186+
execution_environment=execution_environment,
187+
)
188+
189+
mock_ticket_creator.assert_create_ticket_called_once_with(
190+
system_field_values=[
191+
SystemFieldValue(system_field=SystemField.client_email, value="Email")
192+
]
193+
)
194+
195+
assert flow_execution_result == FlowExecutionResult(
196+
answer=Answer(
197+
text="text",
198+
buttons=[],
199+
tracked_links=[],
200+
quick_replies=[],
201+
with_csat=False,
202+
agent_channel_redirection_uuid=None,
203+
),
204+
next_position=StartPosition(),
205+
last_executed_node_uuid=create_ticket_node_uuid,
206+
)
207+
208+
209+
def test_returns_fallback_if_no_success_message_in_language(
210+
mocker,
211+
mock_repository,
212+
mock_ticket_creator,
213+
flow,
214+
create_ticket_node_uuid,
215+
execution_environment,
216+
):
217+
ticket_creation_data: CreateTicketData = flow.get_node(
218+
uuid=create_ticket_node_uuid
219+
).data
220+
ticket_creation_data.ticket_creation_success_bubbles = [
221+
Bubble(
222+
delay_seconds=0,
223+
templated_text_translations={
224+
"another_language": [
225+
TextPiece(
226+
type=TextPieceDataType.plain_text,
227+
data=PlainTextPieceData(text="text"),
228+
)
229+
]
230+
},
231+
)
232+
]
233+
234+
mock_ticket_creator.set_create_ticket_mock(mocker=mocker, return_value={})
235+
mock_repository.set_query_variable_value_return_value(
236+
mocker=mocker, return_value=None
237+
)
238+
239+
with pytest.raises(
240+
InvalidFlowConfiguration,
241+
match=f"Empty text for bubble in language {execution_environment.language}",
242+
):
243+
facade.execute_flow_from_position(
244+
flow=flow,
245+
position=NodePosition(
246+
use_case_uuid=execution_environment.use_case_uuid,
247+
node_uuid=create_ticket_node_uuid,
248+
),
249+
execution_environment=execution_environment,
250+
)
251+
252+
mock_ticket_creator.assert_create_ticket_called_once_with(
253+
system_field_values=[
254+
SystemFieldValue(system_field=SystemField.client_email, value="Email")
255+
]
256+
)

tests/domain/execute_use_case_and_send_answer/test_variables_validation.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# pylint: disable=redefined-outer-name
2+
import contextlib
23
import dataclasses
34
import datetime as dt
45
import uuid
5-
from contextlib import contextmanager
66

77
import pytest
88

@@ -30,11 +30,6 @@
3030
from use_case_executor.domain.use_case.use_case_version import UseCaseVersion
3131

3232

33-
@contextmanager
34-
def does_not_raise():
35-
yield
36-
37-
3833
@pytest.fixture
3934
def variable_uuid():
4035
return uuid.uuid4()
@@ -57,7 +52,7 @@ def flow(content_language):
5752
match="The flow to be executed uses variables that are not defined on this instance",
5853
),
5954
),
60-
(True, does_not_raise()),
55+
(True, contextlib.nullcontext()),
6156
],
6257
)
6358
def test_unknown_variable_in_user_input_node_raises_invalid_flow_configuration_error(
@@ -142,7 +137,7 @@ def test_unknown_variable_in_user_input_node_raises_invalid_flow_configuration_e
142137
match="The flow to be executed uses variables that are not defined on this instance",
143138
),
144139
),
145-
(True, does_not_raise()),
140+
(True, contextlib.nullcontext()),
146141
],
147142
)
148143
def test_unknown_variable_in_variable_text_piece_data_raises_invalid_flow_configuration_error(
@@ -224,7 +219,7 @@ def test_unknown_variable_in_variable_text_piece_data_raises_invalid_flow_config
224219
match="The flow to be executed uses variables that are not defined on this instance",
225220
),
226221
),
227-
(True, does_not_raise()),
222+
(True, contextlib.nullcontext()),
228223
],
229224
)
230225
def test_unknown_variable_in_variable_text_piece_data_in_create_ticket_raises_invalid_flow_configuration_error(
@@ -323,7 +318,7 @@ def test_unknown_variable_in_variable_text_piece_data_in_create_ticket_raises_in
323318
match="The flow to be executed uses variables that are not defined on this instance",
324319
),
325320
),
326-
(True, does_not_raise()),
321+
(True, contextlib.nullcontext()),
327322
],
328323
)
329324
def test_unknown_variable_in_variable_text_piece_data_in_create_ticket_success_raises_invalid_flow_configuration_error(

tests/domain/mocks/mock_ticket_creator.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from uuid import UUID
22

3-
from use_case_executor.domain.message_processing.ticket_creator import SystemFieldValue
3+
from use_case_executor.domain.message_processing.system_field_value import (
4+
SystemFieldValue,
5+
)
46
from use_case_executor.domain.message_processing.ticket_creator import TicketCreator
57

68

79
class MockTicketCreator(TicketCreator):
8-
def create_ticket(self, system_field_values: list[SystemFieldValue]) -> dict:
10+
def create_ticket(self, system_field_values: list[SystemFieldValue]) -> None:
911
raise AssertionError("This test method should never be called")
1012

1113
def set_create_ticket_mock(self, mocker, return_value: bool) -> None:

tests/worker/flow_execution/test_answer_node_text.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,4 @@ def test_flow_returns_fallback_message_when_answer_text_is_empty(
105105
)
106106

107107
with caplog.at_level(logging.ERROR):
108-
assert f"Empty text for answer in language {content_language}" in caplog.text
108+
assert f"Empty text for bubble in language {content_language}" in caplog.text

use_case_executor/adapters/flow_validation/node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ def convert_data_from_domain_object(
9090
for domain_data_type, data_type in [
9191
(DomainAgentHandoverData, AgentHandoverData),
9292
(DomainAnswerData, AnswerData),
93+
(DomainCreateTicketData, CreateTicketData),
9394
(DomainEmptyData, EmptyData),
9495
(DomainGoToUseCaseData, GoToUseCaseData),
9596
(DomainUserInputData, UserInputData),
96-
(DomainCreateTicketData, CreateTicketData),
9797
]:
9898
if isinstance(domain_node_data, domain_data_type):
9999
assert data is None

use_case_executor/adapters/flow_validation/node_data/create_ticket_data.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ def to_domain_object(self) -> DomainSystemFieldValueTemplate:
3333
def from_domain_object(
3434
cls, domain_system_field_value_template: DomainSystemFieldValueTemplate
3535
) -> "SystemFieldValueTemplate":
36-
3736
return cls(
3837
system_field=domain_system_field_value_template.system_field,
3938
value_template=[
@@ -63,7 +62,6 @@ def to_domain_object(self) -> DomainCreateTicketData:
6362
def from_domain_object(
6463
cls, domain_node_data: DomainCreateTicketData
6564
) -> "CreateTicketData":
66-
6765
return cls(
6866
system_field_value_templates=[
6967
SystemFieldValueTemplate.from_domain_object(field)

use_case_executor/adapters/message_router_ticket_creator.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
from requests import HTTPError
1+
from requests import RequestException
22

33
from use_case_executor import config
44
from use_case_executor.domain.errors import ImpossibleTicketCreation
5-
from use_case_executor.domain.message_processing.ticket_creator import SystemFieldValue
5+
from use_case_executor.domain.message_processing.system_field_value import (
6+
SystemFieldValue,
7+
)
68
from use_case_executor.domain.message_processing.ticket_creator import TicketCreator
79
from use_case_executor.monitoring import monitored_requests
810

911

1012
class MessageRouterTicketCreator(TicketCreator):
11-
def create_ticket(self, system_field_values: list[SystemFieldValue]) -> dict:
13+
def create_ticket(self, system_field_values: list[SystemFieldValue]) -> None:
1214
try:
1315
response = monitored_requests.post(
1416
url=f"{config.MESSAGE_ROUTER_URL}/create_ticket",
@@ -24,6 +26,5 @@ def create_ticket(self, system_field_values: list[SystemFieldValue]) -> dict:
2426
},
2527
)
2628
monitored_requests.raise_for_status_with_logging(response)
27-
except HTTPError as exc:
29+
except RequestException as exc:
2830
raise ImpossibleTicketCreation("Could not create ticket") from exc
29-
return response.json()

use_case_executor/api/namespaces/use_cases/clone_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def create_new_use_case_and_version(
8989

9090
def _create_new_variables_for_flow(
9191
instance_id: int, flow: DomainFlow, session: Session
92-
):
92+
) -> None:
9393
flow_variable_uuids = variables_flow_visitor.collect_all_variable_uuids_in_flow(
9494
flow=flow
9595
)

0 commit comments

Comments
 (0)