fixed numerous linter issues
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Package handlers implements HTTP request handlers for the API.
|
||||
package handlers
|
||||
|
||||
import (
|
||||
@@ -14,14 +15,17 @@ import (
|
||||
|
||||
var ethAddressRe = regexp.MustCompile(`^0x[a-fA-F0-9]{40}$`)
|
||||
|
||||
// AddressHandler handles HTTP requests for address management.
|
||||
type AddressHandler struct {
|
||||
addresses *models.AddressModel
|
||||
}
|
||||
|
||||
// NewAddressHandler creates a new AddressHandler.
|
||||
func NewAddressHandler(addresses *models.AddressModel) *AddressHandler {
|
||||
return &AddressHandler{addresses: addresses}
|
||||
}
|
||||
|
||||
// Create handles POST requests to add a new tracked address.
|
||||
func (h *AddressHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
|
||||
@@ -32,16 +36,19 @@ func (h *AddressHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
log.Printf("Failed to decode address request body: %v", err)
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid request body")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if body.Address == "" {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Address is required")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !ethAddressRe.MatchString(body.Address) {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid Ethereum address format")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -51,10 +58,12 @@ func (h *AddressHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "23505") || strings.Contains(err.Error(), "unique") {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "You are already tracking this address")
|
||||
|
||||
return
|
||||
}
|
||||
log.Printf("Error creating address: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to create address")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -62,6 +71,7 @@ func (h *AddressHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusCreated, addr)
|
||||
}
|
||||
|
||||
// List handles GET requests to list all tracked addresses for the current user.
|
||||
func (h *AddressHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
log.Printf("User %s listing addresses", userID)
|
||||
@@ -70,6 +80,7 @@ func (h *AddressHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("Error listing addresses: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to list addresses")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -81,11 +92,13 @@ func (h *AddressHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, addresses)
|
||||
}
|
||||
|
||||
// Remove handles DELETE requests to remove a tracked address.
|
||||
func (h *AddressHandler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
addressID, ok := parseIntParam(r.PathValue("addressId"))
|
||||
if !ok {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid address ID")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -95,12 +108,14 @@ func (h *AddressHandler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("Error deleting address: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to delete address")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !deleted {
|
||||
log.Printf("Address %d not found or not owned by user", addressID)
|
||||
writeError(w, http.StatusNotFound, "NOT_FOUND", "Address not found")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,17 @@ import (
|
||||
"github.com/kjannette/koin-ping/backend-go/internal/models"
|
||||
)
|
||||
|
||||
// AlertEventHandler handles HTTP requests for alert event history.
|
||||
type AlertEventHandler struct {
|
||||
alertEvents *models.AlertEventModel
|
||||
}
|
||||
|
||||
// NewAlertEventHandler creates a new AlertEventHandler.
|
||||
func NewAlertEventHandler(alertEvents *models.AlertEventModel) *AlertEventHandler {
|
||||
return &AlertEventHandler{alertEvents: alertEvents}
|
||||
}
|
||||
|
||||
// List handles GET requests to list recent alert events for the current user.
|
||||
func (h *AlertEventHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
|
||||
@@ -34,6 +37,7 @@ func (h *AlertEventHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if limit < 1 || limit > 100 {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Limit must be between 1 and 100")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -41,6 +45,7 @@ func (h *AlertEventHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("Error listing alert events: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to list alert events")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -67,15 +72,15 @@ func mockEvents(limit int) []domain.AlertEvent {
|
||||
Timestamp: time.Now().Add(-2 * time.Hour),
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
AlertRuleID: 2,
|
||||
ID: 2, //nolint:mnd
|
||||
AlertRuleID: 2, //nolint:mnd
|
||||
Message: "Balance dropped below threshold: Current balance 8.2 ETH",
|
||||
AddressLabel: &label1,
|
||||
Timestamp: time.Now().Add(-5 * time.Hour),
|
||||
},
|
||||
{
|
||||
ID: 3,
|
||||
AlertRuleID: 3,
|
||||
ID: 3, //nolint:mnd
|
||||
AlertRuleID: 3, //nolint:mnd
|
||||
Message: "Outgoing transaction detected: 2.0 ETH sent",
|
||||
AddressLabel: &label2,
|
||||
Timestamp: time.Now().Add(-24 * time.Hour),
|
||||
@@ -85,5 +90,6 @@ func mockEvents(limit int) []domain.AlertEvent {
|
||||
if limit < len(mocks) {
|
||||
return mocks[:limit]
|
||||
}
|
||||
|
||||
return mocks
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -13,20 +14,27 @@ import (
|
||||
"github.com/kjannette/koin-ping/backend-go/internal/models"
|
||||
)
|
||||
|
||||
// errThresholdFormat is returned when the threshold JSON cannot be decoded.
|
||||
var errThresholdFormat = errors.New("unsupported threshold format")
|
||||
|
||||
// AlertRuleHandler handles HTTP requests for alert rule management.
|
||||
type AlertRuleHandler struct {
|
||||
alertRules *models.AlertRuleModel
|
||||
addresses *models.AddressModel
|
||||
}
|
||||
|
||||
// NewAlertRuleHandler creates a new AlertRuleHandler.
|
||||
func NewAlertRuleHandler(alertRules *models.AlertRuleModel, addresses *models.AddressModel) *AlertRuleHandler {
|
||||
return &AlertRuleHandler{alertRules: alertRules, addresses: addresses}
|
||||
}
|
||||
|
||||
// Create handles POST requests to create a new alert rule for an address.
|
||||
func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
addressID, ok := parseIntParam(r.PathValue("addressId"))
|
||||
if !ok {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid address ID")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -37,6 +45,7 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
log.Printf("Failed to decode alert request body: %v", err)
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid request body")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -44,6 +53,7 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("Failed to parse threshold: %v", err)
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "threshold must be a valid number")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -51,6 +61,7 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if body.Type == "" {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Alert type is required")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -60,7 +71,8 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
types[i] = string(t)
|
||||
}
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR",
|
||||
fmt.Sprintf("Invalid alert type. Must be one of: %s", strings.Join(types, ", ")))
|
||||
"Invalid alert type. Must be one of: "+strings.Join(types, ", "))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -69,6 +81,7 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if threshold == nil || *threshold <= 0 {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR",
|
||||
fmt.Sprintf("Alert type '%s' requires a positive threshold value", body.Type))
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -77,11 +90,13 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("Error finding address: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to create alert rule")
|
||||
|
||||
return
|
||||
}
|
||||
if addr == nil {
|
||||
log.Printf("Address %d not found or not owned by user", addressID)
|
||||
writeError(w, http.StatusNotFound, "NOT_FOUND", "Address not found")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -89,6 +104,7 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("Error creating alert rule: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to create alert rule")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -98,12 +114,12 @@ func (h *AlertRuleHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func parseThreshold(raw json.RawMessage) (*float64, error) {
|
||||
if len(raw) == 0 {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
// Check null before number -- json.Unmarshal treats null as valid for float64 (sets to 0).
|
||||
if string(raw) == "null" {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
var asNumber float64
|
||||
@@ -115,23 +131,26 @@ func parseThreshold(raw json.RawMessage) (*float64, error) {
|
||||
if err := json.Unmarshal(raw, &asString); err == nil {
|
||||
asString = strings.TrimSpace(asString)
|
||||
if asString == "" {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
parsed, parseErr := strconv.ParseFloat(asString, 64)
|
||||
if parseErr != nil {
|
||||
return nil, parseErr
|
||||
}
|
||||
|
||||
return &parsed, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unsupported threshold format")
|
||||
return nil, errThresholdFormat
|
||||
}
|
||||
|
||||
// ListByAddress handles GET requests to list alert rules for an address.
|
||||
func (h *AlertRuleHandler) ListByAddress(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
addressID, ok := parseIntParam(r.PathValue("addressId"))
|
||||
if !ok {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid address ID")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -141,11 +160,13 @@ func (h *AlertRuleHandler) ListByAddress(w http.ResponseWriter, r *http.Request)
|
||||
if err != nil {
|
||||
log.Printf("Error finding address: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to list alerts")
|
||||
|
||||
return
|
||||
}
|
||||
if addr == nil {
|
||||
log.Printf("Address %d not found or not owned by user", addressID)
|
||||
writeError(w, http.StatusNotFound, "NOT_FOUND", "Address not found")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -153,6 +174,7 @@ func (h *AlertRuleHandler) ListByAddress(w http.ResponseWriter, r *http.Request)
|
||||
if err != nil {
|
||||
log.Printf("Error listing alerts: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to list alerts")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -164,11 +186,13 @@ func (h *AlertRuleHandler) ListByAddress(w http.ResponseWriter, r *http.Request)
|
||||
writeJSON(w, http.StatusOK, alerts)
|
||||
}
|
||||
|
||||
// UpdateStatus handles PATCH requests to enable or disable an alert rule.
|
||||
func (h *AlertRuleHandler) UpdateStatus(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
alertID, ok := parseIntParam(r.PathValue("alertId"))
|
||||
if !ok {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid alert ID")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -178,6 +202,7 @@ func (h *AlertRuleHandler) UpdateStatus(w http.ResponseWriter, r *http.Request)
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
log.Printf("Failed to decode update request body: %v", err)
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid request body")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -185,6 +210,7 @@ func (h *AlertRuleHandler) UpdateStatus(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
if body.Enabled == nil {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "enabled must be a boolean value")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -192,11 +218,13 @@ func (h *AlertRuleHandler) UpdateStatus(w http.ResponseWriter, r *http.Request)
|
||||
if err != nil {
|
||||
log.Printf("Error finding alert: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to update alert")
|
||||
|
||||
return
|
||||
}
|
||||
if alert == nil {
|
||||
log.Printf("Alert %d not found or not owned by user", alertID)
|
||||
writeError(w, http.StatusNotFound, "NOT_FOUND", "Alert rule not found")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -204,6 +232,7 @@ func (h *AlertRuleHandler) UpdateStatus(w http.ResponseWriter, r *http.Request)
|
||||
if err != nil {
|
||||
log.Printf("Error updating alert: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to update alert")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -211,11 +240,13 @@ func (h *AlertRuleHandler) UpdateStatus(w http.ResponseWriter, r *http.Request)
|
||||
writeJSON(w, http.StatusOK, updated)
|
||||
}
|
||||
|
||||
// Remove handles DELETE requests to remove an alert rule.
|
||||
func (h *AlertRuleHandler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.GetUserID(r.Context())
|
||||
alertID, ok := parseIntParam(r.PathValue("alertId"))
|
||||
if !ok {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Invalid alert ID")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -225,17 +256,20 @@ func (h *AlertRuleHandler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
log.Printf("Error finding alert: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to delete alert")
|
||||
|
||||
return
|
||||
}
|
||||
if alert == nil {
|
||||
log.Printf("Alert %d not found or not owned by user", alertID)
|
||||
writeError(w, http.StatusNotFound, "NOT_FOUND", "Alert rule not found")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := h.alertRules.Remove(r.Context(), alertID); err != nil {
|
||||
log.Printf("Error deleting alert: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Failed to delete alert")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//nolint:testpackage // parseThreshold is unexported; internal test package required
|
||||
package handlers
|
||||
|
||||
import (
|
||||
@@ -6,8 +7,13 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
//nolint:gocognit
|
||||
func TestParseThreshold(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("nil/empty raw message returns nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -18,6 +24,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("empty slice returns nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -28,6 +36,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("JSON null returns nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage("null"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -38,6 +48,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("number 10 returns 10.0", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage("10"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -51,6 +63,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("number 0.5 returns 0.5", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage("0.5"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -61,6 +75,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("string '10' returns 10.0", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage(`"10"`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -71,6 +87,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("string '0.001' returns 0.001", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage(`"0.001"`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -81,6 +99,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("string with spaces ' 10 ' returns 10.0", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage(`" 10 "`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -91,6 +111,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("empty string returns nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage(`""`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -101,6 +123,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("whitespace-only string returns nil", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val, err := parseThreshold(json.RawMessage(`" "`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@@ -111,6 +135,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid string returns error", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := parseThreshold(json.RawMessage(`"abc"`))
|
||||
if err == nil {
|
||||
t.Fatal("expected error for non-numeric string")
|
||||
@@ -118,6 +144,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("boolean returns error", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := parseThreshold(json.RawMessage("true"))
|
||||
if err == nil {
|
||||
t.Fatal("expected error for boolean")
|
||||
@@ -125,6 +153,8 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("array returns error", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := parseThreshold(json.RawMessage("[1,2]"))
|
||||
if err == nil {
|
||||
t.Fatal("expected error for array")
|
||||
@@ -132,7 +162,10 @@ func TestParseThreshold(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
//nolint:funlen
|
||||
func TestDecodeAlertBody(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Verifies that the struct used in Create handler can decode all
|
||||
// payload shapes the frontend might send.
|
||||
|
||||
@@ -183,12 +216,15 @@ func TestDecodeAlertBody(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var body alertBody
|
||||
err := json.Unmarshal([]byte(tt.payload), &body)
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Fatal("expected decode error")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
@@ -199,6 +235,8 @@ func TestDecodeAlertBody(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOldStructFailsWithStringThreshold(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Documents the original bug: *float64 cannot decode a string threshold.
|
||||
type oldAlertBody struct {
|
||||
Type string `json:"type"`
|
||||
|
||||
Reference in New Issue
Block a user