Files
yovision/Bell/web/web_test.go
T

94 lines
3.6 KiB
Go
Raw Normal View History

package web
import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"
"yovision/bell/internal/alert"
)
type fakeRepository struct {
limit int
actor string
}
func (*fakeRepository) AlertReady(context.Context) error { return nil }
func (*fakeRepository) PublishRule(context.Context, alert.RuleSpec) (bool, error) { return true, nil }
func (*fakeRepository) EvaluateNext(context.Context) (bool, error) { return false, nil }
func (f *fakeRepository) ListAlerts(_ context.Context, _, _ int64, _ string, limit int, _ string) (alert.Page, error) {
f.limit = limit
return alert.Page{Items: []alert.Summary{}}, nil
}
func (*fakeRepository) GetAlert(context.Context, int64, int64, string) (alert.Detail, error) {
return alert.Detail{}, alert.ErrNotFound
}
func (f *fakeRepository) Command(_ context.Context, _, _ int64, id, command, key, actor string, _ *string) (int, alert.CommandResponse, error) {
f.actor = actor
return 200, alert.CommandResponse{AlertID: id, State: "acknowledged", ActorRef: actor}, nil
}
func testMux(t *testing.T) (*http.ServeMux, *fakeRepository) {
t.Helper()
repository := &fakeRepository{}
handler, err := NewHandler(repository, Config{Token: "12345678901234567890123456789012", TenantID: 1, SiteID: 2, ActorRef: "operator:local"})
if err != nil {
t.Fatal(err)
}
mux := http.NewServeMux()
handler.Register(mux)
return mux, repository
}
func TestPageIsNoStoreAndDoesNotEmbedToken(t *testing.T) {
mux, _ := testMux(t)
request := httptest.NewRequest(http.MethodGet, "/bell-console/", nil)
response := httptest.NewRecorder()
mux.ServeHTTP(response, request)
if response.Code != 200 || response.Header().Get("Cache-Control") != "no-store" {
t.Fatalf("page response: %d %#v", response.Code, response.Header())
}
if body := response.Body.String(); body == "" || strings.Contains(body, "12345678901234567890123456789012") {
t.Fatal("page missing or leaked console token")
}
}
func TestAPIRequiresBearerAndDefaultsToSixteen(t *testing.T) {
mux, repository := testMux(t)
request := httptest.NewRequest(http.MethodGet, "/bell-console/api/v1/alerts", nil)
response := httptest.NewRecorder()
mux.ServeHTTP(response, request)
if response.Code != http.StatusUnauthorized {
t.Fatalf("unauthorized status %d", response.Code)
}
request = httptest.NewRequest(http.MethodGet, "/bell-console/api/v1/alerts", nil)
request.Header.Set("Authorization", "Bearer 12345678901234567890123456789012")
response = httptest.NewRecorder()
mux.ServeHTTP(response, request)
if response.Code != http.StatusOK || repository.limit != alert.DefaultPageSize {
t.Fatalf("authorized list: status=%d limit=%d", response.Code, repository.limit)
}
}
func TestCommandUsesServerActorAndRequiresIdempotencyKey(t *testing.T) {
mux, repository := testMux(t)
path := "/bell-console/api/v1/alerts/alt_01J8XQ2K7M3P5R9T0V4W6Y8Z2C:ack"
request := httptest.NewRequest(http.MethodPost, path, strings.NewReader(`{"note":null}`))
request.Header.Set("Authorization", "Bearer 12345678901234567890123456789012")
response := httptest.NewRecorder()
mux.ServeHTTP(response, request)
if response.Code != http.StatusBadRequest {
t.Fatalf("missing idempotency status %d", response.Code)
}
request = httptest.NewRequest(http.MethodPost, path, strings.NewReader(`{"note":null}`))
request.Header.Set("Authorization", "Bearer 12345678901234567890123456789012")
request.Header.Set("Idempotency-Key", "command-0001")
response = httptest.NewRecorder()
mux.ServeHTTP(response, request)
if response.Code != http.StatusOK || repository.actor != "operator:local" {
t.Fatalf("command status=%d actor=%q", response.Code, repository.actor)
}
}