package onboardingapi import ( "context" "encoding/json" "net/http" "net/http/httptest" "strings" "testing" "github.com/itworx/pulse/internal/audit" "github.com/itworx/pulse/internal/auth" "github.com/itworx/pulse/internal/onboarding" ) type fakeService struct { status onboarding.Status completed onboarding.Status choices onboarding.Choice } func (f *fakeService) Status(context.Context) (onboarding.Status, error) { return f.status, nil } func (f *fakeService) Complete(_ context.Context, choice onboarding.Choice) (onboarding.Status, error) { f.choices = choice return f.completed, nil } func onboardingRequest(method, body string, principal auth.Principal) *http.Request { request := httptest.NewRequest(method, "/api/v1/onboarding", strings.NewReader(body)) return request.WithContext(auth.WithPrincipal(request.Context(), principal)) } func TestStatusRequiresAuthentication(t *testing.T) { response := httptest.NewRecorder() (Handler{Service: &fakeService{}}).ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/api/v1/onboarding", nil)) if response.Code != http.StatusUnauthorized { t.Fatalf("status=%d, want 401", response.Code) } } func TestViewerCannotCompleteOnboarding(t *testing.T) { service := &fakeService{} response := httptest.NewRecorder() (Handler{Service: service}).ServeHTTP(response, onboardingRequest(http.MethodPost, `{}`, auth.Principal{Subject: "viewer", Role: auth.RoleViewer})) if response.Code != http.StatusForbidden || service.choices != (onboarding.Choice{}) { t.Fatalf("status=%d choices=%#v", response.Code, service.choices) } } func TestAdministratorCompletesAndAuditsOnboarding(t *testing.T) { service := &fakeService{completed: onboarding.Status{State: onboarding.State{Completed: true, Step: "complete"}}} auditStore := &audit.MemoryStore{} response := httptest.NewRecorder() (Handler{Service: service, Audit: auditStore}).ServeHTTP(response, onboardingRequest(http.MethodPost, `{"dashboard":"default","rules":"default"}`, auth.Principal{Subject: "admin", Role: auth.RoleAdministrator})) if response.Code != http.StatusOK || service.choices.Dashboard != "default" || len(auditStore.Events) != 1 { t.Fatalf("status=%d choices=%#v audit=%d", response.Code, service.choices, len(auditStore.Events)) } var status onboarding.Status if err := json.Unmarshal(response.Body.Bytes(), &status); err != nil { t.Fatal(err) } if !status.State.Completed { t.Fatal("completion state missing") } }