252 lines
7.9 KiB
Go
252 lines
7.9 KiB
Go
package rocketchat
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/onsi/ginkgo/v2"
|
|
"github.com/onsi/gomega"
|
|
|
|
"github.com/nicholas-fedor/shoutrrr/internal/testutils"
|
|
"github.com/nicholas-fedor/shoutrrr/pkg/types"
|
|
)
|
|
|
|
var (
|
|
service *Service
|
|
envRocketchatURL *url.URL
|
|
_ = ginkgo.BeforeSuite(func() {
|
|
service = &Service{}
|
|
envRocketchatURL, _ = url.Parse(os.Getenv("SHOUTRRR_ROCKETCHAT_URL"))
|
|
})
|
|
)
|
|
|
|
// Constants for repeated test values.
|
|
const (
|
|
testTokenA = "tokenA"
|
|
testTokenB = "tokenB"
|
|
)
|
|
|
|
func TestRocketchat(t *testing.T) {
|
|
gomega.RegisterFailHandler(ginkgo.Fail)
|
|
ginkgo.RunSpecs(t, "Shoutrrr Rocketchat Suite")
|
|
}
|
|
|
|
var _ = ginkgo.Describe("the rocketchat service", func() {
|
|
// Add tests for Initialize()
|
|
ginkgo.Describe("Initialize method", func() {
|
|
ginkgo.When("initializing with a valid URL", func() {
|
|
ginkgo.It("should set logger and config without error", func() {
|
|
service := &Service{}
|
|
testURL, _ := url.Parse(
|
|
"rocketchat://testUser@rocketchat.my-domain.com:5055/" + testTokenA + "/" + testTokenB + "/#testChannel",
|
|
)
|
|
err := service.Initialize(testURL, testutils.TestLogger())
|
|
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
gomega.Expect(service.Config).NotTo(gomega.BeNil())
|
|
gomega.Expect(service.Config.Host).To(gomega.Equal("rocketchat.my-domain.com"))
|
|
gomega.Expect(service.Config.Port).To(gomega.Equal("5055"))
|
|
gomega.Expect(service.Config.UserName).To(gomega.Equal("testUser"))
|
|
gomega.Expect(service.Config.TokenA).To(gomega.Equal(testTokenA))
|
|
gomega.Expect(service.Config.TokenB).To(gomega.Equal(testTokenB))
|
|
gomega.Expect(service.Config.Channel).To(gomega.Equal("#testChannel"))
|
|
})
|
|
})
|
|
ginkgo.When("initializing with an invalid URL", func() {
|
|
ginkgo.It("should return an error", func() {
|
|
service := &Service{}
|
|
testURL, _ := url.Parse("rocketchat://rocketchat.my-domain.com") // Missing tokens
|
|
err := service.Initialize(testURL, testutils.TestLogger())
|
|
gomega.Expect(err).To(gomega.HaveOccurred())
|
|
gomega.Expect(err).
|
|
To(gomega.Equal(ErrNotEnoughArguments))
|
|
// Updated to use the error variable
|
|
})
|
|
})
|
|
})
|
|
|
|
// Add tests for Send()
|
|
ginkgo.Describe("Send method", func() {
|
|
var (
|
|
mockServer *httptest.Server
|
|
service *Service
|
|
client *http.Client
|
|
)
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
// Create TLS server
|
|
mockServer = httptest.NewTLSServer(nil) // Handler set in each test
|
|
|
|
// Configure client to trust the mock server's certificate
|
|
certPool := x509.NewCertPool()
|
|
for _, cert := range mockServer.TLS.Certificates {
|
|
certPool.AddCert(cert.Leaf)
|
|
}
|
|
client = &http.Client{
|
|
Transport: &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
RootCAs: certPool,
|
|
MinVersion: tls.VersionTLS12, // Explicitly set minimum TLS version to 1.2
|
|
},
|
|
},
|
|
}
|
|
|
|
service = &Service{
|
|
Config: &Config{},
|
|
Client: client, // Assign the custom client here
|
|
}
|
|
service.SetLogger(testutils.TestLogger())
|
|
})
|
|
|
|
ginkgo.AfterEach(func() {
|
|
if mockServer != nil {
|
|
mockServer.Close()
|
|
}
|
|
})
|
|
|
|
ginkgo.When("sending a message to a mock server with success", func() {
|
|
ginkgo.It("should return no error", func() {
|
|
mockServer.Config.Handler = http.HandlerFunc(
|
|
func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
},
|
|
)
|
|
mockURL, _ := url.Parse(mockServer.URL)
|
|
service.Config.Host = mockURL.Hostname()
|
|
service.Config.Port = mockURL.Port()
|
|
service.Config.TokenA = testTokenA
|
|
service.Config.TokenB = testTokenB
|
|
|
|
err := service.Send("test message", nil)
|
|
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
})
|
|
})
|
|
|
|
ginkgo.When("sending a message to a mock server with failure", func() {
|
|
ginkgo.It("should return an error with status code and body", func() {
|
|
mockServer.Config.Handler = http.HandlerFunc(
|
|
func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("bad request"))
|
|
},
|
|
)
|
|
mockURL, _ := url.Parse(mockServer.URL)
|
|
service.Config.Host = mockURL.Hostname()
|
|
service.Config.Port = mockURL.Port()
|
|
service.Config.TokenA = testTokenA
|
|
service.Config.TokenB = testTokenB
|
|
|
|
err := service.Send("test message", nil)
|
|
gomega.Expect(err).To(gomega.HaveOccurred())
|
|
gomega.Expect(err.Error()).
|
|
To(gomega.ContainSubstring("notification failed: 400 bad request"))
|
|
})
|
|
})
|
|
|
|
ginkgo.When("sending a message to an unreachable server", func() {
|
|
ginkgo.It("should return a connection error", func() {
|
|
service.Client = http.DefaultClient // Reset to default client for this test
|
|
service.Config.Host = "nonexistent.domain"
|
|
service.Config.TokenA = testTokenA
|
|
service.Config.TokenB = testTokenB
|
|
|
|
err := service.Send("test message", nil)
|
|
gomega.Expect(err).To(gomega.HaveOccurred())
|
|
gomega.Expect(err.Error()).To(gomega.ContainSubstring("posting to URL"))
|
|
})
|
|
})
|
|
|
|
ginkgo.When("sending a message with params overriding username and channel", func() {
|
|
ginkgo.It("should use params values in the payload", func() {
|
|
mockServer.Config.Handler = http.HandlerFunc(
|
|
func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
},
|
|
)
|
|
mockURL, _ := url.Parse(mockServer.URL)
|
|
service.Config.Host = mockURL.Hostname()
|
|
service.Config.Port = mockURL.Port()
|
|
service.Config.TokenA = testTokenA
|
|
service.Config.TokenB = testTokenB
|
|
service.Config.UserName = "defaultUser"
|
|
service.Config.Channel = "#defaultChannel"
|
|
|
|
params := types.Params{
|
|
"username": "overrideUser",
|
|
"channel": "#overrideChannel",
|
|
}
|
|
err := service.Send("test message", ¶ms)
|
|
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
// Note: We can't directly inspect the payload here without mocking CreateJSONPayload,
|
|
// but this ensures the params path is exercised.
|
|
})
|
|
})
|
|
})
|
|
|
|
// Add tests for GetURL() and SetURL()
|
|
ginkgo.Describe("the rocketchat config", func() {
|
|
ginkgo.When("generating a URL from a config with all fields", func() {
|
|
ginkgo.It("should construct a correct URL", func() {
|
|
config := &Config{
|
|
Host: "rocketchat.my-domain.com",
|
|
Port: "5055",
|
|
TokenA: testTokenA,
|
|
TokenB: testTokenB,
|
|
}
|
|
url := config.GetURL()
|
|
gomega.Expect(url.String()).
|
|
To(gomega.Equal("rocketchat://rocketchat.my-domain.com:5055/" + testTokenA + "/" + testTokenB))
|
|
})
|
|
})
|
|
|
|
ginkgo.When("generating a URL from a config without port", func() {
|
|
ginkgo.It("should construct a correct URL without port", func() {
|
|
config := &Config{
|
|
Host: "rocketchat.my-domain.com",
|
|
TokenA: testTokenA,
|
|
TokenB: testTokenB,
|
|
}
|
|
url := config.GetURL()
|
|
gomega.Expect(url.String()).
|
|
To(gomega.Equal("rocketchat://rocketchat.my-domain.com/" + testTokenA + "/" + testTokenB))
|
|
})
|
|
})
|
|
|
|
ginkgo.When("setting URL with a channel starting with @", func() {
|
|
ginkgo.It("should set channel without adding #", func() {
|
|
config := &Config{}
|
|
testURL, _ := url.Parse(
|
|
"rocketchat://rocketchat.my-domain.com/" + testTokenA + "/" + testTokenB + "/@user",
|
|
)
|
|
err := config.SetURL(testURL)
|
|
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
gomega.Expect(config.Channel).To(gomega.Equal("@user"))
|
|
})
|
|
})
|
|
|
|
ginkgo.When("setting URL with a regular channel without fragment", func() {
|
|
ginkgo.It("should prepend # to the channel", func() {
|
|
config := &Config{}
|
|
testURL, _ := url.Parse(
|
|
"rocketchat://rocketchat.my-domain.com/" + testTokenA + "/" + testTokenB + "/general",
|
|
)
|
|
err := config.SetURL(testURL)
|
|
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
gomega.Expect(config.Channel).To(gomega.Equal("#general"))
|
|
})
|
|
})
|
|
})
|
|
|
|
// Add test for GetID()
|
|
ginkgo.Describe("GetID method", func() {
|
|
ginkgo.It("should return the correct scheme", func() {
|
|
service := &Service{}
|
|
id := service.GetID()
|
|
gomega.Expect(id).To(gomega.Equal(Scheme))
|
|
})
|
|
})
|
|
})
|