Repository: slack-go/slack
Pull request #1368 (2025-01-16 15:13:42)

Add assistant app thread message subtype
##### Pull Request Guidelines

These are recommendations for pull requests.
They are strictly guidelines to help manage expectations.

##### PR preparation
Run `make pr-prep` from the root of the repository to run formatting, linting and tests.

##### Should this be an issue instead
- [ ] is it a convenience method? (no new functionality, streamlines some use case)
- [ ] exposes a previously private type, const, method, etc.
- [ ] is it application specific (caching, retry logic, rate limiting, etc)
- [ ] is it performance related.

##### API changes

Since API changes have to be maintained they undergo a more detailed review and are more likely to require changes.

- no tests, if you're adding to the API include at least a single test of the happy case.
- If you can accomplish your goal without changing the API, then do so.
- dependency changes. updates are okay. adding/removing need justification.

###### Examples of API changes that do not meet guidelines:
- in library cache for users. caches are use case specific.
- Convenience methods for Sending Messages, update, post, ephemeral, etc. consider opening an issue instead.



Patch:
diff --git a/block.go b/block.go
index a3fb1a0..f0e2888 100644
--- a/block.go
+++ b/block.go
@@ -26,6 +26,7 @@ const (
 // to ensure consistency between blocks.
 type Block interface {
 	BlockType() MessageBlockType
+	ID() string
 }
 
 // Blocks is a convenience struct defined to allow dynamic unmarshalling of
diff --git a/block_action.go b/block_action.go
index c15e4a3..819c0ef 100644
--- a/block_action.go
+++ b/block_action.go
@@ -14,6 +14,11 @@ func (s ActionBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s ActionBlock) ID() string {
+	return s.BlockID
+}
+
 // NewActionBlock returns a new instance of an Action Block
 func NewActionBlock(blockID string, elements ...BlockElement) *ActionBlock {
 	return &ActionBlock{
diff --git a/block_call.go b/block_call.go
index 98f2c02..c81dcb8 100644
--- a/block_call.go
+++ b/block_call.go
@@ -14,7 +14,12 @@ func (s CallBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
-// NewFileBlock returns a new instance of a file block
+// ID returns the ID of the block
+func (s CallBlock) ID() string {
+	return s.BlockID
+}
+
+// NewCallBlock returns a new instance of a call block
 func NewCallBlock(callID string) *CallBlock {
 	return &CallBlock{
 		Type:   MBTCall,
diff --git a/block_context.go b/block_context.go
index 384fee2..879ee61 100644
--- a/block_context.go
+++ b/block_context.go
@@ -15,6 +15,11 @@ func (s ContextBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s ContextBlock) ID() string {
+	return s.BlockID
+}
+
 type ContextElements struct {
 	Elements []MixedElement
 }
diff --git a/block_divider.go b/block_divider.go
index 2d442ba..e10d7b0 100644
--- a/block_divider.go
+++ b/block_divider.go
@@ -13,10 +13,14 @@ func (s DividerBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s DividerBlock) ID() string {
+	return s.BlockID
+}
+
 // NewDividerBlock returns a new instance of a divider block
 func NewDividerBlock() *DividerBlock {
 	return &DividerBlock{
 		Type: MBTDivider,
 	}
-
 }
diff --git a/block_file.go b/block_file.go
index ac4453f..2f669b0 100644
--- a/block_file.go
+++ b/block_file.go
@@ -15,6 +15,11 @@ func (s FileBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s FileBlock) ID() string {
+	return s.BlockID
+}
+
 // NewFileBlock returns a new instance of a file block
 func NewFileBlock(blockID string, externalID string, source string) *FileBlock {
 	return &FileBlock{
diff --git a/block_header.go b/block_header.go
index 6dff4b8..3afb4c9 100644
--- a/block_header.go
+++ b/block_header.go
@@ -14,6 +14,11 @@ func (s HeaderBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s HeaderBlock) ID() string {
+	return s.BlockID
+}
+
 // HeaderBlockOption allows configuration of options for a new header block
 type HeaderBlockOption func(*HeaderBlock)
 
diff --git a/block_image.go b/block_image.go
index b3d2cb8..cdee5b4 100644
--- a/block_image.go
+++ b/block_image.go
@@ -12,6 +12,11 @@ type ImageBlock struct {
 	SlackFile *SlackFileObject `json:"slack_file,omitempty"`
 }
 
+// ID returns the ID of the block
+func (s ImageBlock) ID() string {
+	return s.BlockID
+}
+
 // SlackFileObject Defines an object containing Slack file information to be used in an
 // image block or image element.
 //
diff --git a/block_input.go b/block_input.go
index 7c1272a..f74eda6 100644
--- a/block_input.go
+++ b/block_input.go
@@ -18,6 +18,11 @@ func (s InputBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s InputBlock) ID() string {
+	return s.BlockID
+}
+
 // NewInputBlock returns a new instance of an input block
 func NewInputBlock(blockID string, label, hint *TextBlockObject, element BlockElement) *InputBlock {
 	return &InputBlock{
diff --git a/block_rich_text.go b/block_rich_text.go
index 22020be..18faf8c 100644
--- a/block_rich_text.go
+++ b/block_rich_text.go
@@ -16,6 +16,11 @@ func (b RichTextBlock) BlockType() MessageBlockType {
 	return b.Type
 }
 
+// ID returns the ID of the block
+func (s RichTextBlock) ID() string {
+	return s.BlockID
+}
+
 func (e *RichTextBlock) UnmarshalJSON(b []byte) error {
 	var raw struct {
 		Type        MessageBlockType  `json:"type"`
diff --git a/block_section.go b/block_section.go
index 1ffc17e..0d2352a 100644
--- a/block_section.go
+++ b/block_section.go
@@ -17,6 +17,11 @@ func (s SectionBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s SectionBlock) ID() string {
+	return s.BlockID
+}
+
 // SectionBlockOption allows configuration of options for a new section block
 type SectionBlockOption func(*SectionBlock)
 
diff --git a/block_unknown.go b/block_unknown.go
index 97054c7..7a49a2c 100644
--- a/block_unknown.go
+++ b/block_unknown.go
@@ -11,3 +11,8 @@ type UnknownBlock struct {
 func (b UnknownBlock) BlockType() MessageBlockType {
 	return b.Type
 }
+
+// ID returns the ID of the block
+func (s UnknownBlock) ID() string {
+	return s.BlockID
+}
diff --git a/block_video.go b/block_video.go
index 322c614..4d6739c 100644
--- a/block_video.go
+++ b/block_video.go
@@ -22,6 +22,11 @@ func (s VideoBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
+// ID returns the ID of the block
+func (s VideoBlock) ID() string {
+	return s.BlockID
+}
+
 // NewVideoBlock returns an instance of a new Video Block type
 func NewVideoBlock(videoURL, thumbnailURL, altText, blockID string, title *TextBlockObject) *VideoBlock {
 	return &VideoBlock{
diff --git a/files.go b/files.go
index b263171..0682fb6 100644
--- a/files.go
+++ b/files.go
@@ -89,6 +89,17 @@ type File struct {
 	NumStars        int      `json:"num_stars"`
 	IsStarred       bool     `json:"is_starred"`
 	Shares          Share    `json:"shares"`
+
+	Subject string              `json:"subject"`
+	To      []EmailFileUserInfo `json:"to"`
+	From    []EmailFileUserInfo `json:"from"`
+	Cc      []EmailFileUserInfo `json:"cc"`
+}
+
+type EmailFileUserInfo struct {
+	Address  string `json:"address"`
+	Name     string `json:"name"`
+	Original string `json:"original"`
 }
 
 type Share struct {
diff --git a/messages.go b/messages.go
index 13a1ede..90f8fc1 100644
--- a/messages.go
+++ b/messages.go
@@ -49,6 +49,7 @@ const (
 	MsgSubTypeUnpinnedItem              = "unpinned_item"               // [RTM] An item was unpinned from a channel
 	MsgSubTypeEkmAccessDenied           = "ekm_access_denied"           // [Events API, RTM] Message content redacted due to Enterprise Key Management (EKM)
 	MsgSubTypeChannelPostingPermissions = "channel_posting_permissions" // [Events API, RTM] The posting permissions for a channel changed
+	MsgSubTypeAssistantAppThread        = "assistant_app_thread"        // [Events API, RTM] The message is an app assistant thread
 )
 
 // Msg contains information about a slack message
diff --git a/rtm.go b/rtm.go
index ef6ba34..9b30eb3 100644
--- a/rtm.go
+++ b/rtm.go
@@ -25,6 +25,9 @@ const (
 // StartRTM calls the "rtm.start" endpoint and returns the provided URL and the full Info block.
 //
 // To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
+//
+// Deprecated: Use [ConnectRTM] instead.
+// For more details, see: https://api.slack.com/changelog/2021-10-rtm-start-to-stop
 func (api *Client) StartRTM() (info *Info, websocketURL string, err error) {
 	ctx, cancel := context.WithTimeout(context.Background(), websocketDefaultTimeout)
 	defer cancel()
@@ -35,6 +38,9 @@ func (api *Client) StartRTM() (info *Info, websocketURL string, err error) {
 // StartRTMContext calls the "rtm.start" endpoint and returns the provided URL and the full Info block with a custom context.
 //
 // To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
+//
+// Deprecated: Use [ConnectRTMContext] instead.
+// For more details, see: https://api.slack.com/changelog/2021-10-rtm-start-to-stop
 func (api *Client) StartRTMContext(ctx context.Context) (info *Info, websocketURL string, err error) {
 	response := &infoResponseFull{}
 	err = api.postMethod(ctx, "rtm.start", url.Values{"token": {api.token}}, response)
diff --git a/usergroups.go b/usergroups.go
index 0c2ec4c..256f7bd 100644
--- a/usergroups.go
+++ b/usergroups.go
@@ -3,6 +3,7 @@ package slack
 import (
 	"context"
 	"net/url"
+	"strconv"
 	"strings"
 )
 
@@ -50,20 +51,45 @@ func (api *Client) userGroupRequest(ctx context.Context, path string, values url
 	return response, response.Err()
 }
 
+// createUserGroupParams contains arguments for CreateUserGroup method call
+type createUserGroupParams struct {
+	enableSection bool
+}
+
+// CreateUserGroupOption options for the CreateUserGroup method call.
+type CreateUserGroupOption func(*createUserGroupParams)
+
+// CreateUserGroupOptionEnableSection enable the section for the user group (default: false)
+func CreateUserGroupOptionEnableSection(enableSection bool) CreateUserGroupOption {
+	return func(params *createUserGroupParams) {
+		params.enableSection = enableSection
+	}
+}
+
 // CreateUserGroup creates a new user group.
 // For more information see the CreateUserGroupContext documentation.
-func (api *Client) CreateUserGroup(userGroup UserGroup) (UserGroup, error) {
-	return api.CreateUserGroupContext(context.Background(), userGroup)
+func (api *Client) CreateUserGroup(userGroup UserGroup, options ...CreateUserGroupOption) (UserGroup, error) {
+	return api.CreateUserGroupContext(context.Background(), userGroup, options...)
 }
 
 // CreateUserGroupContext creates a new user group with a custom context.
 // Slack API docs: https://api.slack.com/methods/usergroups.create
-func (api *Client) CreateUserGroupContext(ctx context.Context, userGroup UserGroup) (UserGroup, error) {
+func (api *Client) CreateUserGroupContext(ctx context.Context, userGroup UserGroup, options ...CreateUserGroupOption) (UserGroup, error) {
+	params := createUserGroupParams{}
+
+	for _, opt := range options {
+		opt(&params)
+	}
+
 	values := url.Values{
 		"token": {api.token},
 		"name":  {userGroup.Name},
 	}
 
+	if params.enableSection {
+		values["enable_section"] = []string{strconv.FormatBool(params.enableSection)}
+	}
+
 	if userGroup.TeamID != "" {
 		values["team_id"] = []string{userGroup.TeamID}
 	}
@@ -236,12 +262,20 @@ func UpdateUserGroupsOptionChannels(channels []string) UpdateUserGroupsOption {
 	}
 }
 
+// UpdateUserGroupsOptionEnableSection enable the section for the user group (default: false)
+func UpdateUserGroupsOptionEnableSection(enableSection bool) UpdateUserGroupsOption {
+	return func(params *UpdateUserGroupsParams) {
+		params.EnableSection = enableSection
+	}
+}
+
 // UpdateUserGroupsParams contains arguments for UpdateUserGroup method call
 type UpdateUserGroupsParams struct {
-	Name        string
-	Handle      string
-	Description *string
-	Channels    *[]string
+	Name          string
+	Handle        string
+	Description   *string
+	Channels      *[]string
+	EnableSection bool
 }
 
 // UpdateUserGroup will update an existing user group.
@@ -280,6 +314,10 @@ func (api *Client) UpdateUserGroupContext(ctx context.Context, userGroupID strin
 		values["channels"] = []string{strings.Join(*params.Channels, ",")}
 	}
 
+	if params.EnableSection {
+		values["enable_section"] = []string{strconv.FormatBool(params.EnableSection)}
+	}
+
 	response, err := api.userGroupRequest(ctx, "usergroups.update", values)
 	if err != nil {
 		return UserGroup{}, err


Test patch:
diff --git a/block_action_test.go b/block_action_test.go
index 32bd0c2..bb22f45 100644
--- a/block_action_test.go
+++ b/block_action_test.go
@@ -7,13 +7,13 @@ import (
 )
 
 func TestNewActionBlock(t *testing.T) {
-
 	approveBtnTxt := NewTextBlockObject("plain_text", "Approve", false, false)
 	approveBtn := NewButtonBlockElement("", "click_me_123", approveBtnTxt)
-
 	actionBlock := NewActionBlock("test", approveBtn)
+
+	assert.Equal(t, actionBlock.BlockType(), MBTAction)
 	assert.Equal(t, string(actionBlock.Type), "actions")
 	assert.Equal(t, actionBlock.BlockID, "test")
+	assert.Equal(t, actionBlock.ID(), "test")
 	assert.Equal(t, len(actionBlock.Elements.ElementSet), 1)
-
 }
diff --git a/block_call_test.go b/block_call_test.go
index c118542..4966e3d 100644
--- a/block_call_test.go
+++ b/block_call_test.go
@@ -8,6 +8,10 @@ import (
 
 func TestNewCallBlock(t *testing.T) {
 	callBlock := NewCallBlock("ACallID")
+
+	assert.Equal(t, callBlock.BlockType(), MBTCall)
 	assert.Equal(t, string(callBlock.Type), "call")
 	assert.Equal(t, callBlock.CallID, "ACallID")
+	assert.Equal(t, callBlock.BlockID, "")
+	assert.Equal(t, callBlock.ID(), "")
 }
diff --git a/block_context_test.go b/block_context_test.go
index 20fb396..0ecfb80 100644
--- a/block_context_test.go
+++ b/block_context_test.go
@@ -7,15 +7,14 @@ import (
 )
 
 func TestNewContextBlock(t *testing.T) {
-
 	locationPinImage := NewImageBlockElement("https://api.slack.com/img/blocks/bkb_template_images/tripAgentLocationMarker.png", "Location Pin Icon")
 	textExample := NewTextBlockObject("plain_text", "Location: Central Business District", true, false)
-
 	elements := []MixedElement{locationPinImage, textExample}
-
 	contextBlock := NewContextBlock("test", elements...)
+
+	assert.Equal(t, contextBlock.BlockType(), MBTContext)
 	assert.Equal(t, string(contextBlock.Type), "context")
 	assert.Equal(t, contextBlock.BlockID, "test")
+	assert.Equal(t, contextBlock.ID(), "test")
 	assert.Equal(t, len(contextBlock.ContextElements.Elements), 2)
-
 }
diff --git a/block_divider_test.go b/block_divider_test.go
index 35e3d48..27b81aa 100644
--- a/block_divider_test.go
+++ b/block_divider_test.go
@@ -7,8 +7,10 @@ import (
 )
 
 func TestNewDividerBlock(t *testing.T) {
-
 	dividerBlock := NewDividerBlock()
-	assert.Equal(t, string(dividerBlock.Type), "divider")
 
+	assert.Equal(t, dividerBlock.BlockType(), MBTDivider)
+	assert.Equal(t, string(dividerBlock.Type), "divider")
+	assert.Equal(t, dividerBlock.BlockID, "")
+	assert.Equal(t, dividerBlock.ID(), "")
 }
diff --git a/block_element_test.go b/block_element_test.go
index d532fb7..fead400 100644
--- a/block_element_test.go
+++ b/block_element_test.go
@@ -7,17 +7,14 @@ import (
 )
 
 func TestNewImageBlockElement(t *testing.T) {
-
 	imageElement := NewImageBlockElement("https://api.slack.com/img/blocks/bkb_template_images/tripAgentLocationMarker.png", "Location Pin Icon")
 
 	assert.Equal(t, string(imageElement.Type), "image")
 	assert.Contains(t, imageElement.ImageURL, "tripAgentLocationMarker")
 	assert.Equal(t, imageElement.AltText, "Location Pin Icon")
-
 }
 
 func TestNewButtonBlockElement(t *testing.T) {
-
 	btnTxt := NewTextBlockObject("plain_text", "Next 2 Results", false, false)
 	btnElement := NewButtonBlockElement("test", "click_me_123", btnTxt)
 
@@ -25,11 +22,9 @@ func TestNewButtonBlockElement(t *testing.T) {
 	assert.Equal(t, btnElement.ActionID, "test")
 	assert.Equal(t, btnElement.Value, "click_me_123")
 	assert.Equal(t, btnElement.Text.Text, "Next 2 Results")
-
 }
 
 func TestWithStyleForButtonElement(t *testing.T) {
-
 	// these values are irrelevant in this test
 	btnTxt := NewTextBlockObject("plain_text", "Next 2 Results", false, false)
 	btnElement := NewButtonBlockElement("test", "click_me_123", btnTxt)
@@ -40,21 +35,17 @@ func TestWithStyleForButtonElement(t *testing.T) {
 	assert.Equal(t, btnElement.Style, Style("primary"))
 	btnElement.WithStyle(StyleDanger)
 	assert.Equal(t, btnElement.Style, Style("danger"))
-
 }
 
 func TestWithURLForButtonElement(t *testing.T) {
-
 	btnTxt := NewTextBlockObject("plain_text", "Next 2 Results", false, false)
 	btnElement := NewButtonBlockElement("test", "click_me_123", btnTxt)
 
 	btnElement.WithURL("https://foo.bar")
 	assert.Equal(t, btnElement.URL, "https://foo.bar")
-
 }
 
 func TestNewOptionsSelectBlockElement(t *testing.T) {
-
 	testOptionText := NewTextBlockObject("plain_text", "Option One", false, false)
 	testOption := NewOptionBlockObject("test", testOptionText, nil)
 
@@ -62,11 +53,9 @@ func TestNewOptionsSelectBlockElement(t *testing.T) {
 	assert.Equal(t, option.Type, "static_select")
 	assert.Equal(t, len(option.Options), 1)
 	assert.Nil(t, option.OptionGroups)
-
 }
 
 func TestNewOptionsGroupSelectBlockElement(t *testing.T) {
-
 	testOptionText := NewTextBlockObject("plain_text", "Option One", false, false)
 	testOption := NewOptionBlockObject("test", testOptionText, nil)
 	testLabel := NewTextBlockObject("plain_text", "Test Label", false, false)
@@ -77,11 +66,9 @@ func TestNewOptionsGroupSelectBlockElement(t *testing.T) {
 	assert.Equal(t, optGroup.Type, "static_select")
 	assert.Equal(t, optGroup.ActionID, "test")
 	assert.Equal(t, len(optGroup.OptionGroups), 1)
-
 }
 
 func TestNewOptionsMultiSelectBlockElement(t *testing.T) {
-
 	testOptionText := NewTextBlockObject("plain_text", "Option One", false, false)
 	testDescriptionText := NewTextBlockObject("plain_text", "Description One", false, false)
 	testOption := NewOptionBlockObject("test", testOptionText, testDescriptionText)
@@ -90,7 +77,6 @@ func TestNewOptionsMultiSelectBlockElement(t *testing.T) {
 	assert.Equal(t, option.Type, "static_select")
 	assert.Equal(t, len(option.Options), 1)
 	assert.Nil(t, option.OptionGroups)
-
 }
 
 func TestNewOptionsGroupMultiSelectBlockElement(t *testing.T) {
diff --git a/block_file_test.go b/block_file_test.go
index c51a93e..f52270a 100644
--- a/block_file_test.go
+++ b/block_file_test.go
@@ -8,8 +8,11 @@ import (
 
 func TestNewFileBlock(t *testing.T) {
 	fileBlock := NewFileBlock("test", "external_id", "source")
+
+	assert.Equal(t, fileBlock.BlockType(), MBTFile)
 	assert.Equal(t, string(fileBlock.Type), "file")
 	assert.Equal(t, fileBlock.BlockID, "test")
+	assert.Equal(t, fileBlock.ID(), "test")
 	assert.Equal(t, fileBlock.ExternalID, "external_id")
 	assert.Equal(t, fileBlock.Source, "source")
 }
diff --git a/block_header_test.go b/block_header_test.go
index d8ed332..6e6df8a 100644
--- a/block_header_test.go
+++ b/block_header_test.go
@@ -7,11 +7,12 @@ import (
 )
 
 func TestNewHeaderBlock(t *testing.T) {
-
 	textInfo := NewTextBlockObject("plain_text", "This is quite the header", false, false)
-
 	headerBlock := NewHeaderBlock(textInfo, HeaderBlockOptionBlockID("test_block"))
+
+	assert.Equal(t, headerBlock.BlockType(), MBTHeader)
 	assert.Equal(t, string(headerBlock.Type), "header")
+	assert.Equal(t, headerBlock.ID(), "test_block")
 	assert.Equal(t, headerBlock.BlockID, "test_block")
 	assert.Equal(t, headerBlock.Text.Type, "plain_text")
 	assert.Contains(t, headerBlock.Text.Text, "quite the header")
diff --git a/block_image_test.go b/block_image_test.go
index 3cdd203..801a142 100644
--- a/block_image_test.go
+++ b/block_image_test.go
@@ -7,14 +7,14 @@ import (
 )
 
 func TestNewImageBlock(t *testing.T) {
-
 	imageText := NewTextBlockObject("plain_text", "Location", false, false)
 	imageBlock := NewImageBlock("https://api.slack.com/img/blocks/bkb_template_images/tripAgentLocationMarker.png", "Marker", "test", imageText)
 
+	assert.Equal(t, imageBlock.BlockType(), MBTImage)
 	assert.Equal(t, string(imageBlock.Type), "image")
 	assert.Equal(t, imageBlock.Title.Type, "plain_text")
+	assert.Equal(t, imageBlock.ID(), "test")
 	assert.Equal(t, imageBlock.BlockID, "test")
 	assert.Contains(t, imageBlock.Title.Text, "Location")
 	assert.Contains(t, imageBlock.ImageURL, "tripAgentLocationMarker.png")
-
 }
diff --git a/block_input_test.go b/block_input_test.go
index 694e575..fa25f48 100644
--- a/block_input_test.go
+++ b/block_input_test.go
@@ -11,7 +11,10 @@ func TestNewInputBlock(t *testing.T) {
 	element := NewDatePickerBlockElement("action_id")
 	hint := NewTextBlockObject("plain_text", "hint", false, false)
 	inputBlock := NewInputBlock("test", label, hint, element)
+
+	assert.Equal(t, inputBlock.BlockType(), MBTInput)
 	assert.Equal(t, string(inputBlock.Type), "input")
+	assert.Equal(t, inputBlock.ID(), "test")
 	assert.Equal(t, inputBlock.BlockID, "test")
 	assert.Equal(t, inputBlock.Label, label)
 	assert.Equal(t, inputBlock.Element, element)
diff --git a/block_object_test.go b/block_object_test.go
index 1f4874a..b8f55a4 100644
--- a/block_object_test.go
+++ b/block_object_test.go
@@ -9,28 +9,23 @@ import (
 )
 
 func TestNewImageBlockObject(t *testing.T) {
-
 	imageObject := NewImageBlockElement("https://api.slack.com/img/blocks/bkb_template_images/beagle.png", "Beagle")
 
 	assert.Equal(t, string(imageObject.Type), "image")
 	assert.Equal(t, imageObject.AltText, "Beagle")
 	assert.Contains(t, imageObject.ImageURL, "beagle.png")
-
 }
 
 func TestNewTextBlockObject(t *testing.T) {
-
 	textObject := NewTextBlockObject("plain_text", "test", true, false)
 
 	assert.Equal(t, textObject.Type, "plain_text")
 	assert.Equal(t, textObject.Text, "test")
 	assert.True(t, textObject.Emoji, "Emoji property should be true")
 	assert.False(t, textObject.Verbatim, "Verbatim should be false")
-
 }
 
 func TestNewConfirmationBlockObject(t *testing.T) {
-
 	titleObj := NewTextBlockObject("plain_text", "testTitle", false, false)
 	textObj := NewTextBlockObject("plain_text", "testText", false, false)
 	confirmObj := NewTextBlockObject("plain_text", "testConfirm", false, false)
@@ -41,11 +36,9 @@ func TestNewConfirmationBlockObject(t *testing.T) {
 	assert.Equal(t, confirmation.Text.Text, "testText")
 	assert.Equal(t, confirmation.Confirm.Text, "testConfirm")
 	assert.Nil(t, confirmation.Deny, "Deny should be nil")
-
 }
 
 func TestWithStyleForConfirmation(t *testing.T) {
-
 	// these values are irrelevant in this test
 	titleObj := NewTextBlockObject("plain_text", "testTitle", false, false)
 	textObj := NewTextBlockObject("plain_text", "testText", false, false)
@@ -58,11 +51,9 @@ func TestWithStyleForConfirmation(t *testing.T) {
 	assert.Equal(t, confirmation.Style, Style("primary"))
 	confirmation.WithStyle(StyleDanger)
 	assert.Equal(t, confirmation.Style, Style("danger"))
-
 }
 
 func TestNewOptionBlockObject(t *testing.T) {
-
 	valTextObj := NewTextBlockObject("plain_text", "testText", false, false)
 	valDescriptionObj := NewTextBlockObject("plain_text", "testDescription", false, false)
 	optObj := NewOptionBlockObject("testOpt", valTextObj, valDescriptionObj)
@@ -70,11 +61,9 @@ func TestNewOptionBlockObject(t *testing.T) {
 	assert.Equal(t, optObj.Text.Text, "testText")
 	assert.Equal(t, optObj.Description.Text, "testDescription")
 	assert.Equal(t, optObj.Value, "testOpt")
-
 }
 
 func TestNewOptionGroupBlockElement(t *testing.T) {
-
 	labelObj := NewTextBlockObject("plain_text", "testLabel", false, false)
 	valTextObj := NewTextBlockObject("plain_text", "testText", false, false)
 	optObj := NewOptionBlockObject("testOpt", valTextObj, nil)
@@ -83,7 +72,6 @@ func TestNewOptionGroupBlockElement(t *testing.T) {
 
 	assert.Equal(t, optGroup.Label.Text, "testLabel")
 	assert.Len(t, optGroup.Options, 1, "Options should contain one element")
-
 }
 
 func TestValidateTextBlockObject(t *testing.T) {
diff --git a/block_rich_text_test.go b/block_rich_text_test.go
index 903f143..1e26f9e 100644
--- a/block_rich_text_test.go
+++ b/block_rich_text_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/go-test/deep"
+	"github.com/stretchr/testify/assert"
 )
 
 const (
@@ -83,6 +84,15 @@ const (
 	}`
 )
 
+func TestNewRichTextBlock(t *testing.T) {
+	richTextBlock := NewRichTextBlock("test_block")
+
+	assert.Equal(t, richTextBlock.BlockType(), MBTRichText)
+	assert.Equal(t, string(richTextBlock.Type), "rich_text")
+	assert.Equal(t, richTextBlock.BlockID, "test_block")
+	assert.Equal(t, richTextBlock.ID(), "test_block")
+}
+
 func TestRichTextBlock_UnmarshalJSON(t *testing.T) {
 	cases := []struct {
 		raw      []byte
diff --git a/block_section_test.go b/block_section_test.go
index 6832967..8f8374e 100644
--- a/block_section_test.go
+++ b/block_section_test.go
@@ -7,17 +7,17 @@ import (
 )
 
 func TestNewSectionBlock(t *testing.T) {
-
 	textInfo := NewTextBlockObject("mrkdwn", "*<fakeLink.toHotelPage.com|The Ritz-Carlton New Orleans>*\n★★★★★\n$340 per night\nRated: 9.1 - Excellent", false, false)
-
 	sectionBlock := NewSectionBlock(textInfo, nil, nil, SectionBlockOptionBlockID("test_block"))
+
+	assert.Equal(t, sectionBlock.BlockType(), MBTSection)
 	assert.Equal(t, string(sectionBlock.Type), "section")
 	assert.Equal(t, sectionBlock.BlockID, "test_block")
+	assert.Equal(t, sectionBlock.ID(), "test_block")
 	assert.Equal(t, len(sectionBlock.Fields), 0)
 	assert.Nil(t, sectionBlock.Accessory)
 	assert.Equal(t, sectionBlock.Text.Type, "mrkdwn")
 	assert.Contains(t, sectionBlock.Text.Text, "New Orleans")
-
 }
 
 func TestNewBlockSectionContainsAddedTextBlockAndAccessory(t *testing.T) {
diff --git a/block_video_test.go b/block_video_test.go
index d4b791f..1ccece7 100644
--- a/block_video_test.go
+++ b/block_video_test.go
@@ -7,17 +7,17 @@ import (
 )
 
 func TestNewVideoBlock(t *testing.T) {
-
 	videoTitle := NewTextBlockObject("plain_text", "VideoTitle", false, false)
 	videoBlock := NewVideoBlock(
 		"https://example.com/example.mp4",
 		"https://example.com/thumbnail.png",
 		"alternative text", "blockID", videoTitle)
 
+	assert.Equal(t, videoBlock.Type, MBTVideo)
 	assert.Equal(t, string(videoBlock.Type), "video")
 	assert.Equal(t, videoBlock.Title.Type, "plain_text")
 	assert.Equal(t, videoBlock.BlockID, "blockID")
+	assert.Equal(t, videoBlock.ID(), "blockID")
 	assert.Contains(t, videoBlock.Title.Text, "VideoTitle")
 	assert.Contains(t, videoBlock.VideoURL, "example.mp4")
-
 }