From d2473033ef3b20fac551363ae6d298a322a68457 Mon Sep 17 00:00:00 2001 From: Kyle Delaney Date: Thu, 24 Oct 2019 13:52:43 -0700 Subject: [PATCH 1/2] Apply conversation reference in TurnContext.update_activity (#358) * Create test_update_activity_should_apply_conversation_reference * Apply conversation reference in TurnContext.update_activity --- .../botbuilder/core/turn_context.py | 6 +++-- .../tests/test_turn_context.py | 25 +++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/turn_context.py b/libraries/botbuilder-core/botbuilder/core/turn_context.py index 99d53996a..0155a992b 100644 --- a/libraries/botbuilder-core/botbuilder/core/turn_context.py +++ b/libraries/botbuilder-core/botbuilder/core/turn_context.py @@ -173,9 +173,11 @@ async def update_activity(self, activity: Activity): :param activity: :return: """ + reference = TurnContext.get_conversation_reference(self.activity) + return await self._emit( self._on_update_activity, - activity, + TurnContext.apply_conversation_reference(activity, reference), self.adapter.update_activity(self, activity), ) @@ -240,7 +242,7 @@ async def next_handler(): raise error await emit_next(0) - # This should be changed to `return await logic()` + # logic does not use parentheses because it's a coroutine return await logic @staticmethod diff --git a/libraries/botbuilder-core/tests/test_turn_context.py b/libraries/botbuilder-core/tests/test_turn_context.py index 8e7c6f407..2fe6bdcc5 100644 --- a/libraries/botbuilder-core/tests/test_turn_context.py +++ b/libraries/botbuilder-core/tests/test_turn_context.py @@ -10,7 +10,7 @@ Mention, ResourceResponse, ) -from botbuilder.core import BotAdapter, TurnContext +from botbuilder.core import BotAdapter, MessageFactory, TurnContext ACTIVITY = Activity( id="1234", @@ -40,11 +40,12 @@ async def send_activities(self, context, activities): async def update_activity(self, context, activity): assert context is not None assert activity is not None + return ResourceResponse(id=activity.id) async def delete_activity(self, context, reference): assert context is not None assert reference is not None - assert reference.activity_id == "1234" + assert reference.activity_id == ACTIVITY.id class TestBotContext(aiounittest.AsyncTestCase): @@ -225,6 +226,26 @@ async def update_handler(context, activity, next_handler_coroutine): await context.update_activity(ACTIVITY) assert called is True + async def test_update_activity_should_apply_conversation_reference(self): + activity_id = "activity ID" + context = TurnContext(SimpleAdapter(), ACTIVITY) + called = False + + async def update_handler(context, activity, next_handler_coroutine): + nonlocal called + called = True + assert context is not None + assert activity.id == activity_id + assert activity.conversation.id == ACTIVITY.conversation.id + await next_handler_coroutine() + + context.on_update_activity(update_handler) + new_activity = MessageFactory.text("test text") + new_activity.id = activity_id + update_result = await context.update_activity(new_activity) + assert called is True + assert update_result.id == activity_id + def test_get_conversation_reference_should_return_valid_reference(self): reference = TurnContext.get_conversation_reference(ACTIVITY) From 9119769b5f92e2ffdc4493d33c1093d01b8a3fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20Su=C3=A1rez?= Date: Thu, 24 Oct 2019 15:48:38 -0700 Subject: [PATCH 2/2] Added trace activity helper in turn context (#359) --- .../botbuilder/core/turn_context.py | 23 ++++++++++++++- .../tests/test_turn_context.py | 29 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/turn_context.py b/libraries/botbuilder-core/botbuilder/core/turn_context.py index 0155a992b..75bb278d3 100644 --- a/libraries/botbuilder-core/botbuilder/core/turn_context.py +++ b/libraries/botbuilder-core/botbuilder/core/turn_context.py @@ -3,8 +3,15 @@ import re from copy import copy +from datetime import datetime from typing import List, Callable, Union, Dict -from botbuilder.schema import Activity, ConversationReference, Mention, ResourceResponse +from botbuilder.schema import ( + Activity, + ActivityTypes, + ConversationReference, + Mention, + ResourceResponse, +) class TurnContext: @@ -245,6 +252,20 @@ async def next_handler(): # logic does not use parentheses because it's a coroutine return await logic + async def send_trace_activity( + self, name: str, value: object, value_type: str, label: str + ) -> ResourceResponse: + trace_activity = Activity( + type=ActivityTypes.trace, + timestamp=datetime.utcnow(), + name=name, + value=value, + value_type=value_type, + label=label, + ) + + return await self.send_activity(trace_activity) + @staticmethod def get_conversation_reference(activity: Activity) -> ConversationReference: """ diff --git a/libraries/botbuilder-core/tests/test_turn_context.py b/libraries/botbuilder-core/tests/test_turn_context.py index 2fe6bdcc5..d39da5d20 100644 --- a/libraries/botbuilder-core/tests/test_turn_context.py +++ b/libraries/botbuilder-core/tests/test_turn_context.py @@ -1,10 +1,12 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +from typing import Callable, List import aiounittest from botbuilder.schema import ( Activity, + ActivityTypes, ChannelAccount, ConversationAccount, Mention, @@ -33,7 +35,7 @@ async def send_activities(self, context, activities): assert activities for (idx, activity) in enumerate(activities): # pylint: disable=unused-variable assert isinstance(activity, Activity) - assert activity.type == "message" + assert activity.type == "message" or activity.type == ActivityTypes.trace responses.append(ResourceResponse(id="5678")) return responses @@ -319,3 +321,28 @@ def test_should_remove_at_mention_from_activity(self): assert text, " test activity" assert activity.text, " test activity" + + async def test_should_send_a_trace_activity(self): + context = TurnContext(SimpleAdapter(), ACTIVITY) + called = False + + # pylint: disable=unused-argument + async def aux_func( + ctx: TurnContext, activities: List[Activity], next: Callable + ): + nonlocal called + called = True + assert isinstance(activities, list), "activities not array." + assert len(activities) == 1, "invalid count of activities." + assert activities[0].type == ActivityTypes.trace, "type wrong." + assert activities[0].name == "name-text", "name wrong." + assert activities[0].value == "value-text", "value worng." + assert activities[0].value_type == "valueType-text", "valeuType wrong." + assert activities[0].label == "label-text", "label wrong." + return [] + + context.on_send_activities(aux_func) + await context.send_trace_activity( + "name-text", "value-text", "valueType-text", "label-text" + ) + assert called