From 554b9f8497bc46c1ff911a0a3ed53208fb019085 Mon Sep 17 00:00:00 2001 From: MahtabBukhari Date: Mon, 23 Dec 2024 19:02:05 +0500 Subject: [PATCH 1/2] bounty cards route handler response --- db/structs.go | 9 +++++++++ handlers/bounty.go | 42 ++++++++++++++++++++++++++++++++++++++++++ routes/bounty.go | 1 + 3 files changed, 52 insertions(+) diff --git a/db/structs.go b/db/structs.go index d0d7a9aec..ddf31202d 100644 --- a/db/structs.go +++ b/db/structs.go @@ -925,6 +925,15 @@ type FilterStattuCount struct { Failed int64 `json:"failed"` } +type BountyCard struct { + BountyID uint `json:"id"` + Title string `json:"title"` + AssigneePic string `json:"assignee_img,omitempty"` + Features WorkspaceFeatures `json:"features"` + Phase FeaturePhase `json:"phase"` + Workspace Workspace `json:"workspace"` +} + type WfRequestStatus string const ( diff --git a/handlers/bounty.go b/handlers/bounty.go index 8e1d4eb2e..9523d37f4 100644 --- a/handlers/bounty.go +++ b/handlers/bounty.go @@ -1491,3 +1491,45 @@ func GetFilterCount(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(filterCount) } + +func (h *bountyHandler) GetBountyCards(w http.ResponseWriter, r *http.Request) { + bounties := h.db.GetAllBounties(r) + var bountyCardResponse []db.BountyCard = h.GenerateBountyCardResponse(bounties) + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(bountyCardResponse) +} + +func (h *bountyHandler) GenerateBountyCardResponse(bounties []db.NewBounty) []db.BountyCard { + var bountyCardResponse []db.BountyCard + + for i := 0; i < len(bounties); i++ { + bounty := bounties[i] + + assignee := h.db.GetPersonByPubkey(bounty.Assignee) + workspace := h.db.GetWorkspaceByUuid(bounty.WorkspaceUuid) + + var phase db.FeaturePhase + var feature db.WorkspaceFeatures + + if bounty.PhaseUuid != "" { + phase, _ = h.db.GetPhaseByUuid(bounty.PhaseUuid) + } + + if phase.FeatureUuid != "" { + feature = h.db.GetFeatureByUuid(phase.FeatureUuid) + } + b := db.BountyCard{ + BountyID: bounty.ID, + Title: bounty.Title, + AssigneePic: assignee.Img, + Features: feature, + Phase: phase, + Workspace: workspace, + } + + bountyCardResponse = append(bountyCardResponse, b) + } + + return bountyCardResponse +} diff --git a/routes/bounty.go b/routes/bounty.go index ea4eb4c6e..2b4d2b52f 100644 --- a/routes/bounty.go +++ b/routes/bounty.go @@ -34,6 +34,7 @@ func BountyRoutes() chi.Router { r.Group(func(r chi.Router) { r.Use(auth.PubKeyContext) + r.Get("/bounty-cards", bountyHandler.GetBountyCards) r.Post("/budget/withdraw", bountyHandler.BountyBudgetWithdraw) r.Post("/pay/{id}", bountyHandler.MakeBountyPayment) r.Get("/payment/status/{id}", bountyHandler.GetBountyPaymentStatus) From 6742fc46aea8eeea841e587f7ca722c2024e5848 Mon Sep 17 00:00:00 2001 From: MahtabBukhari Date: Mon, 23 Dec 2024 23:19:49 +0500 Subject: [PATCH 2/2] unit tests --- db/test_config.go | 13 +++ handlers/bounty_test.go | 190 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) diff --git a/db/test_config.go b/db/test_config.go index fa877c54e..48fda26ce 100644 --- a/db/test_config.go +++ b/db/test_config.go @@ -81,3 +81,16 @@ func CleanDB() { func DeleteAllChats() { TestDB.db.Exec("DELETE FROM chats") } + +func CleanTestData() { + + TestDB.DeleteAllBounties() + + TestDB.db.Exec("DELETE FROM workspaces") + + TestDB.db.Exec("DELETE FROM workspace_features") + + TestDB.db.Exec("DELETE FROM feature_phases") + + TestDB.db.Exec("DELETE FROM people") +} diff --git a/handlers/bounty_test.go b/handlers/bounty_test.go index d66290101..8f1fdd319 100644 --- a/handlers/bounty_test.go +++ b/handlers/bounty_test.go @@ -2202,3 +2202,193 @@ func TestPollInvoice(t *testing.T) { mockHttpClient.AssertExpectations(t) }) } + +func TestGetBountyCards(t *testing.T) { + teardownSuite := SetupSuite(t) + defer teardownSuite(t) + + mockHttpClient := mocks.NewHttpClient(t) + bHandler := NewBountyHandler(mockHttpClient, db.TestDB) + + db.CleanTestData() + + workspace := db.Workspace{ + ID: 1, + Uuid: "test-workspace-uuid", + Name: "Test Workspace", + Description: "Test Workspace Description", + OwnerPubKey: "test-owner", + } + db.TestDB.CreateOrEditWorkspace(workspace) + + phase := db.FeaturePhase{ + Uuid: "test-phase-uuid", + Name: "Test Phase", + FeatureUuid: "test-feature-uuid", + } + db.TestDB.CreateOrEditFeaturePhase(phase) + + feature := db.WorkspaceFeatures{ + Uuid: "test-feature-uuid", + Name: "Test Feature", + WorkspaceUuid: workspace.Uuid, + } + db.TestDB.CreateOrEditFeature(feature) + + assignee := db.Person{ + OwnerPubKey: "test-assignee", + Img: "test-image-url", + } + db.TestDB.CreateOrEditPerson(assignee) + + now := time.Now() + bounty := db.NewBounty{ + ID: 1, + Type: "coding", + Title: "Test Bounty", + Description: "Test Description", + WorkspaceUuid: workspace.Uuid, + PhaseUuid: phase.Uuid, + Assignee: assignee.OwnerPubKey, + Show: true, + Created: now.Unix(), + OwnerID: "test-owner", + Price: 1000, + Paid: false, + } + db.TestDB.CreateOrEditBounty(bounty) + + t.Run("should successfully return bounty cards", func(t *testing.T) { + rr := httptest.NewRecorder() + handler := http.HandlerFunc(bHandler.GetBountyCards) + + req, err := http.NewRequest(http.MethodGet, "/gobounties/bounty-cards?workspace_uuid="+workspace.Uuid, nil) + assert.NoError(t, err) + + handler.ServeHTTP(rr, req) + + var response []db.BountyCard + err = json.Unmarshal(rr.Body.Bytes(), &response) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, rr.Code) + assert.NotEmpty(t, response, "Response should not be empty") + + firstCard := response[0] + assert.Equal(t, bounty.ID, firstCard.BountyID) + assert.Equal(t, bounty.Title, firstCard.Title) + assert.Equal(t, assignee.Img, firstCard.AssigneePic) + + assert.Equal(t, feature.Uuid, firstCard.Features.Uuid) + assert.Equal(t, feature.Name, firstCard.Features.Name) + assert.Equal(t, feature.WorkspaceUuid, firstCard.Features.WorkspaceUuid) + + assert.Equal(t, phase.Uuid, firstCard.Phase.Uuid) + assert.Equal(t, phase.Name, firstCard.Phase.Name) + assert.Equal(t, phase.FeatureUuid, firstCard.Phase.FeatureUuid) + + assert.Equal(t, workspace, firstCard.Workspace) + }) + + t.Run("should return empty array when no bounties exist", func(t *testing.T) { + + db.TestDB.DeleteAllBounties() + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(bHandler.GetBountyCards) + + req, err := http.NewRequest(http.MethodGet, "/gobounties/bounty-cards", nil) + assert.NoError(t, err) + + handler.ServeHTTP(rr, req) + + var response []db.BountyCard + err = json.Unmarshal(rr.Body.Bytes(), &response) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, rr.Code) + assert.Empty(t, response) + }) + + t.Run("should handle bounties without phase and feature", func(t *testing.T) { + bountyWithoutPhase := db.NewBounty{ + ID: 2, + Type: "coding", + Title: "Test Bounty Without Phase", + Description: "Test Description", + WorkspaceUuid: workspace.Uuid, + Assignee: assignee.OwnerPubKey, + Show: true, + Created: now.Unix(), + OwnerID: "test-owner", + Price: 1000, + Paid: false, + } + db.TestDB.CreateOrEditBounty(bountyWithoutPhase) + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(bHandler.GetBountyCards) + + req, err := http.NewRequest(http.MethodGet, "/gobounties/bounty-cards?workspace_uuid="+workspace.Uuid, nil) + assert.NoError(t, err) + + handler.ServeHTTP(rr, req) + + var response []db.BountyCard + err = json.Unmarshal(rr.Body.Bytes(), &response) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, rr.Code) + assert.NotEmpty(t, response) + + var cardWithoutPhase db.BountyCard + for _, card := range response { + if card.BountyID == bountyWithoutPhase.ID { + cardWithoutPhase = card + break + } + } + + assert.Equal(t, bountyWithoutPhase.ID, cardWithoutPhase.BountyID) + assert.Equal(t, bountyWithoutPhase.Title, cardWithoutPhase.Title) + assert.Equal(t, assignee.Img, cardWithoutPhase.AssigneePic) + assert.Empty(t, cardWithoutPhase.Phase.Uuid) + assert.Empty(t, cardWithoutPhase.Features.Uuid) + }) + + t.Run("should handle bounties without assignee", func(t *testing.T) { + + db.TestDB.DeleteAllBounties() + + bountyWithoutAssignee := db.NewBounty{ + ID: 1, + Type: "coding", + Title: "Test Bounty Without Assignee", + Description: "Test Description", + WorkspaceUuid: workspace.Uuid, + PhaseUuid: phase.Uuid, + Show: true, + Created: now.Unix(), + OwnerID: "test-owner", + Price: 1000, + Paid: false, + } + db.TestDB.CreateOrEditBounty(bountyWithoutAssignee) + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(bHandler.GetBountyCards) + + req, err := http.NewRequest(http.MethodGet, "/gobounties/bounty-cards?workspace_uuid="+workspace.Uuid, nil) + assert.NoError(t, err) + + handler.ServeHTTP(rr, req) + + var response []db.BountyCard + err = json.Unmarshal(rr.Body.Bytes(), &response) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, rr.Code) + assert.NotEmpty(t, response, "Response should not be empty") + + cardWithoutAssignee := response[0] + assert.Equal(t, bountyWithoutAssignee.ID, cardWithoutAssignee.BountyID) + assert.Equal(t, bountyWithoutAssignee.Title, cardWithoutAssignee.Title) + assert.Empty(t, cardWithoutAssignee.AssigneePic) + }) +}