internal/rest/consumer_scope_test.go
Rama main · réplica de lectura del repositorio original.
package rest_test
import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/go-chi/chi/v5"
"github.com/sarathsp06/sparrow/internal/middleware"
"github.com/sarathsp06/sparrow/internal/rest"
"github.com/sarathsp06/sparrow/internal/webhooks"
"github.com/sarathsp06/sparrow/internal/webhooks/store"
)
// scopeRecorder records the consumer scope each batch-job and attempts call
// receives; every other method panics via the nil embedded interface.
type scopeRecorder struct {
webhooks.WebhookServiceInterface
scopes []webhooks.BatchScope
consumers []string
}
func (s *scopeRecorder) job(scope webhooks.BatchScope) (*store.BatchJob, error) {
s.scopes = append(s.scopes, scope)
return &store.BatchJob{JobType: store.BatchTypeDeliveryRetry, Status: store.BatchStatusPending}, nil
}
func (s *scopeRecorder) GetRetryStatus(_ context.Context, scope webhooks.BatchScope, _ string) (*store.BatchJob, error) {
return s.job(scope)
}
func (s *scopeRecorder) GetRepushStatus(_ context.Context, scope webhooks.BatchScope, _ string) (*store.BatchJob, error) {
return s.job(scope)
}
func (s *scopeRecorder) CancelRetry(_ context.Context, scope webhooks.BatchScope, _ string) error {
_, err := s.job(scope)
return err
}
func (s *scopeRecorder) RetryDeliveries(_ context.Context, scope webhooks.BatchScope, _ string) error {
_, err := s.job(scope)
return err
}
func (s *scopeRecorder) GetDeliveryAttempts(_ context.Context, _ string, consumer string) ([]*store.WebhookHealthEvent, error) {
s.consumers = append(s.consumers, consumer)
return nil, nil
}
// Portal requests reach batch jobs and attempts pinned to the token's consumer
// and limited to it; tenant-wide /v1 requests keep the path consumer and may
// also reach all-consumers jobs.
func TestBatchJobsAndAttemptsCarryTheConsumerScope(t *testing.T) {
svc := &scopeRecorder{}
r := chi.NewRouter()
rest.Mount(r, svc, rest.AccessDeps{}, rest.AIDeps{}, nil)
portal := middleware.PortalGateway(func(context.Context, string) (string, error) { return "acme", nil }, middleware.PortalOptions{Retry: true}, r)
const id = "11111111-1111-1111-1111-111111111111"
send := func(h http.Handler, method, path, body, token string) {
t.Helper()
req := httptest.NewRequest(method, path, strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
if token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
rec := httptest.NewRecorder()
h.ServeHTTP(rec, req)
if rec.Code >= 300 {
t.Fatalf("%s %s = %d %s", method, path, rec.Code, rec.Body)
}
}
send(portal, http.MethodGet, "/portal/api/retry-jobs/"+id, "", "t")
send(portal, http.MethodPost, "/portal/api/retry-jobs/"+id+":cancel", "", "t")
send(portal, http.MethodPost, "/portal/api/deliveries:retryBatch", `{"retry_id":"`+id+`"}`, "t")
for i, got := range svc.scopes {
if want := (webhooks.BatchScope{Consumer: "acme", ConsumerOnly: true}); got != want {
t.Fatalf("portal call %d scope = %+v, want %+v", i, got, want)
}
}
svc.scopes = nil
send(r, http.MethodGet, "/v1/consumers/globex/retry-jobs/"+id, "", "")
if want := (webhooks.BatchScope{Consumer: "globex"}); len(svc.scopes) != 1 || svc.scopes[0] != want {
t.Fatalf("tenant-wide scope = %+v, want %+v", svc.scopes, want)
}
send(portal, http.MethodGet, "/portal/api/deliveries/"+id+"/attempts", "", "t")
send(r, http.MethodGet, "/v1/consumers/globex/deliveries/"+id+"/attempts", "", "")
send(r, http.MethodGet, "/v1/deliveries/"+id+"/attempts", "", "")
if want := []string{"acme", "globex", ""}; strings.Join(svc.consumers, ",") != strings.Join(want, ",") {
t.Fatalf("attempts consumers = %q, want %q", svc.consumers, want)
}
}