2020-09-19 22:29:08 +02:00
package slack
2020-10-22 03:18:06 +02:00
import (
2021-02-20 01:06:20 +01:00
"encoding/json"
2021-12-03 05:10:21 +01:00
"net/http"
2020-10-22 03:18:06 +02:00
"testing"
2020-11-18 01:34:35 +01:00
2022-12-06 07:41:09 +01:00
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
2024-05-10 04:56:16 +02:00
"github.com/TwiN/gatus/v5/config/endpoint"
2022-12-06 07:41:09 +01:00
"github.com/TwiN/gatus/v5/test"
2020-10-22 03:18:06 +02:00
)
2020-09-19 22:29:08 +02:00
2024-12-17 02:32:13 +01:00
func TestAlertProvider_Validate ( t * testing . T ) {
invalidProvider := AlertProvider { DefaultConfig : Config { WebhookURL : "" } }
if err := invalidProvider . Validate ( ) ; err == nil {
2020-09-19 22:29:08 +02:00
t . Error ( "provider shouldn't have been valid" )
}
2024-12-17 02:32:13 +01:00
validProvider := AlertProvider { DefaultConfig : Config { WebhookURL : "https://example.com" } }
if err := validProvider . Validate ( ) ; err != nil {
2020-09-19 22:29:08 +02:00
t . Error ( "provider should've been valid" )
}
2022-05-31 04:03:09 +02:00
}
2022-10-05 05:19:55 +02:00
2024-12-17 02:32:13 +01:00
func TestAlertProvider_ValidateWithOverride ( t * testing . T ) {
2022-05-31 04:03:09 +02:00
providerWithInvalidOverrideGroup := AlertProvider {
Overrides : [ ] Override {
{
2024-12-17 02:32:13 +01:00
Config : Config { WebhookURL : "http://example.com" } ,
Group : "" ,
2022-05-31 04:03:09 +02:00
} ,
} ,
}
2024-12-17 02:32:13 +01:00
if err := providerWithInvalidOverrideGroup . Validate ( ) ; err == nil {
2022-05-31 04:03:09 +02:00
t . Error ( "provider Group shouldn't have been valid" )
}
providerWithInvalidOverrideTo := AlertProvider {
Overrides : [ ] Override {
{
2024-12-17 02:32:13 +01:00
Config : Config { WebhookURL : "" } ,
Group : "group" ,
2022-05-31 04:03:09 +02:00
} ,
} ,
}
2024-12-17 02:32:13 +01:00
if err := providerWithInvalidOverrideTo . Validate ( ) ; err == nil {
2022-05-31 04:03:09 +02:00
t . Error ( "provider integration key shouldn't have been valid" )
}
providerWithValidOverride := AlertProvider {
2024-12-17 02:32:13 +01:00
DefaultConfig : Config { WebhookURL : "http://example.com" } ,
2022-05-31 04:03:09 +02:00
Overrides : [ ] Override {
{
2024-12-17 02:32:13 +01:00
Config : Config { WebhookURL : "http://example.com" } ,
Group : "group" ,
2022-05-31 04:03:09 +02:00
} ,
} ,
}
2024-12-17 02:32:13 +01:00
if err := providerWithValidOverride . Validate ( ) ; err != nil {
2022-05-31 04:03:09 +02:00
t . Error ( "provider should've been valid" )
}
}
2022-10-05 05:19:55 +02:00
2021-12-03 05:10:21 +01:00
func TestAlertProvider_Send ( t * testing . T ) {
defer client . InjectHTTPClient ( nil )
firstDescription := "description-1"
secondDescription := "description-2"
scenarios := [ ] struct {
Name string
Provider AlertProvider
Alert alert . Alert
Resolved bool
MockRoundTripper test . MockRoundTripper
ExpectedError bool
} {
{
Name : "triggered" ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "http://example.com" } } ,
2021-12-03 05:10:21 +01:00
Alert : alert . Alert { Description : & firstDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : false ,
MockRoundTripper : test . MockRoundTripper ( func ( r * http . Request ) * http . Response {
return & http . Response { StatusCode : http . StatusOK , Body : http . NoBody }
} ) ,
ExpectedError : false ,
} ,
{
Name : "triggered-error" ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "http://example.com" } } ,
2021-12-03 05:10:21 +01:00
Alert : alert . Alert { Description : & firstDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : false ,
MockRoundTripper : test . MockRoundTripper ( func ( r * http . Request ) * http . Response {
return & http . Response { StatusCode : http . StatusInternalServerError , Body : http . NoBody }
} ) ,
ExpectedError : true ,
} ,
{
Name : "resolved" ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "http://example.com" } } ,
2021-12-03 05:10:21 +01:00
Alert : alert . Alert { Description : & secondDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : true ,
MockRoundTripper : test . MockRoundTripper ( func ( r * http . Request ) * http . Response {
return & http . Response { StatusCode : http . StatusOK , Body : http . NoBody }
} ) ,
ExpectedError : false ,
} ,
{
Name : "resolved-error" ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "http://example.com" } } ,
2021-12-03 05:10:21 +01:00
Alert : alert . Alert { Description : & secondDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : true ,
MockRoundTripper : test . MockRoundTripper ( func ( r * http . Request ) * http . Response {
return & http . Response { StatusCode : http . StatusInternalServerError , Body : http . NoBody }
} ) ,
ExpectedError : true ,
} ,
}
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
client . InjectHTTPClient ( & http . Client { Transport : scenario . MockRoundTripper } )
err := scenario . Provider . Send (
2024-05-10 04:56:16 +02:00
& endpoint . Endpoint { Name : "endpoint-name" } ,
2021-12-03 05:10:21 +01:00
& scenario . Alert ,
2024-05-10 04:56:16 +02:00
& endpoint . Result {
ConditionResults : [ ] * endpoint . ConditionResult {
2021-12-03 05:10:21 +01:00
{ Condition : "[CONNECTED] == true" , Success : scenario . Resolved } ,
{ Condition : "[STATUS] == 200" , Success : scenario . Resolved } ,
} ,
} ,
scenario . Resolved ,
)
if scenario . ExpectedError && err == nil {
t . Error ( "expected error, got none" )
}
if ! scenario . ExpectedError && err != nil {
t . Error ( "expected no error, got" , err . Error ( ) )
}
} )
}
}
2021-12-03 03:05:17 +01:00
func TestAlertProvider_buildRequestBody ( t * testing . T ) {
firstDescription := "description-1"
secondDescription := "description-2"
scenarios := [ ] struct {
Name string
Provider AlertProvider
2024-05-10 04:56:16 +02:00
Endpoint endpoint . Endpoint
2021-12-03 03:05:17 +01:00
Alert alert . Alert
2024-04-11 02:46:17 +02:00
NoConditions bool
2021-12-03 03:05:17 +01:00
Resolved bool
ExpectedBody string
} {
{
Name : "triggered" ,
Provider : AlertProvider { } ,
2024-05-10 04:56:16 +02:00
Endpoint : endpoint . Endpoint { Name : "name" } ,
2021-12-03 03:05:17 +01:00
Alert : alert . Alert { Description : & firstDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : false ,
2022-10-20 22:50:21 +02:00
ExpectedBody : "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":x: - `[CONNECTED] == true`\\n:x: - `[STATUS] == 200`\\n\",\"short\":false}]}]}" ,
2021-12-12 22:44:30 +01:00
} ,
{
Name : "triggered-with-group" ,
Provider : AlertProvider { } ,
2024-05-10 04:56:16 +02:00
Endpoint : endpoint . Endpoint { Name : "name" , Group : "group" } ,
2021-12-12 22:44:30 +01:00
Alert : alert . Alert { Description : & firstDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : false ,
2022-10-20 22:50:21 +02:00
ExpectedBody : "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *group/name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":x: - `[CONNECTED] == true`\\n:x: - `[STATUS] == 200`\\n\",\"short\":false}]}]}" ,
2021-12-03 03:05:17 +01:00
} ,
2024-04-11 02:46:17 +02:00
{
Name : "triggered-with-no-conditions" ,
NoConditions : true ,
Provider : AlertProvider { } ,
2024-05-10 04:56:16 +02:00
Endpoint : endpoint . Endpoint { Name : "name" } ,
2024-04-11 02:46:17 +02:00
Alert : alert . Alert { Description : & firstDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : false ,
ExpectedBody : "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\"}]}" ,
} ,
2021-12-03 03:05:17 +01:00
{
Name : "resolved" ,
Provider : AlertProvider { } ,
2024-05-10 04:56:16 +02:00
Endpoint : endpoint . Endpoint { Name : "name" } ,
2021-12-12 22:44:30 +01:00
Alert : alert . Alert { Description : & secondDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : true ,
2022-10-20 22:50:21 +02:00
ExpectedBody : "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been resolved after passing successfully 5 time(s) in a row:\\n\\u003e description-2\",\"short\":false,\"color\":\"#36A64F\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":white_check_mark: - `[CONNECTED] == true`\\n:white_check_mark: - `[STATUS] == 200`\\n\",\"short\":false}]}]}" ,
2021-12-12 22:44:30 +01:00
} ,
{
Name : "resolved-with-group" ,
Provider : AlertProvider { } ,
2024-05-10 04:56:16 +02:00
Endpoint : endpoint . Endpoint { Name : "name" , Group : "group" } ,
2021-12-03 03:05:17 +01:00
Alert : alert . Alert { Description : & secondDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : true ,
2022-10-20 22:50:21 +02:00
ExpectedBody : "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *group/name* has been resolved after passing successfully 5 time(s) in a row:\\n\\u003e description-2\",\"short\":false,\"color\":\"#36A64F\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":white_check_mark: - `[CONNECTED] == true`\\n:white_check_mark: - `[STATUS] == 200`\\n\",\"short\":false}]}]}" ,
2021-12-03 03:05:17 +01:00
} ,
2020-10-22 03:18:06 +02:00
}
2021-12-03 03:05:17 +01:00
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2024-05-10 04:56:16 +02:00
var conditionResults [ ] * endpoint . ConditionResult
2024-04-11 02:46:17 +02:00
if ! scenario . NoConditions {
2024-05-10 04:56:16 +02:00
conditionResults = [ ] * endpoint . ConditionResult {
2024-04-11 02:46:17 +02:00
{ Condition : "[CONNECTED] == true" , Success : scenario . Resolved } ,
{ Condition : "[STATUS] == 200" , Success : scenario . Resolved } ,
}
}
2021-12-03 03:05:17 +01:00
body := scenario . Provider . buildRequestBody (
2021-12-12 22:44:30 +01:00
& scenario . Endpoint ,
2021-12-03 03:05:17 +01:00
& scenario . Alert ,
2024-05-10 04:56:16 +02:00
& endpoint . Result {
2024-04-11 02:46:17 +02:00
ConditionResults : conditionResults ,
2021-12-03 03:05:17 +01:00
} ,
scenario . Resolved ,
)
2022-10-20 20:45:42 +02:00
if string ( body ) != scenario . ExpectedBody {
2022-10-20 22:50:21 +02:00
t . Errorf ( "expected:\n%s\ngot:\n%s" , scenario . ExpectedBody , body )
2021-12-03 03:05:17 +01:00
}
out := make ( map [ string ] interface { } )
2022-10-20 20:45:42 +02:00
if err := json . Unmarshal ( body , & out ) ; err != nil {
2021-12-03 03:05:17 +01:00
t . Error ( "expected body to be valid JSON, got error:" , err . Error ( ) )
}
} )
2021-02-20 01:06:20 +01:00
}
2020-10-22 03:18:06 +02:00
}
2021-12-03 04:15:51 +01:00
func TestAlertProvider_GetDefaultAlert ( t * testing . T ) {
2024-02-08 02:09:45 +01:00
if ( & AlertProvider { DefaultAlert : & alert . Alert { } } ) . GetDefaultAlert ( ) == nil {
2021-12-03 04:15:51 +01:00
t . Error ( "expected default alert to be not nil" )
}
2024-02-08 02:09:45 +01:00
if ( & AlertProvider { DefaultAlert : nil } ) . GetDefaultAlert ( ) != nil {
2021-12-03 04:15:51 +01:00
t . Error ( "expected default alert to be nil" )
}
}
2022-05-31 04:03:09 +02:00
2024-12-17 02:32:13 +01:00
func TestAlertProvider_GetConfig ( t * testing . T ) {
scenarios := [ ] struct {
2022-05-31 04:03:09 +02:00
Name string
Provider AlertProvider
InputGroup string
2024-12-17 02:32:13 +01:00
InputAlert alert . Alert
ExpectedOutput Config
2022-05-31 04:03:09 +02:00
} {
{
Name : "provider-no-override-specify-no-group-should-default" ,
Provider : AlertProvider {
2024-12-17 02:32:13 +01:00
DefaultConfig : Config { WebhookURL : "http://example.com" } ,
Overrides : nil ,
2022-05-31 04:03:09 +02:00
} ,
InputGroup : "" ,
2024-12-17 02:32:13 +01:00
InputAlert : alert . Alert { } ,
ExpectedOutput : Config { WebhookURL : "http://example.com" } ,
2022-05-31 04:03:09 +02:00
} ,
{
Name : "provider-no-override-specify-group-should-default" ,
Provider : AlertProvider {
2024-12-17 02:32:13 +01:00
DefaultConfig : Config { WebhookURL : "http://example.com" } ,
Overrides : nil ,
2022-05-31 04:03:09 +02:00
} ,
InputGroup : "group" ,
2024-12-17 02:32:13 +01:00
InputAlert : alert . Alert { } ,
ExpectedOutput : Config { WebhookURL : "http://example.com" } ,
2022-05-31 04:03:09 +02:00
} ,
{
Name : "provider-with-override-specify-no-group-should-default" ,
Provider : AlertProvider {
2024-12-17 02:32:13 +01:00
DefaultConfig : Config { WebhookURL : "http://example.com" } ,
2022-05-31 04:03:09 +02:00
Overrides : [ ] Override {
{
2024-12-17 02:32:13 +01:00
Group : "group" ,
Config : Config { WebhookURL : "http://example01.com" } ,
2022-05-31 04:03:09 +02:00
} ,
} ,
} ,
InputGroup : "" ,
2024-12-17 02:32:13 +01:00
InputAlert : alert . Alert { } ,
ExpectedOutput : Config { WebhookURL : "http://example.com" } ,
2022-05-31 04:03:09 +02:00
} ,
{
Name : "provider-with-override-specify-group-should-override" ,
Provider : AlertProvider {
2024-12-17 02:32:13 +01:00
DefaultConfig : Config { WebhookURL : "http://example.com" } ,
Overrides : [ ] Override {
{
Group : "group" ,
Config : Config { WebhookURL : "http://group-example.com" } ,
} ,
} ,
} ,
InputGroup : "group" ,
InputAlert : alert . Alert { } ,
ExpectedOutput : Config { WebhookURL : "http://group-example.com" } ,
} ,
{
Name : "provider-with-group-override-and-alert-override--alert-override-should-take-precedence" ,
Provider : AlertProvider {
DefaultConfig : Config { WebhookURL : "http://example.com" } ,
2022-05-31 04:03:09 +02:00
Overrides : [ ] Override {
{
2024-12-17 02:32:13 +01:00
Group : "group" ,
Config : Config { WebhookURL : "http://group-example.com" } ,
2022-05-31 04:03:09 +02:00
} ,
} ,
} ,
InputGroup : "group" ,
2024-12-17 02:32:13 +01:00
InputAlert : alert . Alert { ProviderOverride : map [ string ] any { "webhook-url" : "http://alert-example.com" } } ,
ExpectedOutput : Config { WebhookURL : "http://alert-example.com" } ,
2022-05-31 04:03:09 +02:00
} ,
}
2024-12-17 02:32:13 +01:00
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
got , err := scenario . Provider . GetConfig ( scenario . InputGroup , & scenario . InputAlert )
if err != nil {
t . Fatalf ( "unexpected error: %s" , err )
}
if got . WebhookURL != scenario . ExpectedOutput . WebhookURL {
t . Errorf ( "expected webhook URL to be %s, got %s" , scenario . ExpectedOutput . WebhookURL , got . WebhookURL )
}
// Test ValidateOverrides as well, since it really just calls GetConfig
if err = scenario . Provider . ValidateOverrides ( scenario . InputGroup , & scenario . InputAlert ) ; err != nil {
t . Errorf ( "unexpected error: %s" , err )
2022-05-31 04:03:09 +02:00
}
} )
}
}