8000 ChoicePrompt properly uses ListStyle that's specified (#260) · aiedward/botbuilder-python@88fa0aa · GitHub
[go: up one dir, main page]

Skip to content

Commit 88fa0aa

Browse files
Zerrythaxelsrz
authored andcommitted
ChoicePrompt properly uses ListStyle that's specified (microsoft#260)
* Prompts now properly uses enum values to get specified ListStyle * changed type hint from object to ListStyle in prompt.append_choices() * default choice opts now set inline_or_more values for cultures * unindented curly brace to align w/variable name * changed double quotes to single quotes in tests * changed double quotes to single quotes in ChoicePrompt * changed double quotes to single in Prompt class * changed single quotes to double quotes in Prompt class * formatted dialogs lib using black tool
1 parent 2dd2c20 commit 88fa0aa

File tree

3 files changed

+110
-59
lines changed

3 files changed

+110
-59
lines changed

libraries/botbuilder-dialogs/botbuilder/dialogs/prompts/choice_prompt.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,52 @@ class ChoicePrompt(Prompt):
3030

3131
_default_choice_options: Dict[str, ChoiceFactoryOptions] = {
3232
Culture.Spanish: ChoiceFactoryOptions(
33-
inline_separator=", ", inline_or=" o ", include_numbers=True
33+
inline_separator=", ",
34+
inline_or=" o ",
< 8000 /td>35+
inline_or_more=", o ",
36+
include_numbers=True,
3437
),
3538
Culture.Dutch: ChoiceFactoryOptions(
36-
inline_separator=", ", inline_or=" of ", include_numbers=True
39+
inline_separator=", ",
40+
inline_or=" of ",
41+
inline_or_more=", of ",
42+
include_numbers=True,
3743
),
3844
Culture.English: ChoiceFactoryOptions(
39-
inline_separator=", ", inline_or=" or ", include_numbers=True
45+
inline_separator=", ",
46+
inline_or=" or ",
47+
inline_or_more=", or ",
48+
include_numbers=True,
4049
),
4150
Culture.French: ChoiceFactoryOptions(
42-
inline_separator=", ", inline_or=" ou ", include_numbers=True
51+
inline_separator=", ",
52+
inline_or=" ou ",
53+
inline_or_more=", ou ",
54+
include_numbers=True,
4355
),
4456
"de-de": ChoiceFactoryOptions(
45-
inline_separator=", ", inline_or=" oder ", include_numbers=True
57+
inline_separator=", ",
58+
inline_or=" oder ",
59+
inline_or_more=", oder ",
60+
include_numbers=True,
4661
),
4762
Culture.Japanese: ChoiceFactoryOptions(
48-
inline_separator="、 ", inline_or=" または ", include_numbers=True
63+
inline_separator="、 ",
64+
inline_or=" または ",
65+
inline_or_more="、 または ",
66+
include_numbers=True,
4967
),
5068
Culture.Portuguese: ChoiceFactoryOptions(
51-
inline_separator=", ", inline_or=" ou ", include_numbers=True
69+
inline_separator=", ",
70+
inline_or=" ou ",
71+
inline_or_more=", ou ",
72+
include_numbers=True,
5273
),
5374
Culture.Chinese: ChoiceFactoryOptions(
54-
inline_separator=", ", inline_or=" 要么 ", include_numbers=True
75+
inline_separator=", ",
76+
inline_or=" 要么 ",
77+
inline_or_more=", 要么 ",
78+
include_numbers=True,
5579
),
5680
}
5781

libraries/botbuilder-dialogs/botbuilder/dialogs/prompts/prompt.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Licensed under the MIT License.
33

44
import copy
5-
from typing import Dict
5+
from typing import Dict, List
66
from .prompt_options import PromptOptions
77
from .prompt_validator_context import PromptValidatorContext
88
from ..dialog_reason import DialogReason
@@ -12,7 +12,12 @@
1212
from ..dialog_context import DialogContext
1313
from botbuilder.core.turn_context import TurnContext
1414
from botbuilder.schema import InputHints, ActivityTypes
15-
from botbuilder.dialogs.choices import ChoiceFactory
15+
from botbuilder.dialogs.choices import (
16+
Choice,
17+
ChoiceFactory,
18+
ChoiceFactoryOptions,
19+
ListStyle,
20+
)
1621

1722
from abc import abstractmethod
1823
from botbuilder.schema import Activity
@@ -142,16 +147,13 @@ async def on_recognize(
142147
):
143148
pass
144149

145-
# TODO: Fix choices to use Choice object when ported.
146-
# TODO: Fix style to use ListStyle when ported.
147-
# TODO: Fix options to use ChoiceFactoryOptions object when ported.
148150
def append_choices(
149151
self,
150152
prompt: Activity,
151153
channel_id: str,
152-
choices: object,
153-
style: object,
154-
options: object = None,
154+
choices: List[Choice],
155+
style: ListStyle,
156+
options: ChoiceFactoryOptions = None,
155157
) -> Activity:
156158
"""
157159
Helper function to compose an output activity containing a set of choices.
@@ -187,23 +189,24 @@ def hero_card() -> Activity:
187189
return ChoiceFactory.hero_card(choices, text)
188190

189191
def list_style_none() -> Activity:
190-
activity = Activity()
192+
activity = Activity(type=ActivityTypes.message)
191193
activity.text = text
192194
return activity
193195

194196
def default() -> Activity:
195197
return ChoiceFactory.for_channel(channel_id, choices, text, None, options)
196198

199+
# Maps to values in ListStyle Enum
197200
switcher = {
198-
# ListStyle.inline
199-
1: inline,
200-
2: list_style,
201-
3: suggested_action,
202-
4: hero_card,
203-
5: list_style_none,
201+
0: list_style_none,
202+
1: default,
203+
2: inline,
204+
3: list_style,
205+
4: suggested_action,
206+
5: hero_card,
204207
}
205208

206-
msg = switcher.get(style, default)()
209+
msg = switcher.get(int(style.value), default)()
207210

208211
# Update prompt with text, actions and attachments
209212
if not prompt:

libraries/botbuilder-dialogs/tests/test_choice_prompt.py

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,8 @@ async def validator(prompt: PromptValidatorContext) -> bool:
267267
dialogs.add(choice_prompt)
268268

269269
step1 = await adapter.send(Activity(type=ActivityTypes.message, text="Hello"))
270-
# TODO ChoiceFactory.inline() is broken, where it only uses hard-coded English locale.
271-
# commented out the CORRECT assertion below, until .inline() is fixed to use proper locale
272-
# step2 = await step1.assert_reply('Please choose a color. (1) red, (2) green, o (3) blue')
273270
step2 = await step1.assert_reply(
274-
"Please choose a color. (1) red, (2) green, or (3) blue"
271+
"Please choose a color. (1) red, (2) green, o (3) blue"
275272
)
276273
step3 = await step2.send(_invalid_message)
277274
step4 = await step3.assert_reply("Bad input.")
@@ -318,11 +315,8 @@ async def validator(prompt: PromptValidatorContext) -> bool:
318315
step1 = await adapter.send(
319316
Activity(type=ActivityTypes.message, text="Hello", locale=Culture.Spanish)
320317
)
321-
# TODO ChoiceFactory.inline() is broken, where it only uses hard-coded English locale.
322-
# commented out the CORRECT assertion below, until .inline() is fixed to use proper locale
323-
# step2 = await step1.assert_reply('Please choose a color. (1) red, (2) green, o (3) blue')
324318
step2 = await step1.assert_reply(
325-
"Please choose a color. (1) red, (2) green, or (3) blue"
319+
"Please choose a color. (1) red, (2) green, o (3) blue"
326320
)
327321
step3 = await step2.send(_answer_message)
328322
await step3.assert_reply("red")
@@ -377,9 +371,7 @@ async def validator(prompt: PromptValidatorContext) -> bool:
377371
step3 = await step2.send(_answer_message)
378372
await step3.assert_reply("red")
379373

380-
async def test_should_not_render_choices_and_not_blow_up_if_choices_are_not_passed_in(
381-
self
382-
):
374+
async def test_should_not_render_choices_if_list_style_none_is_specified(self):
383375
async def exec_test(turn_context: TurnContext):
384376
dc = await dialogs.create_context(turn_context)
385377

@@ -390,7 +382,8 @@ async def exec_test(turn_context: TurnContext):
390382
prompt=Activity(
391383
type=ActivityTypes.message, text="Please choose a color."
392384
),
393-
choices=None,
385+
choices=_color_choices,
386+
style=ListStyle.none,
394387
)
395388
await dc.prompt("prompt", options)
396389
elif results.status == DialogTurnStatus.Complete:
@@ -406,18 +399,15 @@ async def exec_test(turn_context: TurnContext):
406399
dialogs = DialogSet(dialog_state)
407400

408401
choice_prompt = ChoicePrompt("prompt")
409-
choice_prompt.style = ListStyle.none
410402

411403
dialogs.add(choice_prompt)
412404

413405
step1 = await adapter.send("Hello")
414-
await step1.assert_reply("Please choose a color.")
406+
step2 = await step1.assert_reply("Please choose a color.")
407+
step3 = await step2.send(_answer_message)
408+
await step3.assert_reply("red")
415409

416-
# TODO to create parity with JS, need to refactor this so that it does not blow up when choices are None
417-
# Possibly does not work due to the side effect of list styles not applying
418-
# Note: step2 only appears to pass as ListStyle.none, probably because choices is None, and therefore appending
419-
# nothing to the prompt text
420-
async def test_should_not_recognize_if_choices_are_not_passed_in(self):
410+
async def test_should_create_prompt_with_inline_choices_when_specified(self):
421411
async def exec_test(turn_context: TurnContext):
422412
dc = await dialogs.create_context(turn_context)
423413

@@ -428,7 +418,7 @@ async def exec_test(turn_context: TurnContext):
428418
prompt=Activity(
429419
type=ActivityTypes.message, text="Please choose a color."
430420
),
431-
choices=None,
421+
choices=_color_choices,
432422
)
433423
await dc.prompt("prompt", options)
434424
elif results.status == DialogTurnStatus.Complete:
@@ -444,17 +434,18 @@ async def exec_test(turn_context: TurnContext):
444434
dialogs = DialogSet(dialog_state 1CF5 )
445435

446436
choice_prompt = ChoicePrompt("prompt")
447-
choice_prompt.style = ListStyle.none
437+
choice_prompt.style = ListStyle.in_line
448438

449439
dialogs.add(choice_prompt)
450440

451441
step1 = await adapter.send("Hello")
452-
step2 = await step1.assert_reply("Please choose a color.")
453-
# TODO uncomment when styling is fixed for prompts - assertions should pass
454-
# step3 = await step2.send('hello')
455-
# await step3.assert_reply('Please choose a color.')
442+
step2 = await step1.assert_reply(
443+
"Please choose a color. (1) red, (2) green, or (3) blue"
444+
)
445+
step3 = await step2.send(_answer_message)
446+
await step3.assert_reply("red")
456447

457-
async def test_should_create_prompt_with_inline_choices_when_specified(self):
448+
async def test_should_create_prompt_with_list_choices_when_specified(self):
458449
async def exec_test(turn_context: TurnContext):
459450
dc = await dialogs.create_context(turn_context)
460451

@@ -481,20 +472,20 @@ async def exec_test(turn_context: TurnContext):
481472
dialogs = DialogSet(dialog_state)
482473

483474
choice_prompt = ChoicePrompt("prompt")
484-
choice_prompt.style = ListStyle.in_line
475+
choice_prompt.style = ListStyle.list_style
485476

486477
dialogs.add(choice_prompt)
487478

488479
step1 = await adapter.send("Hello")
489480
step2 = await step1.assert_reply(
490-
"Please choose a color. (1) red, (2) green, or (3) blue"
481+
"Please choose a color.\n\n 1. red\n 2. green\n 3. blue"
491482
)
492483
step3 = await step2.send(_answer_message)
493484
await step3.assert_reply("red")
494485

495-
# TODO fix test to actually test for list_style instead of inline
496-
# currently bug where all styling is ignored and only does inline styling for prompts
497-
async def test_should_create_prompt_with_list_choices_when_specified(self):
486+
async def test_should_create_prompt_with_suggested_action_style_when_specified(
487+
self
488+
):
498489
async def exec_test(turn_context: TurnContext):
499490
dc = await dialogs.create_context(turn_context)
500491

@@ -506,6 +497,43 @@ async def exec_test(turn_context: TurnContext):
506497
type=ActivityTypes.message, text="Please choose a color."
507498
),
508499
choices=_color_choices,
500+
style=ListStyle.suggested_action,
501+
)
502+
await dc.prompt("prompt", options)
503+
elif results.status == DialogTurnStatus.Complete:
504+
selected_choice = results.result
505+
await turn_context.send_activity(selected_choice.value)
506+
507+
await convo_state.save_changes(turn_context)
508+
509+
adapter = TestAdapter(exec_test)
510+
511+
convo_state = ConversationState(MemoryStorage())
512+
dialog_state = convo_state.create_property("dialogState")
513+
dialogs = DialogSet(dialog_state)
514+
515+
choice_prompt = ChoicePrompt("prompt")
516+
517+
dialogs.add(choice_prompt)
518+
519+
step1 = await adapter.send("Hello")
520+
step2 = await step1.assert_reply("Please choose a color.")
521+
step3 = await step2.send(_answer_message)
522+
await step3.assert_reply("red")
523+
524+
async def test_should_create_prompt_with_auto_style_when_specified(self):
525+
async def exec_test(turn_context: TurnContext):
526+
dc = await dialogs.create_context(turn_context)
527+
528+
results: DialogTurnResult = await dc.continue_dialog()
529+
530+
if results.status == DialogTurnStatus.Empty:
531+
options = PromptOptions(
532+
prompt=Activity(
533+
type=ActivityTypes.message, text="Please choose a color."
534+
),
535+
choices=_color_choices,
536+
style=ListStyle.auto,
509537
)
510538
await dc.prompt("prompt", options)
511539
elif results.status == DialogTurnStatus.Complete:
@@ -521,14 +549,10 @@ async def exec_test(turn_context: TurnContext):
521549
dialogs = DialogSet(dialog_state)
522550

523551
choice_prompt = ChoicePrompt("prompt")
524-
choice_prompt.style = ListStyle.list_style
525552

526553
dialogs.add(choice_prompt)
527554

528555
step1 = await adapter.send("Hello")
529-
# TODO uncomment assertion when prompt styling has been fixed - assertion should pass with list_style
530-
# Also be sure to remove inline assertion currently being tested below
531-
# step2 = await step1.assert_reply('Please choose a color.\n\n 1. red\n 2. green\n 3. blue')
532556
step2 = await step1.assert_reply(
533557
"Please choose a color. (1) red, (2) green, or (3) blue"
534558
)

0 commit comments

Comments
 (0)
0