def test_warning_when_unable_to_determine_purpose_of_message():
    mock_logger = Mock()
    mock_probe = Gp2gpConversationObservabilityProbe(mock_logger)

    unknown_message_purpose_message = build_message(
        conversation_id="ASD",
        guid="abc",
        interaction_id="urn:nhs:names:services:gp2gp/RCMR_IN010000UK08",
    )
    messages = [
        build_message(
            conversation_id="ASD",
            interaction_id=EHR_REQUEST_STARTED,
        ),
        unknown_message_purpose_message,
    ]

    Gp2gpConversation(messages=messages, probe=mock_probe)

    mock_logger.warning.assert_called_once_with(
        f":Couldn't determine purpose of message with guid: {unknown_message_purpose_message.guid}",
        extra={
            "event": "UNKNOWN_MESSAGE_PURPOSE",
            "conversation_id": unknown_message_purpose_message.conversation_id,
            "interaction_id": unknown_message_purpose_message.interaction_id,
        },
    )
Exemple #2
0
def test_parse_conversation_parses_a_complete_conversation():
    request_started_message = build_message(
        interaction_id=EHR_REQUEST_STARTED, )
    request_completed_message = build_message(
        guid="54F949C0-DC7F-4EBC-8AE2-72BF2D0AF4EE",
        interaction_id=EHR_REQUEST_COMPLETED,
    )
    request_started_ack_message = build_message(
        interaction_id=APPLICATION_ACK, )
    request_completed_ack_message = build_message(
        interaction_id=APPLICATION_ACK,
        message_ref="54F949C0-DC7F-4EBC-8AE2-72BF2D0AF4EE",
    )

    messages = [
        request_started_message,
        request_completed_message,
        request_started_ack_message,
        request_completed_ack_message,
    ]

    conversation = Conversation("F8DAFCAA-5012-427B-BDB4-354256A4874B",
                                messages)

    expected = ParsedConversation(
        id="F8DAFCAA-5012-427B-BDB4-354256A4874B",
        request_started=request_started_message,
        request_completed=request_completed_message,
        request_completed_ack=request_completed_ack_message,
    )
    actual = parse_conversation(conversation)

    assert actual == expected
Exemple #3
0
def test_parse_conversation_parses_incomplete_conversation():
    request_started_message = build_message(
        interaction_id="urn:nhs:names:services:gp2gp/RCMR_IN010000UK05", )
    request_completed_message = build_message(
        interaction_id="urn:nhs:names:services:gp2gp/RCMR_IN030000UK06", )
    request_started_ack_message = build_message(
        interaction_id="urn:nhs:names:services:gp2gp/MCCI_IN010000UK13", )

    messages = [
        request_started_message,
        request_completed_message,
        request_started_ack_message,
    ]

    conversation = Conversation("F8DAFCAA-5012-427B-BDB4-354256A4874B",
                                messages)

    expected = ParsedConversation(
        id="F8DAFCAA-5012-427B-BDB4-354256A4874B",
        request_started=request_started_message,
        request_completed=request_completed_message,
        request_completed_ack=None,
    )
    actual = parse_conversation(conversation)

    assert actual == expected
def test_filter_conversations_by_request_started_time_rejects_conversations_outside_of_range(
):
    date_range = DateTimeRange(start=datetime(year=2020, month=6, day=1),
                               end=datetime(year=2020, month=7, day=1))

    conversation_within_range = build_parsed_conversation(
        request_started=build_message(
            time=datetime(year=2020, month=6, day=15)))
    conversation_before_range = build_parsed_conversation(
        request_started=build_message(
            time=datetime(year=2020, month=5, day=28)))
    conversation_after_range = build_parsed_conversation(
        request_started=build_message(
            time=datetime(year=2020, month=7, day=28)))

    parsed_conversations = [
        conversation_before_range,
        conversation_within_range,
        conversation_after_range,
    ]

    expected = [conversation_within_range]

    actual = filter_conversations_by_request_started_time(
        parsed_conversations, date_range)

    assert list(actual) == expected
def test_parses_a_complete_conversation():
    request_started_message = build_message(guid="abc", interaction_id=EHR_REQUEST_STARTED)
    request_completed_message = build_message(guid="abc-1", interaction_id=EHR_REQUEST_COMPLETED)
    request_started_ack_message = build_message(interaction_id=APPLICATION_ACK, message_ref="abc")
    request_completed_ack_message = build_message(
        interaction_id=APPLICATION_ACK,
        message_ref="abc-1",
    )

    messages = [
        request_started_message,
        request_completed_message,
        request_started_ack_message,
        request_completed_ack_message,
    ]

    conversation = Conversation("abc-0", messages)

    expected = ParsedConversation(
        id="abc-0",
        request_started=request_started_message,
        request_started_ack=request_started_ack_message,
        request_completed=request_completed_message,
        intermediate_messages=[],
        request_completed_ack=request_completed_ack_message,
    )
    actual = parse_conversation(conversation)

    assert actual == expected
def test_intermediate_error_code_is_empty_list_if_no_errors():
    intermediate_messages = [build_message(), build_message(), build_message()]
    conversations = [build_parsed_conversation(intermediate_messages=intermediate_messages)]

    actual = derive_transfers(conversations)

    expected_intermediate_error_codes = [[]]

    _assert_attributes("intermediate_error_codes", actual, expected_intermediate_error_codes)
Exemple #7
0
def test_is_acknowledgement_of_returns_false_when_message_ref_is_wrong():
    message = build_message(interaction_id=APPLICATION_ACK, message_ref="123")
    other_message = build_message(guid="456")

    expected = False

    actual = message.is_acknowledgement_of(other_message)

    assert actual == expected
Exemple #8
0
def test_is_acknowledgement_of_returns_false_when_message_is_not_an_ack():
    message = build_message(interaction_id=COMMON_POINT_TO_POINT,
                            message_ref="123")
    other_message = build_message(guid="123")

    expected = False

    actual = message.is_acknowledgement_of(other_message)

    assert actual == expected
def test_group_into_conversations_produces_correct_conversations():
    message_one = build_message(conversation_id="abc")
    message_two = build_message(conversation_id="xyz")
    messages = [message_one, message_two]

    expected = [Conversation("abc", [message_one]), Conversation("xyz", [message_two])]

    actual = group_into_conversations(messages)

    assert list(actual) == expected
Exemple #10
0
def test_is_acknowledgement_of_returns_true_when_given_message_with_matching_ref(
):
    message = build_message(interaction_id=APPLICATION_ACK, message_ref="123")
    other_message = build_message(guid="123")

    expected = True

    actual = message.is_acknowledgement_of(other_message)

    assert actual == expected
def test_group_into_conversations_sorts_messages_within_conversations():
    message_one = build_message(conversation_id="abc", time=datetime(year=2020, month=6, day=6))
    message_two = build_message(conversation_id="abc", time=datetime(year=2020, month=6, day=5))
    messages = [message_one, message_two]

    expected = [Conversation("abc", [message_two, message_one])]

    actual = group_into_conversations(messages)

    assert list(actual) == expected
def test_warns_about_conversation_with_negative_sla():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            request_completed=build_message(time=datetime(year=2021, month=1, day=5)),
            request_completed_ack=build_message(time=datetime(year=2021, month=1, day=4)),
        )
    ]

    with pytest.warns(RuntimeWarning):
        list(derive_transfers(conversations))
def test_derive_transfer_produces_no_sla_given_pending_request_completed_ack():
    conversation = build_parsed_conversation(
        request_started=build_message(),
        request_completed=build_message(),
        request_completed_ack=None,
    )
    actual = derive_transfer(conversation)

    expected_sla_duration = None

    assert actual.sla_duration == expected_sla_duration
def test_derive_transfer_flags_completed_conversation_as_not_pending():
    conversation = build_parsed_conversation(
        request_started=build_message(),
        request_completed=build_message(),
        request_completed_ack=build_message(),
    )

    actual = derive_transfer(conversation)

    expected_pending = False

    assert actual.pending == expected_pending
def test_date_completed_is_none_when_request_completed_ack_not_present():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            request_completed=build_message(),
            request_completed_ack=None,
        )
    ]

    actual = derive_transfers(conversations)

    _assert_attributes("date_completed", actual, [None])
def test_extracts_multiple_intermediate_message_error_codes():
    intermediate_messages = [
        build_message(error_code=11),
        build_message(),
        build_message(error_code=10),
    ]
    conversations = [build_parsed_conversation(intermediate_messages=intermediate_messages)]

    actual = derive_transfers(conversations)

    expected_intermediate_error_codes = [[11, 10]]

    _assert_attributes("intermediate_error_codes", actual, expected_intermediate_error_codes)
def test_has_pending_status_if_no_final_ack_and_no_intermediate_error():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            intermediate_messages=[build_message(error_code=None)],
            request_completed_ack=None,
        )
    ]

    actual = derive_transfers(conversations)

    expected_statuses = [TransferStatus.PENDING]

    _assert_attributes("status", actual, expected_statuses)
def test_produces_no_sla_given_pending_request_completed_ack():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            request_completed=build_message(),
            request_completed_ack=None,
        )
    ]

    actual = derive_transfers(conversations)

    expected_sla_durations = [None]

    _assert_attributes("sla_duration", actual, expected_sla_durations)
def test_negative_sla_duration_clamped_to_zero():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            request_completed=build_message(time=datetime(year=2021, month=1, day=5)),
            request_completed_ack=build_message(time=datetime(year=2021, month=1, day=4)),
        )
    ]

    expected_sla = timedelta(0)

    actual = derive_transfers(conversations)

    _assert_attributes("sla_duration", actual, [expected_sla])
def test_has_integrated_status_if_error_is_supressed():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            request_completed=build_message(),
            request_completed_ack=build_message(error_code=ERROR_SUPPRESSED),
        )
    ]

    actual = derive_transfers(conversations)

    expected_statuses = [TransferStatus.INTEGRATED]

    _assert_attributes("status", actual, expected_statuses)
def test_has_failed_status_if_error_in_final_ack():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            request_completed=build_message(),
            request_completed_ack=build_message(error_code=30),
        )
    ]

    actual = derive_transfers(conversations)

    expected_statuses = [TransferStatus.FAILED]

    _assert_attributes("status", actual, expected_statuses)
def test_extracts_date_requested_from_request_started_message():
    date_requested = a_datetime()

    conversations = [
        build_parsed_conversation(
            request_started=build_message(time=date_requested),
            request_completed=build_message(),
            request_completed_ack=build_message(),
        )
    ]

    actual = derive_transfers(conversations)

    _assert_attributes("date_requested", actual, [date_requested])
Exemple #23
0
def test_produces_correct_conversations():
    message_one = build_message(conversation_id="abc")
    message_two = build_message(conversation_id="xyz")
    messages = [message_one, message_two]

    expected = [Conversation("abc", [message_one]), Conversation("xyz", [message_two])]

    transfer_service = TransferService(
        message_stream=messages,
        cutoff=timedelta(days=14),
        observability_probe=mock_transfer_observability_probe,
    )
    actual = transfer_service.group_into_conversations()

    assert list(actual) == expected
def test_has_pending_with_error_status_if_error_in_intermediate_message():
    conversations = [
        build_parsed_conversation(
            request_started=build_message(),
            request_completed=build_message(),
            intermediate_messages=[build_message(error_code=30)],
            request_completed_ack=None,
        )
    ]

    actual = derive_transfers(conversations)

    expected_statuses = [TransferStatus.PENDING_WITH_ERROR]

    _assert_attributes("status", actual, expected_statuses)
def test_derive_transfer_produces_sla_of_successful_conversation():
    conversation = build_parsed_conversation(
        request_completed=build_message(
            time=datetime(year=2020, month=6, day=1, hour=12, minute=42, second=0),
        ),
        request_completed_ack=build_message(
            time=datetime(year=2020, month=6, day=1, hour=13, minute=52, second=0), error_code=None
        ),
    )

    actual = derive_transfer(conversation)

    expected_sla_duration = timedelta(hours=1, minutes=10)

    assert actual.sla_duration == expected_sla_duration
Exemple #26
0
def test_sorts_messages_within_conversations():
    message_one = build_message(conversation_id="abc", time=datetime(year=2020, month=6, day=6))
    message_two = build_message(conversation_id="abc", time=datetime(year=2020, month=6, day=5))
    messages = [message_one, message_two]

    expected = [Conversation("abc", [message_two, message_one])]

    transfer_service = TransferService(
        message_stream=messages,
        cutoff=timedelta(days=14),
        observability_probe=mock_transfer_observability_probe,
    )
    actual = transfer_service.group_into_conversations()

    assert list(actual) == expected
def test_derive_transfer_extracts_requesting_practice_ods():
    conversation = build_parsed_conversation(request_started=build_message(from_party_ods="A12345"))

    actual = derive_transfer(conversation)

    expected_ods = "A12345"
    assert actual.requesting_practice_ods == expected_ods
Exemple #28
0
def test_is_copc_returns_false_when_interaction_is__not_copc():
    message = build_message(interaction_id=APPLICATION_ACK)

    expected = False

    actual = message.is_copc()

    assert actual == expected
Exemple #29
0
def test_is_copc_returns_true_when_interaction_is_copc():
    message = build_message(interaction_id=COMMON_POINT_TO_POINT)

    expected = True

    actual = message.is_copc()

    assert actual == expected
Exemple #30
0
def test_is_request_started_returns_true_when_interaction_is_ehr_req_started():
    message = build_message(interaction_id=EHR_REQUEST_STARTED)

    expected = True

    actual = message.is_ehr_request_started()

    assert actual == expected