diff --git a/block-kit/README.md b/block-kit/README.md index 9785597..ecc536c 100644 --- a/block-kit/README.md +++ b/block-kit/README.md @@ -24,3 +24,40 @@ Read the [docs](https://docs.slack.dev/block-kit/) to learn concepts behind thes - **[Table](https://docs.slack.dev/reference/block-kit/blocks/table-block)**: Displays structured information in a table. [Implementation](./src/blocks/table.py). - **[Task card](https://docs.slack.dev/reference/block-kit/blocks/task-card-block)**: Displays a single task, representing a single action. [Implementation](./src/blocks/task_card.py). - **[Video](https://docs.slack.dev/reference/block-kit/blocks/video-block)**: Displays an embedded video player. [Implementation](./src/blocks/video.py). + +### Block elements + +- **[Broadcast](https://docs.slack.dev/reference/block-kit/block-elements/broadcast-element)**: Displays a broadcast mention such as here, channel, or everyone. [Implementation](./src/block_elements/broadcast.py). +- **[Button](https://docs.slack.dev/reference/block-kit/block-elements/button-element)**: Allows users a direct path to performing basic actions. [Implementation](./src/block_elements/button.py). +- **[Channel](https://docs.slack.dev/reference/block-kit/block-elements/channel-element)**: Renders as a mention of a channel. [Implementation](./src/block_elements/channel.py). +- **[Checkboxes](https://docs.slack.dev/reference/block-kit/block-elements/checkboxes-element)**: Allows users to choose multiple items from a list of options. [Implementation](./src/block_elements/checkboxes.py). +- **[Color](https://docs.slack.dev/reference/block-kit/block-elements/color-element)**: Displays a color swatch from a hex value. [Implementation](./src/block_elements/color.py). +- **[Date](https://docs.slack.dev/reference/block-kit/block-elements/date-element)**: Displays a formatted, localized date. [Implementation](./src/block_elements/date.py). +- **[Date picker](https://docs.slack.dev/reference/block-kit/block-elements/date-picker-element)**: Allows users to select a date from a calendar style UI. [Implementation](./src/block_elements/date_picker.py). +- **[Datetime picker](https://docs.slack.dev/reference/block-kit/block-elements/datetime-picker-element)**: Allows users to select both a date and a time of day. [Implementation](./src/block_elements/datetime_picker.py). +- **[Email input](https://docs.slack.dev/reference/block-kit/block-elements/email-input-element)**: Allows user to enter an email into a single-line field. [Implementation](./src/block_elements/email_input.py). +- **[Emoji](https://docs.slack.dev/reference/block-kit/block-elements/emoji-element)**: Displays an emoji. [Implementation](./src/block_elements/emoji.py). +- **[Feedback buttons](https://docs.slack.dev/reference/block-kit/block-elements/feedback-buttons-element)**: Buttons to indicate positive or negative feedback. [Implementation](./src/block_elements/feedback_buttons.py). +- **[File input](https://docs.slack.dev/reference/block-kit/block-elements/file-input-element)**: Allows user to upload files. [Implementation](./src/block_elements/file_input.py). +- **[Icon button](https://docs.slack.dev/reference/block-kit/block-elements/icon-button-element)**: An icon button to perform actions. [Implementation](./src/block_elements/icon_button.py). +- **[Image](https://docs.slack.dev/reference/block-kit/block-elements/image-element)**: Displays an image as part of a larger block of content. [Implementation](./src/block_elements/image.py). +- **[Link](https://docs.slack.dev/reference/block-kit/block-elements/link-element)**: Displays a hyperlink. [Implementation](./src/block_elements/link.py). +- **[Multi-select menu](https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element)**: Allows users to select multiple items from a list of options. [Implementation](./src/block_elements/multi_select_menu.py). +- **[Number input](https://docs.slack.dev/reference/block-kit/block-elements/number-input-element)**: Allows user to enter a number into a single-line field. [Implementation](./src/block_elements/number_input.py). +- **[Overflow menu](https://docs.slack.dev/reference/block-kit/block-elements/overflow-menu-element)**: Allows users to press a button to view a list of options. [Implementation](./src/block_elements/overflow_menu.py). +- **[Plain-text input](https://docs.slack.dev/reference/block-kit/block-elements/plain-text-input-element)**: Allows users to enter freeform text data into a single-line or multi-line field. [Implementation](./src/block_elements/plain_text_input.py). +- **[Radio button group](https://docs.slack.dev/reference/block-kit/block-elements/radio-button-group-element)**: Allows users to choose one item from a list of possible options. [Implementation](./src/block_elements/radio_buttons.py). +- **[Rich text input](https://docs.slack.dev/reference/block-kit/block-elements/rich-text-input-element)**: Allows users to enter formatted text in a WYSIWYG composer, offering the same messaging writing experience as in Slack. [Implementation](./src/block_elements/rich_text_input.py). +- **[Rich text list](https://docs.slack.dev/reference/block-kit/block-elements/rich-text-list-element)**: Displays a list of rich text items. [Implementation](./src/block_elements/rich_text_list.py). +- **[Rich text preformatted](https://docs.slack.dev/reference/block-kit/block-elements/rich-text-preformatted-element)**: Displays a preformatted rich text element. [Implementation](./src/block_elements/rich_text_preformatted.py). +- **[Rich text quote](https://docs.slack.dev/reference/block-kit/block-elements/rich-text-quote-element)**: Displays a rich text quote block. [Implementation](./src/block_elements/rich_text_quote.py). +- **[Rich text section](https://docs.slack.dev/reference/block-kit/block-elements/rich-text-section-element)**: A section element that holds rich text elements. [Implementation](./src/block_elements/rich_text_section.py). +- **[Select menu](https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element)**: Allows users to choose an option from a drop down menu. [Implementation](./src/block_elements/select_menu.py). +- **[Team](https://docs.slack.dev/reference/block-kit/block-elements/team-element)**: Renders as a mention of a workspace or team. [Implementation](./src/block_elements/team.py). +- **[Text](https://docs.slack.dev/reference/block-kit/block-elements/text-element)**: Displays text, optionally with styling. [Implementation](./src/block_elements/text.py). +- **[Time picker](https://docs.slack.dev/reference/block-kit/block-elements/time-picker-element)**: Allows users to select a time of day. [Implementation](./src/block_elements/time_picker.py). +- **[URL input](https://docs.slack.dev/reference/block-kit/block-elements/url-input-element)**: Allows user to enter a URL into a single-line field. [Implementation](./src/block_elements/url_input.py). +- **[URL source](https://docs.slack.dev/reference/block-kit/block-elements/url-source-element)**: Displays a URL source for referencing within a task card block. [Implementation](./src/block_elements/url_source.py). +- **[User](https://docs.slack.dev/reference/block-kit/block-elements/user-element)**: Renders as a mention of a user. [Implementation](./src/block_elements/user.py). +- **[Usergroup](https://docs.slack.dev/reference/block-kit/block-elements/usergroup-element)**: Renders as a mention of a user group. [Implementation](./src/block_elements/usergroup.py). +- **[Workflow button](https://docs.slack.dev/reference/block-kit/block-elements/workflow-button-element)**: Allows users to run a link trigger with customizable inputs. [Implementation](./src/block_elements/workflow_button.py). diff --git a/block-kit/src/block_elements/__init__.py b/block-kit/src/block_elements/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/block-kit/src/block_elements/broadcast.py b/block-kit/src/block_elements/broadcast.py new file mode 100644 index 0000000..9dfff17 --- /dev/null +++ b/block-kit/src/block_elements/broadcast.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays a broadcast mention such as here, channel, or everyone. + https://docs.slack.dev/reference/block-kit/block-elements/broadcast-element/ + + A rich text block whose section holds a broadcast element. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Broadcast(range="everyone"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/button.py b/block-kit/src/block_elements/button.py new file mode 100644 index 0000000..692602a --- /dev/null +++ b/block-kit/src/block_elements/button.py @@ -0,0 +1,76 @@ +from slack_sdk.models.blocks import ActionsBlock, Block, SectionBlock +from slack_sdk.models.blocks.basic_components import MarkdownTextObject, PlainTextObject +from slack_sdk.models.blocks.block_elements import ButtonElement + + +def example01() -> ButtonElement: + """ + Allows users a direct path to performing basic actions. + https://docs.slack.dev/reference/block-kit/block-elements/button-element/ + + A regular interactive button. + """ + element = ButtonElement( + text=PlainTextObject(text="Click Me"), + value="click_me_123", + action_id="button", + ) + return element + + +def example02() -> ButtonElement: + """ + A button with a primary style attribute. + """ + element = ButtonElement( + text=PlainTextObject(text="Save"), + style="primary", + value="click_me_123", + action_id="button", + ) + return element + + +def example03() -> ButtonElement: + """ + A link button. + """ + element = ButtonElement( + text=PlainTextObject(text="Link Button"), + url="https://docs.slack.dev/block-kit", + ) + return element + + +def example04() -> list[Block]: + """ + The button element must be used inside either the section or actions block. + + A section block with a button as an accessory, followed by an actions + block holding a primary button and a link button. + """ + blocks: list[Block] = [ + SectionBlock( + text=MarkdownTextObject(text="This is a section block with a button."), + accessory=ButtonElement( + text=PlainTextObject(text="Click Me"), + value="click_me_123", + action_id="button", + ), + ), + ActionsBlock( + block_id="actionblock789", + elements=[ + ButtonElement( + text=PlainTextObject(text="Primary Button"), + style="primary", + value="click_me_456", + ), + ButtonElement( + text=PlainTextObject(text="Link Button"), + url="https://api.slack.com/block-kit", + ), + ], + ), + ] + return blocks diff --git a/block-kit/src/block_elements/channel.py b/block-kit/src/block_elements/channel.py new file mode 100644 index 0000000..7928700 --- /dev/null +++ b/block-kit/src/block_elements/channel.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Renders as a mention of a channel. + https://docs.slack.dev/reference/block-kit/block-elements/channel-element/ + + A rich text block whose section holds a channel mention element. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Channel(channel_id="C123ABC456"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/checkboxes.py b/block-kit/src/block_elements/checkboxes.py new file mode 100644 index 0000000..80e7625 --- /dev/null +++ b/block-kit/src/block_elements/checkboxes.py @@ -0,0 +1,36 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import ( + MarkdownTextObject, + Option, + PlainTextObject, +) +from slack_sdk.models.blocks.block_elements import CheckboxesElement + + +def example01() -> SectionBlock: + """ + Allows users to choose multiple items from a list of options. + https://docs.slack.dev/reference/block-kit/block-elements/checkboxes-element/ + + A section block with a checkboxes element as an accessory. + """ + block = SectionBlock( + text=PlainTextObject(text="Check out these charming checkboxes"), + accessory=CheckboxesElement( + action_id="this_is_an_action_id", + initial_options=[ + Option(value="A1", text=PlainTextObject(text="Checkbox 1")), + ], + options=[ + Option(value="A1", text=PlainTextObject(text="Checkbox 1")), + Option( + value="A2", + text=PlainTextObject(text="Checkbox 2"), + description=MarkdownTextObject( + text="*A description of option two*" + ), + ), + ], + ), + ) + return block diff --git a/block-kit/src/block_elements/color.py b/block-kit/src/block_elements/color.py new file mode 100644 index 0000000..2e69ca4 --- /dev/null +++ b/block-kit/src/block_elements/color.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays a color swatch from a hex value. + https://docs.slack.dev/reference/block-kit/block-elements/color-element/ + + A rich text block whose section holds a color element. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Color(value="#F405B3"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/date.py b/block-kit/src/block_elements/date.py new file mode 100644 index 0000000..510d2b7 --- /dev/null +++ b/block-kit/src/block_elements/date.py @@ -0,0 +1,28 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays a formatted, localized date. + https://docs.slack.dev/reference/block-kit/block-elements/date-element/ + + A rich text block whose section holds a date element with a fallback. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Date( + timestamp=1720710212, + format="{date_num} at {time}", + fallback="timey", + ), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/date_picker.py b/block-kit/src/block_elements/date_picker.py new file mode 100644 index 0000000..53277dd --- /dev/null +++ b/block-kit/src/block_elements/date_picker.py @@ -0,0 +1,22 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import MarkdownTextObject, PlainTextObject +from slack_sdk.models.blocks.block_elements import DatePickerElement + + +def example01() -> SectionBlock: + """ + Allows users to select a date from a calendar style UI. + https://docs.slack.dev/reference/block-kit/block-elements/date-picker-element/ + + A section block with a date picker as an accessory. + """ + block = SectionBlock( + block_id="section1234", + text=MarkdownTextObject(text="Pick a date for the deadline."), + accessory=DatePickerElement( + action_id="datepicker123", + initial_date="1990-04-28", + placeholder=PlainTextObject(text="Select a date"), + ), + ) + return block diff --git a/block-kit/src/block_elements/datetime_picker.py b/block-kit/src/block_elements/datetime_picker.py new file mode 100644 index 0000000..ab6c6ec --- /dev/null +++ b/block-kit/src/block_elements/datetime_picker.py @@ -0,0 +1,18 @@ +from slack_sdk.models.blocks import InputBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import DateTimePickerElement + + +def example01() -> InputBlock: + """ + Allows users to select both a date and a time of day. + https://docs.slack.dev/reference/block-kit/block-elements/datetime-picker-element/ + + An input block with a datetime picker element. + """ + block = InputBlock( + element=DateTimePickerElement(action_id="datetimepicker-action"), + hint=PlainTextObject(text="This is some hint text", emoji=True), + label=PlainTextObject(text="Start date", emoji=True), + ) + return block diff --git a/block-kit/src/block_elements/email_input.py b/block-kit/src/block_elements/email_input.py new file mode 100644 index 0000000..6747117 --- /dev/null +++ b/block-kit/src/block_elements/email_input.py @@ -0,0 +1,21 @@ +from slack_sdk.models.blocks import InputBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import EmailInputElement + + +def example01() -> InputBlock: + """ + Allows user to enter an email into a single-line field. + https://docs.slack.dev/reference/block-kit/block-elements/email-input-element/ + + An input block with an email input element. + """ + block = InputBlock( + block_id="input123", + label=PlainTextObject(text="Email Address"), + element=EmailInputElement( + action_id="email_text_input-action", + placeholder=PlainTextObject(text="Enter an email"), + ), + ) + return block diff --git a/block-kit/src/block_elements/emoji.py b/block-kit/src/block_elements/emoji.py new file mode 100644 index 0000000..6f5a134 --- /dev/null +++ b/block-kit/src/block_elements/emoji.py @@ -0,0 +1,28 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays an emoji. + https://docs.slack.dev/reference/block-kit/block-elements/emoji-element/ + + A rich text block whose section holds emoji elements separated by text. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Emoji(name="basketball"), + RichTextElementParts.Text(text=" "), + RichTextElementParts.Emoji(name="snowboarder"), + RichTextElementParts.Text(text=" "), + RichTextElementParts.Emoji(name="checkered_flag"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/feedback_buttons.py b/block-kit/src/block_elements/feedback_buttons.py new file mode 100644 index 0000000..200d3db --- /dev/null +++ b/block-kit/src/block_elements/feedback_buttons.py @@ -0,0 +1,33 @@ +from slack_sdk.models.blocks import ContextActionsBlock +from slack_sdk.models.blocks.basic_components import ( + FeedbackButtonObject, + PlainTextObject, +) +from slack_sdk.models.blocks.block_elements import FeedbackButtonsElement + + +def example01() -> ContextActionsBlock: + """ + Buttons to indicate positive or negative feedback. + https://docs.slack.dev/reference/block-kit/block-elements/feedback-buttons-element/ + + A context actions block holding a feedback buttons element. + """ + block = ContextActionsBlock( + elements=[ + FeedbackButtonsElement( + action_id="feedback_buttons_1", + positive_button=FeedbackButtonObject( + text=PlainTextObject(text="Good", emoji=None), + value="positive_feedback", + accessibility_label="Mark this response as good", + ), + negative_button=FeedbackButtonObject( + text=PlainTextObject(text="Bad", emoji=None), + value="negative_feedback", + accessibility_label="Mark this response as bad", + ), + ), + ] + ) + return block diff --git a/block-kit/src/block_elements/file_input.py b/block-kit/src/block_elements/file_input.py new file mode 100644 index 0000000..2468c2c --- /dev/null +++ b/block-kit/src/block_elements/file_input.py @@ -0,0 +1,22 @@ +from slack_sdk.models.blocks import InputBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import FileInputElement + + +def example01() -> InputBlock: + """ + Allows user to upload files. + https://docs.slack.dev/reference/block-kit/block-elements/file-input-element/ + + An input block with a file input element. + """ + block = InputBlock( + block_id="input_block_id", + label=PlainTextObject(text="Upload Files"), + element=FileInputElement( + action_id="file_input_action_id_1", + filetypes=["jpg", "png"], + max_files=5, + ), + ) + return block diff --git a/block-kit/src/block_elements/icon_button.py b/block-kit/src/block_elements/icon_button.py new file mode 100644 index 0000000..96b43f5 --- /dev/null +++ b/block-kit/src/block_elements/icon_button.py @@ -0,0 +1,23 @@ +from slack_sdk.models.blocks import ContextActionsBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import IconButtonElement + + +def example01() -> ContextActionsBlock: + """ + An icon button to perform actions. + https://docs.slack.dev/reference/block-kit/block-elements/icon-button-element/ + + A context actions block holding an icon button element. + """ + block = ContextActionsBlock( + elements=[ + IconButtonElement( + icon="trash", + text=PlainTextObject(text="Delete", emoji=None), + action_id="delete_button", + value="delete_item", + ), + ] + ) + return block diff --git a/block-kit/src/block_elements/image.py b/block-kit/src/block_elements/image.py new file mode 100644 index 0000000..ac91113 --- /dev/null +++ b/block-kit/src/block_elements/image.py @@ -0,0 +1,62 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import ( + MarkdownTextObject, + SlackFile, +) +from slack_sdk.models.blocks.block_elements import ImageElement + + +def example01() -> SectionBlock: + """ + Displays an image as part of a larger block of content. + https://docs.slack.dev/reference/block-kit/block-elements/image-element/ + + A section block with an accessory image referenced by URL. + """ + block = SectionBlock( + block_id="section567", + text=MarkdownTextObject( + text="This is a section block with an accessory image." + ), + accessory=ImageElement( + image_url="https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg", + alt_text="cute cat", + ), + ) + return block + + +def example02() -> SectionBlock: + """ + A section block with an accessory image referenced by a Slack file URL. + """ + block = SectionBlock( + block_id="section567", + text=MarkdownTextObject( + text="This is a section block with an accessory image." + ), + accessory=ImageElement( + slack_file=SlackFile( + url="https://files.slack.com/files-pri/T0123456-F0123456/xyz.png" + ), + alt_text="Slack file object.", + ), + ) + return block + + +def example03() -> SectionBlock: + """ + A section block with an accessory image referenced by a Slack file ID. + """ + block = SectionBlock( + block_id="section567", + text=MarkdownTextObject( + text="This is a section block with an accessory image." + ), + accessory=ImageElement( + slack_file=SlackFile(id="F01234567"), + alt_text="Slack file object.", + ), + ) + return block diff --git a/block-kit/src/block_elements/link.py b/block-kit/src/block_elements/link.py new file mode 100644 index 0000000..c9b779b --- /dev/null +++ b/block-kit/src/block_elements/link.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays a hyperlink. + https://docs.slack.dev/reference/block-kit/block-elements/link-element/ + + A rich text block whose section holds a link element. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Link(url="https://docs.slack.dev"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/multi_select_menu.py b/block-kit/src/block_elements/multi_select_menu.py new file mode 100644 index 0000000..8059ab5 --- /dev/null +++ b/block-kit/src/block_elements/multi_select_menu.py @@ -0,0 +1,106 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import ( + MarkdownTextObject, + Option, + PlainTextObject, +) +from slack_sdk.models.blocks.block_elements import ( + ChannelMultiSelectElement, + ConversationMultiSelectElement, + ExternalDataMultiSelectElement, + StaticMultiSelectElement, + UserMultiSelectElement, +) + + +def example01() -> SectionBlock: + """ + Allows users to select multiple items from a list of options. + https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element/ + + A section block with a static multi-select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick items from the list"), + accessory=StaticMultiSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select items"), + options=[ + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-0", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-1", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-2", + ), + ], + ), + ) + return block + + +def example02() -> SectionBlock: + """ + A section block with an external data source multi-select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick items from the list"), + accessory=ExternalDataMultiSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select items"), + min_query_length=3, + ), + ) + return block + + +def example03() -> SectionBlock: + """ + A section block with a user list multi-select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick users from the list"), + accessory=UserMultiSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select users"), + ), + ) + return block + + +def example04() -> SectionBlock: + """ + A section block with a conversations list multi-select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick conversations from the list"), + accessory=ConversationMultiSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select conversations"), + ), + ) + return block + + +def example05() -> SectionBlock: + """ + A section block with a channels list multi-select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick channels from the list"), + accessory=ChannelMultiSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select channels"), + ), + ) + return block diff --git a/block-kit/src/block_elements/number_input.py b/block-kit/src/block_elements/number_input.py new file mode 100644 index 0000000..383af09 --- /dev/null +++ b/block-kit/src/block_elements/number_input.py @@ -0,0 +1,20 @@ +from slack_sdk.models.blocks import InputBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import NumberInputElement + + +def example01() -> InputBlock: + """ + Allows user to enter a number into a single-line field. + https://docs.slack.dev/reference/block-kit/block-elements/number-input-element/ + + An input block with a number input element. + """ + block = InputBlock( + element=NumberInputElement( + is_decimal_allowed=False, + action_id="number_input-action", + ), + label=PlainTextObject(text="Label", emoji=True), + ) + return block diff --git a/block-kit/src/block_elements/overflow_menu.py b/block-kit/src/block_elements/overflow_menu.py new file mode 100644 index 0000000..524d524 --- /dev/null +++ b/block-kit/src/block_elements/overflow_menu.py @@ -0,0 +1,46 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import ( + MarkdownTextObject, + Option, + PlainTextObject, +) +from slack_sdk.models.blocks.block_elements import OverflowMenuElement + + +def example01() -> SectionBlock: + """ + Allows users to press a button to view a list of options. + https://docs.slack.dev/reference/block-kit/block-elements/overflow-menu-element/ + + A section block with an overflow menu as an accessory. + """ + block = SectionBlock( + block_id="section 890", + text=MarkdownTextObject(text="This is a section block with an overflow menu."), + accessory=OverflowMenuElement( + action_id="overflow", + options=[ + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-0", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-1", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-2", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-3", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-4", + ), + ], + ), + ) + return block diff --git a/block-kit/src/block_elements/plain_text_input.py b/block-kit/src/block_elements/plain_text_input.py new file mode 100644 index 0000000..102b9f8 --- /dev/null +++ b/block-kit/src/block_elements/plain_text_input.py @@ -0,0 +1,17 @@ +from slack_sdk.models.blocks import InputBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import PlainTextInputElement + + +def example01() -> InputBlock: + """ + Allows users to enter freeform text data into a single-line or multi-line field. + https://docs.slack.dev/reference/block-kit/block-elements/plain-text-input-element/ + + An input block containing a plain-text input element. + """ + block = InputBlock( + element=PlainTextInputElement(action_id="plain_text_input-action"), + label=PlainTextObject(text="Label", emoji=True), + ) + return block diff --git a/block-kit/src/block_elements/radio_buttons.py b/block-kit/src/block_elements/radio_buttons.py new file mode 100644 index 0000000..6334ae1 --- /dev/null +++ b/block-kit/src/block_elements/radio_buttons.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import Option, PlainTextObject +from slack_sdk.models.blocks.block_elements import RadioButtonsElement + + +def example01() -> SectionBlock: + """ + Allows users to choose one item from a list of possible options. + https://docs.slack.dev/reference/block-kit/block-elements/radio-button-group-element/ + + A section block with a radio button group element as an accessory. + """ + block = SectionBlock( + text=PlainTextObject(text="Check out these rad radio buttons"), + accessory=RadioButtonsElement( + action_id="this_is_an_action_id", + initial_option=Option(value="A1", text=PlainTextObject(text="Radio 1")), + options=[ + Option(value="A1", text=PlainTextObject(text="Radio 1")), + Option(value="A2", text=PlainTextObject(text="Radio 2")), + ], + ), + ) + return block diff --git a/block-kit/src/block_elements/rich_text_input.py b/block-kit/src/block_elements/rich_text_input.py new file mode 100644 index 0000000..2dc0d29 --- /dev/null +++ b/block-kit/src/block_elements/rich_text_input.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import InputBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import RichTextInputElement + + +def example01() -> InputBlock: + """ + Allows users to enter formatted text in a WYSIWYG composer, offering the same messaging writing experience as in Slack. + https://docs.slack.dev/reference/block-kit/block-elements/rich-text-input-element/ + + An input block containing a rich text input element. + """ + block = InputBlock( + element=RichTextInputElement( + action_id="rich_text_input-action", + dispatch_action_config={ + "trigger_actions_on": ["on_character_entered"], + }, + focus_on_load=True, + placeholder=PlainTextObject(text="Enter text", emoji=None), + ), + label=PlainTextObject(text="Label", emoji=True), + ) + return block diff --git a/block-kit/src/block_elements/rich_text_list.py b/block-kit/src/block_elements/rich_text_list.py new file mode 100644 index 0000000..7d659fe --- /dev/null +++ b/block-kit/src/block_elements/rich_text_list.py @@ -0,0 +1,95 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextListElement, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays a list of rich text items. + https://docs.slack.dev/reference/block-kit/block-elements/rich-text-list-element/ + + A rich text block with a bordered bullet list. + """ + block = RichTextBlock( + block_id="block1", + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Text( + text="My favorite Slack features (in no particular order):" + ), + ] + ), + RichTextListElement( + style="bullet", + indent=0, + border=1, + elements=[ + RichTextSectionElement( + elements=[RichTextElementParts.Text(text="Huddles")] + ), + RichTextSectionElement( + elements=[RichTextElementParts.Text(text="Canvas")] + ), + RichTextSectionElement( + elements=[ + RichTextElementParts.Text(text="Developing with Block Kit") + ] + ), + ], + ), + ], + ) + return block + + +def example02() -> RichTextBlock: + """ + A rich text block with a nested bullet list, created by indenting the + middle list into a sub-list. + """ + block = RichTextBlock( + block_id="block1", + elements=[ + RichTextSectionElement( + elements=[RichTextElementParts.Text(text="Breakfast foods I enjoy:")] + ), + RichTextListElement( + style="bullet", + elements=[ + RichTextSectionElement( + elements=[RichTextElementParts.Text(text="Hashbrowns")] + ), + RichTextSectionElement( + elements=[RichTextElementParts.Text(text="Eggs")] + ), + ], + ), + RichTextListElement( + style="bullet", + indent=1, + elements=[ + RichTextSectionElement( + elements=[RichTextElementParts.Text(text="Scrambled")] + ), + RichTextSectionElement( + elements=[RichTextElementParts.Text(text="Over easy")] + ), + ], + ), + RichTextListElement( + style="bullet", + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Text(text="Pancakes, extra syrup") + ] + ), + ], + ), + ], + ) + return block diff --git a/block-kit/src/block_elements/rich_text_preformatted.py b/block-kit/src/block_elements/rich_text_preformatted.py new file mode 100644 index 0000000..73d1811 --- /dev/null +++ b/block-kit/src/block_elements/rich_text_preformatted.py @@ -0,0 +1,27 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextPreformattedElement, +) + + +def example01() -> RichTextBlock: + """ + Displays a preformatted rich text element. + https://docs.slack.dev/reference/block-kit/block-elements/rich-text-preformatted-element/ + + A rich text block with a borderless preformatted code snippet. + """ + block = RichTextBlock( + elements=[ + RichTextPreformattedElement( + border=0, + elements=[ + RichTextElementParts.Text( + text='{\n "object": {\n "description": "this is an example of a json object"\n }\n}' + ), + ], + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/rich_text_quote.py b/block-kit/src/block_elements/rich_text_quote.py new file mode 100644 index 0000000..8d610b4 --- /dev/null +++ b/block-kit/src/block_elements/rich_text_quote.py @@ -0,0 +1,33 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextQuoteElement, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays a rich text quote block. + https://docs.slack.dev/reference/block-kit/block-elements/rich-text-quote-element/ + + A rich text block with a quote followed by a section. + """ + block = RichTextBlock( + block_id="Vrzsu", + elements=[ + RichTextQuoteElement( + elements=[ + RichTextElementParts.Text( + text="What we need is good examples in our documentation." + ), + ] + ), + RichTextSectionElement( + elements=[ + RichTextElementParts.Text(text="Yes - I completely agree, Luke!"), + ] + ), + ], + ) + return block diff --git a/block-kit/src/block_elements/rich_text_section.py b/block-kit/src/block_elements/rich_text_section.py new file mode 100644 index 0000000..fa6d2b9 --- /dev/null +++ b/block-kit/src/block_elements/rich_text_section.py @@ -0,0 +1,67 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> list[RichTextBlock]: + """ + A section element that holds rich text elements. + https://docs.slack.dev/reference/block-kit/block-elements/rich-text-section-element/ + + Four rich text blocks showing basic, bold, italic, and strikethrough text. + """ + blocks = [ + RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Text( + text="Hello there, I am a basic rich text block!" + ), + ] + ) + ] + ), + RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Text(text="Hello there, "), + RichTextElementParts.Text( + text="I am a bold rich text block!", + style={"bold": True}, + ), + ] + ) + ] + ), + RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Text(text="Hello there, "), + RichTextElementParts.Text( + text="I am an italic rich text block!", + style={"italic": True}, + ), + ] + ) + ] + ), + RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Text(text="Hello there, "), + RichTextElementParts.Text( + text="I am a strikethrough rich text block!", + style={"strike": True}, + ), + ] + ) + ] + ), + ] + return blocks diff --git a/block-kit/src/block_elements/select_menu.py b/block-kit/src/block_elements/select_menu.py new file mode 100644 index 0000000..e45a735 --- /dev/null +++ b/block-kit/src/block_elements/select_menu.py @@ -0,0 +1,106 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import ( + MarkdownTextObject, + Option, + PlainTextObject, +) +from slack_sdk.models.blocks.block_elements import ( + ChannelSelectElement, + ConversationSelectElement, + ExternalDataSelectElement, + StaticSelectElement, + UserSelectElement, +) + + +def example01() -> SectionBlock: + """ + Allows users to choose an option from a drop down menu. + https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element/ + + A section block with a static select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick an item from the dropdown list"), + accessory=StaticSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select an item"), + options=[ + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-0", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-1", + ), + Option( + text=PlainTextObject(text="*this is plain_text text*"), + value="value-2", + ), + ], + ), + ) + return block + + +def example02() -> SectionBlock: + """ + A section block with an external data source select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick an item from the dropdown list"), + accessory=ExternalDataSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select an item"), + min_query_length=3, + ), + ) + return block + + +def example03() -> SectionBlock: + """ + A section block with a user list select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick a user from the dropdown list"), + accessory=UserSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select an item"), + ), + ) + return block + + +def example04() -> SectionBlock: + """ + A section block with a conversations list select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick a conversation from the dropdown list"), + accessory=ConversationSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select an item"), + ), + ) + return block + + +def example05() -> SectionBlock: + """ + A section block with a channels list select menu as an accessory. + """ + block = SectionBlock( + block_id="section678", + text=MarkdownTextObject(text="Pick a channel from the dropdown list"), + accessory=ChannelSelectElement( + action_id="text1234", + placeholder=PlainTextObject(text="Select an item"), + ), + ) + return block diff --git a/block-kit/src/block_elements/team.py b/block-kit/src/block_elements/team.py new file mode 100644 index 0000000..396806d --- /dev/null +++ b/block-kit/src/block_elements/team.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Renders as a mention of a workspace or team. + https://docs.slack.dev/reference/block-kit/block-elements/team-element/ + + A rich text block whose section holds a team mention element. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Team(team_id="T123ABC456"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/text.py b/block-kit/src/block_elements/text.py new file mode 100644 index 0000000..a457b89 --- /dev/null +++ b/block-kit/src/block_elements/text.py @@ -0,0 +1,28 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Displays text, optionally with styling. + https://docs.slack.dev/reference/block-kit/block-elements/text-element/ + + A rich text block whose section holds plain and bold-styled text elements. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.Text(text="Hello there, "), + RichTextElementParts.Text( + text="I am a bold rich text block!", + style={"bold": True}, + ), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/time_picker.py b/block-kit/src/block_elements/time_picker.py new file mode 100644 index 0000000..874d0dc --- /dev/null +++ b/block-kit/src/block_elements/time_picker.py @@ -0,0 +1,23 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import MarkdownTextObject, PlainTextObject +from slack_sdk.models.blocks.block_elements import TimePickerElement + + +def example01() -> SectionBlock: + """ + Allows users to select a time of day. + https://docs.slack.dev/reference/block-kit/block-elements/time-picker-element/ + + A section block with a time picker as an accessory. + """ + block = SectionBlock( + block_id="section1234", + text=MarkdownTextObject(text="Pick a date for the deadline."), + accessory=TimePickerElement( + timezone="America/Los_Angeles", + action_id="timepicker123", + initial_time="11:40", + placeholder=PlainTextObject(text="Select a time"), + ), + ) + return block diff --git a/block-kit/src/block_elements/url_input.py b/block-kit/src/block_elements/url_input.py new file mode 100644 index 0000000..cb0702d --- /dev/null +++ b/block-kit/src/block_elements/url_input.py @@ -0,0 +1,17 @@ +from slack_sdk.models.blocks import InputBlock +from slack_sdk.models.blocks.basic_components import PlainTextObject +from slack_sdk.models.blocks.block_elements import UrlInputElement + + +def example01() -> InputBlock: + """ + Allows user to enter a URL into a single-line field. + https://docs.slack.dev/reference/block-kit/block-elements/url-input-element/ + + An input block with a URL input element. + """ + block = InputBlock( + element=UrlInputElement(action_id="url_text_input-action"), + label=PlainTextObject(text="Label", emoji=True), + ) + return block diff --git a/block-kit/src/block_elements/url_source.py b/block-kit/src/block_elements/url_source.py new file mode 100644 index 0000000..a25281e --- /dev/null +++ b/block-kit/src/block_elements/url_source.py @@ -0,0 +1,38 @@ +from slack_sdk.models.blocks import TaskCardBlock +from slack_sdk.models.blocks.block_elements import UrlSourceElement + + +def example01() -> UrlSourceElement: + """ + Displays a URL source with optional icon. + https://docs.slack.dev/reference/block-kit/block-elements/url-source-element/ + + A standalone URL source element. + """ + element = UrlSourceElement( + url="https://docs.slack.dev/", + text="Slack API docs", + ) + return element + + +def example02() -> TaskCardBlock: + """ + A task card block whose sources are URL source elements. + """ + block = TaskCardBlock( + task_id="task_1", + title="Scientific findings", + status="complete", + sources=[ + UrlSourceElement( + url="https://docs.example.com/", + text="Tracy's delightful docs", + ), + UrlSourceElement( + url="https://research.example.com/", + text="Haley's resourceful research", + ), + ], + ) + return block diff --git a/block-kit/src/block_elements/user.py b/block-kit/src/block_elements/user.py new file mode 100644 index 0000000..9dabe50 --- /dev/null +++ b/block-kit/src/block_elements/user.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Renders as a mention of a user. + https://docs.slack.dev/reference/block-kit/block-elements/user-element/ + + A rich text block whose section holds a user mention element. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.User(user_id="U123ABC456"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/usergroup.py b/block-kit/src/block_elements/usergroup.py new file mode 100644 index 0000000..71b93d0 --- /dev/null +++ b/block-kit/src/block_elements/usergroup.py @@ -0,0 +1,24 @@ +from slack_sdk.models.blocks import RichTextBlock +from slack_sdk.models.blocks.block_elements import ( + RichTextElementParts, + RichTextSectionElement, +) + + +def example01() -> RichTextBlock: + """ + Renders as a mention of a user group. + https://docs.slack.dev/reference/block-kit/block-elements/usergroup-element/ + + A rich text block whose section holds a user group mention element. + """ + block = RichTextBlock( + elements=[ + RichTextSectionElement( + elements=[ + RichTextElementParts.UserGroup(usergroup_id="G123ABC456"), + ] + ) + ] + ) + return block diff --git a/block-kit/src/block_elements/workflow_button.py b/block-kit/src/block_elements/workflow_button.py new file mode 100644 index 0000000..c054a0d --- /dev/null +++ b/block-kit/src/block_elements/workflow_button.py @@ -0,0 +1,42 @@ +from slack_sdk.models.blocks import SectionBlock +from slack_sdk.models.blocks.basic_components import ( + MarkdownTextObject, + PlainTextObject, + Workflow, + WorkflowTrigger, +) +from slack_sdk.models.blocks.block_elements import WorkflowButtonElement + + +def example01() -> SectionBlock: + """ + Allows users to run a link trigger with customizable inputs. + https://docs.slack.dev/reference/block-kit/block-elements/workflow-button-element/ + + A section block with a workflow button as an accessory. + """ + block = SectionBlock( + text=MarkdownTextObject( + text="A message *with some bold text* and _some italicized text_." + ), + accessory=WorkflowButtonElement( + text=PlainTextObject(text="Run Workflow"), + action_id="workflowbutton123", + workflow=Workflow( + trigger=WorkflowTrigger( + url="https://slack.com/shortcuts/Ft0123ABC456/xyz...zyx", + customizable_input_parameters=[ + { + "name": "input_parameter_a", + "value": "Value for input param A", + }, + { + "name": "input_parameter_b", + "value": "Value for input param B", + }, + ], + ), + ), + ), + ) + return block diff --git a/block-kit/tests/block_elements/__init__.py b/block-kit/tests/block_elements/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/block-kit/tests/block_elements/test_broadcast.py b/block-kit/tests/block_elements/test_broadcast.py new file mode 100644 index 0000000..27dfff9 --- /dev/null +++ b/block-kit/tests/block_elements/test_broadcast.py @@ -0,0 +1,23 @@ +import json + +from src.block_elements import broadcast + + +def test_example01(): + block = broadcast.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "broadcast", + "range": "everyone", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_button.py b/block-kit/tests/block_elements/test_button.py new file mode 100644 index 0000000..3180252 --- /dev/null +++ b/block-kit/tests/block_elements/test_button.py @@ -0,0 +1,95 @@ +import json + +from src.block_elements import button + + +def test_example01(): + element = button.example01() + actual = element.to_dict() + expected = { + "type": "button", + "text": { + "type": "plain_text", + "text": "Click Me", + }, + "value": "click_me_123", + "action_id": "button", + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example02(): + element = button.example02() + actual = element.to_dict() + expected = { + "type": "button", + "text": { + "type": "plain_text", + "text": "Save", + }, + "style": "primary", + "value": "click_me_123", + "action_id": "button", + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example03(): + element = button.example03() + actual = element.to_dict() + expected = { + "type": "button", + "text": { + "type": "plain_text", + "text": "Link Button", + }, + "url": "https://docs.slack.dev/block-kit", + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example04(): + blocks = button.example04() + actual = [block.to_dict() for block in blocks] + expected = [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "This is a section block with a button.", + }, + "accessory": { + "type": "button", + "text": { + "type": "plain_text", + "text": "Click Me", + }, + "value": "click_me_123", + "action_id": "button", + }, + }, + { + "type": "actions", + "block_id": "actionblock789", + "elements": [ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Primary Button", + }, + "style": "primary", + "value": "click_me_456", + }, + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Link Button", + }, + "url": "https://api.slack.com/block-kit", + }, + ], + }, + ] + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_channel.py b/block-kit/tests/block_elements/test_channel.py new file mode 100644 index 0000000..fdb8f56 --- /dev/null +++ b/block-kit/tests/block_elements/test_channel.py @@ -0,0 +1,23 @@ +import json + +from src.block_elements import channel + + +def test_example01(): + block = channel.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "channel", + "channel_id": "C123ABC456", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_checkboxes.py b/block-kit/tests/block_elements/test_checkboxes.py new file mode 100644 index 0000000..2956521 --- /dev/null +++ b/block-kit/tests/block_elements/test_checkboxes.py @@ -0,0 +1,49 @@ +import json + +from src.block_elements import checkboxes + + +def test_example01(): + block = checkboxes.example01() + actual = block.to_dict() + expected = { + "type": "section", + "text": { + "type": "plain_text", + "text": "Check out these charming checkboxes", + }, + "accessory": { + "type": "checkboxes", + "action_id": "this_is_an_action_id", + "initial_options": [ + { + "value": "A1", + "text": { + "type": "plain_text", + "text": "Checkbox 1", + }, + }, + ], + "options": [ + { + "value": "A1", + "text": { + "type": "plain_text", + "text": "Checkbox 1", + }, + }, + { + "value": "A2", + "text": { + "type": "plain_text", + "text": "Checkbox 2", + }, + "description": { + "type": "mrkdwn", + "text": "*A description of option two*", + }, + }, + ], + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_color.py b/block-kit/tests/block_elements/test_color.py new file mode 100644 index 0000000..0d6f544 --- /dev/null +++ b/block-kit/tests/block_elements/test_color.py @@ -0,0 +1,23 @@ +import json + +from src.block_elements import color + + +def test_example01(): + block = color.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "color", + "value": "#F405B3", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_date.py b/block-kit/tests/block_elements/test_date.py new file mode 100644 index 0000000..53f5c2a --- /dev/null +++ b/block-kit/tests/block_elements/test_date.py @@ -0,0 +1,25 @@ +import json + +from src.block_elements import date + + +def test_example01(): + block = date.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "date", + "timestamp": 1720710212, + "format": "{date_num} at {time}", + "fallback": "timey", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_date_picker.py b/block-kit/tests/block_elements/test_date_picker.py new file mode 100644 index 0000000..16db365 --- /dev/null +++ b/block-kit/tests/block_elements/test_date_picker.py @@ -0,0 +1,26 @@ +import json + +from src.block_elements import date_picker + + +def test_example01(): + block = date_picker.example01() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section1234", + "text": { + "type": "mrkdwn", + "text": "Pick a date for the deadline.", + }, + "accessory": { + "type": "datepicker", + "action_id": "datepicker123", + "initial_date": "1990-04-28", + "placeholder": { + "type": "plain_text", + "text": "Select a date", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_datetime_picker.py b/block-kit/tests/block_elements/test_datetime_picker.py new file mode 100644 index 0000000..60098ce --- /dev/null +++ b/block-kit/tests/block_elements/test_datetime_picker.py @@ -0,0 +1,26 @@ +import json + +from src.block_elements import datetime_picker + + +def test_example01(): + block = datetime_picker.example01() + actual = block.to_dict() + expected = { + "type": "input", + "element": { + "type": "datetimepicker", + "action_id": "datetimepicker-action", + }, + "hint": { + "type": "plain_text", + "text": "This is some hint text", + "emoji": True, + }, + "label": { + "type": "plain_text", + "text": "Start date", + "emoji": True, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_email_input.py b/block-kit/tests/block_elements/test_email_input.py new file mode 100644 index 0000000..1758b25 --- /dev/null +++ b/block-kit/tests/block_elements/test_email_input.py @@ -0,0 +1,25 @@ +import json + +from src.block_elements import email_input + + +def test_example01(): + block = email_input.example01() + actual = block.to_dict() + expected = { + "type": "input", + "block_id": "input123", + "label": { + "type": "plain_text", + "text": "Email Address", + }, + "element": { + "type": "email_text_input", + "action_id": "email_text_input-action", + "placeholder": { + "type": "plain_text", + "text": "Enter an email", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_emoji.py b/block-kit/tests/block_elements/test_emoji.py new file mode 100644 index 0000000..dfe7851 --- /dev/null +++ b/block-kit/tests/block_elements/test_emoji.py @@ -0,0 +1,39 @@ +import json + +from src.block_elements import emoji + + +def test_example01(): + block = emoji.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "emoji", + "name": "basketball", + }, + { + "type": "text", + "text": " ", + }, + { + "type": "emoji", + "name": "snowboarder", + }, + { + "type": "text", + "text": " ", + }, + { + "type": "emoji", + "name": "checkered_flag", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_feedback_buttons.py b/block-kit/tests/block_elements/test_feedback_buttons.py new file mode 100644 index 0000000..9fc5c8f --- /dev/null +++ b/block-kit/tests/block_elements/test_feedback_buttons.py @@ -0,0 +1,34 @@ +import json + +from src.block_elements import feedback_buttons + + +def test_example01(): + block = feedback_buttons.example01() + actual = block.to_dict() + expected = { + "type": "context_actions", + "elements": [ + { + "type": "feedback_buttons", + "action_id": "feedback_buttons_1", + "positive_button": { + "text": { + "type": "plain_text", + "text": "Good", + }, + "value": "positive_feedback", + "accessibility_label": "Mark this response as good", + }, + "negative_button": { + "text": { + "type": "plain_text", + "text": "Bad", + }, + "value": "negative_feedback", + "accessibility_label": "Mark this response as bad", + }, + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_file_input.py b/block-kit/tests/block_elements/test_file_input.py new file mode 100644 index 0000000..8e53c5c --- /dev/null +++ b/block-kit/tests/block_elements/test_file_input.py @@ -0,0 +1,26 @@ +import json + +from src.block_elements import file_input + + +def test_example01(): + block = file_input.example01() + actual = block.to_dict() + expected = { + "type": "input", + "block_id": "input_block_id", + "label": { + "type": "plain_text", + "text": "Upload Files", + }, + "element": { + "type": "file_input", + "action_id": "file_input_action_id_1", + "filetypes": [ + "jpg", + "png", + ], + "max_files": 5, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_icon_button.py b/block-kit/tests/block_elements/test_icon_button.py new file mode 100644 index 0000000..1f5a341 --- /dev/null +++ b/block-kit/tests/block_elements/test_icon_button.py @@ -0,0 +1,24 @@ +import json + +from src.block_elements import icon_button + + +def test_example01(): + block = icon_button.example01() + actual = block.to_dict() + expected = { + "type": "context_actions", + "elements": [ + { + "type": "icon_button", + "icon": "trash", + "text": { + "type": "plain_text", + "text": "Delete", + }, + "action_id": "delete_button", + "value": "delete_item", + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_image.py b/block-kit/tests/block_elements/test_image.py new file mode 100644 index 0000000..19a34fc --- /dev/null +++ b/block-kit/tests/block_elements/test_image.py @@ -0,0 +1,64 @@ +import json + +from src.block_elements import image + + +def test_example01(): + block = image.example01() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section567", + "text": { + "type": "mrkdwn", + "text": "This is a section block with an accessory image.", + }, + "accessory": { + "type": "image", + "image_url": "https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg", + "alt_text": "cute cat", + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example02(): + block = image.example02() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section567", + "text": { + "type": "mrkdwn", + "text": "This is a section block with an accessory image.", + }, + "accessory": { + "type": "image", + "slack_file": { + "url": "https://files.slack.com/files-pri/T0123456-F0123456/xyz.png", + }, + "alt_text": "Slack file object.", + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example03(): + block = image.example03() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section567", + "text": { + "type": "mrkdwn", + "text": "This is a section block with an accessory image.", + }, + "accessory": { + "type": "image", + "slack_file": { + "id": "F01234567", + }, + "alt_text": "Slack file object.", + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_link.py b/block-kit/tests/block_elements/test_link.py new file mode 100644 index 0000000..3667c90 --- /dev/null +++ b/block-kit/tests/block_elements/test_link.py @@ -0,0 +1,23 @@ +import json + +from src.block_elements import link + + +def test_example01(): + block = link.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "link", + "url": "https://docs.slack.dev", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_multi_select_menu.py b/block-kit/tests/block_elements/test_multi_select_menu.py new file mode 100644 index 0000000..96a2f8c --- /dev/null +++ b/block-kit/tests/block_elements/test_multi_select_menu.py @@ -0,0 +1,137 @@ +import json + +from src.block_elements import multi_select_menu + + +def test_example01(): + block = multi_select_menu.example01() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick items from the list", + }, + "accessory": { + "type": "multi_static_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select items", + }, + "options": [ + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-0", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-1", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-2", + }, + ], + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example02(): + block = multi_select_menu.example02() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick items from the list", + }, + "accessory": { + "type": "multi_external_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select items", + }, + "min_query_length": 3, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example03(): + block = multi_select_menu.example03() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick users from the list", + }, + "accessory": { + "type": "multi_users_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select users", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example04(): + block = multi_select_menu.example04() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick conversations from the list", + }, + "accessory": { + "type": "multi_conversations_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select conversations", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example05(): + block = multi_select_menu.example05() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick channels from the list", + }, + "accessory": { + "type": "multi_channels_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select channels", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_number_input.py b/block-kit/tests/block_elements/test_number_input.py new file mode 100644 index 0000000..65dd15e --- /dev/null +++ b/block-kit/tests/block_elements/test_number_input.py @@ -0,0 +1,22 @@ +import json + +from src.block_elements import number_input + + +def test_example01(): + block = number_input.example01() + actual = block.to_dict() + expected = { + "type": "input", + "element": { + "type": "number_input", + "is_decimal_allowed": False, + "action_id": "number_input-action", + }, + "label": { + "type": "plain_text", + "text": "Label", + "emoji": True, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_overflow_menu.py b/block-kit/tests/block_elements/test_overflow_menu.py new file mode 100644 index 0000000..a87dbc5 --- /dev/null +++ b/block-kit/tests/block_elements/test_overflow_menu.py @@ -0,0 +1,58 @@ +import json + +from src.block_elements import overflow_menu + + +def test_example01(): + block = overflow_menu.example01() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section 890", + "text": { + "type": "mrkdwn", + "text": "This is a section block with an overflow menu.", + }, + "accessory": { + "type": "overflow", + "action_id": "overflow", + "options": [ + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-0", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-1", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-2", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-3", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-4", + }, + ], + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_plain_text_input.py b/block-kit/tests/block_elements/test_plain_text_input.py new file mode 100644 index 0000000..74f616c --- /dev/null +++ b/block-kit/tests/block_elements/test_plain_text_input.py @@ -0,0 +1,21 @@ +import json + +from src.block_elements import plain_text_input + + +def test_example01(): + block = plain_text_input.example01() + actual = block.to_dict() + expected = { + "type": "input", + "element": { + "type": "plain_text_input", + "action_id": "plain_text_input-action", + }, + "label": { + "type": "plain_text", + "text": "Label", + "emoji": True, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_radio_buttons.py b/block-kit/tests/block_elements/test_radio_buttons.py new file mode 100644 index 0000000..1c41352 --- /dev/null +++ b/block-kit/tests/block_elements/test_radio_buttons.py @@ -0,0 +1,43 @@ +import json + +from src.block_elements import radio_buttons + + +def test_example01(): + block = radio_buttons.example01() + actual = block.to_dict() + expected = { + "type": "section", + "text": { + "type": "plain_text", + "text": "Check out these rad radio buttons", + }, + "accessory": { + "type": "radio_buttons", + "action_id": "this_is_an_action_id", + "initial_option": { + "value": "A1", + "text": { + "type": "plain_text", + "text": "Radio 1", + }, + }, + "options": [ + { + "value": "A1", + "text": { + "type": "plain_text", + "text": "Radio 1", + }, + }, + { + "value": "A2", + "text": { + "type": "plain_text", + "text": "Radio 2", + }, + }, + ], + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_rich_text_input.py b/block-kit/tests/block_elements/test_rich_text_input.py new file mode 100644 index 0000000..d0a85a8 --- /dev/null +++ b/block-kit/tests/block_elements/test_rich_text_input.py @@ -0,0 +1,31 @@ +import json + +from src.block_elements import rich_text_input + + +def test_example01(): + block = rich_text_input.example01() + actual = block.to_dict() + expected = { + "type": "input", + "label": { + "type": "plain_text", + "text": "Label", + "emoji": True, + }, + "element": { + "type": "rich_text_input", + "action_id": "rich_text_input-action", + "dispatch_action_config": { + "trigger_actions_on": [ + "on_character_entered", + ], + }, + "focus_on_load": True, + "placeholder": { + "type": "plain_text", + "text": "Enter text", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_rich_text_list.py b/block-kit/tests/block_elements/test_rich_text_list.py new file mode 100644 index 0000000..cf57906 --- /dev/null +++ b/block-kit/tests/block_elements/test_rich_text_list.py @@ -0,0 +1,144 @@ +import json + +from src.block_elements import rich_text_list + + +def test_example01(): + block = rich_text_list.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "block_id": "block1", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "My favorite Slack features (in no particular order):", + }, + ], + }, + { + "type": "rich_text_list", + "style": "bullet", + "indent": 0, + "border": 1, + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Huddles", + }, + ], + }, + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Canvas", + }, + ], + }, + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Developing with Block Kit", + }, + ], + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example02(): + block = rich_text_list.example02() + actual = block.to_dict() + expected = { + "type": "rich_text", + "block_id": "block1", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Breakfast foods I enjoy:", + }, + ], + }, + { + "type": "rich_text_list", + "style": "bullet", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Hashbrowns", + }, + ], + }, + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Eggs", + }, + ], + }, + ], + }, + { + "type": "rich_text_list", + "style": "bullet", + "indent": 1, + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Scrambled", + }, + ], + }, + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Over easy", + }, + ], + }, + ], + }, + { + "type": "rich_text_list", + "style": "bullet", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Pancakes, extra syrup", + }, + ], + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_rich_text_preformatted.py b/block-kit/tests/block_elements/test_rich_text_preformatted.py new file mode 100644 index 0000000..4da8e24 --- /dev/null +++ b/block-kit/tests/block_elements/test_rich_text_preformatted.py @@ -0,0 +1,24 @@ +import json + +from src.block_elements import rich_text_preformatted + + +def test_example01(): + block = rich_text_preformatted.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_preformatted", + "border": 0, + "elements": [ + { + "type": "text", + "text": '{\n "object": {\n "description": "this is an example of a json object"\n }\n}', + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_rich_text_quote.py b/block-kit/tests/block_elements/test_rich_text_quote.py new file mode 100644 index 0000000..1f40444 --- /dev/null +++ b/block-kit/tests/block_elements/test_rich_text_quote.py @@ -0,0 +1,33 @@ +import json + +from src.block_elements import rich_text_quote + + +def test_example01(): + block = rich_text_quote.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "block_id": "Vrzsu", + "elements": [ + { + "type": "rich_text_quote", + "elements": [ + { + "type": "text", + "text": "What we need is good examples in our documentation.", + }, + ], + }, + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Yes - I completely agree, Luke!", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_rich_text_section.py b/block-kit/tests/block_elements/test_rich_text_section.py new file mode 100644 index 0000000..a34ab44 --- /dev/null +++ b/block-kit/tests/block_elements/test_rich_text_section.py @@ -0,0 +1,88 @@ +import json + +from src.block_elements import rich_text_section + + +def test_example01(): + blocks = rich_text_section.example01() + actual = [block.to_dict() for block in blocks] + expected = [ + { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Hello there, I am a basic rich text block!", + }, + ], + }, + ], + }, + { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Hello there, ", + }, + { + "type": "text", + "text": "I am a bold rich text block!", + "style": { + "bold": True, + }, + }, + ], + }, + ], + }, + { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Hello there, ", + }, + { + "type": "text", + "text": "I am an italic rich text block!", + "style": { + "italic": True, + }, + }, + ], + }, + ], + }, + { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Hello there, ", + }, + { + "type": "text", + "text": "I am a strikethrough rich text block!", + "style": { + "strike": True, + }, + }, + ], + }, + ], + }, + ] + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_select_menu.py b/block-kit/tests/block_elements/test_select_menu.py new file mode 100644 index 0000000..aa98165 --- /dev/null +++ b/block-kit/tests/block_elements/test_select_menu.py @@ -0,0 +1,137 @@ +import json + +from src.block_elements import select_menu + + +def test_example01(): + block = select_menu.example01() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick an item from the dropdown list", + }, + "accessory": { + "type": "static_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select an item", + }, + "options": [ + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-0", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-1", + }, + { + "text": { + "type": "plain_text", + "text": "*this is plain_text text*", + }, + "value": "value-2", + }, + ], + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example02(): + block = select_menu.example02() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick an item from the dropdown list", + }, + "accessory": { + "type": "external_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select an item", + }, + "min_query_length": 3, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example03(): + block = select_menu.example03() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick a user from the dropdown list", + }, + "accessory": { + "type": "users_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select an item", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example04(): + block = select_menu.example04() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick a conversation from the dropdown list", + }, + "accessory": { + "type": "conversations_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select an item", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example05(): + block = select_menu.example05() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick a channel from the dropdown list", + }, + "accessory": { + "type": "channels_select", + "action_id": "text1234", + "placeholder": { + "type": "plain_text", + "text": "Select an item", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_team.py b/block-kit/tests/block_elements/test_team.py new file mode 100644 index 0000000..b7fe0ba --- /dev/null +++ b/block-kit/tests/block_elements/test_team.py @@ -0,0 +1,23 @@ +import json + +from src.block_elements import team + + +def test_example01(): + block = team.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "team", + "team_id": "T123ABC456", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_text.py b/block-kit/tests/block_elements/test_text.py new file mode 100644 index 0000000..cc0849f --- /dev/null +++ b/block-kit/tests/block_elements/test_text.py @@ -0,0 +1,30 @@ +import json + +from src.block_elements import text + + +def test_example01(): + block = text.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Hello there, ", + }, + { + "type": "text", + "text": "I am a bold rich text block!", + "style": { + "bold": True, + }, + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_time_picker.py b/block-kit/tests/block_elements/test_time_picker.py new file mode 100644 index 0000000..256c925 --- /dev/null +++ b/block-kit/tests/block_elements/test_time_picker.py @@ -0,0 +1,27 @@ +import json + +from src.block_elements import time_picker + + +def test_example01(): + block = time_picker.example01() + actual = block.to_dict() + expected = { + "type": "section", + "block_id": "section1234", + "text": { + "type": "mrkdwn", + "text": "Pick a date for the deadline.", + }, + "accessory": { + "type": "timepicker", + "timezone": "America/Los_Angeles", + "action_id": "timepicker123", + "initial_time": "11:40", + "placeholder": { + "type": "plain_text", + "text": "Select a time", + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_url_input.py b/block-kit/tests/block_elements/test_url_input.py new file mode 100644 index 0000000..bb0c737 --- /dev/null +++ b/block-kit/tests/block_elements/test_url_input.py @@ -0,0 +1,21 @@ +import json + +from src.block_elements import url_input + + +def test_example01(): + block = url_input.example01() + actual = block.to_dict() + expected = { + "type": "input", + "element": { + "type": "url_text_input", + "action_id": "url_text_input-action", + }, + "label": { + "type": "plain_text", + "text": "Label", + "emoji": True, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_url_source.py b/block-kit/tests/block_elements/test_url_source.py new file mode 100644 index 0000000..41c286a --- /dev/null +++ b/block-kit/tests/block_elements/test_url_source.py @@ -0,0 +1,38 @@ +import json + +from src.block_elements import url_source + + +def test_example01(): + element = url_source.example01() + actual = element.to_dict() + expected = { + "type": "url", + "url": "https://docs.slack.dev/", + "text": "Slack API docs", + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) + + +def test_example02(): + block = url_source.example02() + actual = block.to_dict() + expected = { + "type": "task_card", + "task_id": "task_1", + "title": "Scientific findings", + "status": "complete", + "sources": [ + { + "type": "url", + "url": "https://docs.example.com/", + "text": "Tracy's delightful docs", + }, + { + "type": "url", + "url": "https://research.example.com/", + "text": "Haley's resourceful research", + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_user.py b/block-kit/tests/block_elements/test_user.py new file mode 100644 index 0000000..2c72e00 --- /dev/null +++ b/block-kit/tests/block_elements/test_user.py @@ -0,0 +1,23 @@ +import json + +from src.block_elements import user + + +def test_example01(): + block = user.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "user", + "user_id": "U123ABC456", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_usergroup.py b/block-kit/tests/block_elements/test_usergroup.py new file mode 100644 index 0000000..94d629d --- /dev/null +++ b/block-kit/tests/block_elements/test_usergroup.py @@ -0,0 +1,23 @@ +import json + +from src.block_elements import usergroup + + +def test_example01(): + block = usergroup.example01() + actual = block.to_dict() + expected = { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "usergroup", + "usergroup_id": "G123ABC456", + }, + ], + }, + ], + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True) diff --git a/block-kit/tests/block_elements/test_workflow_button.py b/block-kit/tests/block_elements/test_workflow_button.py new file mode 100644 index 0000000..184a365 --- /dev/null +++ b/block-kit/tests/block_elements/test_workflow_button.py @@ -0,0 +1,39 @@ +import json + +from src.block_elements import workflow_button + + +def test_example01(): + block = workflow_button.example01() + actual = block.to_dict() + expected = { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "A message *with some bold text* and _some italicized text_.", + }, + "accessory": { + "type": "workflow_button", + "text": { + "type": "plain_text", + "text": "Run Workflow", + }, + "action_id": "workflowbutton123", + "workflow": { + "trigger": { + "url": "https://slack.com/shortcuts/Ft0123ABC456/xyz...zyx", + "customizable_input_parameters": [ + { + "name": "input_parameter_a", + "value": "Value for input param A", + }, + { + "name": "input_parameter_b", + "value": "Value for input param B", + }, + ], + }, + }, + }, + } + assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True)