Repository: microsoft/botbuilder-python

Issue:
[PORT] Create test for waterfall cancellation telemetry
> Port this change from botbuilder-dotnet/master branch:
https://github.com/microsoft/botbuilder-dotnet/pull/3314

For https://github.com/microsoft/botbuilder-js/issues/1619


# Changed projects
* Microsoft.Bot.Builder.Dialogs.Tests






Discussion:
@tomlm - Should I take care of this?

Resolving patch:
diff --git a/libraries/botbuilder-dialogs/botbuilder/dialogs/waterfall_dialog.py b/libraries/botbuilder-dialogs/botbuilder/dialogs/waterfall_dialog.py
--- a/libraries/botbuilder-dialogs/botbuilder/dialogs/waterfall_dialog.py
+++ b/libraries/botbuilder-dialogs/botbuilder/dialogs/waterfall_dialog.py
@@ -164,7 +164,7 @@ def get_step_name(self, index: int) -> str:
         """
         step_name = self._steps[index].__qualname__
 
-        if not step_name or ">" in step_name:
+        if not step_name or step_name.endswith("<lambda>"):
             step_name = f"Step{index + 1}of{len(self._steps)}"
 
         return step_name


Test patch:
diff --git a/libraries/botbuilder-applicationinsights/tests/test_telemetry_waterfall.py b/libraries/botbuilder-applicationinsights/tests/test_telemetry_waterfall.py
--- a/libraries/botbuilder-applicationinsights/tests/test_telemetry_waterfall.py
+++ b/libraries/botbuilder-applicationinsights/tests/test_telemetry_waterfall.py
@@ -1,7 +1,7 @@
 # Copyright (c) Microsoft Corporation. All rights reserved.
 # Licensed under the MIT License.
 
-from unittest.mock import MagicMock
+from unittest.mock import create_autospec, MagicMock
 from typing import Dict
 import aiounittest
 from botbuilder.core.adapters import TestAdapter, TestFlow
@@ -14,6 +14,8 @@
 )
 from botbuilder.dialogs import (
     Dialog,
+    DialogInstance,
+    DialogReason,
     DialogSet,
     WaterfallDialog,
     DialogTurnResult,
@@ -83,11 +85,10 @@ async def exec_test(turn_context: TurnContext) -> None:
         await tf4.assert_reply("ending WaterfallDialog.")
 
         # assert
-
         telemetry_calls = [
             ("WaterfallStart", {"DialogId": "test"}),
-            ("WaterfallStep", {"DialogId": "test", "StepName": "Step1of2"}),
-            ("WaterfallStep", {"DialogId": "test", "StepName": "Step2of2"}),
+            ("WaterfallStep", {"DialogId": "test", "StepName": step1.__qualname__}),
+            ("WaterfallStep", {"DialogId": "test", "StepName": step2.__qualname__}),
         ]
         self.assert_telemetry_calls(telemetry, telemetry_calls)
 
@@ -138,15 +139,49 @@ async def exec_test(turn_context: TurnContext) -> None:
         # assert
         telemetry_calls = [
             ("WaterfallStart", {"DialogId": "test"}),
-            ("WaterfallStep", {"DialogId": "test", "StepName": "Step1of2"}),
-            ("WaterfallStep", {"DialogId": "test", "StepName": "Step2of2"}),
+            ("WaterfallStep", {"DialogId": "test", "StepName": step1.__qualname__}),
+            ("WaterfallStep", {"DialogId": "test", "StepName": step2.__qualname__}),
             ("WaterfallComplete", {"DialogId": "test"}),
             ("WaterfallStart", {"DialogId": "test"}),
-            ("WaterfallStep", {"DialogId": "test", "StepName": "Step1of2"}),
+            ("WaterfallStep", {"DialogId": "test", "StepName": step1.__qualname__}),
         ]
-        print(str(telemetry.track_event.call_args_list))
         self.assert_telemetry_calls(telemetry, telemetry_calls)
 
+    async def test_cancelling_waterfall_telemetry(self):
+        # Arrange
+        dialog_id = "waterfall"
+        index = 0
+        guid = "(guid)"
+
+        async def my_waterfall_step(step) -> DialogTurnResult:
+            await step.context.send_activity("step1 response")
+            return Dialog.end_of_turn
+
+        dialog = WaterfallDialog(dialog_id, [my_waterfall_step])
+
+        telemetry_client = create_autospec(NullTelemetryClient)
+        dialog.telemetry_client = telemetry_client
+
+        dialog_instance = DialogInstance()
+        dialog_instance.id = dialog_id
+        dialog_instance.state = {"instanceId": guid, "stepIndex": index}
+
+        # Act
+        await dialog.end_dialog(
+            TurnContext(TestAdapter(), Activity()),
+            dialog_instance,
+            DialogReason.CancelCalled,
+        )
+
+        # Assert
+        telemetry_props = telemetry_client.track_event.call_args_list[0][0][1]
+
+        self.assertEqual(3, len(telemetry_props))
+        self.assertEqual(dialog_id, telemetry_props["DialogId"])
+        self.assertEqual(my_waterfall_step.__qualname__, telemetry_props["StepName"])
+        self.assertEqual(guid, telemetry_props["InstanceId"])
+        telemetry_client.track_event.assert_called_once()
+
     def assert_telemetry_call(
         self, telemetry_mock, index: int, event_name: str, props: Dict[str, str]
     ) -> None: