Adding upstream version 0.8.9.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
3b2c48b5e4
commit
c0c4addb85
285 changed files with 25880 additions and 0 deletions
332
pkg/services/slack/slack_test.go
Normal file
332
pkg/services/slack/slack_test.go
Normal file
|
@ -0,0 +1,332 @@
|
|||
package slack_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/jarcoal/httpmock"
|
||||
"github.com/onsi/ginkgo/v2"
|
||||
"github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/format"
|
||||
|
||||
"github.com/nicholas-fedor/shoutrrr/internal/testutils"
|
||||
"github.com/nicholas-fedor/shoutrrr/pkg/services/slack"
|
||||
)
|
||||
|
||||
const (
|
||||
TestWebhookURL = "https://hooks.slack.com/services/AAAAAAAAA/BBBBBBBBB/123456789123456789123456"
|
||||
)
|
||||
|
||||
func TestSlack(t *testing.T) {
|
||||
format.CharactersAroundMismatchToInclude = 20
|
||||
|
||||
gomega.RegisterFailHandler(ginkgo.Fail)
|
||||
ginkgo.RunSpecs(t, "Shoutrrr Slack Suite")
|
||||
}
|
||||
|
||||
var (
|
||||
service *slack.Service
|
||||
envSlackURL *url.URL
|
||||
logger *log.Logger
|
||||
_ = ginkgo.BeforeSuite(func() {
|
||||
service = &slack.Service{}
|
||||
logger = log.New(ginkgo.GinkgoWriter, "Test", log.LstdFlags)
|
||||
envSlackURL, _ = url.Parse(os.Getenv("SHOUTRRR_SLACK_URL"))
|
||||
})
|
||||
)
|
||||
|
||||
var _ = ginkgo.Describe("the slack service", func() {
|
||||
ginkgo.When("running integration tests", func() {
|
||||
ginkgo.It("should not error out", func() {
|
||||
if envSlackURL.String() == "" {
|
||||
return
|
||||
}
|
||||
|
||||
serviceURL, _ := url.Parse(envSlackURL.String())
|
||||
err := service.Initialize(serviceURL, testutils.TestLogger())
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
err = service.Send("This is an integration test message", nil)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
})
|
||||
ginkgo.It("returns the correct service identifier", func() {
|
||||
gomega.Expect(service.GetID()).To(gomega.Equal("slack"))
|
||||
})
|
||||
})
|
||||
|
||||
// xoxb:123456789012-1234567890123-4mt0t4l1YL3g1T5L4cK70k3N
|
||||
|
||||
ginkgo.When("given a token with a malformed part", func() {
|
||||
ginkgo.It("should return an error if part A is not 9 letters", func() {
|
||||
expectErrorMessageGivenURL(
|
||||
slack.ErrInvalidToken,
|
||||
"slack://lol@12345678/123456789/123456789123456789123456",
|
||||
)
|
||||
})
|
||||
ginkgo.It("should return an error if part B is not 9 letters", func() {
|
||||
expectErrorMessageGivenURL(
|
||||
slack.ErrInvalidToken,
|
||||
"slack://lol@123456789/12345678/123456789123456789123456",
|
||||
)
|
||||
})
|
||||
ginkgo.It("should return an error if part C is not 24 letters", func() {
|
||||
expectErrorMessageGivenURL(
|
||||
slack.ErrInvalidToken,
|
||||
"slack://123456789/123456789/12345678912345678912345",
|
||||
)
|
||||
})
|
||||
})
|
||||
ginkgo.When("given a token missing a part", func() {
|
||||
ginkgo.It("should return an error if the missing part is A", func() {
|
||||
expectErrorMessageGivenURL(
|
||||
slack.ErrInvalidToken,
|
||||
"slack://lol@/123456789/123456789123456789123456",
|
||||
)
|
||||
})
|
||||
ginkgo.It("should return an error if the missing part is B", func() {
|
||||
expectErrorMessageGivenURL(slack.ErrInvalidToken, "slack://lol@123456789//123456789")
|
||||
})
|
||||
ginkgo.It("should return an error if the missing part is C", func() {
|
||||
expectErrorMessageGivenURL(slack.ErrInvalidToken, "slack://lol@123456789/123456789/")
|
||||
})
|
||||
})
|
||||
ginkgo.Describe("the slack config", func() {
|
||||
ginkgo.When("parsing the configuration URL", func() {
|
||||
ginkgo.When("given a config using the legacy format", func() {
|
||||
ginkgo.It("should be converted to the new format after de-/serialization", func() {
|
||||
oldURL := "slack://testbot@AAAAAAAAA/BBBBBBBBB/123456789123456789123456?color=3f00fe&title=Test+title"
|
||||
newURL := "slack://hook:AAAAAAAAA-BBBBBBBBB-123456789123456789123456@webhook?botname=testbot&color=3f00fe&title=Test+title"
|
||||
|
||||
config := &slack.Config{}
|
||||
err := config.SetURL(testutils.URLMust(oldURL))
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred(), "verifying")
|
||||
|
||||
gomega.Expect(config.GetURL().String()).To(gomega.Equal(newURL))
|
||||
})
|
||||
})
|
||||
})
|
||||
ginkgo.When("the URL contains an invalid property", func() {
|
||||
testURL := testutils.URLMust(
|
||||
"slack://hook:AAAAAAAAA-BBBBBBBBB-123456789123456789123456@webhook?bass=dirty",
|
||||
)
|
||||
err := (&slack.Config{}).SetURL(testURL)
|
||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
||||
})
|
||||
ginkgo.It("should be identical after de-/serialization", func() {
|
||||
testURL := "slack://hook:AAAAAAAAA-BBBBBBBBB-123456789123456789123456@webhook?botname=testbot&color=3f00fe&title=Test+title"
|
||||
|
||||
config := &slack.Config{}
|
||||
err := config.SetURL(testutils.URLMust(testURL))
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred(), "verifying")
|
||||
|
||||
outputURL := config.GetURL()
|
||||
gomega.Expect(outputURL.String()).To(gomega.Equal(testURL))
|
||||
})
|
||||
ginkgo.When("generating a config object", func() {
|
||||
ginkgo.It(
|
||||
"should use the default botname if the argument list contains three strings",
|
||||
func() {
|
||||
slackURL, _ := url.Parse("slack://AAAAAAAAA/BBBBBBBBB/123456789123456789123456")
|
||||
config, configError := slack.CreateConfigFromURL(slackURL)
|
||||
|
||||
gomega.Expect(configError).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(config.BotName).To(gomega.BeEmpty())
|
||||
},
|
||||
)
|
||||
ginkgo.It("should set the botname if the argument list is three", func() {
|
||||
slackURL, _ := url.Parse(
|
||||
"slack://testbot@AAAAAAAAA/BBBBBBBBB/123456789123456789123456",
|
||||
)
|
||||
config, configError := slack.CreateConfigFromURL(slackURL)
|
||||
|
||||
gomega.Expect(configError).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(config.BotName).To(gomega.Equal("testbot"))
|
||||
})
|
||||
ginkgo.It("should return an error if the argument list is shorter than three", func() {
|
||||
slackURL, _ := url.Parse("slack://AAAAAAAA")
|
||||
|
||||
_, configError := slack.CreateConfigFromURL(slackURL)
|
||||
gomega.Expect(configError).To(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
ginkgo.When("getting credentials from token", func() {
|
||||
ginkgo.It("should return a valid webhook URL for the given token", func() {
|
||||
token := tokenMust("AAAAAAAAA/BBBBBBBBB/123456789123456789123456")
|
||||
gomega.Expect(token.WebhookURL()).To(gomega.Equal(TestWebhookURL))
|
||||
})
|
||||
ginkgo.It(
|
||||
"should return a valid authorization header value for the given token",
|
||||
func() {
|
||||
token := tokenMust("xoxb:AAAAAAAAA-BBBBBBBBB-123456789123456789123456")
|
||||
expected := "Bearer xoxb-AAAAAAAAA-BBBBBBBBB-123456789123456789123456"
|
||||
gomega.Expect(token.Authorization()).To(gomega.Equal(expected))
|
||||
},
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
ginkgo.Describe("creating the payload", func() {
|
||||
ginkgo.Describe("the icon fields", func() {
|
||||
payload := slack.MessagePayload{}
|
||||
ginkgo.It("should set IconURL when the configured icon looks like an URL", func() {
|
||||
payload.SetIcon("https://example.com/logo.png")
|
||||
gomega.Expect(payload.IconURL).To(gomega.Equal("https://example.com/logo.png"))
|
||||
gomega.Expect(payload.IconEmoji).To(gomega.BeEmpty())
|
||||
})
|
||||
ginkgo.It(
|
||||
"should set IconEmoji when the configured icon does not look like an URL",
|
||||
func() {
|
||||
payload.SetIcon("tanabata_tree")
|
||||
gomega.Expect(payload.IconEmoji).To(gomega.Equal("tanabata_tree"))
|
||||
gomega.Expect(payload.IconURL).To(gomega.BeEmpty())
|
||||
},
|
||||
)
|
||||
ginkgo.It("should clear both fields when icon is empty", func() {
|
||||
payload.SetIcon("")
|
||||
gomega.Expect(payload.IconEmoji).To(gomega.BeEmpty())
|
||||
gomega.Expect(payload.IconURL).To(gomega.BeEmpty())
|
||||
})
|
||||
})
|
||||
ginkgo.When("when more than 99 lines are being sent", func() {
|
||||
ginkgo.It("should append the exceeding lines to the last attachment", func() {
|
||||
config := slack.Config{}
|
||||
sb := strings.Builder{}
|
||||
for i := 1; i <= 110; i++ {
|
||||
sb.WriteString(fmt.Sprintf("Line %d\n", i))
|
||||
}
|
||||
payload := slack.CreateJSONPayload(&config, sb.String()).(slack.MessagePayload)
|
||||
atts := payload.Attachments
|
||||
|
||||
fmt.Fprint(
|
||||
ginkgo.GinkgoWriter,
|
||||
"\nLines: ",
|
||||
len(atts),
|
||||
" Last: ",
|
||||
atts[len(atts)-1],
|
||||
"\n",
|
||||
)
|
||||
|
||||
gomega.Expect(atts).To(gomega.HaveLen(100))
|
||||
gomega.Expect(atts[len(atts)-1].Text).To(gomega.ContainSubstring("Line 110"))
|
||||
})
|
||||
})
|
||||
ginkgo.When("when the last message line ends with a newline", func() {
|
||||
ginkgo.It("should not send an empty attachment", func() {
|
||||
payload := slack.CreateJSONPayload(&slack.Config{}, "One\nTwo\nThree\n").(slack.MessagePayload)
|
||||
atts := payload.Attachments
|
||||
gomega.Expect(atts[len(atts)-1].Text).NotTo(gomega.BeEmpty())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
ginkgo.Describe("sending the payload", func() {
|
||||
ginkgo.When("sending via webhook URL", func() {
|
||||
var err error
|
||||
ginkgo.BeforeEach(func() {
|
||||
httpmock.Activate()
|
||||
})
|
||||
ginkgo.AfterEach(func() {
|
||||
httpmock.DeactivateAndReset()
|
||||
})
|
||||
|
||||
ginkgo.It("should not report an error if the server accepts the payload", func() {
|
||||
serviceURL, _ := url.Parse(
|
||||
"slack://testbot@AAAAAAAAA/BBBBBBBBB/123456789123456789123456",
|
||||
)
|
||||
err = service.Initialize(serviceURL, logger)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
httpmock.RegisterResponder(
|
||||
"POST",
|
||||
TestWebhookURL,
|
||||
httpmock.NewStringResponder(200, ""),
|
||||
)
|
||||
|
||||
err = service.Send("Message", nil)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
})
|
||||
ginkgo.It("should not panic if an error occurs when sending the payload", func() {
|
||||
serviceURL, _ := url.Parse(
|
||||
"slack://testbot@AAAAAAAAA/BBBBBBBBB/123456789123456789123456",
|
||||
)
|
||||
err = service.Initialize(serviceURL, logger)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
httpmock.RegisterResponder(
|
||||
"POST",
|
||||
TestWebhookURL,
|
||||
httpmock.NewErrorResponder(errors.New("dummy error")),
|
||||
)
|
||||
|
||||
err = service.Send("Message", nil)
|
||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
ginkgo.When("sending via bot API", func() {
|
||||
var err error
|
||||
ginkgo.BeforeEach(func() {
|
||||
httpmock.Activate()
|
||||
})
|
||||
ginkgo.AfterEach(func() {
|
||||
httpmock.DeactivateAndReset()
|
||||
})
|
||||
|
||||
ginkgo.It("should not report an error if the server accepts the payload", func() {
|
||||
serviceURL := testutils.URLMust(
|
||||
"slack://xoxb:123456789012-1234567890123-4mt0t4l1YL3g1T5L4cK70k3N@C0123456789",
|
||||
)
|
||||
err = service.Initialize(serviceURL, logger)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
targetURL := "https://slack.com/api/chat.postMessage"
|
||||
httpmock.RegisterResponder(
|
||||
"POST",
|
||||
targetURL,
|
||||
testutils.JSONRespondMust(200, slack.APIResponse{
|
||||
Ok: true,
|
||||
}),
|
||||
)
|
||||
|
||||
err = service.Send("Message", nil)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
})
|
||||
ginkgo.It("should not panic if an error occurs when sending the payload", func() {
|
||||
serviceURL := testutils.URLMust(
|
||||
"slack://xoxb:123456789012-1234567890123-4mt0t4l1YL3g1T5L4cK70k3N@C0123456789",
|
||||
)
|
||||
err = service.Initialize(serviceURL, logger)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
targetURL := "https://slack.com/api/chat.postMessage"
|
||||
httpmock.RegisterResponder(
|
||||
"POST",
|
||||
targetURL,
|
||||
testutils.JSONRespondMust(200, slack.APIResponse{
|
||||
Error: "someone turned off the internet",
|
||||
}),
|
||||
)
|
||||
|
||||
err = service.Send("Message", nil)
|
||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
func tokenMust(rawToken string) *slack.Token {
|
||||
token, err := slack.ParseToken(rawToken)
|
||||
gomega.ExpectWithOffset(1, err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
func expectErrorMessageGivenURL(expected error, rawURL string) {
|
||||
err := service.Initialize(testutils.URLMust(rawURL), testutils.TestLogger())
|
||||
gomega.ExpectWithOffset(1, err).To(gomega.HaveOccurred())
|
||||
gomega.ExpectWithOffset(1, err).To(gomega.Equal(expected))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue