2023-05-31 03:57:15 +02:00
package gitlab
import (
"net/http"
"strings"
"testing"
"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"
2023-05-31 03:57:15 +02:00
"github.com/TwiN/gatus/v5/test"
)
2024-12-17 02:32:13 +01:00
func TestAlertProvider_Validate ( t * testing . T ) {
2023-05-31 03:57:15 +02:00
scenarios := [ ] struct {
2024-12-17 02:32:13 +01:00
Name string
Provider AlertProvider
ExpectedError bool
2023-05-31 03:57:15 +02:00
} {
{
2024-12-17 02:32:13 +01:00
Name : "invalid" ,
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "" , AuthorizationKey : "" } } ,
ExpectedError : true ,
2023-05-31 03:57:15 +02:00
} ,
{
2024-12-17 02:32:13 +01:00
Name : "missing-webhook-url" ,
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "" , AuthorizationKey : "12345" } } ,
ExpectedError : true ,
2023-05-31 03:57:15 +02:00
} ,
{
2024-12-17 02:32:13 +01:00
Name : "missing-authorization-key" ,
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "https://gitlab.com/whatever/text/alerts/notify/gatus/xxxxxxxxxxxxxxxx.json" , AuthorizationKey : "" } } ,
ExpectedError : true ,
2023-05-31 03:57:15 +02:00
} ,
{
2024-12-17 02:32:13 +01:00
Name : "invalid-url" ,
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : " http://foo.com" , AuthorizationKey : "12345" } } ,
ExpectedError : true ,
2023-05-31 03:57:15 +02:00
} ,
}
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2024-12-17 02:32:13 +01:00
err := scenario . Provider . Validate ( )
if scenario . ExpectedError && err == nil {
t . Error ( "expected error, got none" )
}
if ! scenario . ExpectedError && err != nil && ! strings . Contains ( err . Error ( ) , "user does not exist" ) && ! strings . Contains ( err . Error ( ) , "no such host" ) {
t . Error ( "expected no error, got" , err . Error ( ) )
2023-05-31 03:57:15 +02: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-error" ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "https://gitlab.com/hlidotbe/text/alerts/notify/gatus/xxxxxxxxxxxxxxxx.json" , AuthorizationKey : "12345" } } ,
2023-05-31 03:57:15 +02:00
Alert : alert . Alert { Description : & firstDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : false ,
ExpectedError : false ,
MockRoundTripper : test . MockRoundTripper ( func ( r * http . Request ) * http . Response {
return & http . Response { StatusCode : http . StatusOK , Body : http . NoBody }
} ) ,
} ,
{
Name : "resolved-error" ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "https://gitlab.com/hlidotbe/text/alerts/notify/gatus/xxxxxxxxxxxxxxxx.json" , AuthorizationKey : "12345" } } ,
2023-05-31 03:57:15 +02:00
Alert : alert . Alert { Description : & secondDescription , SuccessThreshold : 5 , FailureThreshold : 3 } ,
Resolved : true ,
ExpectedError : false ,
MockRoundTripper : test . MockRoundTripper ( func ( r * http . Request ) * http . Response {
return & http . Response { StatusCode : http . StatusOK , Body : http . NoBody }
} ) ,
} ,
}
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" , Group : "endpoint-group" } ,
2023-05-31 03:57:15 +02:00
& scenario . Alert ,
2024-05-10 04:56:16 +02:00
& endpoint . Result {
ConditionResults : [ ] * endpoint . ConditionResult {
2023-05-31 03:57:15 +02: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 ( ) )
}
} )
}
}
func TestAlertProvider_buildAlertBody ( t * testing . T ) {
firstDescription := "description-1"
scenarios := [ ] struct {
Name string
2024-05-10 04:56:16 +02:00
Endpoint endpoint . Endpoint
2023-05-31 03:57:15 +02:00
Provider AlertProvider
Alert alert . Alert
ExpectedBody string
} {
{
Name : "triggered" ,
2024-05-10 04:56:16 +02:00
Endpoint : endpoint . Endpoint { Name : "endpoint-name" , URL : "https://example.org" } ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "https://gitlab.com/hlidotbe/text/alerts/notify/gatus/xxxxxxxxxxxxxxxx.json" , AuthorizationKey : "12345" } } ,
2023-05-31 03:57:15 +02:00
Alert : alert . Alert { Description : & firstDescription , FailureThreshold : 3 } ,
2024-12-17 02:32:13 +01:00
ExpectedBody : "{\"title\":\"alert(gatus): endpoint-name\",\"description\":\"An alert for *endpoint-name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\\n\\n## Condition results\\n- :white_check_mark: - `[CONNECTED] == true`\\n- :x: - `[STATUS] == 200`\\n\",\"start_time\":\"0001-01-01T00:00:00Z\",\"service\":\"endpoint-name\",\"monitoring_tool\":\"gatus\",\"hosts\":\"https://example.org\",\"severity\":\"critical\"}" ,
2023-05-31 03:57:15 +02:00
} ,
{
Name : "no-description" ,
2024-05-10 04:56:16 +02:00
Endpoint : endpoint . Endpoint { Name : "endpoint-name" , URL : "https://example.org" } ,
2024-12-17 02:32:13 +01:00
Provider : AlertProvider { DefaultConfig : Config { WebhookURL : "https://gitlab.com/hlidotbe/text/alerts/notify/gatus/xxxxxxxxxxxxxxxx.json" , AuthorizationKey : "12345" } } ,
2023-05-31 03:57:15 +02:00
Alert : alert . Alert { FailureThreshold : 10 } ,
2024-12-17 02:32:13 +01:00
ExpectedBody : "{\"title\":\"alert(gatus): endpoint-name\",\"description\":\"An alert for *endpoint-name* has been triggered due to having failed 10 time(s) in a row\\n\\n## Condition results\\n- :white_check_mark: - `[CONNECTED] == true`\\n- :x: - `[STATUS] == 200`\\n\",\"start_time\":\"0001-01-01T00:00:00Z\",\"service\":\"endpoint-name\",\"monitoring_tool\":\"gatus\",\"hosts\":\"https://example.org\",\"severity\":\"critical\"}" ,
2023-05-31 03:57:15 +02:00
} ,
}
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2024-12-17 02:32:13 +01:00
cfg , err := scenario . Provider . GetConfig ( "" , & scenario . Alert )
if err != nil {
t . Error ( "expected no error, got" , err . Error ( ) )
}
2023-05-31 03:57:15 +02:00
body := scenario . Provider . buildAlertBody (
2024-12-17 02:32:13 +01:00
cfg ,
2023-05-31 03:57:15 +02:00
& scenario . Endpoint ,
& scenario . Alert ,
2024-05-10 04:56:16 +02:00
& endpoint . Result {
ConditionResults : [ ] * endpoint . ConditionResult {
2023-05-31 03:57:15 +02:00
{ Condition : "[CONNECTED] == true" , Success : true } ,
{ Condition : "[STATUS] == 200" , Success : false } ,
} ,
} ,
false ,
)
if strings . TrimSpace ( string ( body ) ) != strings . TrimSpace ( scenario . ExpectedBody ) {
t . Errorf ( "expected:\n%s\ngot:\n%s" , scenario . ExpectedBody , body )
}
} )
}
}
func TestAlertProvider_GetDefaultAlert ( t * testing . T ) {
2024-02-08 02:09:45 +01:00
if ( & AlertProvider { DefaultAlert : & alert . Alert { } } ) . GetDefaultAlert ( ) == nil {
2023-05-31 03:57:15 +02:00
t . Error ( "expected default alert to be not nil" )
}
2024-02-08 02:09:45 +01:00
if ( & AlertProvider { DefaultAlert : nil } ) . GetDefaultAlert ( ) != nil {
2023-05-31 03:57:15 +02:00
t . Error ( "expected default alert to be nil" )
}
}
2024-12-17 02:32:13 +01:00
func TestAlertProvider_GetConfig ( t * testing . T ) {
scenarios := [ ] struct {
Name string
Provider AlertProvider
InputAlert alert . Alert
ExpectedOutput Config
} {
{
Name : "provider-no-override-should-default" ,
Provider : AlertProvider {
DefaultConfig : Config { WebhookURL : "https://github.com/TwiN/test" , AuthorizationKey : "12345" } ,
} ,
InputAlert : alert . Alert { } ,
ExpectedOutput : Config { WebhookURL : "https://github.com/TwiN/test" , AuthorizationKey : "12345" , Severity : DefaultSeverity , MonitoringTool : DefaultMonitoringTool } ,
} ,
{
Name : "provider-with-alert-override" ,
Provider : AlertProvider {
DefaultConfig : Config { WebhookURL : "https://github.com/TwiN/test" , AuthorizationKey : "12345" } ,
} ,
InputAlert : alert . Alert { ProviderOverride : map [ string ] any { "repository-url" : "https://github.com/TwiN/alert-test" , "authorization-key" : "54321" , "severity" : "info" , "monitoring-tool" : "not-gatus" , "environment-name" : "prod" , "service" : "example" } } ,
ExpectedOutput : Config { WebhookURL : "https://github.com/TwiN/test" , AuthorizationKey : "54321" , Severity : "info" , MonitoringTool : "not-gatus" , EnvironmentName : "prod" , Service : "example" } ,
} ,
}
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
got , err := scenario . Provider . GetConfig ( "" , & scenario . InputAlert )
if err != nil && ! strings . Contains ( err . Error ( ) , "user does not exist" ) && ! strings . Contains ( err . Error ( ) , "no such host" ) {
t . Fatalf ( "unexpected error: %s" , err )
}
if got . WebhookURL != scenario . ExpectedOutput . WebhookURL {
t . Errorf ( "expected repository URL %s, got %s" , scenario . ExpectedOutput . WebhookURL , got . WebhookURL )
}
if got . AuthorizationKey != scenario . ExpectedOutput . AuthorizationKey {
t . Errorf ( "expected AuthorizationKey %s, got %s" , scenario . ExpectedOutput . AuthorizationKey , got . AuthorizationKey )
}
if got . Severity != scenario . ExpectedOutput . Severity {
t . Errorf ( "expected Severity %s, got %s" , scenario . ExpectedOutput . Severity , got . Severity )
}
if got . MonitoringTool != scenario . ExpectedOutput . MonitoringTool {
t . Errorf ( "expected MonitoringTool %s, got %s" , scenario . ExpectedOutput . MonitoringTool , got . MonitoringTool )
}
if got . EnvironmentName != scenario . ExpectedOutput . EnvironmentName {
t . Errorf ( "expected EnvironmentName %s, got %s" , scenario . ExpectedOutput . EnvironmentName , got . EnvironmentName )
}
if got . Service != scenario . ExpectedOutput . Service {
t . Errorf ( "expected Service %s, got %s" , scenario . ExpectedOutput . Service , got . Service )
}
// Test ValidateOverrides as well, since it really just calls GetConfig
if err = scenario . Provider . ValidateOverrides ( "" , & scenario . InputAlert ) ; err != nil {
t . Errorf ( "unexpected error: %s" , err )
}
} )
}
}