package org import ( "context" "encoding/json" "fmt" "io" "net/http" "net/http/httptest" "os" "strings" "testing" "github.com/artifacthub/hub/internal/authz" "github.com/artifacthub/hub/internal/handlers/helpers" "github.com/artifacthub/hub/internal/hub" "github.com/artifacthub/hub/internal/org" "github.com/artifacthub/hub/internal/tests" "github.com/go-chi/chi/v5" "github.com/rs/zerolog" "github.com/spf13/viper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) func TestMain(m *testing.M) { zerolog.SetGlobalLevel(zerolog.Disabled) os.Exit(m.Run()) } func TestAdd(t *testing.T) { t.Run("invalid organization provided", func(t *testing.T) { testCases := []struct { description string orgJSON string omErr error }{ { "no organization provided", "", nil, }, { "invalid json", "-", nil, }, { "missing name", `{"display_name": "Display Name"}`, hub.ErrInvalidInput, }, { "invalid name", `{"name": "_org"}`, hub.ErrInvalidInput, }, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("POST", "/", strings.NewReader(tc.orgJSON)) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) hw := newHandlersWrapper() if tc.omErr != nil { hw.om.On("Add", r.Context(), mock.Anything).Return(tc.omErr) } hw.h.Add(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) t.Run("valid organization provided", func(t *testing.T) { orgJSON := ` { "name": "org1", "display_name": "Organization 1", "description": "description" } ` o := &hub.Organization{} _ = json.Unmarshal([]byte(orgJSON), &o) testCases := []struct { description string err error expectedStatusCode int }{ { "add organization succeeded", nil, http.StatusCreated, }, { "error adding organization", tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("POST", "/", strings.NewReader(orgJSON)) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) hw := newHandlersWrapper() hw.om.On("Add", r.Context(), o).Return(tc.err) hw.h.Add(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) } func TestAddMember(t *testing.T) { testCases := []struct { omErr error expectedStatusCode int }{ { nil, http.StatusCreated, }, { hub.ErrInvalidInput, http.StatusBadRequest, }, { hub.ErrInsufficientPrivilege, http.StatusForbidden, }, { tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { var desc string if tc.omErr != nil { desc = tc.omErr.Error() } t.Run(desc, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("POST", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName", "userAlias"}, Values: []string{"org1", "userAlias"}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("AddMember", r.Context(), "org1", "userAlias").Return(tc.omErr) hw.h.AddMember(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } } func TestCheckAvailability(t *testing.T) { t.Run("invalid input", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("HEAD", "/?v=value", nil) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"resourceKind"}, Values: []string{"invalid"}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("CheckAvailability", r.Context(), "invalid", "value"). Return(false, hub.ErrInvalidInput) hw.h.CheckAvailability(w, r) resp := w.Result() defer resp.Body.Close() h := resp.Header assert.Equal(t, http.StatusBadRequest, resp.StatusCode) assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control")) hw.om.AssertExpectations(t) }) t.Run("valid input", func(t *testing.T) { t.Run("check availability succeeded", func(t *testing.T) { testCases := []struct { resourceKind string available bool }{ { "organizationName", true, }, } for _, tc := range testCases { t.Run(fmt.Sprintf("resource kind: %s", tc.resourceKind), func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("HEAD", "/?v=value", nil) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"resourceKind"}, Values: []string{tc.resourceKind}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("CheckAvailability", r.Context(), tc.resourceKind, "value").Return(tc.available, nil) hw.h.CheckAvailability(w, r) resp := w.Result() defer resp.Body.Close() h := resp.Header if tc.available { assert.Equal(t, http.StatusNotFound, resp.StatusCode) } else { assert.Equal(t, http.StatusNoContent, resp.StatusCode) } assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control")) hw.om.AssertExpectations(t) }) } }) t.Run("check availability failed", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("HEAD", "/?v=value", nil) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"resourceKind"}, Values: []string{"organizationName"}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("CheckAvailability", r.Context(), "organizationName", "value"). Return(false, tests.ErrFakeDB) hw.h.CheckAvailability(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) hw.om.AssertExpectations(t) }) }) } func TestConfirmMembership(t *testing.T) { testCases := []struct { omErr error expectedStatusCode int }{ { nil, http.StatusNoContent, }, { hub.ErrInvalidInput, http.StatusBadRequest, }, { tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { var desc string if tc.omErr != nil { desc = tc.omErr.Error() } t.Run(desc, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("PUT", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("ConfirmMembership", r.Context(), "org1").Return(tc.omErr) hw.h.ConfirmMembership(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } } func TestDelete(t *testing.T) { testCases := []struct { omErr error expectedStatusCode int }{ { nil, http.StatusNoContent, }, { hub.ErrInvalidInput, http.StatusBadRequest, }, { hub.ErrInsufficientPrivilege, http.StatusForbidden, }, { tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { var desc string if tc.omErr != nil { desc = tc.omErr.Error() } t.Run(desc, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("DELETE", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("Delete", r.Context(), "org1").Return(tc.omErr) hw.h.Delete(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } } func TestDeleteMember(t *testing.T) { testCases := []struct { omErr error expectedStatusCode int }{ { nil, http.StatusNoContent, }, { hub.ErrInvalidInput, http.StatusBadRequest, }, { hub.ErrInsufficientPrivilege, http.StatusForbidden, }, { tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { var desc string if tc.omErr != nil { desc = tc.omErr.Error() } t.Run(desc, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("DELETE", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName", "userAlias"}, Values: []string{"org1", "userAlias"}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("DeleteMember", r.Context(), "org1", "userAlias").Return(tc.omErr) hw.h.DeleteMember(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } } func TestGet(t *testing.T) { rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } t.Run("error getting organization", func(t *testing.T) { testCases := []struct { omErr error expectedStatusCode int }{ { hub.ErrInvalidInput, http.StatusBadRequest, }, { tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { t.Run(tc.omErr.Error(), func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("GetJSON", r.Context(), "org1").Return(nil, tc.omErr) hw.h.Get(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) t.Run("get organization succeeded", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("GetJSON", r.Context(), "org1").Return([]byte("dataJSON"), nil) hw.h.Get(w, r) resp := w.Result() defer resp.Body.Close() h := resp.Header data, _ := io.ReadAll(resp.Body) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", h.Get("Content-Type")) assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control")) assert.Equal(t, []byte("dataJSON"), data) hw.om.AssertExpectations(t) }) } func TestGetAuthorizationPolicy(t *testing.T) { rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } t.Run("error getting authorization policy", func(t *testing.T) { testCases := []struct { omErr error expectedStatusCode int }{ { hub.ErrInvalidInput, http.StatusBadRequest, }, { tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { t.Run(tc.omErr.Error(), func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("GetAuthorizationPolicyJSON", r.Context(), "org1").Return(nil, tc.omErr) hw.h.GetAuthorizationPolicy(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) t.Run("get authorization policy succeeded", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("GetAuthorizationPolicyJSON", r.Context(), "org1").Return([]byte("dataJSON"), nil) hw.h.GetAuthorizationPolicy(w, r) resp := w.Result() defer resp.Body.Close() h := resp.Header data, _ := io.ReadAll(resp.Body) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", h.Get("Content-Type")) assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control")) assert.Equal(t, []byte("dataJSON"), data) hw.om.AssertExpectations(t) }) } func TestGetByUser(t *testing.T) { t.Run("get user organizations succeeded", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) hw := newHandlersWrapper() hw.om.On("GetByUserJSON", r.Context(), &hub.Pagination{ Limit: 10, Offset: 1, }).Return(&hub.JSONQueryResult{ Data: []byte("dataJSON"), TotalCount: 1, }, nil) hw.h.GetByUser(w, r) resp := w.Result() defer resp.Body.Close() h := resp.Header data, _ := io.ReadAll(resp.Body) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, h.Get(helpers.PaginationTotalCount), "1") assert.Equal(t, "application/json", h.Get("Content-Type")) assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control")) assert.Equal(t, []byte("dataJSON"), data) hw.om.AssertExpectations(t) }) t.Run("error getting user organizations", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) hw := newHandlersWrapper() hw.om.On("GetByUserJSON", r.Context(), &hub.Pagination{ Limit: 10, Offset: 1, }).Return(nil, tests.ErrFakeDB) hw.h.GetByUser(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) hw.om.AssertExpectations(t) }) } func TestGetMembers(t *testing.T) { rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } t.Run("error getting organization members", func(t *testing.T) { testCases := []struct { omErr error expectedStatusCode int }{ { hub.ErrInvalidInput, http.StatusBadRequest, }, { tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { t.Run(tc.omErr.Error(), func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("GetMembersJSON", r.Context(), "org1", &hub.Pagination{ Limit: 10, Offset: 1, }).Return(nil, tc.omErr) hw.h.GetMembers(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) t.Run("get organization members succeeded", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/?limit=10&offset=1", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("GetMembersJSON", r.Context(), "org1", &hub.Pagination{ Limit: 10, Offset: 1, }).Return(&hub.JSONQueryResult{ Data: []byte("dataJSON"), TotalCount: 1, }, nil) hw.h.GetMembers(w, r) resp := w.Result() defer resp.Body.Close() h := resp.Header data, _ := io.ReadAll(resp.Body) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, h.Get(helpers.PaginationTotalCount), "1") assert.Equal(t, "application/json", h.Get("Content-Type")) assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control")) assert.Equal(t, []byte("dataJSON"), data) hw.om.AssertExpectations(t) }) } func TestUpdate(t *testing.T) { rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } t.Run("invalid organization provided", func(t *testing.T) { testCases := []struct { description string orgJSON string omErr error }{ { "no organization provided", "", nil, }, { "invalid json", "-", nil, }, { "invalid logo image id", `{"name": "org1", "logo_image_id": "invalid"}`, hub.ErrInvalidInput, }, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("PUT", "/", strings.NewReader(tc.orgJSON)) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() if tc.omErr != nil { hw.om.On("Update", r.Context(), "org1", mock.Anything).Return(tc.omErr) } hw.h.Update(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) t.Run("valid organization provided", func(t *testing.T) { orgJSON := ` { "name": "org1", "display_name": "Organization 1 updated", "description": "description updated" } ` o := &hub.Organization{} _ = json.Unmarshal([]byte(orgJSON), &o) testCases := []struct { description string err error expectedStatusCode int }{ { "organization update succeeded", nil, http.StatusNoContent, }, { "error updating organization (insufficiente privilege)", hub.ErrInsufficientPrivilege, http.StatusForbidden, }, { "error updating organization (db error)", tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("PUT", "/", strings.NewReader(orgJSON)) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("Update", r.Context(), "org1", o).Return(tc.err) hw.h.Update(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) } func TestUpdateAuthorizationPolicy(t *testing.T) { rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } t.Run("invalid authorization policy provided", func(t *testing.T) { testCases := []struct { description string policyJSON string omErr error }{ { "no authorization policy provided", "", nil, }, { "invalid json", "-", nil, }, { "invalid policy data", `{"policy_data": "invalid"}`, hub.ErrInvalidInput, }, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("PUT", "/", strings.NewReader(tc.policyJSON)) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() if tc.omErr != nil { hw.om.On("UpdateAuthorizationPolicy", r.Context(), "org1", mock.Anything).Return(tc.omErr) } hw.h.UpdateAuthorizationPolicy(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) t.Run("valid authorization policy provided", func(t *testing.T) { policyJSON := ` { "authorization_enabled": true, "predefined_policy": "rbac.v1", "custom_policy": "", "policy_data": "{\"k\": \"v\"}" } ` policy := &hub.AuthorizationPolicy{} _ = json.Unmarshal([]byte(policyJSON), &policy) testCases := []struct { description string err error expectedStatusCode int }{ { "authorization policy update succeeded", nil, http.StatusNoContent, }, { "error updating organization policy (insufficiente privilege)", hub.ErrInsufficientPrivilege, http.StatusForbidden, }, { "error updating organization policy (db error)", tests.ErrFakeDB, http.StatusInternalServerError, }, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("PUT", "/", strings.NewReader(policyJSON)) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.om.On("UpdateAuthorizationPolicy", r.Context(), "org1", policy).Return(tc.err) hw.h.UpdateAuthorizationPolicy(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, tc.expectedStatusCode, resp.StatusCode) hw.om.AssertExpectations(t) }) } }) } func TestGetUserAllowedActions(t *testing.T) { rctx := &chi.Context{ URLParams: chi.RouteParams{ Keys: []string{"orgName"}, Values: []string{"org1"}, }, } t.Run("get allowed actions failed", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.az.On("GetAllowedActions", r.Context(), "userID", "org1").Return(nil, tests.ErrFake) hw.h.GetUserAllowedActions(w, r) resp := w.Result() defer resp.Body.Close() assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) hw.om.AssertExpectations(t) }) t.Run("get allowed actions succeeded", func(t *testing.T) { t.Parallel() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID")) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) hw := newHandlersWrapper() hw.az.On("GetAllowedActions", r.Context(), "userID", "org1").Return([]hub.Action{ hub.AddOrganizationMember, hub.DeleteOrganizationMember, }, nil) hw.h.GetUserAllowedActions(w, r) resp := w.Result() defer resp.Body.Close() h := resp.Header data, _ := io.ReadAll(resp.Body) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", h.Get("Content-Type")) assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control")) assert.Equal(t, []byte(`["addOrganizationMember","deleteOrganizationMember"]`), data) hw.om.AssertExpectations(t) }) } type handlersWrapper struct { cfg *viper.Viper om *org.ManagerMock az *authz.AuthorizerMock h *Handlers } func newHandlersWrapper() *handlersWrapper { cfg := viper.New() cfg.Set("server.baseURL", "baseURL") om := &org.ManagerMock{} az := &authz.AuthorizerMock{} return &handlersWrapper{ cfg: cfg, om: om, az: az, h: NewHandlers(om, az, cfg), } }