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')
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)
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")
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)
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")
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")
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')
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)
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)
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")