Spaces:
Build error
Build error
Validify-testbot-1
/
botbuilder-python
/libraries
/botbuilder-testing
/botbuilder
/testing
/dialog_test_client.py
| # Copyright (c) Microsoft Corporation. All rights reserved. | |
| # Licensed under the MIT License. | |
| from typing import List, Union | |
| from botbuilder.core import ( | |
| AutoSaveStateMiddleware, | |
| ConversationState, | |
| MemoryStorage, | |
| Middleware, | |
| StatePropertyAccessor, | |
| TurnContext, | |
| ) | |
| from botbuilder.core.adapters import TestAdapter | |
| from botbuilder.dialogs import Dialog, DialogSet, DialogTurnResult, DialogTurnStatus | |
| from botbuilder.schema import Activity, ConversationReference | |
| class DialogTestClient: | |
| """A client for testing dialogs in isolation.""" | |
| def __init__( | |
| self, | |
| channel_or_adapter: Union[str, TestAdapter], | |
| target_dialog: Dialog, | |
| initial_dialog_options: object = None, | |
| middlewares: List[Middleware] = None, | |
| conversation_state: ConversationState = None, | |
| ): | |
| """ | |
| Create a DialogTestClient to test a dialog without having to create a full-fledged adapter. | |
| ```python | |
| client = DialogTestClient("test", MY_DIALOG, MY_OPTIONS) | |
| reply = await client.send_activity("first message") | |
| self.assertEqual(reply.text, "first reply", "reply failed") | |
| ``` | |
| :param channel_or_adapter: The channel Id or test adapter to be used for the test. | |
| For channel Id, use 'emulator' or 'test' if you are uncertain of the channel you are targeting. | |
| Otherwise, it is recommended that you use the id for the channel(s) your bot will be using and | |
| write a test case for each channel. | |
| Or, a test adapter instance can be used. | |
| :type channel_or_adapter: Union[str, TestAdapter] | |
| :param target_dialog: The dialog to be tested. This will be the root dialog for the test client. | |
| :type target_dialog: Dialog | |
| :param initial_dialog_options: (Optional) additional argument(s) to pass to the dialog being started. | |
| :type initial_dialog_options: object | |
| :param middlewares: (Optional) The test adapter to use. If this parameter is not provided, the test client will | |
| use a default TestAdapter. | |
| :type middlewares: List[Middleware] | |
| :param conversation_state: (Optional) A ConversationState instance to use in the test client. | |
| :type conversation_state: ConversationState | |
| """ | |
| self.dialog_turn_result: DialogTurnResult = None | |
| self.dialog_context = None | |
| self.conversation_state: ConversationState = ( | |
| ConversationState(MemoryStorage()) | |
| if conversation_state is None | |
| else conversation_state | |
| ) | |
| dialog_state = self.conversation_state.create_property("DialogState") | |
| self._callback = self._get_default_callback( | |
| target_dialog, initial_dialog_options, dialog_state | |
| ) | |
| if isinstance(channel_or_adapter, str): | |
| conversation_reference = ConversationReference( | |
| channel_id=channel_or_adapter | |
| ) | |
| self.test_adapter = TestAdapter(self._callback, conversation_reference) | |
| self.test_adapter.use( | |
| AutoSaveStateMiddleware().add(self.conversation_state) | |
| ) | |
| else: | |
| self.test_adapter = channel_or_adapter | |
| self._add_user_middlewares(middlewares) | |
| async def send_activity(self, activity) -> Activity: | |
| """ | |
| Send an activity into the dialog. | |
| :param activity: an activity potentially with text. | |
| :type activity: | |
| :return: a TestFlow that can be used to assert replies etc. | |
| :rtype: Activity | |
| """ | |
| await self.test_adapter.receive_activity(activity) | |
| return self.test_adapter.get_next_activity() | |
| def get_next_reply(self) -> Activity: | |
| """ | |
| Get the next reply waiting to be delivered (if one exists) | |
| :return: a TestFlow that can be used to assert replies etc. | |
| :rtype: Activity | |
| """ | |
| return self.test_adapter.get_next_activity() | |
| def _get_default_callback( | |
| self, | |
| target_dialog: Dialog, | |
| initial_dialog_options: object, | |
| dialog_state: StatePropertyAccessor, | |
| ): | |
| async def default_callback(turn_context: TurnContext) -> None: | |
| dialog_set = DialogSet(dialog_state) | |
| dialog_set.add(target_dialog) | |
| self.dialog_context = await dialog_set.create_context(turn_context) | |
| self.dialog_turn_result = await self.dialog_context.continue_dialog() | |
| if self.dialog_turn_result.status == DialogTurnStatus.Empty: | |
| self.dialog_turn_result = await self.dialog_context.begin_dialog( | |
| target_dialog.id, initial_dialog_options | |
| ) | |
| return default_callback | |
| def _add_user_middlewares(self, middlewares: List[Middleware]) -> None: | |
| if middlewares is not None: | |
| for middleware in middlewares: | |
| self.test_adapter.use(middleware) | |