Skip to content

Unit tests & tightening up teams activity handler object types #467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 4, 2019
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@
from botbuilder.core.turn_context import TurnContext
from botbuilder.core import ActivityHandler, InvokeResponse, BotFrameworkAdapter
from botbuilder.schema.teams import (
AppBasedLinkQuery,
TeamInfo,
ChannelInfo,
FileConsentCardResponse,
TeamsChannelData,
TeamsChannelAccount,
MessagingExtensionAction,
MessagingExtensionQuery,
O365ConnectorCardActionQuery,
TaskModuleRequest,
)
from botframework.connector import Channels

Expand Down Expand Up @@ -55,26 +61,28 @@ async def on_invoke_activity(self, turn_context: TurnContext):

if turn_context.activity.name == "fileConsent/invoke":
return await self.on_teams_file_consent(
turn_context, turn_context.activity.value
turn_context, FileConsentCardResponse(**turn_context.activity.value)
)

if turn_context.activity.name == "actionableMessage/executeAction":
await self.on_teams_o365_connector_card_action(
turn_context, turn_context.activity.value
turn_context,
O365ConnectorCardActionQuery(**turn_context.activity.value),
)
return self._create_invoke_response()

if turn_context.activity.name == "composeExtension/queryLink":
return self._create_invoke_response(
await self.on_teams_app_based_link_query(
turn_context, turn_context.activity.value
turn_context, AppBasedLinkQuery(**turn_context.activity.value)
)
)

if turn_context.activity.name == "composeExtension/query":
return self._create_invoke_response(
await self.on_teams_messaging_extension_query(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionQuery(**turn_context.activity.value),
)
)

Expand All @@ -88,21 +96,24 @@ async def on_invoke_activity(self, turn_context: TurnContext):
if turn_context.activity.name == "composeExtension/submitAction":
return self._create_invoke_response(
await self.on_teams_messaging_extension_submit_action_dispatch(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionAction(**turn_context.activity.value),
)
)

if turn_context.activity.name == "composeExtension/fetchTask":
return self._create_invoke_response(
await self.on_teams_messaging_extension_fetch_task(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionAction(**turn_context.activity.value),
)
)

if turn_context.activity.name == "composeExtension/querySettingUrl":
return self._create_invoke_response(
await self.on_teams_messaging_extension_configuration_query_settings_url(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionQuery(**turn_context.activity.value),
)
)

Expand All @@ -121,14 +132,14 @@ async def on_invoke_activity(self, turn_context: TurnContext):
if turn_context.activity.name == "task/fetch":
return self._create_invoke_response(
await self.on_teams_task_module_fetch(
turn_context, turn_context.activity.value
turn_context, TaskModuleRequest(**turn_context.activity.value)
)
)

if turn_context.activity.name == "task/submit":
return self._create_invoke_response(
await self.on_teams_task_module_submit(
turn_context, turn_context.activity.value
turn_context, TaskModuleRequest(**turn_context.activity.value)
)
)

Expand All @@ -143,7 +154,9 @@ async def on_teams_signin_verify_state(self, turn_context: TurnContext):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_file_consent(
self, turn_context: TurnContext, file_consent_card_response
self,
turn_context: TurnContext,
file_consent_card_response: FileConsentCardResponse,
):
if file_consent_card_response.action == "accept":
await self.on_teams_file_consent_accept_activity(
Expand All @@ -163,27 +176,31 @@ async def on_teams_file_consent(
)

async def on_teams_file_consent_accept_activity( # pylint: disable=unused-argument
self, turn_context: TurnContext, file_consent_card_response
self,
turn_context: TurnContext,
file_consent_card_response: FileConsentCardResponse,
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_file_consent_decline_activity( # pylint: disable=unused-argument
self, turn_context: TurnContext, file_consent_card_response
self,
turn_context: TurnContext,
file_consent_card_response: FileConsentCardResponse,
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_o365_connector_card_action( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: O365ConnectorCardActionQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_app_based_link_query( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: AppBasedLinkQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_query( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: MessagingExtensionQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

Expand All @@ -193,9 +210,9 @@ async def on_teams_messaging_extension_select_item( # pylint: disable=unused-ar
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_submit_action_dispatch(
self, turn_context: TurnContext, action
self, turn_context: TurnContext, action: MessagingExtensionAction
):
if not action:
if not action.bot_message_preview_action:
return await self.on_teams_messaging_extension_submit_action_activity(
turn_context, action
)
Expand Down Expand Up @@ -226,17 +243,17 @@ async def on_teams_messaging_extension_bot_message_send_activity( # pylint: dis
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_submit_action_activity( # pylint: disable=unused-argument
self, turn_context: TurnContext, action
self, turn_context: TurnContext, action: MessagingExtensionAction
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_fetch_task( # pylint: disable=unused-argument
self, turn_context: TurnContext, task_module_request
self, turn_context: TurnContext, action: MessagingExtensionAction
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_configuration_query_settings_url( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: MessagingExtensionQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

Expand All @@ -251,19 +268,19 @@ async def on_teams_messaging_extension_card_button_clicked( # pylint: disable=u
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_task_module_fetch( # pylint: disable=unused-argument
self, turn_context: TurnContext, task_module_request
self, turn_context: TurnContext, task_module_request: TaskModuleRequest
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_task_module_submit( # pylint: disable=unused-argument
self, turn_context: TurnContext, task_module_request
self, turn_context: TurnContext, task_module_request: TaskModuleRequest
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_conversation_update_activity(self, turn_context: TurnContext):

if turn_context.activity.channel_id == Channels.ms_teams:
channel_data = TeamsChannelData(**turn_context.activity.channel_data)

if turn_context.activity.members_added:
return await self.on_teams_members_added_dispatch_activity(
turn_context.activity.members_added, channel_data.team, turn_context
Expand All @@ -279,7 +296,9 @@ async def on_conversation_update_activity(self, turn_context: TurnContext):
if channel_data:
if channel_data.event_type == "channelCreated":
return await self.on_teams_channel_created_activity(
channel_data.channel, channel_data.team, turn_context
ChannelInfo(**channel_data.channel),
channel_data.team,
turn_context,
)
if channel_data.event_type == "channelDeleted":
return await self.on_teams_channel_deleted_activity(
Expand Down Expand Up @@ -337,17 +356,26 @@ async def on_teams_members_added_dispatch_activity( # pylint: disable=unused-ar

return await self.on_teams_members_added_activity(teams_members_added, team_info, turn_context)
"""
team_accounts_added = []
for member in members_added:
new_account_json = member.serialize()
del new_account_json["additional_properties"]
if "additional_properties" in new_account_json:
del new_account_json["additional_properties"]
member = TeamsChannelAccount(**new_account_json)
return await self.on_teams_members_added_activity(members_added, turn_context)
team_accounts_added.append(member)
return await self.on_teams_members_added_activity(
team_accounts_added, turn_context
)

async def on_teams_members_added_activity(
self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext
):
teams_members_added = [ChannelAccount(member) for member in teams_members_added]
return super().on_members_added_activity(teams_members_added, turn_context)
teams_members_added = [
ChannelAccount(**member.serialize()) for member in teams_members_added
]
return await super().on_members_added_activity(
teams_members_added, turn_context
)

async def on_teams_members_removed_dispatch_activity( # pylint: disable=unused-argument
self,
Expand All @@ -358,7 +386,8 @@ async def on_teams_members_removed_dispatch_activity( # pylint: disable=unused-
teams_members_removed = []
for member in members_removed:
new_account_json = member.serialize()
del new_account_json["additional_properties"]
if "additional_properties" in new_account_json:
del new_account_json["additional_properties"]
teams_members_removed.append(TeamsChannelAccount(**new_account_json))

return await self.on_teams_members_removed_activity(
Expand All @@ -368,8 +397,10 @@ async def on_teams_members_removed_dispatch_activity( # pylint: disable=unused-
async def on_teams_members_removed_activity(
self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext
):
members_removed = [ChannelAccount(member) for member in teams_members_removed]
return super().on_members_removed_activity(members_removed, turn_context)
members_removed = [
ChannelAccount(**member.serialize()) for member in teams_members_removed
]
return await super().on_members_removed_activity(members_removed, turn_context)

async def on_teams_channel_deleted_activity( # pylint: disable=unused-argument
self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext
Expand Down
60 changes: 60 additions & 0 deletions libraries/botbuilder-core/tests/teams/simple_adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import unittest
from typing import List
from botbuilder.core import BotAdapter, TurnContext
from botbuilder.schema import Activity, ConversationReference, ResourceResponse


class SimpleAdapter(BotAdapter):
# pylint: disable=unused-argument

def __init__(self, call_on_send=None, call_on_update=None, call_on_delete=None):
super(SimpleAdapter, self).__init__()
self.test_aux = unittest.TestCase("__init__")
self._call_on_send = call_on_send
self._call_on_update = call_on_update
self._call_on_delete = call_on_delete

async def delete_activity(
self, context: TurnContext, reference: ConversationReference
):
self.test_aux.assertIsNotNone(
reference, "SimpleAdapter.delete_activity: missing reference"
)
if self._call_on_delete is not None:
self._call_on_delete(reference)

async def send_activities(
self, context: TurnContext, activities: List[Activity]
) -> List[ResourceResponse]:
self.test_aux.assertIsNotNone(
activities, "SimpleAdapter.delete_activity: missing reference"
)
self.test_aux.assertTrue(
len(activities) > 0,
"SimpleAdapter.send_activities: empty activities array.",
)

if self._call_on_send is not None:
self._call_on_send(activities)
responses = []

for activity in activities:
responses.append(ResourceResponse(id=activity.id))

return responses

async def update_activity(self, context: TurnContext, activity: Activity):
self.test_aux.assertIsNotNone(
activity, "SimpleAdapter.update_activity: missing activity"
)
if self._call_on_update is not None:
self._call_on_update(activity)

return ResourceResponse(activity.id)

async def process_request(self, activity, handler):
context = TurnContext(self, activity)
return self.run_pipeline(context, handler)
Loading