1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
package standard
import (
"errors"
"fmt"
"io"
"log"
"os"
"strings"
"testing"
"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
"github.com/nicholas-fedor/shoutrrr/internal/failures"
)
func TestStandard(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "Shoutrrr Standard Suite")
}
var (
logger *Logger
builder *strings.Builder
stringLogger *log.Logger
)
var _ = ginkgo.Describe("the standard logging implementation", func() {
ginkgo.When("setlogger is called with nil", func() {
ginkgo.It("should provide the logging API without any errors", func() {
logger = &Logger{}
logger.SetLogger(nil)
logger.Log("discarded log message")
gomega.Expect(logger.logger).ToNot(gomega.BeNil())
})
})
ginkgo.When("setlogger is called with a proper logger", func() {
ginkgo.BeforeEach(func() {
logger = &Logger{}
builder = &strings.Builder{}
stringLogger = log.New(builder, "", 0)
})
ginkgo.When("when logger.Log is called", func() {
ginkgo.It("should log messages", func() {
logger.SetLogger(stringLogger)
logger.Log("foo")
logger.Log("bar")
gomega.Expect(builder.String()).To(gomega.Equal("foo\nbar\n"))
})
})
ginkgo.When("when logger.Logf is called", func() {
ginkgo.It("should log messages", func() {
logger.SetLogger(stringLogger)
logger.Logf("foo %d", 7)
gomega.Expect(builder.String()).To(gomega.Equal("foo 7\n"))
})
})
})
})
var _ = ginkgo.Describe("the standard template implementation", func() {
ginkgo.When("a template is being set from a file", func() {
ginkgo.It("should load the template without any errors", func() {
file, err := os.CreateTemp("", "")
if err != nil {
ginkgo.Skip(fmt.Sprintf("Could not create temp file: %s", err))
return
}
fileName := file.Name()
defer os.Remove(fileName)
_, err = io.WriteString(file, "template content")
if err != nil {
ginkgo.Skip(fmt.Sprintf("Could not write to temp file: %s", err))
return
}
templater := &Templater{}
err = templater.SetTemplateFile("foo", fileName)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
})
})
ginkgo.When("a template is being set from a file that does not exist", func() {
ginkgo.It("should return an error", func() {
templater := &Templater{}
err := templater.SetTemplateFile("foo", "filename_that_should_not_exist")
gomega.Expect(err).To(gomega.HaveOccurred())
})
})
ginkgo.When("a template is being set with a badly formatted string", func() {
ginkgo.It("should return an error", func() {
templater := &Templater{}
err := templater.SetTemplateString("foo", "template {{ missing end tag")
gomega.Expect(err).To(gomega.HaveOccurred())
})
})
ginkgo.When("a template is being retrieved with a present ID", func() {
ginkgo.It("should return the corresponding template", func() {
templater := &Templater{}
err := templater.SetTemplateString("bar", "template body")
gomega.Expect(err).NotTo(gomega.HaveOccurred())
tpl, found := templater.GetTemplate("bar")
gomega.Expect(tpl).ToNot(gomega.BeNil())
gomega.Expect(found).To(gomega.BeTrue())
})
})
ginkgo.When("a template is being retrieved with an invalid ID", func() {
ginkgo.It("should return an error", func() {
templater := &Templater{}
err := templater.SetTemplateString("bar", "template body")
gomega.Expect(err).NotTo(gomega.HaveOccurred())
tpl, found := templater.GetTemplate("bad ID")
gomega.Expect(tpl).To(gomega.BeNil())
gomega.Expect(found).ToNot(gomega.BeTrue())
})
})
})
var _ = ginkgo.Describe("the standard enumless config implementation", func() {
ginkgo.When("it's enum method is called", func() {
ginkgo.It("should return an empty map", func() {
gomega.Expect((&EnumlessConfig{}).Enums()).To(gomega.BeEmpty())
})
})
})
var _ = ginkgo.Describe("the standard failure implementation", func() {
ginkgo.Describe("Failure function", func() {
ginkgo.When("called with FailParseURL", func() {
ginkgo.It("should return a failure with the correct message", func() {
err := errors.New("invalid URL")
failure := Failure(FailParseURL, err)
gomega.Expect(failure.ID()).To(gomega.Equal(FailParseURL))
gomega.Expect(failure.Error()).
To(gomega.ContainSubstring("error parsing Service URL"))
gomega.Expect(failure.Error()).To(gomega.ContainSubstring("invalid URL"))
})
})
ginkgo.When("called with FailUnknown", func() {
ginkgo.It("should return a failure with the unknown error message", func() {
err := errors.New("something went wrong")
failure := Failure(FailUnknown, err)
gomega.Expect(failure.ID()).To(gomega.Equal(FailUnknown))
gomega.Expect(failure.Error()).
To(gomega.ContainSubstring("an unknown error occurred"))
gomega.Expect(failure.Error()).To(gomega.ContainSubstring("something went wrong"))
})
})
ginkgo.When("called with an unrecognized FailureID", func() {
ginkgo.It("should fallback to the unknown error message", func() {
err := errors.New("unrecognized error")
failure := Failure(failures.FailureID(999), err) // Arbitrary unknown ID
gomega.Expect(failure.ID()).To(gomega.Equal(failures.FailureID(999)))
gomega.Expect(failure.Error()).
To(gomega.ContainSubstring("an unknown error occurred"))
gomega.Expect(failure.Error()).To(gomega.ContainSubstring("unrecognized error"))
})
})
ginkgo.When("called with additional arguments", func() {
ginkgo.It("should include formatted arguments in the error", func() {
err := errors.New("base error")
failure := Failure(FailParseURL, err, "extra info: %s", "details")
gomega.Expect(failure.Error()).
To(gomega.ContainSubstring("error parsing Service URL extra info: details"))
gomega.Expect(failure.Error()).To(gomega.ContainSubstring("base error"))
})
})
})
ginkgo.Describe("IsTestSetupFailure function", func() {
ginkgo.When("called with a FailTestSetup failure", func() {
ginkgo.It("should return true and the correct message", func() {
err := errors.New("setup issue")
failure := Failure(FailTestSetup, err)
msg, isSetupFailure := IsTestSetupFailure(failure)
gomega.Expect(isSetupFailure).To(gomega.BeTrue())
gomega.Expect(msg).To(gomega.ContainSubstring("test setup failed: setup issue"))
})
})
ginkgo.When("called with a different failure", func() {
ginkgo.It("should return false and an empty message", func() {
err := errors.New("parse issue")
failure := Failure(FailParseURL, err)
msg, isSetupFailure := IsTestSetupFailure(failure)
gomega.Expect(isSetupFailure).To(gomega.BeFalse())
gomega.Expect(msg).To(gomega.BeEmpty())
})
})
ginkgo.When("called with nil", func() {
ginkgo.It("should return false and an empty message", func() {
msg, isSetupFailure := IsTestSetupFailure(nil)
gomega.Expect(isSetupFailure).To(gomega.BeFalse())
gomega.Expect(msg).To(gomega.BeEmpty())
})
})
})
})
|