From 8259f2d6c5b9cb771fa70fbb3e80a38874a35c0a Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 26 Jun 2026 16:44:08 -0700 Subject: [PATCH] feat(model): add alert Block Kit block Add the `alert` layout block to slack-api-model, mirroring the existing HeaderBlock/MarkdownBlock conventions. - AlertBlock with text (plain_text|mrkdwn TextObject), level, blockId - Register type in GsonLayoutBlockFactory - Add alert(...) DSL helper to Blocks - Add parse + builder round-trip tests in BlockKitTest Ref: https://docs.slack.dev/reference/block-kit/blocks/alert-block Co-Authored-By: Claude --- .../com/slack/api/model/block/AlertBlock.java | 41 +++++++++++++ .../com/slack/api/model/block/Blocks.java | 6 ++ .../api/util/json/GsonLayoutBlockFactory.java | 2 + .../api/model/block/BlockKitTest.java | 57 +++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 slack-api-model/src/main/java/com/slack/api/model/block/AlertBlock.java diff --git a/slack-api-model/src/main/java/com/slack/api/model/block/AlertBlock.java b/slack-api-model/src/main/java/com/slack/api/model/block/AlertBlock.java new file mode 100644 index 000000000..80003adb3 --- /dev/null +++ b/slack-api-model/src/main/java/com/slack/api/model/block/AlertBlock.java @@ -0,0 +1,41 @@ +package com.slack.api.model.block; + +import com.slack.api.model.block.composition.TextObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * https://docs.slack.dev/reference/block-kit/blocks/alert-block + *

+ * Displays an inline alert message. Alert blocks are currently only supported in modals. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AlertBlock implements LayoutBlock { + public static final String TYPE = "alert"; + private final String type = TYPE; + + /** + * The message content of the alert, as a plain_text or mrkdwn text object. + * Maximum length for the text in this field is 200 characters. + */ + private TextObject text; + + /** + * The severity level of the alert. One of default, info, warning, error, or success. + * Will be default if omitted. + */ + private String level; + + /** + * A string acting as a unique identifier for a block. If not specified, one will be generated. + * Maximum length for this field is 255 characters. + * block_id should be unique for each message and each iteration of a message. + * If a message is updated, use a new block_id. + */ + private String blockId; +} diff --git a/slack-api-model/src/main/java/com/slack/api/model/block/Blocks.java b/slack-api-model/src/main/java/com/slack/api/model/block/Blocks.java index fd451d8d2..0ef675042 100644 --- a/slack-api-model/src/main/java/com/slack/api/model/block/Blocks.java +++ b/slack-api-model/src/main/java/com/slack/api/model/block/Blocks.java @@ -129,4 +129,10 @@ public static ShareShortcutBlock shareShortcut() { return ShareShortcutBlock.builder().build(); } + // AlertBlock + + public static AlertBlock alert(ModelConfigurator configurator) { + return configurator.configure(AlertBlock.builder()).build(); + } + } diff --git a/slack-api-model/src/main/java/com/slack/api/util/json/GsonLayoutBlockFactory.java b/slack-api-model/src/main/java/com/slack/api/util/json/GsonLayoutBlockFactory.java index 9286e6b51..4c4533808 100644 --- a/slack-api-model/src/main/java/com/slack/api/util/json/GsonLayoutBlockFactory.java +++ b/slack-api-model/src/main/java/com/slack/api/util/json/GsonLayoutBlockFactory.java @@ -61,6 +61,8 @@ private Class getLayoutClassInstance(String typeName) { return RichTextBlock.class; case ShareShortcutBlock.TYPE: return ShareShortcutBlock.class; + case AlertBlock.TYPE: + return AlertBlock.class; default: if (failOnUnknownProperties) { throw new JsonParseException("Unsupported layout block type: " + typeName); diff --git a/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java b/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java index 1fc12d58d..eff72529a 100644 --- a/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java +++ b/slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java @@ -1742,6 +1742,63 @@ public void parseVideoBlocks() { assertEquals("https://www.youtube.com/embed/RRxQQxiM7AA?feature=oembed&autoplay=1", block.getVideoUrl()); } + @Test + public void parseAlertBlocks() { + // https://docs.slack.dev/reference/block-kit/blocks/alert-block + String json = "{\n" + + " \"blocks\": [\n" + + " {\n" + + " \"type\": \"alert\",\n" + + " \"block_id\": \"alert-1\",\n" + + " \"text\": {\n" + + " \"type\": \"mrkdwn\",\n" + + " \"text\": \"Something went *wrong*.\"\n" + + " },\n" + + " \"level\": \"error\"\n" + + " },\n" + + " {\n" + + " \"type\": \"alert\",\n" + + " \"text\": {\n" + + " \"type\": \"plain_text\",\n" + + " \"text\": \"A plain text alert with no markup.\"\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + View view = GsonFactory.createSnakeCase().fromJson(json, View.class); + assertNotNull(view); + assertEquals(2, view.getBlocks().size()); + + AlertBlock errorAlert = (AlertBlock) view.getBlocks().get(0); + assertEquals("alert", errorAlert.getType()); + assertEquals("alert-1", errorAlert.getBlockId()); + assertEquals("error", errorAlert.getLevel()); + assertEquals("mrkdwn", errorAlert.getText().getType()); + assertEquals("Something went *wrong*.", errorAlert.getText().getText()); + + AlertBlock defaultAlert = (AlertBlock) view.getBlocks().get(1); + assertEquals("plain_text", defaultAlert.getText().getType()); + assertNull(defaultAlert.getLevel()); + assertNull(defaultAlert.getBlockId()); + } + + @Test + public void buildAlertBlock() { + AlertBlock block = alert(a -> a + .blockId("alert-1") + .level("info") + .text(plainText("Heads up!"))); + assertNotNull(block); + assertEquals("alert", block.getType()); + + Gson gson = GsonFactory.createSnakeCase(); + String output = gson.toJson(block); + AlertBlock parsed = gson.fromJson(output, AlertBlock.class); + assertEquals("alert-1", parsed.getBlockId()); + assertEquals("info", parsed.getLevel()); + assertEquals("Heads up!", parsed.getText().getText()); + } + @Test public void parseLinkTriggerMessages() { // https://tools.slack.dev/deno-slack-sdk/