121 lines
3.8 KiB
Go
121 lines
3.8 KiB
Go
package slack
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestPostMessageSendsThreadedReply(t *testing.T) {
|
|
var (
|
|
gotPath string
|
|
gotAuth string
|
|
gotBody map[string]any
|
|
)
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotPath = r.URL.Path
|
|
gotAuth = r.Header.Get("Authorization")
|
|
raw, _ := io.ReadAll(r.Body)
|
|
_ = json.Unmarshal(raw, &gotBody)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"ok":true,"channel":"C0123","ts":"1725260000.000100"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient("xoxb-test-token")
|
|
client.SetBaseURL(server.URL)
|
|
|
|
resp, err := client.PostMessage(context.Background(), "C0123", "hello there", "1725260000.000200")
|
|
if err != nil {
|
|
t.Fatalf("PostMessage failed: %v", err)
|
|
}
|
|
if resp == nil || resp.TS != "1725260000.000100" {
|
|
t.Fatalf("response = %+v, want the posted message ts", resp)
|
|
}
|
|
|
|
if gotPath != "/chat.postMessage" {
|
|
t.Errorf("path = %q, want /chat.postMessage", gotPath)
|
|
}
|
|
if gotAuth != "Bearer xoxb-test-token" {
|
|
t.Errorf("authorization = %q, want the bot token as a bearer", gotAuth)
|
|
}
|
|
if gotBody["channel"] != "C0123" {
|
|
t.Errorf("channel = %v, want C0123", gotBody["channel"])
|
|
}
|
|
if gotBody["text"] != "hello there" {
|
|
t.Errorf("text = %v, want 'hello there'", gotBody["text"])
|
|
}
|
|
// A reply has to stay in the customer's thread, otherwise the workspace
|
|
// timeline fills up with support answers.
|
|
if gotBody["thread_ts"] != "1725260000.000200" {
|
|
t.Errorf("thread_ts = %v, want the parent ts", gotBody["thread_ts"])
|
|
}
|
|
}
|
|
|
|
func TestPostMessageOmitsThreadTSForTopLevel(t *testing.T) {
|
|
var gotRaw string
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
raw, _ := io.ReadAll(r.Body)
|
|
gotRaw = string(raw)
|
|
_, _ = w.Write([]byte(`{"ok":true}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient("xoxb-test-token")
|
|
client.SetBaseURL(server.URL)
|
|
|
|
if _, err := client.PostMessage(context.Background(), "C0123", "top level", ""); err != nil {
|
|
t.Fatalf("PostMessage failed: %v", err)
|
|
}
|
|
// thread_ts is omitempty on the request struct, so a top-level post must not
|
|
// carry an empty one.
|
|
var body map[string]any
|
|
if err := json.Unmarshal([]byte(gotRaw), &body); err != nil {
|
|
t.Fatalf("unmarshal request body: %v", err)
|
|
}
|
|
if _, present := body["thread_ts"]; present {
|
|
t.Errorf("request body carried thread_ts for a top-level message: %s", gotRaw)
|
|
}
|
|
}
|
|
|
|
func TestPostMessageSurfacesSlackAPIError(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Slack returns HTTP 200 with ok:false for application-level failures, so
|
|
// the client has to read the envelope rather than the status code.
|
|
_, _ = w.Write([]byte(`{"ok":false,"error":"channel_not_found"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient("xoxb-test-token")
|
|
client.SetBaseURL(server.URL)
|
|
|
|
_, err := client.PostMessage(context.Background(), "C_MISSING", "hello", "")
|
|
if err == nil {
|
|
t.Fatalf("expected an error when Slack answers ok:false")
|
|
}
|
|
if got := err.Error(); got != "slack api error: channel_not_found" {
|
|
t.Errorf("error = %q, want the slack error code to be carried through", got)
|
|
}
|
|
}
|
|
|
|
func TestPostMessageValidatesInputs(t *testing.T) {
|
|
client := NewClient("xoxb-test-token")
|
|
|
|
if _, err := client.PostMessage(context.Background(), "", "hello", ""); err == nil {
|
|
t.Errorf("expected an error for an empty channel")
|
|
}
|
|
if _, err := client.PostMessage(context.Background(), "C0123", " ", ""); err == nil {
|
|
t.Errorf("expected an error for blank text")
|
|
}
|
|
|
|
noToken := NewClient("")
|
|
if _, err := noToken.PostMessage(context.Background(), "C0123", "hello", ""); err == nil {
|
|
t.Errorf("expected an error when no bot token is configured")
|
|
}
|
|
}
|