Skip to content

Commit 94cc3fa

Browse files
authored
Merge pull request #62 from teknologi-umum/test/backend/more-tests
test(backend): Add comprehensive integration tests
2 parents b9c9f31 + b37a997 commit 94cc3fa

14 files changed

+1711
-132
lines changed

backend/alerter_discord_test.go

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package main_test
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
"net/http/httptest"
8+
"testing"
9+
"time"
10+
11+
main "semyi"
12+
"semyi/testutils"
13+
14+
"github.com/getsentry/sentry-go"
15+
)
16+
17+
func TestDiscordProvider_Send(t *testing.T) {
18+
// Create a mock HTTP server
19+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
20+
// Verify request method and content type
21+
testutils.AssertEqual(t, http.MethodPost, r.Method, "Expected POST method")
22+
testutils.AssertEqual(t, "application/json", r.Header.Get("Content-Type"), "Expected JSON content type")
23+
24+
// Parse the request body
25+
var payload map[string]interface{}
26+
err := json.NewDecoder(r.Body).Decode(&payload)
27+
testutils.AssertNoError(t, err, "Failed to decode request body")
28+
29+
// Verify embeds structure
30+
embeds := payload["embeds"].([]interface{})
31+
testutils.AssertEqual(t, 1, len(embeds), "Expected 1 embed")
32+
33+
// Verify embed content
34+
embed := embeds[0].(map[string]interface{})
35+
testutils.AssertEqual(t, "✅ Service Up", embed["title"], "Expected success indicator")
36+
testutils.AssertEqual(t, float64(0x00FF00), embed["color"], "Expected green color for success")
37+
38+
// Verify fields
39+
fields := embed["fields"].([]interface{})
40+
testutils.AssertEqual(t, 5, len(fields), "Expected 5 fields")
41+
42+
// Verify field values
43+
fieldMap := make(map[string]interface{})
44+
for _, f := range fields {
45+
field := f.(map[string]interface{})
46+
fieldMap[field["name"].(string)] = field["value"]
47+
}
48+
49+
testutils.AssertEqual(t, "test-monitor-1", fieldMap["Monitor ID"], "Expected correct monitor ID")
50+
testutils.AssertEqual(t, "Test Monitor", fieldMap["Monitor Name"], "Expected correct monitor name")
51+
testutils.AssertEqual(t, "200", fieldMap["Status Code"], "Expected correct status code")
52+
testutils.AssertEqual(t, "100 ms", fieldMap["Latency"], "Expected correct latency")
53+
54+
// Send success response
55+
w.WriteHeader(http.StatusOK)
56+
}))
57+
defer server.Close()
58+
59+
// Setup context with Sentry
60+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
61+
defer cancel()
62+
ctx = sentry.SetHubOnContext(ctx, sentry.CurrentHub())
63+
64+
// Create Discord provider
65+
provider := main.NewDiscordAlertProvider(main.DiscordProviderConfig{
66+
WebhookURL: server.URL,
67+
HttpClient: server.Client(),
68+
})
69+
70+
// Create test alert message
71+
msg := main.AlertMessage{
72+
Success: true,
73+
StatusCode: 200,
74+
Timestamp: time.Now(),
75+
MonitorID: "test-monitor-1",
76+
MonitorName: "Test Monitor",
77+
Latency: 100,
78+
}
79+
80+
// Send the alert
81+
err := provider.Send(ctx, msg)
82+
testutils.AssertNoError(t, err, "Failed to send Discord alert")
83+
}
84+
85+
func TestDiscordProvider_Send_ErrorCases(t *testing.T) {
86+
// Setup context with Sentry
87+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
88+
defer cancel()
89+
ctx = sentry.SetHubOnContext(ctx, sentry.CurrentHub())
90+
91+
// Test case: Empty webhook URL
92+
provider := main.NewDiscordAlertProvider(main.DiscordProviderConfig{
93+
WebhookURL: "",
94+
})
95+
96+
msg := main.AlertMessage{
97+
Success: true,
98+
StatusCode: 200,
99+
Timestamp: time.Now(),
100+
MonitorID: "test-monitor-1",
101+
MonitorName: "Test Monitor",
102+
Latency: 100,
103+
}
104+
105+
err := provider.Send(ctx, msg)
106+
testutils.AssertError(t, err, "Expected error for empty webhook URL")
107+
108+
// Test case: Server returns error status
109+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
110+
w.WriteHeader(http.StatusInternalServerError)
111+
}))
112+
defer server.Close()
113+
114+
provider = main.NewDiscordAlertProvider(main.DiscordProviderConfig{
115+
WebhookURL: server.URL,
116+
HttpClient: server.Client(),
117+
})
118+
119+
err = provider.Send(ctx, msg)
120+
testutils.AssertError(t, err, "Expected error for server error status")
121+
}
122+
123+
func TestDiscordProvider_Send_Timeout(t *testing.T) {
124+
// Setup context with Sentry
125+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
126+
defer cancel()
127+
ctx = sentry.SetHubOnContext(ctx, sentry.CurrentHub())
128+
129+
// Create a slow server that times out
130+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
131+
time.Sleep(5 * time.Second) // Longer than the client timeout
132+
w.WriteHeader(http.StatusOK)
133+
}))
134+
defer server.Close()
135+
136+
// Create Discord provider with short timeout
137+
client := &http.Client{Timeout: 1 * time.Second}
138+
provider := main.NewDiscordAlertProvider(main.DiscordProviderConfig{
139+
WebhookURL: server.URL,
140+
HttpClient: client,
141+
})
142+
143+
msg := main.AlertMessage{
144+
Success: true,
145+
StatusCode: 200,
146+
Timestamp: time.Now(),
147+
MonitorID: "test-monitor-1",
148+
MonitorName: "Test Monitor",
149+
Latency: 100,
150+
}
151+
152+
err := provider.Send(ctx, msg)
153+
testutils.AssertError(t, err, "Expected timeout error")
154+
}

backend/alerter_http_test.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package main_test
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
"net/http/httptest"
8+
"testing"
9+
"time"
10+
11+
main "semyi"
12+
"semyi/testutils"
13+
14+
"github.com/getsentry/sentry-go"
15+
)
16+
17+
func TestHTTPProvider_Send(t *testing.T) {
18+
// Create a mock HTTP server
19+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
20+
// Verify request method and content type
21+
testutils.AssertEqual(t, http.MethodPost, r.Method, "Expected POST method")
22+
testutils.AssertEqual(t, "application/json", r.Header.Get("Content-Type"), "Expected JSON content type")
23+
24+
// Parse the request body
25+
var payload map[string]interface{}
26+
err := json.NewDecoder(r.Body).Decode(&payload)
27+
testutils.AssertNoError(t, err, "Failed to decode request body")
28+
29+
// Verify payload fields
30+
testutils.AssertEqual(t, true, payload["success"], "Expected success to be true")
31+
testutils.AssertEqual(t, "test-monitor-1", payload["monitor_id"], "Expected correct monitor ID")
32+
testutils.AssertEqual(t, "Test Monitor", payload["monitor_name"], "Expected correct monitor name")
33+
testutils.AssertEqual(t, float64(200), payload["status_code"], "Expected correct status code")
34+
testutils.AssertEqual(t, float64(100), payload["latency"], "Expected correct latency")
35+
36+
// Verify timestamp format
37+
_, err = time.Parse(time.RFC3339, payload["timestamp"].(string))
38+
testutils.AssertNoError(t, err, "Expected valid RFC3339 timestamp")
39+
40+
// Send success response
41+
w.WriteHeader(http.StatusOK)
42+
}))
43+
defer server.Close()
44+
45+
// Setup context with Sentry
46+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
47+
defer cancel()
48+
ctx = sentry.SetHubOnContext(ctx, sentry.CurrentHub())
49+
50+
// Create HTTP provider
51+
provider := main.NewHTTPAlertProvider(main.HTTPProviderConfig{
52+
WebhookURL: server.URL,
53+
HttpClient: server.Client(),
54+
})
55+
56+
// Create test alert message
57+
msg := main.AlertMessage{
58+
Success: true,
59+
StatusCode: 200,
60+
Timestamp: time.Now(),
61+
MonitorID: "test-monitor-1",
62+
MonitorName: "Test Monitor",
63+
Latency: 100,
64+
}
65+
66+
// Send the alert
67+
err := provider.Send(ctx, msg)
68+
testutils.AssertNoError(t, err, "Failed to send HTTP alert")
69+
}
70+
71+
func TestHTTPProvider_Send_ErrorCases(t *testing.T) {
72+
// Test case: Empty webhook URL
73+
provider := main.NewHTTPAlertProvider(main.HTTPProviderConfig{
74+
WebhookURL: "",
75+
})
76+
77+
msg := main.AlertMessage{
78+
Success: true,
79+
StatusCode: 200,
80+
Timestamp: time.Now(),
81+
MonitorID: "test-monitor-1",
82+
MonitorName: "Test Monitor",
83+
Latency: 100,
84+
}
85+
86+
err := provider.Send(context.Background(), msg)
87+
testutils.AssertError(t, err, "Expected error for empty webhook URL")
88+
89+
// Test case: Invalid webhook URL
90+
provider = main.NewHTTPAlertProvider(main.HTTPProviderConfig{
91+
WebhookURL: "invalid-url",
92+
})
93+
94+
err = provider.Send(context.Background(), msg)
95+
testutils.AssertError(t, err, "Expected error for invalid webhook URL")
96+
97+
// Test case: Server returns error status
98+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
99+
w.WriteHeader(http.StatusInternalServerError)
100+
}))
101+
defer server.Close()
102+
103+
provider = main.NewHTTPAlertProvider(main.HTTPProviderConfig{
104+
WebhookURL: server.URL,
105+
HttpClient: server.Client(),
106+
})
107+
108+
err = provider.Send(context.Background(), msg)
109+
testutils.AssertError(t, err, "Expected error for server error status")
110+
}
111+
112+
func TestHTTPProvider_Send_Timeout(t *testing.T) {
113+
// Create a slow server that times out
114+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
115+
time.Sleep(5 * time.Second) // Longer than the client timeout
116+
w.WriteHeader(http.StatusOK)
117+
}))
118+
defer server.Close()
119+
120+
// Create HTTP provider with short timeout
121+
client := &http.Client{Timeout: 1 * time.Second}
122+
provider := main.NewHTTPAlertProvider(main.HTTPProviderConfig{
123+
WebhookURL: server.URL,
124+
HttpClient: client,
125+
})
126+
127+
msg := main.AlertMessage{
128+
Success: true,
129+
StatusCode: 200,
130+
Timestamp: time.Now(),
131+
MonitorID: "test-monitor-1",
132+
MonitorName: "Test Monitor",
133+
Latency: 100,
134+
}
135+
136+
err := provider.Send(context.Background(), msg)
137+
testutils.AssertError(t, err, "Expected timeout error")
138+
}

0 commit comments

Comments
 (0)