def test_state_none_name(self):
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))

        # Act
        with self.assertRaises(TypeError) as _:
            user_state.create_property(None)
    async def test_state_multiple_loads(self):
        """Should be able to load multiple times"""
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        user_state.create_property("property_a")
        await user_state.load(context)
        await user_state.load(context)
    def __init__(
        self, 
        config: DefaultConfig, 
        conversation_state: ConversationState, 
        user_state: UserState, 
        dialog: Dialog
        ):
        luis_application = LuisApplication(
            config.LUIS_APP_ID, 
            config.LUIS_API_KEY, 
            "https://" + config.LUIS_API_HOST_NAME
            )
        luis_options = LuisPredictionOptions(include_all_intents=True, include_instance_data=True)
        self.recognizer = LuisRecognizer(luis_application, luis_options, True)

        self.subscription_key = config.LUIS_API_KEY
        self.version_id = config.LUIS_APP_VERSION_ID
        # 可空白或直接填寫一個現有的luis app,不過需要注意其version_id是否與config.py裡的一樣
        self.luis_appid = ''              
        
        # 激活dialog_data.py裡的資訊
        self.user_profile_accessor = user_state.create_property("DialogData")

        if conversation_state is None:
            raise TypeError("[DialogBot]: Missing parameter. conversation_state is required but None was given")
        if user_state is None:
            raise TypeError("[DialogBot]: Missing parameter. user_state is required but None was given")
        if dialog is None:
            raise Exception("[DialogBot]: Missing parameter. dialog is required")
        self.conversation_state = conversation_state
        self.user_state = user_state
        self.dialog = dialog
Beispiel #4
0
    def __init__(self, user_state: UserState,
                 luis_recognizer: InsuranceQueryRecognizer,
                 insurance_renewal_dialog: InsuranceRenewalDialog,
                 reservation_booking_dialog: ReservationBookingDialog):
        super(MainDialog, self).__init__(MainDialog.__name__)

        self.qna_maker = QnAMaker(
            QnAMakerEndpoint(knowledge_base_id=config.QNA_KNOWLEDGEBASE_ID,
                             endpoint_key=config.QNA_ENDPOINT_KEY,
                             host=config.QNA_ENDPOINT_HOST))

        self.user_profile_accessor = user_state.create_property("UserData")
        self.insurance_renewal_dialog_id = insurance_renewal_dialog.id
        self.reservation_booking_dialog_id = reservation_booking_dialog.id
        self._luis_recognizer = luis_recognizer
        self.user_state = user_state
        self.add_dialog(TextPrompt(TextPrompt.__name__))
        self.add_dialog(ChoicePrompt(INS_PROMPT_OPTIONS))
        self.add_dialog(insurance_renewal_dialog)
        self.add_dialog(reservation_booking_dialog)
        self.add_dialog(
            WaterfallDialog("WFDialog", [
                self.intro_step, self.name_process_step, self.luis_query_step,
                self.closing_step
            ]))
        self.initial_dialog_id = "WFDialog"
    def __init__(self, nlu_recognizer: NLU, user_state: UserState):
        super(BookingRoomDialog, self).__init__(BookingRoomDialog.__name__)

        # Load the NLU module
        self._nlu_recognizer = nlu_recognizer

        # Load the RoomReservation class
        self.room_reservation_accessor = user_state.create_property(
            "RoomReservation")

        # Setup the waterfall dialog
        self.add_dialog(
            WaterfallDialog("WFBookingDialog", [
                self.people_step,
                self.duration_step,
                self.breakfast_step,
                self.summary_step,
            ]))

        # Append the prompts and custom prompts
        self.add_dialog(
            NumberPrompt("PeoplePrompt",
                         BookingRoomDialog.people_prompt_validator))
        self.add_dialog(
            NumberPrompt("DurationPrompt",
                         BookingRoomDialog.duration_prompt_validator))
        self.add_dialog(ConfirmPrompt("IsTakingBreakfastPrompt"))

        self.initial_dialog_id = "WFBookingDialog"
    def __init__(self, user_state: UserState, course: Course, luis_recognizer: Recognizer, dialog_id: str = None):
        super(StudentProfileDialog, self).__init__(dialog_id or StudentProfileDialog.__name__)
        self.course = course
        self.luis_recognizer = luis_recognizer

        # create accessor
        self.student_profile_accessor: StatePropertyAccessor = user_state.create_property("StudentProfile")

        # add dialogs
        self.add_dialog(
            WaterfallDialog(
                WaterfallDialog.__name__,
                [
                    self.name_step,
                    self.admission_number_step,
                    self.picture_step,
                    self.courses_step,
                    self.summary_step
                ]
            ),
        )

        self.add_dialog(TextPrompt(TextPrompt.__name__))
        self.add_dialog(ChoicePrompt(ChoicePrompt.__name__))
        self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
        self.add_dialog(AttachmentPrompt(AttachmentPrompt.__name__, StudentProfileDialog.picture_prompt_validator))
        self.add_dialog(CourseQueryDialog(course, luis_recognizer, CourseQueryDialog.__name__))

        self.initial_dialog_id = WaterfallDialog.__name__
Beispiel #7
0
    def __init__(self, user_state: UserState):
        super(UserProfileDialog, self).__init__(UserProfileDialog.__name__)

        self.user_profile_accessor = user_state.create_property("UserProfile")

        self.add_dialog(
            WaterfallDialog(
                WaterfallDialog.__name__,
                [
                    self.transport_step,
                    self.name_step,
                    self.name_confirm_step,
                    self.age_step,
                    self.picture_step,
                    self.confirm_step,
                    self.summary_step,
                ],
            ))
        self.add_dialog(TextPrompt(TextPrompt.__name__))
        self.add_dialog(
            NumberPrompt(NumberPrompt.__name__,
                         UserProfileDialog.age_prompt_validator))
        self.add_dialog(ChoicePrompt(ChoicePrompt.__name__))
        self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
        self.add_dialog(
            AttachmentPrompt(AttachmentPrompt.__name__,
                             UserProfileDialog.picture_prompt_validator))

        self.initial_dialog_id = WaterfallDialog.__name__
Beispiel #8
0
    def __init__(self, user_state: UserState):
        super(WaterfallMain, self).__init__(WaterfallMain.__name__)

        self.user_profile_accessor = user_state.create_property("UserProfile")

        luisRecognizer = CalcoloImportoRecognizer(configuration=DefaultConfig)
        calcoloDialog = CalcoloDialog()
        cancellaDialogo = CancellaDialogo()

        self.add_dialog(
            WaterfallQuery(luis_recognizer=luisRecognizer,
                           calcolo_dialog=calcoloDialog,
                           cancella_dialogo=cancellaDialogo))
        self.add_dialog(WaterfallPhoto(WaterfallPhoto.__name__))
        self.add_dialog(WaterfallText(WaterfallText.__name__))

        self.add_dialog(
            WaterfallDialog(
                WaterfallDialog.__name__,
                [
                    self.what_step,
                    self.summary_step,
                    self.replace_step,
                ],
            ))

        self.add_dialog(ChoicePrompt(ChoicePrompt.__name__))

        self.initial_dialog_id = WaterfallDialog.__name__
Beispiel #9
0
    def __init__(self, user_state: UserState):
        super(UserProfileDialog, self).__init__(UserProfileDialog.__name__)

        self.user_profile_accessor = user_state.create_property("UserProfile")

        self.add_dialog(
            WaterfallDialog(
                WaterfallDialog.__name__,
                [
                    self.first_step,
                    self.second_step,
                    self.third_step,
                    self.fourth_step,
                    self.fifth_step,
                    self.sixth_step,
                    self.seventh_step,
                    self.eighth_step,
                ],
            ))
        self.add_dialog(TextPrompt(TextPrompt.__name__))
        self.add_dialog(
            NumberPrompt(NumberPrompt.__name__,
                         UserProfileDialog.age_prompt_validator))
        self.add_dialog(ChoicePrompt(ChoicePrompt.__name__))
        self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
        self.add_dialog(
            AttachmentPrompt(AttachmentPrompt.__name__,
                             UserProfileDialog.picture_prompt_validator))

        self.initial_dialog_id = WaterfallDialog.__name__
Beispiel #10
0
    def __init__(self, dialog_id: str, connection_name: str,
                 user_state: UserState, logged_users: Dict[str, str]):
        super(LogoutDialog, self).__init__(dialog_id)

        self.connection_name = connection_name
        self.user_profile_accessor = user_state.create_property("UserProfile")
        self.logged_users = logged_users
 async def test_user_state_bad_from_throws(self):
     dictionary = {}
     user_state = UserState(MemoryStorage(dictionary))
     context = TestUtilities.create_empty_context()
     context.activity.from_property = None
     test_property = user_state.create_property("test")
     with self.assertRaises(AttributeError):
         await test_property.get(context)
    async def test_state_set_no_load(self):
        """Should be able to set a property with no Load"""
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        property_a = user_state.create_property("property_a")
        await property_a.set(context, "hello")
    async def test_state_get_no_load_with_default(self):
        """Should be able to get a property with no Load and default"""
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        property_a = user_state.create_property("property_a")
        value_a = await property_a.get(context, lambda: "Default!")
        self.assertEqual("Default!", value_a)
    async def test_state_bool_no_default(self):
        """Cannot get a bool with no default set"""
        # Arange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        test_property = user_state.create_property("test")
        value = await test_property.get(context)

        # Assert
        self.assertFalse(value)
    async def test_load_set_save_twice(self):
        # Arrange
        dictionary = {}
        context = TestUtilities.create_empty_context()

        # Act
        user_state = UserState(MemoryStorage(dictionary))

        property_a = user_state.create_property("property-a")
        property_b = user_state.create_property("property-b")
        property_c = user_state.create_property("property-c")

        await user_state.load(context)
        await property_a.set(context, "hello")
        await property_b.set(context, "world")
        await property_c.set(context, "test")
        await user_state.save_changes(context)

        # Assert
        obj = dictionary["EmptyContext/users/[email protected]"]
        self.assertEqual("hello", obj["property-a"])
        self.assertEqual("world", obj["property-b"])

        # Act 2
        user_state2 = UserState(MemoryStorage(dictionary))

        property_a2 = user_state2.create_property("property-a")
        property_b2 = user_state2.create_property("property-b")

        await user_state2.load(context)
        await property_a2.set(context, "hello-2")
        await property_b2.set(context, "world-2")
        await user_state2.save_changes(context)

        # Assert 2
        obj2 = dictionary["EmptyContext/users/[email protected]"]
        self.assertEqual("hello-2", obj2["property-a"])
        self.assertEqual("world-2", obj2["property-b"])
        self.assertEqual("test", obj2["property-c"])
    async def test_state_get_no_load_no_default(self):
        """Cannot get a string with no default set"""
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        property_a = user_state.create_property("property_a")
        value_a = await property_a.get(context)

        # Assert
        self.assertIsNone(value_a)
    async def test_load_save_delete(self):
        # Arrange
        dictionary = {}
        context = TestUtilities.create_empty_context()

        # Act
        user_state = UserState(MemoryStorage(dictionary))

        property_a = user_state.create_property("property-a")
        property_b = user_state.create_property("property-b")

        await user_state.load(context)
        await property_a.set(context, "hello")
        await property_b.set(context, "world")
        await user_state.save_changes(context)

        # Assert
        obj = dictionary["EmptyContext/users/[email protected]"]
        self.assertEqual("hello", obj["property-a"])
        self.assertEqual("world", obj["property-b"])

        # Act 2
        user_state2 = UserState(MemoryStorage(dictionary))

        property_a2 = user_state2.create_property("property-a")
        property_b2 = user_state2.create_property("property-b")

        await user_state2.load(context)
        await property_a2.set(context, "hello-2")
        await property_b2.delete(context)
        await user_state2.save_changes(context)

        # Assert 2
        obj2 = dictionary["EmptyContext/users/[email protected]"]
        self.assertEqual("hello-2", obj2["property-a"])
        with self.assertRaises(KeyError) as _:
            obj2["property-b"]  # pylint: disable=pointless-statement
    async def test_storage_not_called_no_changes(self):
        """Verify storage not called when no changes are made"""
        # Mock a storage provider, which counts read/writes
        dictionary = {}

        async def mock_write_result(self):  # pylint: disable=unused-argument
            return

        async def mock_read_result(self):  # pylint: disable=unused-argument
            return {}

        mock_storage = MemoryStorage(dictionary)
        mock_storage.write = MagicMock(side_effect=mock_write_result)
        mock_storage.read = MagicMock(side_effect=mock_read_result)

        # Arrange
        user_state = UserState(mock_storage)
        context = TestUtilities.create_empty_context()

        # Act
        property_a = user_state.create_property("property_a")
        self.assertEqual(mock_storage.write.call_count, 0)
        await user_state.save_changes(context)
        await property_a.set(context, "hello")
        self.assertEqual(mock_storage.read.call_count,
                         1)  # Initial save bumps count
        self.assertEqual(mock_storage.write.call_count,
                         0)  # Initial save bumps count
        await property_a.set(context, "there")
        self.assertEqual(mock_storage.write.call_count,
                         0)  # Set on property should not bump
        await user_state.save_changes(context)
        self.assertEqual(mock_storage.write.call_count,
                         1)  # Explicit save should bump
        value_a = await property_a.get(context)
        self.assertEqual("there", value_a)
        self.assertEqual(mock_storage.write.call_count,
                         1)  # Gets should not bump
        await user_state.save_changes(context)
        self.assertEqual(mock_storage.write.call_count, 1)
        await property_a.delete(context)  # Delete alone no bump
        self.assertEqual(mock_storage.write.call_count, 1)
        await user_state.save_changes(context)  # Save when dirty should bump
        self.assertEqual(mock_storage.write.call_count, 2)
        self.assertEqual(mock_storage.read.call_count, 1)
        await user_state.save_changes(context
                                      )  # Save not dirty should not bump
        self.assertEqual(mock_storage.write.call_count, 2)
        self.assertEqual(mock_storage.read.call_count, 1)
Beispiel #19
0
    def __init__(self, user_state: UserState):
        super(AddUtteranceDialog, self).__init__(AddUtteranceDialog.__name__)

        self.user_profile_accessor = user_state.create_property("DialogData")

        ### add_dialog --> 增加來回對話的round
        self.add_dialog(
            WaterfallDialog(WaterfallDialog.__name__, [
                self.enter_a_training_utterance,
                self.enter_the_specified_intent,
                self.enter_the_specified_entity, self.enter_the_tagged_entity,
                self.inquire_keep_going_or_not, self.final_step
            ]))
        #依照本次dialog對話需要的方法,增加方法(yes/no問題、選項問題、純文字題等等)
        self.add_dialog(TextPrompt(TextPrompt.__name__))
        self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
Beispiel #20
0
    def __init__(self, user_state: UserState):
        super(Dialog, self).__init__(Dialog.__name__)
        self.user_profile_accesor = user_state.create_property("UserProfile")

        self.add_dialog(
            WaterfallDialog(
                WaterfallDialog.__name__,
                [
                    self.options_step,
                ],
            )
        )
        self.add_dialog(ChoicePrompt("options_step"))
        self.add_dialog(ChoicePrompt(ChoicePrompt.__name__))
        self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
        self.initial_dialog_id = WaterfallDialog.__name__
        self.add_dialog(TextPrompt(TextPrompt.__name__))
    async def test_state_set_after_save(self):
        """Verify setting property after save"""
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        property_a = user_state.create_property("property-a")
        property_b = user_state.create_property("property-b")

        await user_state.load(context)
        await property_a.set(context, "hello")
        await property_b.set(context, "world")
        await user_state.save_changes(context)

        await property_a.set(context, "hello2")
    async def test_LoadSetSave(self):
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        property_a = user_state.create_property("property-a")
        property_b = user_state.create_property("property-b")

        await user_state.load(context)
        await property_a.set(context, "hello")
        await property_b.set(context, "world")
        await user_state.save_changes(context)

        # Assert
        obj = dictionary["EmptyContext/users/[email protected]"]
        self.assertEqual("hello", obj["property-a"])
        self.assertEqual("world", obj["property-b"])
    async def test_state_multiple_save(self):
        """Verify multiple saves"""
        # Arrange
        dictionary = {}
        user_state = UserState(MemoryStorage(dictionary))
        context = TestUtilities.create_empty_context()

        # Act
        property_a = user_state.create_property("property-a")
        property_b = user_state.create_property("property-b")

        await user_state.load(context)
        await property_a.set(context, "hello")
        await property_b.set(context, "world")
        await user_state.save_changes(context)

        await property_a.set(context, "hello2")
        await user_state.save_changes(context)
        value_a = await property_a.get(context)
        self.assertEqual("hello2", value_a)
Beispiel #24
0
    def __init__(self, user_state: UserState):
        super(OrderDialog, self).__init__(OrderDialog.__name__)
        self.current_order: Order = None
        self.order_list: List[Order] = list()
        self.user_profile_accesor = user_state.create_property("UserProfile")

        self.add_dialog(
            WaterfallDialog(
                WaterfallDialog.__name__,
                [
                    self.options_step,
                    self.interpret_user_intention,
                    self.goodbye_step,
                ],
            ))
        self.add_dialog(ChoicePrompt("options_step"))
        self.add_dialog(TextPrompt("interpret_user_intention"))
        self.add_dialog(ChoicePrompt(ChoicePrompt.__name__))
        self.add_dialog(ConfirmPrompt(ConfirmPrompt.__name__))
        self.initial_dialog_id = WaterfallDialog.__name__
        self.add_dialog(TextPrompt(TextPrompt.__name__))
Beispiel #25
0
 def __init__(
     self,
     user_state: UserState,
     connection_name: str,
     site_url: str,
 ):
     if user_state is None:
         raise Exception(
             "[TeamsMessagingExtensionsSearchAuthConfigBot]: Missing parameter. user_state is required"
         )
     if connection_name is None:
         raise Exception(
             "[TeamsMessagingExtensionsSearchAuthConfigBot]: Missing parameter. connection_name is required"
         )
     if site_url is None:
         raise Exception(
             "[TeamsMessagingExtensionsSearchAuthConfigBot]: Missing parameter. site_url is required"
         )
     self.user_state = user_state
     self.connection_name = connection_name
     self.site_url = site_url
     self.user_config_property = user_state.create_property(
         "UserConfiguration")
Beispiel #26
0
    def __init__(self, user_state: UserState):
        super(RootDialog, self).__init__(RootDialog.__name__)

        self.user_state_accessor = user_state.create_property("result")

        # Rather than explicitly coding a Waterfall we have only to declare what properties we want collected.
        # In this example we will want two text prompts to run, one for the first name and one for the last
        fullname_slots = [
            SlotDetails(name="first",
                        dialog_id="text",
                        prompt="Please enter your first name."),
            SlotDetails(name="last",
                        dialog_id="text",
                        prompt="Please enter your last name."),
        ]

        # This defines an address dialog that collects street, city and zip properties.
        address_slots = [
            SlotDetails(
                name="street",
                dialog_id="text",
                prompt="Please enter the street address.",
            ),
            SlotDetails(name="city",
                        dialog_id="text",
                        prompt="Please enter the city."),
            SlotDetails(name="zip",
                        dialog_id="text",
                        prompt="Please enter the zip."),
        ]

        # Dialogs can be nested and the slot filling dialog makes use of that. In this example some of the child
        # dialogs are slot filling dialogs themselves.
        slots = [
            SlotDetails(
                name="fullname",
                dialog_id="fullname",
            ),
            SlotDetails(name="age",
                        dialog_id="number",
                        prompt="Please enter your age."),
            SlotDetails(
                name="shoesize",
                dialog_id="shoesize",
                prompt="Please enter your shoe size.",
                retry_prompt=
                "You must enter a size between 0 and 16. Half sizes are acceptable.",
            ),
            SlotDetails(name="address", dialog_id="address"),
        ]

        # Add the various dialogs that will be used to the DialogSet.
        self.add_dialog(SlotFillingDialog("address", address_slots))
        self.add_dialog(SlotFillingDialog("fullname", fullname_slots))
        self.add_dialog(TextPrompt("text"))
        self.add_dialog(NumberPrompt("number", default_locale=Culture.English))
        self.add_dialog(
            NumberPrompt(
                "shoesize",
                RootDialog.shoe_size_validator,
                default_locale=Culture.English,
            ))
        self.add_dialog(SlotFillingDialog("slot-dialog", slots))

        # Defines a simple two step Waterfall to test the slot dialog.
        self.add_dialog(
            WaterfallDialog("waterfall",
                            [self.start_dialog, self.process_result]))

        # The initial child Dialog to run.
        self.initial_dialog_id = "waterfall"
Beispiel #27
0
    TurnContext,
    UserState,
    MemoryStorage,
)
from botbuilder.schema import Activity, ActivityTypes, ConversationReference

from botbuilder.testing import DialogTestClient

from unittest.mock import Mock, MagicMock
import aiounittest
from helpers import Messages

MEMORY = MemoryStorage()
USER_STATE = UserState(MEMORY)
CONVERSATION_STATE = ConversationState(MEMORY)
ACCESSOR = USER_STATE.create_property("RemindersState")
DIALOG = RemindersDialog(USER_STATE, CONVERSATION_STATE, ACCESSOR)


class TestRemindersDialog(aiounittest.AsyncTestCase):
    async def test_show_reminders_with_no_reminders(self):
        testClient = DialogTestClient("test", DIALOG)
        reply = await testClient.send_activity("show reminders")
        assert reply.text == "You don't have any reminders!"

    async def test_create_reminder(self):
        testClient = DialogTestClient("test", DIALOG)
        reply = await testClient.send_activity("remind me to go in 10 seconds")

        assert reply.text == "I have set the reminder!"
    async def test_should_replicate_activity_data_to_listening_emulator_following_open_and_attach(
        self
    ):
        inbound_expectation, outbound_expectation, state_expectation = (
            False,
            False,
            False,
        )

        with requests_mock.Mocker() as mocker:
            # set up our expectations in nock - each corresponds to a trace message we expect to receive in the emulator

            def match_response(request):
                nonlocal inbound_expectation, outbound_expectation, state_expectation
                r_json = loads(request.text)
                if r_json.get("type", None) != "trace":
                    return None

                if r_json.get("value", {}).get("text", None) == "hi":
                    inbound_expectation = True
                    return inbound_expectation
                if r_json.get("value", {}).get("text", None) == "echo: hi":
                    outbound_expectation = True
                    return outbound_expectation

                x_property = (
                    r_json.get("value", {})
                    .get("user_state", {})
                    .get("x", {})
                    .get("property", None)
                )
                y_property = (
                    r_json.get("value", {})
                    .get("conversation_state", {})
                    .get("y", {})
                    .get("property", None)
                )
                state_expectation = x_property == "hello" and y_property == "world"
                return state_expectation

            mocker.post(
                "https://test.com/v3/conversations/Convo1/activities",
                additional_matcher=match_response,
                json={"id": "test"},
                status_code=200,
            )

            # create the various storage and middleware objects we will be using

            storage = MemoryStorage()
            inspection_state = InspectionState(storage)
            user_state = UserState(storage)
            conversation_state = ConversationState(storage)
            inspection_middleware = InspectionMiddleware(
                inspection_state, user_state, conversation_state
            )

            # the emulator sends an /INSPECT open command - we can use another adapter here

            open_activity = MessageFactory.text("/INSPECT open")

            async def exec_test(turn_context):
                await inspection_middleware.process_command(turn_context)

            inspection_adapter = TestAdapter(exec_test, None, True)

            await inspection_adapter.receive_activity(open_activity)

            inspection_open_result_activity = inspection_adapter.activity_buffer[0]
            attach_command = inspection_open_result_activity.value

            # the logic of teh bot including replying with a message and updating user and conversation state

            x_prop = user_state.create_property("x")
            y_prop = conversation_state.create_property("y")

            async def exec_test2(turn_context):

                await turn_context.send_activity(
                    MessageFactory.text(f"echo: { turn_context.activity.text }")
                )

                (await x_prop.get(turn_context, {"property": ""}))["property"] = "hello"
                (await y_prop.get(turn_context, {"property": ""}))["property"] = "world"

                await user_state.save_changes(turn_context)
                await conversation_state.save_changes(turn_context)

            application_adapter = TestAdapter(exec_test2, None, True)

            # IMPORTANT add the InspectionMiddleware to the adapter that is running our bot

            application_adapter.use(inspection_middleware)

            await application_adapter.receive_activity(
                MessageFactory.text(attach_command)
            )

            # the attach command response is a informational message

            await application_adapter.receive_activity(MessageFactory.text("hi"))

            # trace activities should be sent to the emulator using the connector and the conversation reference

        # verify that all our expectations have been met
        assert inbound_expectation
        assert outbound_expectation
        assert state_expectation
        assert mocker.call_count, 3
 def __init__(self, translator: MicrosoftTranslator, user_state: UserState):
     self.translator = translator
     self.language_preference_accessor = user_state.create_property(
         "LanguagePreference")