mirror of https://github.com/artifacthub/hub.git
398 lines
9.9 KiB
Go
398 lines
9.9 KiB
Go
package apikey
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/artifacthub/hub/internal/apikey"
|
|
"github.com/artifacthub/hub/internal/handlers/helpers"
|
|
"github.com/artifacthub/hub/internal/hub"
|
|
"github.com/artifacthub/hub/internal/tests"
|
|
"github.com/go-chi/chi"
|
|
"github.com/rs/zerolog"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
const apiKeyID = "00000000-0000-0000-0000-000000000001"
|
|
|
|
func TestMain(m *testing.M) {
|
|
zerolog.SetGlobalLevel(zerolog.Disabled)
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
func TestAdd(t *testing.T) {
|
|
akJSON := `{"name": "apikey1"}`
|
|
ak := &hub.APIKey{}
|
|
_ = json.Unmarshal([]byte(akJSON), &ak)
|
|
|
|
t.Run("invalid input", func(t *testing.T) {
|
|
testCases := []struct {
|
|
description string
|
|
akJSON string
|
|
err error
|
|
}{
|
|
{
|
|
"no api key provided",
|
|
"",
|
|
nil,
|
|
},
|
|
{
|
|
"invalid json",
|
|
"-",
|
|
nil,
|
|
},
|
|
{
|
|
"missing name",
|
|
`{}`,
|
|
hub.ErrInvalidInput,
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
t.Run(tc.description, func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("POST", "/", strings.NewReader(tc.akJSON))
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
|
|
hw := newHandlersWrapper()
|
|
if tc.err != nil {
|
|
hw.am.On("Add", r.Context(), mock.Anything).Return(nil, tc.err)
|
|
}
|
|
hw.h.Add(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("error adding api key", func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("POST", "/", strings.NewReader(akJSON))
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
|
|
hw := newHandlersWrapper()
|
|
hw.am.On("Add", r.Context(), ak).Return(nil, tests.ErrFakeDB)
|
|
hw.h.Add(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("api key added successfully", func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("POST", "/", strings.NewReader(akJSON))
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
|
|
hw := newHandlersWrapper()
|
|
akOUT := &hub.APIKey{
|
|
APIKeyID: "apiKeyID",
|
|
Secret: "secret",
|
|
}
|
|
hw.am.On("Add", r.Context(), ak).Return(akOUT, nil)
|
|
hw.h.Add(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
h := resp.Header
|
|
data, _ := ioutil.ReadAll(resp.Body)
|
|
|
|
assert.Equal(t, http.StatusCreated, resp.StatusCode)
|
|
assert.Equal(t, "application/json", h.Get("Content-Type"))
|
|
assert.Equal(t, helpers.BuildCacheControlHeader(0), h.Get("Cache-Control"))
|
|
outputAKJSON, _ := json.Marshal(akOUT)
|
|
assert.Equal(t, outputAKJSON, data)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
|
|
func TestDelete(t *testing.T) {
|
|
rctx := &chi.Context{
|
|
URLParams: chi.RouteParams{
|
|
Keys: []string{"apiKeyID"},
|
|
Values: []string{apiKeyID},
|
|
},
|
|
}
|
|
|
|
t.Run("error deleting api key", func(t *testing.T) {
|
|
testCases := []struct {
|
|
err error
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
hub.ErrInvalidInput,
|
|
http.StatusBadRequest,
|
|
},
|
|
{
|
|
tests.ErrFakeDB,
|
|
http.StatusInternalServerError,
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
t.Run(tc.err.Error(), func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("DELETE", "/", nil)
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
|
|
|
|
hw := newHandlersWrapper()
|
|
hw.am.On("Delete", r.Context(), apiKeyID).Return(tc.err)
|
|
hw.h.Delete(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("delete api key succeeded", func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("DELETE", "/", nil)
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
|
|
|
|
hw := newHandlersWrapper()
|
|
hw.am.On("Delete", r.Context(), apiKeyID).Return(nil)
|
|
hw.h.Delete(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, http.StatusNoContent, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
|
|
func TestGet(t *testing.T) {
|
|
rctx := &chi.Context{
|
|
URLParams: chi.RouteParams{
|
|
Keys: []string{"apiKeyID"},
|
|
Values: []string{apiKeyID},
|
|
},
|
|
}
|
|
|
|
t.Run("error getting api key", func(t *testing.T) {
|
|
testCases := []struct {
|
|
err error
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
hub.ErrInvalidInput,
|
|
http.StatusBadRequest,
|
|
},
|
|
{
|
|
tests.ErrFakeDB,
|
|
http.StatusInternalServerError,
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
t.Run(tc.err.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.am.On("GetJSON", r.Context(), apiKeyID).Return(nil, tc.err)
|
|
hw.h.Get(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("api key get 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.am.On("GetJSON", r.Context(), apiKeyID).Return([]byte("dataJSON"), nil)
|
|
hw.h.Get(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
h := resp.Header
|
|
data, _ := ioutil.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.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
|
|
func TestGetOwnedByUser(t *testing.T) {
|
|
t.Run("error getting api keys owned by user", func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("GET", "/", nil)
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
|
|
hw := newHandlersWrapper()
|
|
hw.am.On("GetOwnedByUserJSON", r.Context()).Return(nil, tests.ErrFakeDB)
|
|
hw.h.GetOwnedByUser(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("get api keys owned by user 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"))
|
|
|
|
hw := newHandlersWrapper()
|
|
hw.am.On("GetOwnedByUserJSON", r.Context()).Return([]byte("dataJSON"), nil)
|
|
hw.h.GetOwnedByUser(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
h := resp.Header
|
|
data, _ := ioutil.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.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
|
|
func TestUpdate(t *testing.T) {
|
|
t.Run("invalid input", func(t *testing.T) {
|
|
testCases := []struct {
|
|
description string
|
|
akJSON string
|
|
err error
|
|
}{
|
|
{
|
|
"no api key provided",
|
|
"",
|
|
nil,
|
|
},
|
|
{
|
|
"invalid json",
|
|
"-",
|
|
nil,
|
|
},
|
|
{
|
|
"missing name",
|
|
`{}`,
|
|
hub.ErrInvalidInput,
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
t.Run(tc.description, func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("PUT", "/", strings.NewReader(tc.akJSON))
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
|
|
hw := newHandlersWrapper()
|
|
if tc.err != nil {
|
|
hw.am.On("Update", r.Context(), mock.Anything).Return(tc.err)
|
|
}
|
|
hw.h.Update(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("valid api key provided", func(t *testing.T) {
|
|
ak := &hub.APIKey{
|
|
APIKeyID: apiKeyID,
|
|
Name: "apikey1",
|
|
}
|
|
akJSON, _ := json.Marshal(ak)
|
|
|
|
testCases := []struct {
|
|
description string
|
|
err error
|
|
expectedStatusCode int
|
|
}{
|
|
{
|
|
"api key update succeeded",
|
|
nil,
|
|
http.StatusNoContent,
|
|
},
|
|
{
|
|
"error updating api key (db error)",
|
|
tests.ErrFakeDB,
|
|
http.StatusInternalServerError,
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
t.Run(tc.description, func(t *testing.T) {
|
|
t.Parallel()
|
|
w := httptest.NewRecorder()
|
|
r, _ := http.NewRequest("PUT", "/", bytes.NewReader(akJSON))
|
|
r = r.WithContext(context.WithValue(r.Context(), hub.UserIDKey, "userID"))
|
|
rctx := &chi.Context{
|
|
URLParams: chi.RouteParams{
|
|
Keys: []string{"apiKeyID"},
|
|
Values: []string{apiKeyID},
|
|
},
|
|
}
|
|
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
|
|
|
|
hw := newHandlersWrapper()
|
|
hw.am.On("Update", r.Context(), ak).Return(tc.err)
|
|
hw.h.Update(w, r)
|
|
resp := w.Result()
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, tc.expectedStatusCode, resp.StatusCode)
|
|
hw.am.AssertExpectations(t)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
type handlersWrapper struct {
|
|
am *apikey.ManagerMock
|
|
h *Handlers
|
|
}
|
|
|
|
func newHandlersWrapper() *handlersWrapper {
|
|
am := &apikey.ManagerMock{}
|
|
|
|
return &handlersWrapper{
|
|
am: am,
|
|
h: NewHandlers(am),
|
|
}
|
|
}
|