Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend [Integration Test] bots.go handlers CreateOrEditBot, GetListedBots, & GetBot #1577

Merged
merged 2 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions handlers/bots.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func NewBotHandler(db db.Database) *botHandler {
}
}

func CreateOrEditBot(w http.ResponseWriter, r *http.Request) {
func (bt *botHandler) CreateOrEditBot(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)

Expand All @@ -48,7 +48,7 @@ func CreateOrEditBot(w http.ResponseWriter, r *http.Request) {

now := time.Now()

extractedPubkey, err := auth.VerifyTribeUUID(bot.UUID, false)
extractedPubkey, err := bt.verifyTribeUUID(bot.UUID, false)
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusUnauthorized)
Expand All @@ -66,9 +66,9 @@ func CreateOrEditBot(w http.ResponseWriter, r *http.Request) {

bot.OwnerPubKey = extractedPubkey
bot.Updated = &now
bot.UniqueName, _ = BotUniqueNameFromName(bot.Name)
bot.UniqueName, _ = bt.BotUniqueNameFromName(bot.Name)

_, err = db.DB.CreateOrEditBot(bot)
_, err = bt.db.CreateOrEditBot(bot)
if err != nil {
fmt.Println("=> ERR createOrEditBot", err)
w.WriteHeader(http.StatusBadRequest)
Expand All @@ -79,15 +79,15 @@ func CreateOrEditBot(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(bot)
}

func GetListedBots(w http.ResponseWriter, r *http.Request) {
bots := db.DB.GetListedBots(r)
func (bt *botHandler) GetListedBots(w http.ResponseWriter, r *http.Request) {
bots := bt.db.GetListedBots(r)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(bots)
}

func GetBot(w http.ResponseWriter, r *http.Request) {
func (bt *botHandler) GetBot(w http.ResponseWriter, r *http.Request) {
uuid := chi.URLParam(r, "uuid")
bot := db.DB.GetBot(uuid)
bot := bt.db.GetBot(uuid)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(bot)
}
Expand Down Expand Up @@ -155,7 +155,7 @@ func (bt *botHandler) DeleteBot(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(true)
}

func BotUniqueNameFromName(name string) (string, error) {
func (h *botHandler) BotUniqueNameFromName(name string) (string, error) {
pathOne := strings.ToLower(strings.Join(strings.Fields(name), ""))
reg, err := regexp.Compile("[^a-zA-Z0-9]+")
if err != nil {
Expand All @@ -168,7 +168,7 @@ func BotUniqueNameFromName(name string) (string, error) {
if n > 0 {
uniquepath = path + strconv.Itoa(n)
}
existing := db.DB.GetBotByUniqueName(uniquepath)
existing := h.db.GetBotByUniqueName(uniquepath)
if existing.UUID != "" {
n = n + 1
} else {
Expand Down
242 changes: 242 additions & 0 deletions handlers/bots_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package handlers

import (
"bytes"
"context"
"encoding/json"
"net/http"
Expand Down Expand Up @@ -245,3 +246,244 @@ func TestDeleteBot(t *testing.T) {
mockDb.AssertCalled(t, "UpdateBot", expectedUUID, map[string]interface{}{"deleted": true})
})
}
func TestCreateOrEditBot(t *testing.T) {
mockDb := dbMocks.NewDatabase(t)
bHandler := NewBotHandler(mockDb)

t.Run("should test that a 401 error is returned during bot creation if there is no bot uuid", func(t *testing.T) {
mockUUID := "valid_uuid"

requestBody := map[string]interface{}{
"UUID": mockUUID,
}

requestBodyBytes, err := json.Marshal(requestBody)
if err != nil {
t.Fatal(err)
}

req, err := http.NewRequest("POST", "/", bytes.NewBuffer(requestBodyBytes))
if err != nil {
t.Fatal(err)
}

rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.CreateOrEditBot)

handler.ServeHTTP(rr, req)

assert.Equal(t, http.StatusUnauthorized, rr.Code)
})

t.Run("should test that a 401 error is returned if the user public key can't be verified during bot creation", func(t *testing.T) {
ctx := context.WithValue(context.Background(), auth.ContextKey, "pubkey")
mockPubKey := "valid_pubkey"
mockUUID := "valid_uuid"

requestBody := map[string]interface{}{
"UUID": mockUUID,
}

requestBodyBytes, err := json.Marshal(requestBody)
if err != nil {
t.Fatal(err)
}

mockVerifyTribeUUID := func(uuid string, checkTimestamp bool) (string, error) {
return mockPubKey, nil
}

bHandler.verifyTribeUUID = mockVerifyTribeUUID

rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.CreateOrEditBot)

req, err := http.NewRequestWithContext(ctx, "POST", "/", bytes.NewBuffer(requestBodyBytes))
if err != nil {
t.Fatal(err)
}

chiCtx := chi.NewRouteContext()
chiCtx.URLParams.Add("uuid", mockUUID)

req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, chiCtx))
handler.ServeHTTP(rr, req)

assert.Equal(t, http.StatusUnauthorized, rr.Code)
})

t.Run("should test that a bot gets created successfully if an authenticated user sends the right data", func(t *testing.T) {
mockPubKey := "valid_pubkey"
mockUUID := "valid_uuid"
mockName := "Test Bot"
mockUniqueName := "unique test bot"

mockVerifyTribeUUID := func(uuid string, checkTimestamp bool) (string, error) {
return mockPubKey, nil
}

bHandler.verifyTribeUUID = mockVerifyTribeUUID

requestBody := map[string]interface{}{
"UUID": mockUUID,
"Name": mockName,
}
requestBodyBytes, err := json.Marshal(requestBody)
if err != nil {
t.Fatal(err)
}

mockDb.On("GetBotByUniqueName", mock.Anything).Return(db.Bot{
UniqueName: mockUniqueName,
}, nil)

mockDb.On("CreateOrEditBot", mock.Anything).Return(db.Bot{
UUID: mockUUID,
}, nil)

req, err := http.NewRequest("POST", "/", bytes.NewBuffer(requestBodyBytes))
if err != nil {
t.Fatal(err)
}

ctx := context.WithValue(req.Context(), auth.ContextKey, mockPubKey)
req = req.WithContext(ctx)

rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.CreateOrEditBot)
handler.ServeHTTP(rr, req)

assert.Equal(t, http.StatusOK, rr.Code)
var responseData map[string]interface{}
err = json.Unmarshal(rr.Body.Bytes(), &responseData)
if err != nil {
t.Fatalf("Error decoding JSON response: %s", err)
}
assert.Equal(t, mockUUID, responseData["uuid"])
})

t.Run("should test that an existing bot gets updated when passed to POST bots", func(t *testing.T) {
mockPubKey := "valid_pubkey"
mockUUID := "valid_uuid"
mockName := "Updated Test Bot"
mockUniqueName := "unique test bot"

mockVerifyTribeUUID := func(uuid string, checkTimestamp bool) (string, error) {
return mockPubKey, nil
}
bHandler.verifyTribeUUID = mockVerifyTribeUUID

requestBody := map[string]interface{}{
"UUID": mockUUID,
"Name": mockName,
}
requestBodyBytes, err := json.Marshal(requestBody)
if err != nil {
t.Fatal(err)
}

mockDb.On("GetBotByUniqueName", mock.Anything).Return(db.Bot{
UUID: mockUUID,
UniqueName: mockUniqueName,
Name: "Original Test Bot",
}, nil)

mockDb.On("CreateOrEditBot", mock.Anything).Return(db.Bot{
UUID: mockUUID,
Name: mockName,
}, nil)

req, err := http.NewRequest("POST", "/", bytes.NewBuffer(requestBodyBytes))
if err != nil {
t.Fatal(err)
}
ctx := context.WithValue(req.Context(), auth.ContextKey, mockPubKey)
req = req.WithContext(ctx)

rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.CreateOrEditBot)
handler.ServeHTTP(rr, req)

assert.Equal(t, http.StatusOK, rr.Code)
var responseData map[string]interface{}
err = json.Unmarshal(rr.Body.Bytes(), &responseData)
if err != nil {
t.Fatalf("Error decoding JSON response: %s", err)
}
assert.Equal(t, mockUUID, responseData["uuid"])
assert.Equal(t, mockName, responseData["name"])
})

}

func TestGetBot(t *testing.T) {
mockDb := dbMocks.NewDatabase(t)
bHandler := NewBotHandler(mockDb)

t.Run("should test that a bot can be fetched with its uuid", func(t *testing.T) {

mockUUID := "valid_uuid"
mockBot := db.Bot{UUID: mockUUID, Name: "Test Bot"}
mockDb.On("GetBot", mock.Anything).Return(mockBot).Once()

rr := httptest.NewRecorder()
rctx := chi.NewRouteContext()
rctx.URLParams.Add("uuid", mockUUID)
req, err := http.NewRequestWithContext(context.WithValue(context.Background(), chi.RouteCtxKey, rctx), http.MethodGet, "/"+mockUUID, nil)

if err != nil {
t.Fatal(err)
}

handler := http.HandlerFunc(bHandler.GetBot)
handler.ServeHTTP(rr, req)

assert.Equal(t, http.StatusOK, rr.Code)
var returnedBot db.Bot
json.Unmarshal(rr.Body.Bytes(), &returnedBot)
assert.Equal(t, mockBot, returnedBot)
})
}

func TestGetListedBots(t *testing.T) {
mockDb := dbMocks.NewDatabase(t)
bHandler := NewBotHandler(mockDb)

t.Run("should test that all bots that are not unlisted or deleted get listed", func(t *testing.T) {
rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.GetListedBots)

allBots := []db.Bot{
{UUID: "uuid1", Name: "Bot1", Unlisted: false, Deleted: false},
{UUID: "uuid2", Name: "Bot2", Unlisted: false, Deleted: true},
{UUID: "uuid3", Name: "Bot3", Unlisted: true, Deleted: false},
{UUID: "uuid4", Name: "Bot4", Unlisted: true, Deleted: true},
}

expectedBots := []db.Bot{
{UUID: "uuid1", Name: "Bot1", Unlisted: false, Deleted: false},
}

rctx := chi.NewRouteContext()
req, err := http.NewRequestWithContext(context.WithValue(context.Background(), chi.RouteCtxKey, rctx), http.MethodGet, "/", nil)
assert.NoError(t, err)

mockDb.On("GetListedBots", mock.Anything).Return(allBots)
handler.ServeHTTP(rr, req)
var returnedBots []db.Bot
err = json.Unmarshal(rr.Body.Bytes(), &returnedBots)
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, rr.Code)

var filteredBots []db.Bot
for _, bot := range returnedBots {
if !bot.Deleted && !bot.Unlisted {
filteredBots = append(filteredBots, bot)
}
}

assert.ElementsMatch(t, expectedBots, filteredBots)
mockDb.AssertExpectations(t)
})

}
2 changes: 1 addition & 1 deletion routes/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func BotRoutes() chi.Router {
r.Group(func(r chi.Router) {
r.Use(auth.PubKeyContext)

r.Put("/", handlers.CreateOrEditBot)
r.Put("/", botHandler.CreateOrEditBot)
r.Delete("/{uuid}", botHandler.DeleteBot)
})
return r
Expand Down
7 changes: 4 additions & 3 deletions routes/bots.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import (
func BotsRoutes() chi.Router {
r := chi.NewRouter()
botHandler := handlers.NewBotHandler(db.DB)

r.Group(func(r chi.Router) {
r.Post("/", handlers.CreateOrEditBot)
r.Get("/", handlers.GetListedBots)
r.Post("/", botHandler.CreateOrEditBot)
r.Get("/", botHandler.GetListedBots)
r.Get("/owner/{pubkey}", botHandler.GetBotsByOwner)
r.Get("/{uuid}", handlers.GetBot)
r.Get("/{uuid}", botHandler.GetBot)
})
return r
}
Loading