From 06fdd0e7a86cdfe0209f626a3e94226703d3336a Mon Sep 17 00:00:00 2001 From: henrygd Date: Tue, 7 Apr 2026 14:26:36 -0400 Subject: [PATCH] refactor(hub,alerts): move api functions/tests to alerts_api.go --- internal/alerts/alerts.go | 15 -- internal/alerts/alerts_api.go | 16 ++ internal/alerts/alerts_api_test.go | 368 +++++++++++++++++++++++++++++ internal/alerts/alerts_test.go | 355 ---------------------------- 4 files changed, 384 insertions(+), 370 deletions(-) create mode 100644 internal/alerts/alerts_api_test.go diff --git a/internal/alerts/alerts.go b/internal/alerts/alerts.go index 7506f774..5918cfd9 100644 --- a/internal/alerts/alerts.go +++ b/internal/alerts/alerts.go @@ -302,21 +302,6 @@ func (am *AlertManager) SendShoutrrrAlert(notificationUrl, title, message, link, return nil } -func (am *AlertManager) SendTestNotification(e *core.RequestEvent) error { - var data struct { - URL string `json:"url"` - } - err := e.BindBody(&data) - if err != nil || data.URL == "" { - return e.BadRequestError("URL is required", err) - } - err = am.SendShoutrrrAlert(data.URL, "Test Alert", "This is a notification from Beszel.", am.hub.Settings().Meta.AppURL, "View Beszel") - if err != nil { - return e.JSON(200, map[string]string{"err": err.Error()}) - } - return e.JSON(200, map[string]bool{"err": false}) -} - // setAlertTriggered updates the "triggered" status of an alert record in the database func (am *AlertManager) setAlertTriggered(alert CachedAlertData, triggered bool) error { alertRecord, err := am.hub.FindRecordById("alerts", alert.Id) diff --git a/internal/alerts/alerts_api.go b/internal/alerts/alerts_api.go index 972f01bf..7138f537 100644 --- a/internal/alerts/alerts_api.go +++ b/internal/alerts/alerts_api.go @@ -117,3 +117,19 @@ func DeleteUserAlerts(e *core.RequestEvent) error { return e.JSON(http.StatusOK, map[string]any{"success": true, "count": numDeleted}) } + +// SendTestNotification handles API request to send a test notification to a specified Shoutrrr URL +func (am *AlertManager) SendTestNotification(e *core.RequestEvent) error { + var data struct { + URL string `json:"url"` + } + err := e.BindBody(&data) + if err != nil || data.URL == "" { + return e.BadRequestError("URL is required", err) + } + err = am.SendShoutrrrAlert(data.URL, "Test Alert", "This is a notification from Beszel.", am.hub.Settings().Meta.AppURL, "View Beszel") + if err != nil { + return e.JSON(200, map[string]string{"err": err.Error()}) + } + return e.JSON(200, map[string]bool{"err": false}) +} diff --git a/internal/alerts/alerts_api_test.go b/internal/alerts/alerts_api_test.go new file mode 100644 index 00000000..954fb456 --- /dev/null +++ b/internal/alerts/alerts_api_test.go @@ -0,0 +1,368 @@ +//go:build testing + +package alerts_test + +import ( + "bytes" + "encoding/json" + "io" + "net/http" + "strings" + "testing" + + beszelTests "github.com/henrygd/beszel/internal/tests" + pbTests "github.com/pocketbase/pocketbase/tests" + + "github.com/pocketbase/dbx" + "github.com/pocketbase/pocketbase/core" + + "github.com/stretchr/testify/assert" +) + +// marshal to json and return an io.Reader (for use in ApiScenario.Body) +func jsonReader(v any) io.Reader { + data, err := json.Marshal(v) + if err != nil { + panic(err) + } + return bytes.NewReader(data) +} + +func TestUserAlertsApi(t *testing.T) { + hub, _ := beszelTests.NewTestHub(t.TempDir()) + defer hub.Cleanup() + + hub.StartHub() + + user1, _ := beszelTests.CreateUser(hub, "alertstest@example.com", "password") + user1Token, _ := user1.NewAuthToken() + + user2, _ := beszelTests.CreateUser(hub, "alertstest2@example.com", "password") + user2Token, _ := user2.NewAuthToken() + + system1, _ := beszelTests.CreateRecord(hub, "systems", map[string]any{ + "name": "system1", + "users": []string{user1.Id}, + "host": "127.0.0.1", + }) + + system2, _ := beszelTests.CreateRecord(hub, "systems", map[string]any{ + "name": "system2", + "users": []string{user1.Id, user2.Id}, + "host": "127.0.0.2", + }) + + userRecords, _ := hub.CountRecords("users") + assert.EqualValues(t, 2, userRecords, "all users should be created") + + systemRecords, _ := hub.CountRecords("systems") + assert.EqualValues(t, 2, systemRecords, "all systems should be created") + + testAppFactory := func(t testing.TB) *pbTests.TestApp { + return hub.TestApp + } + + scenarios := []beszelTests.ApiScenario{ + // { + // Name: "GET not implemented - returns index", + // Method: http.MethodGet, + // URL: "/api/beszel/user-alerts", + // ExpectedStatus: 200, + // ExpectedContent: []string{"