diff --git a/block-kit/README.md b/block-kit/README.md index 3cd3768..7f29d5e 100644 --- a/block-kit/README.md +++ b/block-kit/README.md @@ -20,3 +20,24 @@ Read the [docs](https://docs.slack.dev/block-kit/) to learn concepts behind thes - **[Section](https://docs.slack.dev/reference/block-kit/blocks/section-block)**: Displays text, possibly alongside elements. [Implementation](./src/main/java/blocks/Section.java). - **[Video](https://docs.slack.dev/reference/block-kit/blocks/video-block)**: Displays an embedded video player. [Implementation](./src/main/java/blocks/Video.java). +### Block elements + +- **[Button](https://docs.slack.dev/reference/block-kit/block-elements/button-element)**: Allows users a direct path to performing basic actions. [Implementation](./src/main/java/blockelements/Button.java). +- **[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/main/java/blockelements/DatePicker.java). +- **[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/main/java/blockelements/DatetimePicker.java). +- **[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/main/java/blockelements/EmailInput.java). +- **[Feedback buttons](https://docs.slack.dev/reference/block-kit/block-elements/feedback-buttons-element)**: Buttons to indicate positive or negative feedback. [Implementation](./src/main/java/blockelements/FeedbackButtons.java). +- **[File input](https://docs.slack.dev/reference/block-kit/block-elements/file-input-element)**: Allows user to upload files. [Implementation](./src/main/java/blockelements/FileInput.java). +- **[Icon button](https://docs.slack.dev/reference/block-kit/block-elements/icon-button-element)**: An icon button to perform actions. [Implementation](./src/main/java/blockelements/IconButton.java). +- **[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/main/java/blockelements/Image.java). +- **[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/main/java/blockelements/MultiSelectMenu.java). +- **[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/main/java/blockelements/NumberInput.java). +- **[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/main/java/blockelements/OverflowMenu.java). +- **[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/main/java/blockelements/PlainTextInput.java). +- **[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/main/java/blockelements/RadioButtons.java). +- **[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/main/java/blockelements/RichTextInput.java). +- **[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/main/java/blockelements/SelectMenu.java). +- **[Time picker](https://docs.slack.dev/reference/block-kit/block-elements/time-picker-element)**: A time picker element; on desktop a dropdown with free-text entry, on mobile the native time picker UI. [Implementation](./src/main/java/blockelements/TimePicker.java). +- **[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/main/java/blockelements/UrlInput.java). +- **[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/main/java/blockelements/WorkflowButton.java). + diff --git a/block-kit/src/main/java/blockelements/Button.java b/block-kit/src/main/java/blockelements/Button.java new file mode 100644 index 0000000..6255873 --- /dev/null +++ b/block-kit/src/main/java/blockelements/Button.java @@ -0,0 +1,62 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.LayoutBlock; +import com.slack.api.model.block.element.BlockElements; +import com.slack.api.model.block.element.ButtonElement; +import java.util.List; + +/** + * Allows users a direct path to performing basic actions. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/button-element/} + */ +public class Button { + /** + * A regular button. + */ + public static ButtonElement example01() { + ButtonElement element = BlockElements.button( + b -> b.text(plainText("Click Me")).value("click_me_123").actionId("button")); + return element; + } + + /** + * A button using the primary style. + */ + public static ButtonElement example02() { + ButtonElement element = BlockElements.button(b -> + b.text(plainText("Save")).style("primary").value("click_me_123").actionId("button")); + return element; + } + + /** + * A button that opens a link. + */ + public static ButtonElement example03() { + ButtonElement element = + BlockElements.button(b -> b.text(plainText("Link Button")).url("https://docs.slack.dev/block-kit")); + return element; + } + + /** + * Buttons hosted in a section accessory and an actions block. + */ + public static List example04() { + List blocks = List.of( + Blocks.section(s -> s.text(markdownText("This is a section block with a button.")) + .accessory(BlockElements.button(b -> b.text(plainText("Click Me")) + .value("click_me_123") + .actionId("button")))), + Blocks.actions(a -> a.blockId("actionblock789") + .elements(List.of( + BlockElements.button(b -> b.text(plainText("Primary Button")) + .style("primary") + .value("click_me_456")), + BlockElements.button(b -> + b.text(plainText("Link Button")).url("https://api.slack.com/block-kit")))))); + return blocks; + } +} diff --git a/block-kit/src/main/java/blockelements/DatePicker.java b/block-kit/src/main/java/blockelements/DatePicker.java new file mode 100644 index 0000000..4fbd6c3 --- /dev/null +++ b/block-kit/src/main/java/blockelements/DatePicker.java @@ -0,0 +1,26 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.element.BlockElements; + +/** + * Allows users to select a date from a calendar style UI. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/date-picker-element/} + */ +public class DatePicker { + /** + * A section block with a date picker accessory. + */ + public static SectionBlock example01() { + SectionBlock block = Blocks.section(s -> s.blockId("section1234") + .text(markdownText("Pick a date for the deadline.")) + .accessory(BlockElements.datePicker(d -> d.actionId("datepicker123") + .initialDate("1990-04-28") + .placeholder(plainText("Select a date"))))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/DatetimePicker.java b/block-kit/src/main/java/blockelements/DatetimePicker.java new file mode 100644 index 0000000..7a65b61 --- /dev/null +++ b/block-kit/src/main/java/blockelements/DatetimePicker.java @@ -0,0 +1,24 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.InputBlock; +import com.slack.api.model.block.element.BlockElements; + +/** + * Allows users to select both a date and a time of day. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/datetime-picker-element/} + */ +public class DatetimePicker { + /** + * An input block with a datetime picker element. + */ + public static InputBlock example01() { + InputBlock block = + Blocks.input(i -> i.element(BlockElements.datetimePicker(d -> d.actionId("datetimepicker-action"))) + .hint(plainText(pt -> pt.text("This is some hint text").emoji(true))) + .label(plainText(pt -> pt.text("Start date").emoji(true)))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/EmailInput.java b/block-kit/src/main/java/blockelements/EmailInput.java new file mode 100644 index 0000000..d99d588 --- /dev/null +++ b/block-kit/src/main/java/blockelements/EmailInput.java @@ -0,0 +1,24 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.InputBlock; +import com.slack.api.model.block.element.BlockElements; + +/** + * Allows user to enter an email into a single-line field. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/email-input-element/} + */ +public class EmailInput { + /** + * An input block with an email input element. + */ + public static InputBlock example01() { + InputBlock block = Blocks.input(i -> i.blockId("input123") + .label(plainText("Email Address")) + .element(BlockElements.emailTextInput( + e -> e.actionId("email_text_input-action").placeholder(plainText("Enter an email"))))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/FeedbackButtons.java b/block-kit/src/main/java/blockelements/FeedbackButtons.java new file mode 100644 index 0000000..6b65ea7 --- /dev/null +++ b/block-kit/src/main/java/blockelements/FeedbackButtons.java @@ -0,0 +1,34 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.ContextActionsBlock; +import com.slack.api.model.block.composition.FeedbackButtonObject; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Buttons to indicate positive or negative feedback. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/feedback-buttons-element/} + */ +public class FeedbackButtons { + /** + * A context actions block with a feedback buttons element. + */ + public static ContextActionsBlock example01() { + ContextActionsBlock block = + Blocks.contextActions(List.of(BlockElements.feedbackButtons(fb -> fb.actionId("feedback_buttons_1") + .positiveButton(FeedbackButtonObject.builder() + .text(plainText("Good")) + .value("positive_feedback") + .accessibilityLabel("Mark this response as good") + .build()) + .negativeButton(FeedbackButtonObject.builder() + .text(plainText("Bad")) + .value("negative_feedback") + .accessibilityLabel("Mark this response as bad") + .build())))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/FileInput.java b/block-kit/src/main/java/blockelements/FileInput.java new file mode 100644 index 0000000..261ed46 --- /dev/null +++ b/block-kit/src/main/java/blockelements/FileInput.java @@ -0,0 +1,26 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.InputBlock; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Allows user to upload files. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/file-input-element/} + */ +public class FileInput { + /** + * An input block with a file input element. + */ + public static InputBlock example01() { + InputBlock block = Blocks.input(i -> i.blockId("input_block_id") + .label(plainText("Upload Files")) + .element(BlockElements.fileInput(f -> f.actionId("file_input_action_id_1") + .filetypes(List.of("jpg", "png")) + .maxFiles(5)))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/IconButton.java b/block-kit/src/main/java/blockelements/IconButton.java new file mode 100644 index 0000000..10e264d --- /dev/null +++ b/block-kit/src/main/java/blockelements/IconButton.java @@ -0,0 +1,25 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.ContextActionsBlock; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * An icon button to perform actions. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/icon-button-element/} + */ +public class IconButton { + /** + * A context actions block with an icon button element. + */ + public static ContextActionsBlock example01() { + ContextActionsBlock block = Blocks.contextActions(List.of(BlockElements.iconButton(ib -> ib.icon("trash") + .text(plainText("Delete")) + .actionId("delete_button") + .value("delete_item")))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/Image.java b/block-kit/src/main/java/blockelements/Image.java new file mode 100644 index 0000000..08db8dd --- /dev/null +++ b/block-kit/src/main/java/blockelements/Image.java @@ -0,0 +1,51 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.composition.SlackFileObject; +import com.slack.api.model.block.element.BlockElements; + +/** + * Displays an image as part of a larger block of content. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/image-element/} + */ +public class Image { + /** + * A section block with an image accessory using image_url. + */ + public static SectionBlock example01() { + SectionBlock block = Blocks.section(s -> s.blockId("section567") + .text(markdownText("This is a section block with an accessory image.")) + .accessory(BlockElements.image( + i -> i.imageUrl("https://pbs.twimg.com/profile_images/625633822235693056/lNGUneLX_400x400.jpg") + .altText("cute cat")))); + return block; + } + + /** + * A section block with an image accessory using a slack_file url. + */ + public static SectionBlock example02() { + SectionBlock block = Blocks.section(s -> s.blockId("section567") + .text(markdownText("This is a section block with an accessory image.")) + .accessory(BlockElements.image(i -> i.slackFile(SlackFileObject.builder() + .url("https://files.slack.com/files-pri/T0123456-F0123456/xyz.png") + .build()) + .altText("Slack file object.")))); + return block; + } + + /** + * A section block with an image accessory using a slack_file id. + */ + public static SectionBlock example03() { + SectionBlock block = Blocks.section(s -> s.blockId("section567") + .text(markdownText("This is a section block with an accessory image.")) + .accessory(BlockElements.image(i -> i.slackFile( + SlackFileObject.builder().id("F01234567").build()) + .altText("Slack file object.")))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/MultiSelectMenu.java b/block-kit/src/main/java/blockelements/MultiSelectMenu.java new file mode 100644 index 0000000..f2f4eb1 --- /dev/null +++ b/block-kit/src/main/java/blockelements/MultiSelectMenu.java @@ -0,0 +1,85 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.composition.OptionObject; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Allows users to select multiple items from a list of options. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element/} + */ +public class MultiSelectMenu { + /** + * A section block with a multi-select menu of static options. + */ + public static SectionBlock example01() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick items from the list")) + .accessory(BlockElements.multiStaticSelect(m -> m.actionId("text1234") + .placeholder(plainText("Select items")) + .options(List.of( + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-0") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-1") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-2") + .build()))))); + return block; + } + + /** + * A section block with a multi-select menu of options loaded from an external source. + */ + public static SectionBlock example02() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick items from the list")) + .accessory(BlockElements.multiExternalSelect(m -> m.actionId("text1234") + .placeholder(plainText("Select items")) + .minQueryLength(3)))); + return block; + } + + /** + * A section block with a multi-select menu of users. + */ + public static SectionBlock example03() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick users from the list")) + .accessory(BlockElements.multiUsersSelect( + m -> m.actionId("text1234").placeholder(plainText("Select users"))))); + return block; + } + + /** + * A section block with a multi-select menu of conversations. + */ + public static SectionBlock example04() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick conversations from the list")) + .accessory(BlockElements.multiConversationsSelect( + m -> m.actionId("text1234").placeholder(plainText("Select conversations"))))); + return block; + } + + /** + * A section block with a multi-select menu of channels. + */ + public static SectionBlock example05() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick channels from the list")) + .accessory(BlockElements.multiChannelsSelect( + m -> m.actionId("text1234").placeholder(plainText("Select channels"))))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/NumberInput.java b/block-kit/src/main/java/blockelements/NumberInput.java new file mode 100644 index 0000000..656533b --- /dev/null +++ b/block-kit/src/main/java/blockelements/NumberInput.java @@ -0,0 +1,23 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.InputBlock; +import com.slack.api.model.block.element.BlockElements; + +/** + * Allows user to enter a number into a single-line field. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/number-input-element/} + */ +public class NumberInput { + /** + * An input block with a number input element. + */ + public static InputBlock example01() { + InputBlock block = Blocks.input(i -> i.element( + BlockElements.numberInput(n -> n.decimalAllowed(false).actionId("number_input-action"))) + .label(plainText(pt -> pt.text("Label").emoji(true)))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/OverflowMenu.java b/block-kit/src/main/java/blockelements/OverflowMenu.java new file mode 100644 index 0000000..d86e993 --- /dev/null +++ b/block-kit/src/main/java/blockelements/OverflowMenu.java @@ -0,0 +1,47 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.composition.OptionObject; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Allows users to press a button to view a list of options. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/overflow-menu-element/} + */ +public class OverflowMenu { + /** + * A section block with an overflow menu accessory. + */ + public static SectionBlock example01() { + SectionBlock block = Blocks.section(s -> s.blockId("section 890") + .text(markdownText("This is a section block with an overflow menu.")) + .accessory(BlockElements.overflowMenu(o -> o.actionId("overflow") + .options(List.of( + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-0") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-1") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-2") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-3") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-4") + .build()))))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/PlainTextInput.java b/block-kit/src/main/java/blockelements/PlainTextInput.java new file mode 100644 index 0000000..7fa1787 --- /dev/null +++ b/block-kit/src/main/java/blockelements/PlainTextInput.java @@ -0,0 +1,23 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.InputBlock; +import com.slack.api.model.block.element.BlockElements; + +/** + * Allows users to enter freeform text data into a single-line or multi-line field. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/plain-text-input-element/} + */ +public class PlainTextInput { + /** + * An input block with a plain-text input element. + */ + public static InputBlock example01() { + InputBlock block = + Blocks.input(i -> i.element(BlockElements.plainTextInput(pt -> pt.actionId("plain_text_input-action"))) + .label(plainText(l -> l.text("Label").emoji(true)))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/RadioButtons.java b/block-kit/src/main/java/blockelements/RadioButtons.java new file mode 100644 index 0000000..bab9957 --- /dev/null +++ b/block-kit/src/main/java/blockelements/RadioButtons.java @@ -0,0 +1,37 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.composition.OptionObject; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Allows users to choose one item from a list of possible options. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/radio-button-group-element/} + */ +public class RadioButtons { + /** + * A section block with a radio button group accessory. + */ + public static SectionBlock example01() { + SectionBlock block = Blocks.section(s -> s.text(plainText("Check out these rad radio buttons")) + .accessory(BlockElements.radioButtons(r -> r.actionId("this_is_an_action_id") + .initialOption(OptionObject.builder() + .value("A1") + .text(plainText("Radio 1")) + .build()) + .options(List.of( + OptionObject.builder() + .value("A1") + .text(plainText("Radio 1")) + .build(), + OptionObject.builder() + .value("A2") + .text(plainText("Radio 2")) + .build()))))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/RichTextInput.java b/block-kit/src/main/java/blockelements/RichTextInput.java new file mode 100644 index 0000000..7034ebe --- /dev/null +++ b/block-kit/src/main/java/blockelements/RichTextInput.java @@ -0,0 +1,31 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.InputBlock; +import com.slack.api.model.block.composition.DispatchActionConfig; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Allows users to enter formatted text in a WYSIWYG composer, offering the same messaging writing experience as in + * Slack. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/rich-text-input-element/} + */ +public class RichTextInput { + /** + * An input block with a rich text input element. + */ + public static InputBlock example01() { + InputBlock block = + Blocks.input(i -> i.element(BlockElements.richTextInput(rt -> rt.actionId("rich_text_input-action") + .dispatchActionConfig(DispatchActionConfig.builder() + .triggerActionsOn(List.of("on_character_entered")) + .build()) + .focusOnLoad(true) + .placeholder(plainText("Enter text")))) + .label(plainText(l -> l.text("Label").emoji(true)))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/SelectMenu.java b/block-kit/src/main/java/blockelements/SelectMenu.java new file mode 100644 index 0000000..0688b5e --- /dev/null +++ b/block-kit/src/main/java/blockelements/SelectMenu.java @@ -0,0 +1,85 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.composition.OptionObject; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Allows users to choose an option from a drop down menu. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element/} + */ +public class SelectMenu { + /** + * A section block with a select menu of static options. + */ + public static SectionBlock example01() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick an item from the dropdown list")) + .accessory(BlockElements.staticSelect(m -> m.actionId("text1234") + .placeholder(plainText("Select an item")) + .options(List.of( + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-0") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-1") + .build(), + OptionObject.builder() + .text(plainText("*this is plain_text text*")) + .value("value-2") + .build()))))); + return block; + } + + /** + * A section block with a select menu of options loaded from an external source. + */ + public static SectionBlock example02() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick an item from the dropdown list")) + .accessory(BlockElements.externalSelect(m -> m.actionId("text1234") + .placeholder(plainText("Select an item")) + .minQueryLength(3)))); + return block; + } + + /** + * A section block with a select menu of users. + */ + public static SectionBlock example03() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick a user from the dropdown list")) + .accessory(BlockElements.usersSelect( + m -> m.actionId("text1234").placeholder(plainText("Select an item"))))); + return block; + } + + /** + * A section block with a select menu of conversations. + */ + public static SectionBlock example04() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick a conversation from the dropdown list")) + .accessory(BlockElements.conversationsSelect( + m -> m.actionId("text1234").placeholder(plainText("Select an item"))))); + return block; + } + + /** + * A section block with a select menu of channels. + */ + public static SectionBlock example05() { + SectionBlock block = Blocks.section(s -> s.blockId("section678") + .text(markdownText("Pick a channel from the dropdown list")) + .accessory(BlockElements.channelsSelect( + m -> m.actionId("text1234").placeholder(plainText("Select an item"))))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/TimePicker.java b/block-kit/src/main/java/blockelements/TimePicker.java new file mode 100644 index 0000000..5ec12d3 --- /dev/null +++ b/block-kit/src/main/java/blockelements/TimePicker.java @@ -0,0 +1,27 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.element.BlockElements; + +/** + * A time picker element; on desktop a dropdown with free-text entry, on mobile the native time picker UI. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/time-picker-element/} + */ +public class TimePicker { + /** + * A section block with a time picker accessory. + */ + public static SectionBlock example01() { + SectionBlock block = Blocks.section(s -> s.blockId("section1234") + .text(markdownText("Pick a date for the deadline.")) + .accessory(BlockElements.timePicker(t -> t.timezone("America/Los_Angeles") + .actionId("timepicker123") + .initialTime("11:40") + .placeholder(plainText("Select a time"))))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/UrlInput.java b/block-kit/src/main/java/blockelements/UrlInput.java new file mode 100644 index 0000000..d9e853c --- /dev/null +++ b/block-kit/src/main/java/blockelements/UrlInput.java @@ -0,0 +1,23 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.InputBlock; +import com.slack.api.model.block.element.BlockElements; + +/** + * Allows user to enter a URL into a single-line field. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/url-input-element/} + */ +public class UrlInput { + /** + * An input block with a URL input element. + */ + public static InputBlock example01() { + InputBlock block = + Blocks.input(i -> i.element(BlockElements.urlTextInput(u -> u.actionId("url_text_input-action"))) + .label(plainText(pt -> pt.text("Label").emoji(true)))); + return block; + } +} diff --git a/block-kit/src/main/java/blockelements/WorkflowButton.java b/block-kit/src/main/java/blockelements/WorkflowButton.java new file mode 100644 index 0000000..3c8adf8 --- /dev/null +++ b/block-kit/src/main/java/blockelements/WorkflowButton.java @@ -0,0 +1,41 @@ +package blockelements; + +import static com.slack.api.model.block.composition.BlockCompositions.markdownText; +import static com.slack.api.model.block.composition.BlockCompositions.plainText; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.model.block.composition.WorkflowObject; +import com.slack.api.model.block.element.BlockElements; +import java.util.List; + +/** + * Allows users to run a link trigger with customizable inputs. + * {@link https://docs.slack.dev/reference/block-kit/block-elements/workflow-button-element/} + */ +public class WorkflowButton { + /** + * A section block with a workflow button accessory. + */ + public static SectionBlock example01() { + SectionBlock block = + Blocks.section(s -> s.text(markdownText("A message *with some bold text* and _some italicized text_.")) + .accessory(BlockElements.workflowButton(w -> w.text(plainText("Run Workflow")) + .actionId("workflowbutton123") + .workflow(WorkflowObject.builder() + .trigger(WorkflowObject.Trigger.builder() + .url("https://slack.com/shortcuts/Ft0123ABC456/xyz...zyx") + .customizableInputParameters(List.of( + WorkflowObject.Trigger.InputParameter.builder() + .name("input_parameter_a") + .value("Value for input param A") + .build(), + WorkflowObject.Trigger.InputParameter.builder() + .name("input_parameter_b") + .value("Value for input param B") + .build())) + .build()) + .build())))); + return block; + } +} diff --git a/block-kit/src/main/java/blocks/RichText.java b/block-kit/src/main/java/blocks/RichText.java index 63e9944..d400121 100644 --- a/block-kit/src/main/java/blocks/RichText.java +++ b/block-kit/src/main/java/blocks/RichText.java @@ -281,4 +281,16 @@ public static RichTextBlock example13() { .build()))); return block; } + + /** + * A rich text block with a team mention element. + */ + public static RichTextBlock example14() { + RichTextBlock block = Blocks.richText(rt -> rt.elements(List.of(RichTextSectionElement.builder() + .elements(List.of(RichTextSectionElement.Team.builder() + .teamId("T123ABC456") + .build())) + .build()))); + return block; + } } diff --git a/block-kit/src/test/java/blockelements/ButtonTest.java b/block-kit/src/test/java/blockelements/ButtonTest.java new file mode 100644 index 0000000..4d2ad65 --- /dev/null +++ b/block-kit/src/test/java/blockelements/ButtonTest.java @@ -0,0 +1,116 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.LayoutBlock; +import com.slack.api.model.block.element.ButtonElement; +import com.slack.api.util.json.GsonFactory; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class ButtonTest { + @Test + public void testExample01() { + ButtonElement element = Button.example01(); + String actual = GsonFactory.createSnakeCase().toJson(element); + String expected = """ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Click Me" + }, + "value": "click_me_123", + "action_id": "button" + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample02() { + ButtonElement element = Button.example02(); + String actual = GsonFactory.createSnakeCase().toJson(element); + String expected = """ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Save" + }, + "style": "primary", + "value": "click_me_123", + "action_id": "button" + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample03() { + ButtonElement element = Button.example03(); + String actual = GsonFactory.createSnakeCase().toJson(element); + String expected = """ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Link Button" + }, + "url": "https://docs.slack.dev/block-kit" + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample04() { + List blocks = Button.example04(); + String actual = GsonFactory.createSnakeCase().toJson(blocks); + String 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" + } + ] + } + ] + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/DatePickerTest.java b/block-kit/src/test/java/blockelements/DatePickerTest.java new file mode 100644 index 0000000..655b588 --- /dev/null +++ b/block-kit/src/test/java/blockelements/DatePickerTest.java @@ -0,0 +1,36 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class DatePickerTest { + @Test + public void testExample01() { + SectionBlock block = DatePicker.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/DatetimePickerTest.java b/block-kit/src/test/java/blockelements/DatetimePickerTest.java new file mode 100644 index 0000000..7267009 --- /dev/null +++ b/block-kit/src/test/java/blockelements/DatetimePickerTest.java @@ -0,0 +1,37 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.InputBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class DatetimePickerTest { + @Test + public void testExample01() { + InputBlock block = DatetimePicker.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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 + }, + "optional": false + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/EmailInputTest.java b/block-kit/src/test/java/blockelements/EmailInputTest.java new file mode 100644 index 0000000..28b0ffd --- /dev/null +++ b/block-kit/src/test/java/blockelements/EmailInputTest.java @@ -0,0 +1,36 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.InputBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class EmailInputTest { + @Test + public void testExample01() { + InputBlock block = EmailInput.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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" + } + }, + "optional": false + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/FeedbackButtonsTest.java b/block-kit/src/test/java/blockelements/FeedbackButtonsTest.java new file mode 100644 index 0000000..c3a736e --- /dev/null +++ b/block-kit/src/test/java/blockelements/FeedbackButtonsTest.java @@ -0,0 +1,44 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.ContextActionsBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class FeedbackButtonsTest { + @Test + public void testExample01() { + ContextActionsBlock block = FeedbackButtons.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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" + } + } + ] + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/FileInputTest.java b/block-kit/src/test/java/blockelements/FileInputTest.java new file mode 100644 index 0000000..51ed593 --- /dev/null +++ b/block-kit/src/test/java/blockelements/FileInputTest.java @@ -0,0 +1,34 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.InputBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class FileInputTest { + @Test + public void testExample01() { + InputBlock block = FileInput.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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 + }, + "optional": false + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/IconButtonTest.java b/block-kit/src/test/java/blockelements/IconButtonTest.java new file mode 100644 index 0000000..2ff3e51 --- /dev/null +++ b/block-kit/src/test/java/blockelements/IconButtonTest.java @@ -0,0 +1,34 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.ContextActionsBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class IconButtonTest { + @Test + public void testExample01() { + ContextActionsBlock block = IconButton.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "context_actions", + "elements": [ + { + "type": "icon_button", + "icon": "trash", + "text": { + "type": "plain_text", + "text": "Delete" + }, + "action_id": "delete_button", + "value": "delete_item" + } + ] + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/ImageTest.java b/block-kit/src/test/java/blockelements/ImageTest.java new file mode 100644 index 0000000..8e4fd75 --- /dev/null +++ b/block-kit/src/test/java/blockelements/ImageTest.java @@ -0,0 +1,80 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class ImageTest { + @Test + public void testExample01() { + SectionBlock block = Image.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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" + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample02() { + SectionBlock block = Image.example02(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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." + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample03() { + SectionBlock block = Image.example03(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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." + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/MultiSelectMenuTest.java b/block-kit/src/test/java/blockelements/MultiSelectMenuTest.java new file mode 100644 index 0000000..cd79151 --- /dev/null +++ b/block-kit/src/test/java/blockelements/MultiSelectMenuTest.java @@ -0,0 +1,159 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class MultiSelectMenuTest { + @Test + public void testExample01() { + SectionBlock block = MultiSelectMenu.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick items from the list" + }, + "accessory": { + "action_id": "text1234", + "type": "multi_static_select", + "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" + } + ] + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample02() { + SectionBlock block = MultiSelectMenu.example02(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick items from the list" + }, + "accessory": { + "action_id": "text1234", + "type": "multi_external_select", + "placeholder": { + "type": "plain_text", + "text": "Select items" + }, + "min_query_length": 3 + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample03() { + SectionBlock block = MultiSelectMenu.example03(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick users from the list" + }, + "accessory": { + "action_id": "text1234", + "type": "multi_users_select", + "placeholder": { + "type": "plain_text", + "text": "Select users" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample04() { + SectionBlock block = MultiSelectMenu.example04(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick conversations from the list" + }, + "accessory": { + "action_id": "text1234", + "type": "multi_conversations_select", + "placeholder": { + "type": "plain_text", + "text": "Select conversations" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample05() { + SectionBlock block = MultiSelectMenu.example05(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick channels from the list" + }, + "accessory": { + "action_id": "text1234", + "type": "multi_channels_select", + "placeholder": { + "type": "plain_text", + "text": "Select channels" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/NumberInputTest.java b/block-kit/src/test/java/blockelements/NumberInputTest.java new file mode 100644 index 0000000..bf877cf --- /dev/null +++ b/block-kit/src/test/java/blockelements/NumberInputTest.java @@ -0,0 +1,33 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.InputBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class NumberInputTest { + @Test + public void testExample01() { + InputBlock block = NumberInput.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "input", + "element": { + "type": "number_input", + "is_decimal_allowed": false, + "action_id": "number_input-action" + }, + "label": { + "type": "plain_text", + "text": "Label", + "emoji": true + }, + "optional": false + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/OverflowMenuTest.java b/block-kit/src/test/java/blockelements/OverflowMenuTest.java new file mode 100644 index 0000000..f652d44 --- /dev/null +++ b/block-kit/src/test/java/blockelements/OverflowMenuTest.java @@ -0,0 +1,68 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class OverflowMenuTest { + @Test + public void testExample01() { + SectionBlock block = OverflowMenu.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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" + } + ] + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/PlainTextInputTest.java b/block-kit/src/test/java/blockelements/PlainTextInputTest.java new file mode 100644 index 0000000..27bb4c1 --- /dev/null +++ b/block-kit/src/test/java/blockelements/PlainTextInputTest.java @@ -0,0 +1,33 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.InputBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class PlainTextInputTest { + @Test + public void testExample01() { + InputBlock block = PlainTextInput.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "input", + "element": { + "type": "plain_text_input", + "action_id": "plain_text_input-action", + "multiline": false + }, + "label": { + "type": "plain_text", + "text": "Label", + "emoji": true + }, + "optional": false + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/RadioButtonsTest.java b/block-kit/src/test/java/blockelements/RadioButtonsTest.java new file mode 100644 index 0000000..bf45e3f --- /dev/null +++ b/block-kit/src/test/java/blockelements/RadioButtonsTest.java @@ -0,0 +1,53 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class RadioButtonsTest { + @Test + public void testExample01() { + SectionBlock block = RadioButtons.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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" + } + } + ] + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/RichTextInputTest.java b/block-kit/src/test/java/blockelements/RichTextInputTest.java new file mode 100644 index 0000000..1280151 --- /dev/null +++ b/block-kit/src/test/java/blockelements/RichTextInputTest.java @@ -0,0 +1,42 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.InputBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class RichTextInputTest { + @Test + public void testExample01() { + InputBlock block = RichTextInput.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "input", + "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" + } + }, + "label": { + "type": "plain_text", + "text": "Label", + "emoji": true + }, + "optional": false + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/SelectMenuTest.java b/block-kit/src/test/java/blockelements/SelectMenuTest.java new file mode 100644 index 0000000..aba093b --- /dev/null +++ b/block-kit/src/test/java/blockelements/SelectMenuTest.java @@ -0,0 +1,159 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class SelectMenuTest { + @Test + public void testExample01() { + SectionBlock block = SelectMenu.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick an item from the dropdown list" + }, + "accessory": { + "action_id": "text1234", + "type": "static_select", + "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" + } + ] + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample02() { + SectionBlock block = SelectMenu.example02(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick an item from the dropdown list" + }, + "accessory": { + "action_id": "text1234", + "type": "external_select", + "placeholder": { + "type": "plain_text", + "text": "Select an item" + }, + "min_query_length": 3 + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample03() { + SectionBlock block = SelectMenu.example03(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick a user from the dropdown list" + }, + "accessory": { + "action_id": "text1234", + "type": "users_select", + "placeholder": { + "type": "plain_text", + "text": "Select an item" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample04() { + SectionBlock block = SelectMenu.example04(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick a conversation from the dropdown list" + }, + "accessory": { + "action_id": "text1234", + "type": "conversations_select", + "placeholder": { + "type": "plain_text", + "text": "Select an item" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } + + @Test + public void testExample05() { + SectionBlock block = SelectMenu.example05(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "block_id": "section678", + "text": { + "type": "mrkdwn", + "text": "Pick a channel from the dropdown list" + }, + "accessory": { + "action_id": "text1234", + "type": "channels_select", + "placeholder": { + "type": "plain_text", + "text": "Select an item" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/TimePickerTest.java b/block-kit/src/test/java/blockelements/TimePickerTest.java new file mode 100644 index 0000000..4d80900 --- /dev/null +++ b/block-kit/src/test/java/blockelements/TimePickerTest.java @@ -0,0 +1,37 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class TimePickerTest { + @Test + public void testExample01() { + SectionBlock block = TimePicker.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String 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" + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/UrlInputTest.java b/block-kit/src/test/java/blockelements/UrlInputTest.java new file mode 100644 index 0000000..bde3c03 --- /dev/null +++ b/block-kit/src/test/java/blockelements/UrlInputTest.java @@ -0,0 +1,32 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.InputBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class UrlInputTest { + @Test + public void testExample01() { + InputBlock block = UrlInput.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "input", + "element": { + "type": "url_text_input", + "action_id": "url_text_input-action" + }, + "label": { + "type": "plain_text", + "text": "Label", + "emoji": true + }, + "optional": false + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blockelements/WorkflowButtonTest.java b/block-kit/src/test/java/blockelements/WorkflowButtonTest.java new file mode 100644 index 0000000..01c0635 --- /dev/null +++ b/block-kit/src/test/java/blockelements/WorkflowButtonTest.java @@ -0,0 +1,49 @@ +package blockelements; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.SectionBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class WorkflowButtonTest { + @Test + public void testExample01() { + SectionBlock block = WorkflowButton.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "section", + "text": { + "text": "A message *with some bold text* and _some italicized text_.", + "type": "mrkdwn" + }, + "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" + } + ] + } + } + } + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +} diff --git a/block-kit/src/test/java/blocks/RichTextTest.java b/block-kit/src/test/java/blocks/RichTextTest.java index c67af51..3d023bf 100644 --- a/block-kit/src/test/java/blocks/RichTextTest.java +++ b/block-kit/src/test/java/blocks/RichTextTest.java @@ -522,4 +522,27 @@ public void testExample13() { """; assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); } + + @Test + public void testExample14() { + RichTextBlock block = RichText.example14(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "team", + "team_id": "T123ABC456" + } + ] + } + ] + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } }