async def test_view_update_2(self): ack = AsyncAck() response: BoltResponse = await ack( response_action="update", view=View( type="modal", callback_id="view-id", title=PlainTextObject(text="My App"), close=PlainTextObject(text="Cancel"), blocks=[DividerBlock(block_id="b")], ), ) assert (response.status, response.body) == ( 200, "" '{"response_action": "update", ' '"view": {' '"blocks": [{"block_id": "b", "type": "divider"}], ' '"callback_id": "view-id", ' '"close": {"text": "Cancel", "type": "plain_text"}, ' '"title": {"text": "My App", "type": "plain_text"}, ' '"type": "modal"' "}" "}", )
def test_home_tab_construction(self): home_tab_view = View( type="home", blocks=[ SectionBlock( text=MarkdownTextObject( text="*Here's what you can do with Project Tracker:*" ), ), ActionsBlock( elements=[ ButtonElement( text=PlainTextObject(text="Create New Task", emoji=True), style="primary", value="create_task", ), ButtonElement( text=PlainTextObject(text="Create New Project", emoji=True), value="create_project", ), ButtonElement( text=PlainTextObject(text="Help", emoji=True), value="help", ), ], ), ContextBlock( elements=[ ImageElement( image_url="https://api.slack.com/img/blocks/bkb_template_images/placeholder.png", alt_text="placeholder", ), ], ), SectionBlock( text=MarkdownTextObject(text="*Your Configurations*"), ), DividerBlock(), SectionBlock( text=MarkdownTextObject( text="*#public-relations*\n<fakelink.toUrl.com|PR Strategy 2019> posts new tasks, comments, and project updates to <fakelink.toChannel.com|#public-relations>" ), accessory=ButtonElement( text=PlainTextObject(text="Edit", emoji=True), value="public-relations", ), ), ], ) home_tab_view.validate_json()
def show_multi_options(ack: Ack) -> None: ack(option_groups=[ OptionGroup( label=PlainTextObject(text="Group 1"), options=[ Option(text=PlainTextObject(text="Option 1"), value="1-1"), Option(text=PlainTextObject(text="Option 2"), value="1-2"), ], ), OptionGroup( label=PlainTextObject(text="Group 2"), options=[ Option(text=PlainTextObject(text="Option 1"), value="2-1"), ], ), ])
def test_basic_json(self): self.elements = [ ImageElement( image_url= "https://api.slack.com/img/blocks/bkb_template_images/palmtree.png", alt_text="palmtree", ), PlainTextObject(text="Just text"), ] e = { "elements": [ { "type": "image", "image_url": "https://api.slack.com/img/blocks/bkb_template_images/palmtree.png", "alt_text": "palmtree", }, { "type": "plain_text", "text": "Just text" }, ], "type": "context", } d = ContextBlock(elements=self.elements).to_dict() self.assertDictEqual(e, d) with self.assertRaises(SlackObjectFormationError): ContextBlock(elements=self.elements * 6).to_dict()
def test_basic_json(self): self.assertDictEqual( { "text": "some text", "type": "plain_text" }, PlainTextObject(text="some text").to_dict(), ) self.assertDictEqual( { "text": "some text", "emoji": False, "type": "plain_text" }, PlainTextObject(text="some text", emoji=False).to_dict(), )
def test_invalid_type_value(self): modal_view = View( type="modallll", callback_id="modal-id", title=PlainTextObject(text="Awesome Modal"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( block_id="b-id", label=PlainTextObject(text="Input label"), element=PlainTextInputElement(action_id="a-id"), ), ], ) with self.assertRaises(SlackObjectFormationError): modal_view.validate_json()
def test_text_length_with_object(self): with self.assertRaises(SlackObjectFormationError): plaintext = PlainTextObject(text=STRING_301_CHARS) ConfirmObject(title="title", text=plaintext).to_dict() with self.assertRaises(SlackObjectFormationError): markdown = MarkdownTextObject(text=STRING_301_CHARS) ConfirmObject(title="title", text=markdown).to_dict()
def test_close_in_home_tab(self): modal_view = View( type="home", callback_id="home-tab-id", close=PlainTextObject(text="Cancel"), blocks=[DividerBlock()], ) with self.assertRaises(SlackObjectFormationError): modal_view.validate_json()
def test_from_list_of_json_objects(self): json_objects = [ PlainTextObject.from_str("foo"), MarkdownTextObject.from_str("bar"), ] output = extract_json(json_objects) expected = { "result": [ {"type": "plain_text", "text": "foo", "emoji": True}, {"type": "mrkdwn", "text": "bar"}, ] } self.assertDictEqual(expected, {"result": output})
def modal_button(text: str) -> dict[str, str]: """ Generate modal button. Modal buttons are the confirmation and cancelation ones. Args: text (str): Button text to display. Returns: dict: Modal button with desired text. """ return PlainTextObject(text=text, emoji=True).to_dict()
def test_text_patterns_issue_1178(self): button = LinkButtonElement( action_id="test", text=PlainTextObject(text="button text"), url="http://slack.com", ) self.assertDictEqual( { "text": { "text": "button text", "type": "plain_text" }, "url": "http://slack.com", "type": "button", "action_id": button.action_id, }, button.to_dict(), )
def test_valid_description_for_blocks(self): option = Option(label="label", value="v", description="this is an option") self.assertDictEqual( option.to_dict(), { "text": { "type": "plain_text", "text": "label", "emoji": True, }, "value": "v", "description": { "type": "plain_text", "text": "this is an option", "emoji": True, }, }, ) option = Option( # Note that mrkdwn type is not allowed for this (as of April 2021) text=PlainTextObject(text="label"), value="v", description="this is an option", ) self.assertDictEqual( option.to_dict(), { "text": { "type": "plain_text", "text": "label" }, "value": "v", "description": { "type": "plain_text", "text": "this is an option", "emoji": True, }, }, )
def test_passing_text_objects(self): direct_construction = ConfirmObject(title="title", text="Are you sure?") mrkdwn = MarkdownTextObject(text="Are you sure?") preconstructed = ConfirmObject(title="title", text=mrkdwn) self.assertDictEqual(direct_construction.to_dict(), preconstructed.to_dict()) plaintext = PlainTextObject(text="Are you sure?", emoji=False) passed_plaintext = ConfirmObject(title="title", text=plaintext) self.assertDictEqual( { "confirm": { "emoji": True, "text": "Yes", "type": "plain_text" }, "deny": { "emoji": True, "text": "No", "type": "plain_text" }, "text": { "emoji": False, "text": "Are you sure?", "type": "plain_text" }, "title": { "emoji": True, "text": "title", "type": "plain_text" }, }, passed_plaintext.to_dict(), )
def test_valid_construction(self): modal_view = View( type="modal", callback_id="modal-id", title=PlainTextObject(text="Awesome Modal"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( block_id="b-id", label=PlainTextObject(text="Input label"), element=PlainTextInputElement(action_id="a-id"), ), InputBlock( block_id="cb-id", label=PlainTextObject(text="Label"), element=CheckboxesElement( action_id="a-cb-id", options=[ Option( text=PlainTextObject( text="*this is plain_text text*"), value="v1", ), Option( text=MarkdownTextObject( text="*this is mrkdwn text*"), value="v2", ), ], ), ), SectionBlock( block_id="sb-id", text=MarkdownTextObject( text="This is a mrkdwn text section block."), fields=[ PlainTextObject(text="*this is plain_text text*", emoji=True), MarkdownTextObject(text="*this is mrkdwn text*"), PlainTextObject(text="*this is plain_text text*", emoji=True), ], ), DividerBlock(), SectionBlock( block_id="rb-id", text=MarkdownTextObject( text= "This is a section block with radio button accessory"), accessory=RadioButtonsElement( initial_option=Option( text=PlainTextObject(text="Option 1"), value="option 1", description=PlainTextObject( text="Description for option 1"), ), options=[ Option( text=PlainTextObject(text="Option 1"), value="option 1", description=PlainTextObject( text="Description for option 1"), ), Option( text=PlainTextObject(text="Option 2"), value="option 2", description=PlainTextObject( text="Description for option 2"), ), ], ), ), ], ) modal_view.validate_json()
def test_all_state_values(self): # Testing with # {"type":"modal","title":{"type":"plain_text","text":"My App","emoji":true},"submit":{"type":"plain_text","text":"Submit","emoji":true},"close":{"type":"plain_text","text":"Cancel","emoji":true},"blocks":[{"type":"input","element":{"type":"plain_text_input"},"label":{"type":"plain_text","text":"Label","emoji":true}},{"type":"input","element":{"type":"plain_text_input","multiline":true},"label":{"type":"plain_text","text":"Label","emoji":true}},{"type":"input","element":{"type":"datepicker","initial_date":"1990-04-28","placeholder":{"type":"plain_text","text":"Select a date","emoji":true}},"label":{"type":"plain_text","text":"Label","emoji":true}},{"type":"input","element":{"type":"users_select","placeholder":{"type":"plain_text","text":"Select a user","emoji":true}},"label":{"type":"plain_text","text":"Label","emoji":true}},{"type":"input","element":{"type":"multi_static_select","placeholder":{"type":"plain_text","text":"Select options","emoji":true},"options":[{"text":{"type":"plain_text","text":"*this is plain_text text*","emoji":true},"value":"value-0"},{"text":{"type":"plain_text","text":"*this is plain_text text*","emoji":true},"value":"value-1"},{"text":{"type":"plain_text","text":"*this is plain_text text*","emoji":true},"value":"value-2"}]},"label":{"type":"plain_text","text":"Label","emoji":true}},{"type":"input","element":{"type":"checkboxes","options":[{"text":{"type":"plain_text","text":"*this is plain_text text*","emoji":true},"value":"value-0"},{"text":{"type":"plain_text","text":"*this is plain_text text*","emoji":true},"value":"value-1"},{"text":{"type":"plain_text","text":"*this is plain_text text*","emoji":true},"value":"value-2"}]},"label":{"type":"plain_text","text":"Label","emoji":true}},{"type":"input","element":{"type":"radio_buttons","initial_option":{"text":{"type":"plain_text","text":"Option 1"},"value":"option 1","description":{"type":"plain_text","text":"Description for option 1"}},"options":[{"text":{"type":"plain_text","text":"Option 1"},"value":"option 1","description":{"type":"plain_text","text":"Description for option 1"}},{"text":{"type":"plain_text","text":"Option 2"},"value":"option 2","description":{"type":"plain_text","text":"Description for option 2"}},{"text":{"type":"plain_text","text":"Option 3"},"value":"option 3","description":{"type":"plain_text","text":"Description for option 3"}}]},"label":{"type":"plain_text","text":"Label","emoji":true}}]} expected = { "values": { "b1": { "a1": { "type": "datepicker", "selected_date": "1990-04-12" } }, "b2": { "a2": { "type": "plain_text_input", "value": "This is a test" } }, # multiline "b3": { "a3": { "type": "plain_text_input", "value": "Something wrong\nPlease help me!", } }, "b4": { "a4": { "type": "users_select", "selected_user": "******" } }, "b4-2": { "a4-2": { "type": "multi_users_select", "selected_users": ["U123", "U234"], } }, "b5": { "a5": { "type": "conversations_select", "selected_conversation": "C123", } }, "b5-2": { "a5-2": { "type": "multi_conversations_select", "selected_conversations": ["C123", "C234"], } }, "b6": { "a6": { "type": "channels_select", "selected_channel": "C123" } }, "b6-2": { "a6-2": { "type": "multi_channels_select", "selected_channels": ["C123", "C234"], } }, "b7": { "a7": { "type": "multi_static_select", "selected_options": [ { "text": { "type": "plain_text", "text": "*this is plain_text text*", "emoji": True, }, "value": "value-0", }, { "text": { "type": "plain_text", "text": "*this is plain_text text*", "emoji": True, }, "value": "value-1", }, ], } }, "b8": { "a8": { "type": "checkboxes", "selected_options": [ { "text": { "type": "plain_text", "text": "*this is plain_text text*", "emoji": True, }, "value": "value-0", }, { "text": { "type": "plain_text", "text": "*this is plain_text text*", "emoji": True, }, "value": "value-1", }, ], } }, "b9": { "a9": { "type": "radio_buttons", "selected_option": { "text": { "type": "plain_text", "text": "Option 1", "emoji": True, }, "value": "option 1", "description": { "type": "plain_text", "text": "Description for option 1", "emoji": True, }, }, } }, } } state = ViewState( values={ "b1": { "a1": ViewStateValue(type="datepicker", selected_date="1990-04-12") }, "b2": { "a2": ViewStateValue(type="plain_text_input", value="This is a test") }, "b3": { "a3": ViewStateValue( type="plain_text_input", value="Something wrong\nPlease help me!", ) }, "b4": { "a4": ViewStateValue(type="users_select", selected_user="******") }, "b4-2": { "a4-2": ViewStateValue(type="multi_users_select", selected_users=["U123", "U234"]) }, "b5": { "a5": ViewStateValue(type="conversations_select", selected_conversation="C123") }, "b5-2": { "a5-2": ViewStateValue( type="multi_conversations_select", selected_conversations=["C123", "C234"], ) }, "b6": { "a6": ViewStateValue(type="channels_select", selected_channel="C123") }, "b6-2": { "a6-2": ViewStateValue(type="multi_channels_select", selected_channels=["C123", "C234"]) }, "b7": { "a7": ViewStateValue( type="multi_static_select", selected_options=[ Option( text=PlainTextObject( text="*this is plain_text text*", emoji=True), value="value-0", ), Option( text=PlainTextObject( text="*this is plain_text text*", emoji=True), value="value-1", ), ], ) }, "b8": { "a8": ViewStateValue( type="checkboxes", selected_options=[ Option( text=PlainTextObject( text="*this is plain_text text*", emoji=True), value="value-0", ), Option( text=PlainTextObject( text="*this is plain_text text*", emoji=True), value="value-1", ), ], ) }, "b9": { "a9": ViewStateValue( type="radio_buttons", selected_option=Option( text=PlainTextObject(text="Option 1", emoji=True), value="option 1", description=PlainTextObject( text="Description for option 1", emoji=True), ), ) }, }) self.assertDictEqual(expected, ViewState(**expected).to_dict()) self.assertDictEqual(expected, state.to_dict())
def test_from_single_json_object(self): single_json_object = PlainTextObject.from_str("foo") output = extract_json(single_json_object) expected = {"result": {"type": "plain_text", "text": "foo", "emoji": True}} self.assertDictEqual(expected, {"result": output})
def show_options(ack: Ack) -> None: ack(options=[Option(text=PlainTextObject(text="Maru"), value="maru")])
def handle_command(body: dict, ack: Ack, respond: Respond, client: WebClient, logger: Logger) -> None: logger.info(body) ack( text="Accepted!", blocks=[ SectionBlock( block_id="b", text=MarkdownTextObject(text=":white_check_mark: Accepted!"), ) ], ) respond(blocks=[ SectionBlock( block_id="b", text=MarkdownTextObject( text="You can add a button alongside text in your message. "), accessory=ButtonElement( action_id="a", text=PlainTextObject(text="Button"), value="click_me_123", ), ), ]) res = client.views_open( trigger_id=body["trigger_id"], view=View( type="modal", callback_id="view-id", title=PlainTextObject(text="My App"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( element=PlainTextInputElement(action_id="text"), label=PlainTextObject(text="Label"), ), InputBlock( block_id="es_b", element=ExternalDataSelectElement( action_id="es_a", placeholder=PlainTextObject(text="Select an item"), min_query_length=0, ), label=PlainTextObject(text="Search"), ), InputBlock( block_id="mes_b", element=ExternalDataMultiSelectElement( action_id="mes_a", placeholder=PlainTextObject(text="Select an item"), min_query_length=0, ), label=PlainTextObject(text="Search (multi)"), ), ], ), ) logger.info(res)
def test_from_string(self): plaintext = PlainTextObject(text="some text", emoji=True) self.assertDictEqual(plaintext.to_dict(), PlainTextObject.direct_from_string("some text"))