Beispiel #1
0
class TestUserState:
    storage = MemoryStorage()
    adapter = TestAdapter()
    context = BotContext(adapter, RECEIVED_MESSAGE)
    middleware = UserState(storage)

    @pytest.mark.asyncio
    async def test_should_load_and_save_state_from_storage(self):
        async def next_middleware():
            state = await self.middleware.get(self.context)
            assert isinstance(state, StoreItem), 'State not loaded'
            state.test = 'foo'

        await self.middleware.on_process_request(self.context, next_middleware)
        key = self.middleware.get_storage_key(self.context)
        assert type(key) == str, 'Key not found'
        items = await self.storage.read([key])
        assert key in items, 'Saved state not found in storage'
        assert items[key].test == 'foo', 'Missing test value in stored state.'

    @pytest.mark.asyncio
    async def test_should_reject_with_error_if_channel_id_is_missing(self):
        context = BotContext(self.adapter, MISSING_CHANNEL_ID)

        async def next_middleware():
            assert False, 'Should not have called next_middleware'

        try:
            await self.middleware.on_process_request(context, next_middleware)
        except AttributeError:
            pass
        else:
            raise AssertionError(
                'Should not have completed and not raised AttributeError.')

    @pytest.mark.asyncio
    async def test_should_reject_with_error_if_from_property_is_missing(self):
        context = BotContext(self.adapter, MISSING_FROM_PROPERTY)

        async def next_middleware():
            assert False, 'Should not have called next_middleware'

        try:
            await self.middleware.on_process_request(context, next_middleware)
        except AttributeError:
            pass
        else:
            raise AssertionError(
                'Should not have completed and not raised AttributeError.')
    async def test_should_send_ignore_retry_rompt_if_validator_replies(self):
        async def exec_test(turn_context: TurnContext):
            dc = await dialogs.create_context(turn_context)

            results = await dc.continue_dialog()
            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message, text='please add an attachment.'),
                    retry_prompt=Activity(type=ActivityTypes.message, text='please try again.')
                )
                await dc.prompt('AttachmentPrompt', options)
            elif results.status == DialogTurnStatus.Complete:
                attachment = results.result[0]
                content = MessageFactory.text(attachment.content)
                await turn_context.send_activity(content)

            await convo_state.save_changes(turn_context)

        # Initialize TestAdapter.
        adapter = TestAdapter(exec_test)

        # Create ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and AttachmentPrompt.
        dialog_state = convo_state.create_property('dialog_state')
        dialogs = DialogSet(dialog_state)

        async def aux_validator(prompt_context: PromptValidatorContext):
            assert prompt_context, 'Validator missing prompt_context'

            if not prompt_context.recognized.succeeded:
                await prompt_context.context.send_activity('Bad input.')

            return prompt_context.recognized.succeeded

        dialogs.add(AttachmentPrompt('AttachmentPrompt', aux_validator))

        # Create incoming activity with attachment.
        attachment = Attachment(content='some content', content_type='text/plain')
        attachment_activity = Activity(type=ActivityTypes.message, attachments=[attachment])
        invalid_activty = Activity(type=ActivityTypes.message, text='invalid')

        step1 = await adapter.send('hello')
        step2 = await step1.assert_reply('please add an attachment.')
        step3 = await step2.send(invalid_activty)
        step4 = await step3.assert_reply('Bad input.')
        step5 = await step4.send(attachment_activity)
        await step5.assert_reply('some content')
Beispiel #3
0
    async def test_memory_storage_write_should_raise_a_key_error_with_older_e_tag(
            self):
        storage = MemoryStorage()
        await storage.write({'user': SimpleStoreItem(e_tag='1')})

        await storage.read(['user'])
        try:
            await storage.write({'user': SimpleStoreItem()})
            await storage.read(['user'])
        except KeyError as e:
            pass
        else:
            raise AssertionError(
                "test_memory_storage_read_should_raise_a_key_error_with_invalid_e_tag(): should have "
                "raised a KeyError with an invalid e_tag.")
    async def test_bot_state_get_cached_state(self):
        # pylint: disable=unnecessary-lambda
        turn_context = TestUtilities.create_empty_context()
        turn_context.activity.conversation = ConversationAccount(id="1234")

        storage = MemoryStorage({})

        test_bot_state = BotStateForTest(storage)
        (await test_bot_state.create_property("test-name").get(
            turn_context, lambda: TestPocoState())).value = "test-value"

        result = test_bot_state.get_cached_state(turn_context)

        assert result is not None
        assert result == test_bot_state.get_cached_state(turn_context)
Beispiel #5
0
    async def test_bot_state_get(self):
        turn_context = TestUtilities.create_empty_context()
        turn_context.activity.conversation = ConversationAccount(id="1234")

        storage = MemoryStorage({})

        conversation_state = ConversationState(storage)
        (await conversation_state.create_property("test-name").get(
            turn_context,
            lambda: TestPocoState()  # pylint: disable=unnecessary-lambda
        )).value = "test-value"

        result = conversation_state.get(turn_context)

        assert result["test-name"].value == "test-value"
    async def test_should_use_context_activity_locale_when_rendering_choices(self):
        async def exec_test(turn_context: TurnContext):
            dc = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dc.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message, text='Please choose a color.'),
                    choices=_color_choices
                )
                await dc.prompt('prompt', options)
            elif results.status == DialogTurnStatus.Complete:
                selected_choice = results.result
                await turn_context.send_activity(selected_choice.value)
            
            await convo_state.save_changes(turn_context)
        
        adapter = TestAdapter(exec_test)

        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property('dialogState')
        dialogs = DialogSet(dialog_state)

        async def validator(prompt: PromptValidatorContext) -> bool:
            assert prompt

            if not prompt.recognized.succeeded:
                await prompt.context.send_activity('Bad input.')

            return prompt.recognized.succeeded
        
        choice_prompt = ChoicePrompt('prompt', validator)
        dialogs.add(choice_prompt)

        step1 = await adapter.send(
            Activity(
                type=ActivityTypes.message,
                text='Hello',
                locale=Culture.Spanish
            )
        )
        # TODO ChoiceFactory.inline() is broken, where it only uses hard-coded English locale.
        # commented out the CORRECT assertion below, until .inline() is fixed to use proper locale
        # step2 = await step1.assert_reply('Please choose a color. (1) red, (2) green, o (3) blue')
        step2 = await step1.assert_reply('Please choose a color. (1) red, (2) green, or (3) blue')
        step3 = await step2.send(_answer_message)
        await step3.assert_reply('red')
    async def test_confirm_prompt_choice_options_numbers(self):
        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message,
                                    text="Please confirm."),
                    retry_prompt=Activity(
                        type=ActivityTypes.message,
                        text=
                        "Please confirm, say 'yes' or 'no' or something like that.",
                    ),
                )
                await dialog_context.prompt("ConfirmPrompt", options)
            elif results.status == DialogTurnStatus.Complete:
                message_text = "Confirmed" if results.result else "Not confirmed"
                await turn_context.send_activity(
                    MessageFactory.text(message_text))

            await convo_state.save_changes(turn_context)

        # Initialize TestAdapter.
        adapter = TestAdapter(exec_test)

        # Create new ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet, and ChoicePrompt.
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)
        confirm_prompt = ConfirmPrompt("ConfirmPrompt",
                                       default_locale="English")
        confirm_prompt.choice_options = ChoiceFactoryOptions(
            include_numbers=True)
        confirm_prompt.style = ListStyle.in_line
        dialogs.add(confirm_prompt)

        step1 = await adapter.send("hello")
        step2 = await step1.assert_reply("Please confirm. (1) Yes or (2) No")
        step3 = await step2.send("lala")
        step4 = await step3.assert_reply(
            "Please confirm, say 'yes' or 'no' or something like that. (1) Yes or (2) No"
        )
        step5 = await step4.send("2")
        await step5.assert_reply("Not confirmed")
Beispiel #8
0
    async def test_should_display_choices_on_hero_card_with_additional_attachment(
            self):
        size_choices = ["large", "medium", "small"]
        card = CardFactory.adaptive_card({
            "type": "AdaptiveCard",
            "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
            "version": "1.2",
            "body": [],
        })
        card_activity = Activity(attachments=[card])

        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(prompt=card_activity,
                                        choices=size_choices)
                await dialog_context.prompt("prompt", options)
            elif results.status == DialogTurnStatus.Complete:
                selected_choice = results.result
                await turn_context.send_activity(selected_choice.value)

            await convo_state.save_changes(turn_context)

        def assert_expected_activity(activity: Activity, description):  # pylint: disable=unused-argument
            assert len(activity.attachments) == 2
            assert (activity.attachments[0].content_type ==
                    CardFactory.content_types.adaptive_card)
            assert (activity.attachments[1].content_type ==
                    CardFactory.content_types.hero_card)

        adapter = TestAdapter(exec_test)

        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)

        choice_prompt = ChoicePrompt("prompt")

        # Change the ListStyle of the prompt to ListStyle.none.
        choice_prompt.style = ListStyle.hero_card

        dialogs.add(choice_prompt)

        step1 = await adapter.send("Hello")
        await step1.assert_reply(assert_expected_activity)
Beispiel #9
0
    async def test_should_use_default_locale_when_rendering_choices(self):
        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message,
                                    text="Please choose a color."),
                    choices=_color_choices,
                )
                await dialog_context.prompt("prompt", options)
            elif results.status == DialogTurnStatus.Complete:
                selected_choice = results.result
                await turn_context.send_activity(selected_choice.value)

            await convo_state.save_changes(turn_context)

        adapter = TestAdapter(exec_test)

        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)

        async def validator(prompt: PromptValidatorContext) -> bool:
            assert prompt

            if not prompt.recognized.succeeded:
                await prompt.context.send_activity("Bad input.")

            return prompt.recognized.succeeded

        choice_prompt = ChoicePrompt("prompt",
                                     validator,
                                     default_locale=Culture.Spanish)

        dialogs.add(choice_prompt)

        step1 = await adapter.send(
            Activity(type=ActivityTypes.message, text="Hello"))
        step2 = await step1.assert_reply(
            "Please choose a color. (1) red, (2) green, o (3) blue")
        step3 = await step2.send(_invalid_message)
        step4 = await step3.assert_reply("Bad input.")
        step5 = await step4.send(
            Activity(type=ActivityTypes.message, text="red"))
        await step5.assert_reply("red")
 async def test_waterfall_callback(self):
     convo_state = ConversationState(MemoryStorage())
     adapter = TestAdapter()
     dialog_state = convo_state.create_property("dialogState")
     dialogs = DialogSet(dialog_state)
     async def step_callback1(step: WaterfallStepContext) -> DialogTurnResult:
         await step.context.send_activity("step1")
     async def step_callback2(step: WaterfallStepContext) -> DialogTurnResult:
         await step.context.send_activity("step2")
     async def step_callback3(step: WaterfallStepContext) -> DialogTurnResult:
         await step.context.send_activity("step3")
   
     steps = [step_callback1, step_callback2, step_callback3]
     await dialogs.add(WaterfallDialog("test", steps))
     self.assertNotEqual(dialogs, None)
     self.assertEqual(len(dialogs._dialogs), 1)
    async def test_number_uses_locale_specified_in_constructor(self):
        # Create new ConversationState with MemoryStorage and register the state as middleware.
        conver_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and register the WaterfallDialog.
        dialog_state = conver_state.create_property("dialogState")

        dialogs = DialogSet(dialog_state)

        # Create and add number prompt to DialogSet.
        number_prompt = NumberPrompt("NumberPrompt",
                                     None,
                                     default_locale=Culture.Spanish)
        dialogs.add(number_prompt)

        async def exec_test(turn_context: TurnContext) -> None:

            dialog_context = await dialogs.create_context(turn_context)
            results = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                await dialog_context.begin_dialog(
                    "NumberPrompt",
                    PromptOptions(prompt=MessageFactory.text(
                        "How much money is in your gaming account?")),
                )
            else:
                if results.status == DialogTurnStatus.Complete:
                    number_result = results.result
                    await turn_context.send_activity(
                        MessageFactory.text(
                            f"You say you have ${number_result} in your gaming account."
                        ))

            await conver_state.save_changes(turn_context)

        adapter = TestAdapter(exec_test)

        test_flow = TestFlow(None, adapter)

        test_flow2 = await test_flow.send("Hello")
        test_flow3 = await test_flow2.assert_reply(
            "How much money is in your gaming account?")
        test_flow4 = await test_flow3.send(
            "I've got $1.200.555,42 in my account.")
        await test_flow4.assert_reply(
            "You say you have $1200555.42 in your gaming account.")
    async def test_end_of_conversation_from_expect_replies_calls_delete_conversation_reference(
        self, ):
        activity_sent: Activity = None

        # Callback to capture the parameters sent to the skill
        async def capture_action(
            from_bot_id: str,  # pylint: disable=unused-argument
            to_bot_id: str,  # pylint: disable=unused-argument
            to_uri: str,  # pylint: disable=unused-argument
            service_url: str,  # pylint: disable=unused-argument
            conversation_id: str,  # pylint: disable=unused-argument
            activity: Activity,
        ):
            # Capture values sent to the skill so we can assert the right parameters were used.
            nonlocal activity_sent
            activity_sent = activity

        eoc = Activity.create_end_of_conversation_activity()
        expected_replies = list([eoc])

        # Create a mock skill client to intercept calls and capture what is sent.
        mock_skill_client = self._create_mock_skill_client(
            capture_action, expected_replies=expected_replies)

        # Use Memory for conversation state
        conversation_state = ConversationState(MemoryStorage())
        dialog_options = self.create_skill_dialog_options(
            conversation_state, mock_skill_client)

        # Create the SkillDialogInstance and the activity to send.
        sut = SkillDialog(dialog_options, dialog_id="dialog")
        activity_to_send = Activity.create_message_activity()
        activity_to_send.delivery_mode = DeliveryModes.expect_replies
        activity_to_send.text = str(uuid.uuid4())
        client = DialogTestClient(
            "test",
            sut,
            BeginSkillDialogOptions(activity_to_send),
            conversation_state=conversation_state,
        )

        # Send something to the dialog to start it
        await client.send_activity("hello")

        simple_id_factory: SimpleConversationIdFactory = dialog_options.conversation_id_factory
        self.assertEqual(0, len(simple_id_factory.conversation_refs))
        self.assertEqual(1, simple_id_factory.create_count)
    async def test_should_call_oauth_prompt_with_code(self):
        connection_name = "myConnection"
        token = "abc123"
        magic_code = "888999"

        async def exec_test(turn_context: TurnContext):
            dc = await dialogs.create_context(turn_context)

            results = await dc.continue_dialog()
            if results.status == DialogTurnStatus.Empty:
                await dc.prompt('prompt', PromptOptions())
            elif results.status == DialogTurnStatus.Complete:
                if results.result.token:
                    await turn_context.send_activity('Logged in.')

                else:
                    await turn_context.send_activity('Failed')

            await convo_state.save_changes(turn_context)

        # Initialize TestAdapter.
        adapter = TestAdapter(exec_test)

        # Create ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and AttachmentPrompt.
        dialog_state = convo_state.create_property('dialog_state')
        dialogs = DialogSet(dialog_state)
        dialogs.add(
            OAuthPrompt(
                'prompt',
                OAuthPromptSettings(connection_name, 'Login', None, 300000)))

        def inspector(activity: Activity, description: str = None):
            assert (len(activity.attachments) == 1)
            assert (activity.attachments[0].content_type ==
                    CardFactory.content_types.oauth_card)

            # send a mock EventActivity back to the bot with the token
            adapter.add_user_token(connection_name, activity.channel_id,
                                   activity.recipient.id, token, magic_code)

        step1 = await adapter.send('Hello')
        step2 = await step1.assert_reply(inspector)
        step3 = await step2.send(magic_code)
        await step3.assert_reply('Logged in.')
    async def test_scenario_with_inspection_middlware_passthrough(self):
        inspection_state = InspectionState(MemoryStorage())
        inspection_middleware = InspectionMiddleware(inspection_state)

        adapter = TestAdapter()
        adapter.use(inspection_middleware)

        inbound_activity = MessageFactory.text("hello")

        async def aux_func(context: TurnContext):
            await context.send_activity(MessageFactory.text("hi"))

        await adapter.process_activity(inbound_activity, aux_func)

        outbound_activity = adapter.activity_buffer.pop(0)

        assert outbound_activity.text, "hi"
    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")
Beispiel #16
0
    async def test_attachment_prompt_with_validator(self):
        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results = await dialog_context.continue_dialog()
            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(
                        type=ActivityTypes.message, text="please add an attachment."
                    )
                )
                await dialog_context.prompt("AttachmentPrompt", options)
            elif results.status == DialogTurnStatus.Complete:
                attachment = results.result[0]
                content = MessageFactory.text(attachment.content)
                await turn_context.send_activity(content)

            await convo_state.save_changes(turn_context)

        # Initialize TestAdapter.
        adapter = TestAdapter(exec_test)

        # Create ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and AttachmentPrompt.
        dialog_state = convo_state.create_property("dialog_state")
        dialogs = DialogSet(dialog_state)

        async def aux_validator(prompt_context: PromptValidatorContext):
            assert prompt_context, "Validator missing prompt_context"
            return prompt_context.recognized.succeeded

        dialogs.add(AttachmentPrompt("AttachmentPrompt", aux_validator))

        # Create incoming activity with attachment.
        attachment = Attachment(content="some content", content_type="text/plain")
        attachment_activity = Activity(
            type=ActivityTypes.message, attachments=[attachment]
        )

        step1 = await adapter.send("hello")
        step2 = await step1.assert_reply("please add an attachment.")
        step3 = await step2.send(attachment_activity)
        await step3.assert_reply("some content")
Beispiel #17
0
    async def test_should_display_choices_on_hero_card(self):
        size_choices = ["large", "medium", "small"]

        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message,
                                    text="Please choose a size."),
                    choices=size_choices,
                )
                await dialog_context.prompt("prompt", options)
            elif results.status == DialogTurnStatus.Complete:
                selected_choice = results.result
                await turn_context.send_activity(selected_choice.value)

            await convo_state.save_changes(turn_context)

        def assert_expected_activity(activity: Activity, description):  # pylint: disable=unused-argument
            assert len(activity.attachments) == 1
            assert (activity.attachments[0].content_type ==
                    CardFactory.content_types.hero_card)
            assert activity.attachments[
                0].content.text == "Please choose a size."

        adapter = TestAdapter(exec_test)

        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)

        choice_prompt = ChoicePrompt("prompt")

        # Change the ListStyle of the prompt to ListStyle.none.
        choice_prompt.style = ListStyle.hero_card

        dialogs.add(choice_prompt)

        step1 = await adapter.send("Hello")
        step2 = await step1.assert_reply(assert_expected_activity)
        step3 = await step2.send("1")
        await step3.assert_reply(size_choices[0])
    async def test_oauth_prompt_doesnt_detect_code_in_begin_dialog(self):
        connection_name = "myConnection"
        token = "abc123"
        magic_code = "888999"

        async def exec_test(turn_context: TurnContext):
            # Add a magic code to the adapter preemptively so that we can test if the message that triggers BeginDialogAsync uses magic code detection
            adapter.add_user_token(connection_name,
                                   turn_context.activity.channel_id,
                                   turn_context.activity.from_property.id,
                                   token, magic_code)

            dc = await dialogs.create_context(turn_context)

            results = await dc.continue_dialog()
            if results.status == DialogTurnStatus.Empty:

                # If magicCode is detected when prompting, this will end the dialog and return the token in tokenResult
                token_result = await dc.prompt('prompt', PromptOptions())
                if isinstance(token_result.result, TokenResponse):
                    self.assertTrue(False)

            await convo_state.save_changes(turn_context)

        # Initialize TestAdapter.
        adapter = TestAdapter(exec_test)

        # Create ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and AttachmentPrompt.
        dialog_state = convo_state.create_property('dialog_state')
        dialogs = DialogSet(dialog_state)
        dialogs.add(
            OAuthPrompt(
                'prompt',
                OAuthPromptSettings(connection_name, 'Login', None, 300000)))

        def inspector(activity: Activity, description: str = None):
            assert (len(activity.attachments) == 1)
            assert (activity.attachments[0].content_type ==
                    CardFactory.content_types.oauth_card)

        step1 = await adapter.send(magic_code)
        await step1.assert_reply(inspector)
    async def test_number_prompt(self):
        # Create new ConversationState with MemoryStorage and register the state as middleware.
        conver_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and register the WaterfallDialog.
        dialog_state = conver_state.create_property("dialogState")

        dialogs = DialogSet(dialog_state)

        # Create and add number prompt to DialogSet.
        number_prompt = NumberPrompt("NumberPrompt", None, "English")
        dialogs.add(number_prompt)

        async def exec_test(turn_context: TurnContext) -> None:

            dialog_context = await dialogs.create_context(turn_context)
            results = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                await dialog_context.begin_dialog(
                    "NumberPrompt",
                    PromptOptions(
                        prompt=MessageFactory.text("Enter quantity of cable")
                    ),
                )
            else:
                if results.status == DialogTurnStatus.Complete:
                    number_result = results.result
                    await turn_context.send_activity(
                        MessageFactory.text(
                            f"You asked me for '{number_result}' meters of cable."
                        )
                    )

            await conver_state.save_changes(turn_context)

        adapter = TestAdapter(exec_test)

        test_flow = TestFlow(None, adapter)

        test_flow2 = await test_flow.send("Hello")
        test_flow3 = await test_flow2.assert_reply("Enter quantity of cable")
        test_flow4 = await test_flow3.send("Give me twenty meters of cable")
        await test_flow4.assert_reply("You asked me for '20' meters of cable.")
    async def test_should_send_ignore_retry_prompt_if_validator_replies(self):
        async def exec_test(turn_context: TurnContext):
            dc = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dc.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message, text='Please choose a color.'),
                    retry_prompt=Activity(type=ActivityTypes.message, text='Please choose red, blue, or green.'),
                    choices=_color_choices
                )
                await dc.prompt('prompt', options)
            elif results.status == DialogTurnStatus.Complete:
                selected_choice = results.result
                await turn_context.send_activity(selected_choice.value)
            
            await convo_state.save_changes(turn_context)
        
        adapter = TestAdapter(exec_test)
        
        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property('dialogState')
        dialogs = DialogSet(dialog_state)

        async def validator(prompt: PromptValidatorContext) -> bool:
            assert prompt

            if not prompt.recognized.succeeded:
                await prompt.context.send_activity('Bad input.')
            
            return prompt.recognized.succeeded
        
        choice_prompt = ChoicePrompt('prompt', validator)

        dialogs.add(choice_prompt)

        step1 = await adapter.send('Hello')
        step2 = await step1.assert_reply('Please choose a color. (1) red, (2) green, or (3) blue')
        step3 = await step2.send(_invalid_message)
        step4 = await step3.assert_reply('Bad input.')
        step5 = await step4.send(_answer_message)
        await step5.assert_reply('red')
Beispiel #21
0
    async def test_should_not_intercept_oauth_cards_for_empty_connection_name(
            self):
        connection_name = "connectionName"
        first_response = ExpectedReplies(activities=[
            SkillDialogTests.create_oauth_card_attachment_activity(
                "https://test")
        ])

        sequence = 0

        async def post_return():
            nonlocal sequence
            if sequence == 0:
                result = InvokeResponse(body=first_response,
                                        status=HTTPStatus.OK)
            else:
                result = InvokeResponse(status=HTTPStatus.OK)
            sequence += 1
            return result

        mock_skill_client = self._create_mock_skill_client(None, post_return)
        conversation_state = ConversationState(MemoryStorage())

        dialog_options = SkillDialogTests.create_skill_dialog_options(
            conversation_state, mock_skill_client)
        sut = SkillDialog(dialog_options, dialog_id="dialog")
        activity_to_send = SkillDialogTests.create_send_activity()

        client = DialogTestClient(
            "test",
            sut,
            BeginSkillDialogOptions(activity=activity_to_send, ),
            conversation_state=conversation_state,
        )

        client.test_adapter.add_exchangeable_token(connection_name, "test",
                                                   "User1", "https://test",
                                                   "https://test1")

        final_activity = await client.send_activity(
            MessageFactory.text("irrelevant"))
        self.assertIsNotNone(final_activity)
        self.assertEqual(len(final_activity.attachments), 1)
Beispiel #22
0
    async def test_date_time_prompt(self):
        # Create new ConversationState with MemoryStorage and register the state as middleware.
        conver_state = ConversationState(MemoryStorage())

        # Create a DialogState property
        dialog_state = conver_state.create_property("dialogState")

        # Create new DialogSet.
        dialogs = DialogSet(dialog_state)

        # Create and add DateTime prompt to DialogSet.
        date_time_prompt = DateTimePrompt("DateTimePrompt")

        dialogs.add(date_time_prompt)

        # Initialize TestAdapter
        async def exec_test(turn_context: TurnContext) -> None:
            prompt_msg = "What date would you like?"
            dialog_context = await dialogs.create_context(turn_context)

            results = await dialog_context.continue_dialog()
            if results.status == DialogTurnStatus.Empty:

                options = PromptOptions(prompt=MessageFactory.text(prompt_msg))
                await dialog_context.begin_dialog("DateTimePrompt", options)
            else:
                if results.status == DialogTurnStatus.Complete:
                    resolution = results.result[0]
                    reply = MessageFactory.text(
                        f"Timex: '{resolution.timex}' Value: '{resolution.value}'"
                    )
                    await turn_context.send_activity(reply)
            await conver_state.save_changes(turn_context)

        adapt = TestAdapter(exec_test)

        test_flow = TestFlow(None, adapt)
        tf2 = await test_flow.send("hello")
        tf3 = await tf2.assert_reply("What date would you like?")
        tf4 = await tf3.send("5th December 2018 at 9am")
        await tf4.assert_reply(
            "Timex: '2018-12-05T09' Value: '2018-12-05 09:00:00'"
        )
    async def test_load_set_save(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_activity_prompt_resume_dialog_should_return_dialog_end(self):
        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results = await dialog_context.continue_dialog()
            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(
                        type=ActivityTypes.message, text="please send an event."
                    )
                )
                await dialog_context.prompt("EventActivityPrompt", options)

            second_results = await event_prompt.resume_dialog(
                dialog_context, DialogReason.NextCalled
            )

            assert (
                second_results.status == DialogTurnStatus.Waiting
            ), "resume_dialog did not returned Dialog.EndOfTurn"

            await convo_state.save_changes(turn_context)

        async def aux_validator(prompt_context: PromptValidatorContext):
            assert prompt_context, "Validator missing prompt_context"
            return False

        # Initialize TestAdapter.
        adapter = TestAdapter(exec_test)

        # Create ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and AttachmentPrompt.
        dialog_state = convo_state.create_property("dialog_state")
        dialogs = DialogSet(dialog_state)
        event_prompt = SimpleActivityPrompt("EventActivityPrompt", aux_validator)
        dialogs.add(event_prompt)

        step1 = await adapter.send("hello")
        step2 = await step1.assert_reply("please send an event.")
        await step2.assert_reply("please send an event.")
    async def test_should_add_accepting_input_hint_oauth_prompt(self):
        connection_name = "myConnection"
        called = False

        async def callback_handler(turn_context: TurnContext):
            nonlocal called
            dialog_context = await dialogs.create_context(turn_context)

            await dialog_context.continue_dialog()
            await dialog_context.prompt(
                "prompt", PromptOptions(prompt=Activity(), retry_prompt=Activity())
            )

            self.assertTrue(
                dialog_context.active_dialog.state["options"].prompt.input_hint
                == InputHints.accepting_input
            )
            self.assertTrue(
                dialog_context.active_dialog.state["options"].retry_prompt.input_hint
                == InputHints.accepting_input
            )

            await convo_state.save_changes(turn_context)
            called = True

        # Initialize TestAdapter.
        adapter = TestAdapter(callback_handler)

        # Create ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and AttachmentPrompt.
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)
        dialogs.add(
            OAuthPrompt(
                "prompt", OAuthPromptSettings(connection_name, "Login", None, 300000)
            )
        )

        await adapter.send("Hello")
        self.assertTrue(called)
Beispiel #26
0
    async def test_should_send_custom_retry_prompt(self):
        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(
                        type=ActivityTypes.message, text="Please choose a color."
                    ),
                    retry_prompt=Activity(
                        type=ActivityTypes.message,
                        text="Please choose red, blue, or green.",
                    ),
                    choices=_color_choices,
                )
                await dialog_context.prompt("prompt", options)
            elif results.status == DialogTurnStatus.Complete:
                selected_choice = results.result
                await turn_context.send_activity(selected_choice.value)

            await convo_state.save_changes(turn_context)

        adapter = TestAdapter(exec_test)

        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)
        choice_prompt = ChoicePrompt("prompt")
        dialogs.add(choice_prompt)

        step1 = await adapter.send("Hello")
        step2 = await step1.assert_reply(
            "Please choose a color. (1) red, (2) green, or (3) blue"
        )
        step3 = await step2.send(_invalid_message)
        step4 = await step3.assert_reply(
            "Please choose red, blue, or green. (1) red, (2) green, or (3) blue"
        )
        step5 = await step4.send(_answer_message)
        await step5.assert_reply("red")
    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)
    async def test_memory_storage_write_should_raise_a_key_error_with_older_e_tag(
            self):
        storage = MemoryStorage()
        first_item = SimpleStoreItem(e_tag='0')

        await storage.write({'user': first_item})

        updated_item = (await storage.read(['user']))['user']
        updated_item.counter += 1
        await storage.write({'user': first_item})

        try:
            await storage.write({'user': first_item})
            await storage.read(['user'])
        except KeyError as _:
            pass
        else:
            raise AssertionError(
                "test_memory_storage_read_should_raise_a_key_error_with_invalid_e_tag(): should have "
                "raised a KeyError with an invalid e_tag.")
    async def test_active_learning(self):
        # Set Up QnAMakerDialog
        convo_state = ConversationState(MemoryStorage())
        dialog_state = convo_state.create_property("dialogState")
        dialogs = DialogSet(dialog_state)

        qna_dialog = QnAMakerDialog(self._knowledge_base_id,
                                    self._endpoint_key, self._host)
        dialogs.add(qna_dialog)

        # Callback that runs the dialog
        async def execute_qna_dialog(turn_context: TurnContext) -> None:
            if turn_context.activity.type != ActivityTypes.message:
                raise TypeError(
                    "Failed to execute QnA dialog. Should have received a message activity."
                )

            response_json = self._get_json_res(turn_context.activity.text)
            dialog_context = await dialogs.create_context(turn_context)
            with patch(
                    "aiohttp.ClientSession.post",
                    return_value=aiounittest.futurized(response_json),
            ):
                results = await dialog_context.continue_dialog()

                if results.status == DialogTurnStatus.Empty:
                    await dialog_context.begin_dialog("QnAMakerDialog")

                await convo_state.save_changes(turn_context)

        # Send and receive messages from QnA dialog
        test_adapter = TestAdapter(execute_qna_dialog)
        test_flow = TestFlow(None, test_adapter)
        tf2 = await test_flow.send(self._esper)
        dialog_reply: Activity = tf2.adapter.activity_buffer[0]
        self._assert_has_valid_hero_card_buttons(dialog_reply, button_count=3)
        tf3 = await tf2.assert_reply(self.DEFAULT_ACTIVE_LEARNING_TITLE)
        tf4 = await tf3.send(self.DEFAULT_NO_MATCH_TEXT)
        await tf4.assert_reply(self.DEFAULT_CARD_NO_MATCH_RESPONSE)

        print(tf2)
    async def test_activity_prompt_onerror_should_return_dialogcontext(self):
        # Create ConversationState with MemoryStorage and register the state as middleware.
        convo_state = ConversationState(MemoryStorage())

        # Create a DialogState property, DialogSet and AttachmentPrompt.
        dialog_state = convo_state.create_property("dialog_state")
        dialogs = DialogSet(dialog_state)
        dialogs.add(SimpleActivityPrompt("EventActivityPrompt", validator))

        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(prompt=Activity(
                    type=ActivityTypes.message, text="please send an event."))

                try:
                    await dialog_context.prompt("EventActivityPrompt", options)
                    await dialog_context.prompt("Non existent id", options)
                except Exception as err:
                    self.assertIsNotNone(err.data["DialogContext"]  # pylint: disable=no-member
                                         )
                    self.assertEqual(
                        err.data["DialogContext"][  # pylint: disable=no-member
                            "active_dialog"],
                        "EventActivityPrompt",
                    )
                else:
                    raise Exception("Should have thrown an error.")

            elif results.status == DialogTurnStatus.Complete:
                await turn_context.send_activity(results.result)

            await convo_state.save_changes(turn_context)

        # Initialize TestAdapter.
        adapter = TestAdapter(exec_test)

        await adapter.send("hello")