Repository: nicklaw5/helix
Pull request #138 (2022-07-20 15:03:48)

feat: Send Chat Announcements
https://dev.twitch.tv/docs/api/reference#send-chat-announcement

- add api parameters, response, func to chat.go
- add unit tests

coveralls: ## Pull Request Test Coverage Report for [Build 2705683681](https://coveralls.io/builds/51024550)

* **9** of **9**   **(100.0%)**  changed or added relevant lines in **1** file are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage decreased (**-7.4%**) to **92.557%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/51024550/badge)](https://coveralls.io/builds/51024550) |
| :-- | --: |
| Change from base [Build 2517160898](https://coveralls.io/builds/50137648): |  -7.4% |
| Covered Lines: | 1256 |
| Relevant Lines: | 1357 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/chat.go b/chat.go
index 8150ffc..f790a7d 100644
--- a/chat.go
+++ b/chat.go
@@ -59,6 +59,18 @@ type GetEmoteSetsParams struct {
 	EmoteSetIDs []string `query:"emote_set_id"` // Minimum: 1. Maximum: 25.
 }
 
+type SendChatAnnouncementParams struct {
+	BroadcasterID string `query:"broadcaster_id"` // required
+	ModeratorID   string `query:"moderator_id"`   // required
+	Message       string `json:"message"`         // upto 500 chars, thereafter str is truncated
+	// blue || green || orange || purple are valid, default 'primary' or empty str result in channel accent color.
+	Color string `json:"color"`
+}
+
+type SendChatAnnouncementResponse struct {
+	ResponseCommon
+}
+
 type GetChannelEmotesResponse struct {
 	ResponseCommon
 	Data ManyEmotes
@@ -136,3 +148,17 @@ func (c *Client) GetEmoteSets(params *GetEmoteSetsParams) (*GetEmoteSetsResponse
 
 	return emotes, nil
 }
+
+// SendChatAnnouncement sends an announcement to the broadcaster’s chat room.
+// Required scope: moderator:manage:announcements
+func (c *Client) SendChatAnnouncement(params *SendChatAnnouncementParams) (*SendChatAnnouncementResponse, error) {
+	resp, err := c.postAsJSON("/chat/announcements", nil, params)
+	if err != nil {
+		return nil, err
+	}
+
+	chatResp := &SendChatAnnouncementResponse{}
+	resp.HydrateResponseCommon(&chatResp.ResponseCommon)
+
+	return chatResp, nil
+}


Test patch:
diff --git a/chat_test.go b/chat_test.go
index 9af87ab..04ea5d2 100644
--- a/chat_test.go
+++ b/chat_test.go
@@ -397,3 +397,77 @@ func TestGetEmoteSets(t *testing.T) {
 		t.Error("expected error does match return error")
 	}
 }
+
+func TestSendChatAnnouncement(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		statusCode                 int
+		options                    *Options
+		SendChatAnnouncementParams *SendChatAnnouncementParams
+		respBody                   string
+	}{
+		{
+			http.StatusBadRequest,
+			&Options{ClientID: "my-client-id", UserAccessToken: "moderator-access-token"},
+			&SendChatAnnouncementParams{BroadcasterID: "100249558", ModeratorID: "100249558", Message: "hello world", Color: "blue"},
+			`{"error":"Bad Request","status":400,"message":"The parameter \"Color\" was malformed: the value must be a valid color"}`,
+		},
+		{
+			http.StatusNoContent,
+			&Options{ClientID: "my-client-id", UserAccessToken: "moderator-access-token"},
+			&SendChatAnnouncementParams{BroadcasterID: "100249558", ModeratorID: "100249558", Message: "hello twitch chat", Color: "blue"},
+			``,
+		},
+	}
+
+	for _, testCase := range testCases {
+		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
+
+		resp, err := c.SendChatAnnouncement(testCase.SendChatAnnouncementParams)
+		if err != nil {
+			t.Error(err)
+		}
+
+		if resp.StatusCode != testCase.statusCode {
+			t.Errorf("expected status code to be %d, got %d", testCase.statusCode, resp.StatusCode)
+		}
+
+		if resp.StatusCode == http.StatusBadRequest {
+			if resp.Error != "Bad Request" {
+				t.Errorf("expected error to be %s, got %s", "Bad Request", resp.Error)
+			}
+
+			if resp.ErrorStatus != http.StatusBadRequest {
+				t.Errorf("expected error status to be %d, got %d", http.StatusBadRequest, resp.ErrorStatus)
+			}
+
+			expectedErrMsg := "The parameter \"Color\" was malformed: the value must be a valid color"
+			if resp.ErrorMessage != expectedErrMsg {
+				t.Errorf("expected error message to be %s, got %s", expectedErrMsg, resp.ErrorMessage)
+			}
+
+			continue
+		}
+	}
+
+	// Test with HTTP Failure
+	options := &Options{
+		ClientID: "my-client-id",
+		HTTPClient: &badMockHTTPClient{
+			newMockHandler(0, "", nil),
+		},
+	}
+	c := &Client{
+		opts: options,
+	}
+
+	_, err := c.SendChatAnnouncement(&SendChatAnnouncementParams{})
+	if err == nil {
+		t.Error("expected error but got nil")
+	}
+
+	if err.Error() != "Failed to execute API request: Oops, that's bad :(" {
+		t.Error("expected error does match return error")
+	}
+}