From 33a3ba6d287cbd1627e5c1d475e4dd55050f0cb3 Mon Sep 17 00:00:00 2001 From: MahtabBukhari Date: Wed, 4 Dec 2024 11:30:49 +0500 Subject: [PATCH 1/3] update unmarshalling on the the update ticket handler --- handlers/ticket.go | 32 +++++++++++++++---- handlers/ticket_test.go | 68 +++++++++++------------------------------ 2 files changed, 44 insertions(+), 56 deletions(-) diff --git a/handlers/ticket.go b/handlers/ticket.go index 4cf3d167b..03a71bb4e 100644 --- a/handlers/ticket.go +++ b/handlers/ticket.go @@ -36,6 +36,14 @@ func NewTicketHandler(httpClient HttpClient, database db.Database) *ticketHandle } } +type UpdateTicketRequest struct { + Metadata struct { + Source string `json:"source"` + ID string `json:"id"` + } `json:"metadata"` + Ticket *db.Tickets `json:"ticket"` +} + func (th *ticketHandler) GetTicket(w http.ResponseWriter, r *http.Request) { uuid := chi.URLParam(r, "uuid") if uuid == "" { @@ -93,22 +101,34 @@ func (th *ticketHandler) UpdateTicket(w http.ResponseWriter, r *http.Request) { } defer r.Body.Close() - var ticket db.Tickets - if err := json.Unmarshal(body, &ticket); err != nil { + var updateRequest UpdateTicketRequest + if err := json.Unmarshal(body, &updateRequest); err != nil { + + var ticket db.Tickets + if err := json.Unmarshal(body, &ticket); err != nil { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(map[string]string{"error": "Error parsing request body"}) + return + } + + updateRequest.Ticket = &ticket + } + + if updateRequest.Ticket == nil { w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(map[string]string{"error": "Error parsing request body"}) + json.NewEncoder(w).Encode(map[string]string{"error": "Ticket data is required"}) return } - ticket.UUID = ticketUUID + updateRequest.Ticket.UUID = ticketUUID - if ticket.Status != "" && !db.IsValidTicketStatus(ticket.Status) { + if updateRequest.Ticket.Status != "" && !db.IsValidTicketStatus(updateRequest.Ticket.Status) { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]string{"error": "Invalid ticket status"}) return } - updatedTicket, err := th.db.CreateOrEditTicket(&ticket) + updatedTicket, err := th.db.CreateOrEditTicket(updateRequest.Ticket) if err != nil { if err.Error() == "feature_uuid, phase_uuid, and name are required" { w.WriteHeader(http.StatusBadRequest) diff --git a/handlers/ticket_test.go b/handlers/ticket_test.go index 890a405c0..fe5b2efe3 100644 --- a/handlers/ticket_test.go +++ b/handlers/ticket_test.go @@ -247,58 +247,29 @@ func TestUpdateTicket(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rr.Code) }) - t.Run("should update ticket with only UUID and optional fields", func(t *testing.T) { + t.Run("should update ticket with new format", func(t *testing.T) { rr := httptest.NewRecorder() handler := http.HandlerFunc(tHandler.UpdateTicket) - // Create a ticket with only UUID and some optional fields - updateTicket := db.Tickets{ - UUID: createdTicket.UUID, - Description: "Updated description", // Optional field - Status: db.ReadyTicket, // Optional field + updateRequest := UpdateTicketRequest{ + Metadata: struct { + Source string `json:"source"` + ID string `json:"id"` + }{ + Source: "websocket", + ID: "ws-12345", + }, + Ticket: &db.Tickets{ + UUID: createdTicket.UUID, + Description: "Updated Description via new format", + Status: db.ReadyTicket, + }, } - requestBody, _ := json.Marshal(updateTicket) - rctx := chi.NewRouteContext() - rctx.URLParams.Add("uuid", updateTicket.UUID.String()) - req, err := http.NewRequest(http.MethodPost, "/tickets/"+updateTicket.UUID.String(), bytes.NewReader(requestBody)) - if err != nil { - t.Fatal(err) - } - - ctx := context.WithValue(req.Context(), auth.ContextKey, person.OwnerPubKey) - req = req.WithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx)) - - handler.ServeHTTP(rr, req) - assert.Equal(t, http.StatusOK, rr.Code) - - var returnedTicket db.Tickets - err = json.Unmarshal(rr.Body.Bytes(), &returnedTicket) - assert.NoError(t, err) - - // Verify that only the provided fields were updated - assert.Equal(t, updateTicket.Description, returnedTicket.Description) - assert.Equal(t, updateTicket.Status, returnedTicket.Status) - // Original fields should remain unchanged - assert.Equal(t, createdTicket.FeatureUUID, returnedTicket.FeatureUUID) - assert.Equal(t, createdTicket.PhaseUUID, returnedTicket.PhaseUUID) - assert.Equal(t, createdTicket.Name, returnedTicket.Name) - }) - - t.Run("should update ticket successfully", func(t *testing.T) { - rr := httptest.NewRecorder() - handler := http.HandlerFunc(tHandler.UpdateTicket) - - updatedTicket := createdTicket - updatedTicket.Name = "Updated Test Ticket" - updatedTicket.Description = "Updated Description" - updatedTicket.Status = db.CompletedTicket - - requestBody, _ := json.Marshal(updatedTicket) + requestBody, _ := json.Marshal(updateRequest) rctx := chi.NewRouteContext() rctx.URLParams.Add("uuid", createdTicket.UUID.String()) - - req, err := http.NewRequest(http.MethodPut, "/tickets/"+createdTicket.UUID.String(), bytes.NewReader(requestBody)) + req, err := http.NewRequest(http.MethodPost, "/tickets/"+createdTicket.UUID.String(), bytes.NewReader(requestBody)) if err != nil { t.Fatal(err) } @@ -313,11 +284,8 @@ func TestUpdateTicket(t *testing.T) { var returnedTicket db.Tickets err = json.Unmarshal(rr.Body.Bytes(), &returnedTicket) assert.NoError(t, err) - assert.Equal(t, updatedTicket.Name, returnedTicket.Name) - assert.Equal(t, updatedTicket.Description, returnedTicket.Description) - assert.Equal(t, updatedTicket.Status, returnedTicket.Status) - assert.Equal(t, updatedTicket.FeatureUUID, returnedTicket.FeatureUUID) - assert.Equal(t, updatedTicket.PhaseUUID, returnedTicket.PhaseUUID) + assert.Equal(t, updateRequest.Ticket.Description, returnedTicket.Description) + assert.Equal(t, updateRequest.Ticket.Status, returnedTicket.Status) }) } From 522e241a08f47792bfe9668e9a4ecac5310b0d24 Mon Sep 17 00:00:00 2001 From: MahtabBukhari Date: Wed, 4 Dec 2024 12:28:29 +0500 Subject: [PATCH 2/3] update unit tests --- handlers/ticket_test.go | 72 +++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/handlers/ticket_test.go b/handlers/ticket_test.go index fe5b2efe3..aa46a554d 100644 --- a/handlers/ticket_test.go +++ b/handlers/ticket_test.go @@ -247,28 +247,78 @@ func TestUpdateTicket(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rr.Code) }) - t.Run("should update ticket with new format", func(t *testing.T) { + t.Run("should update ticket with only UUID and optional fields", func(t *testing.T) { rr := httptest.NewRecorder() handler := http.HandlerFunc(tHandler.UpdateTicket) + updateTicket := db.Tickets{ + UUID: createdTicket.UUID, + Description: "Updated description", // Optional field + Status: db.ReadyTicket, // Optional field + } + updateRequest := UpdateTicketRequest{ Metadata: struct { Source string `json:"source"` ID string `json:"id"` }{ - Source: "websocket", - ID: "ws-12345", + Source: "test-source", + ID: "test-id", }, - Ticket: &db.Tickets{ - UUID: createdTicket.UUID, - Description: "Updated Description via new format", - Status: db.ReadyTicket, + Ticket: &updateTicket, + } + + requestBody, _ := json.Marshal(updateRequest) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("uuid", updateTicket.UUID.String()) + req, err := http.NewRequest(http.MethodPost, "/tickets/"+updateTicket.UUID.String(), bytes.NewReader(requestBody)) + if err != nil { + t.Fatal(err) + } + + ctx := context.WithValue(req.Context(), auth.ContextKey, person.OwnerPubKey) + req = req.WithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx)) + + handler.ServeHTTP(rr, req) + assert.Equal(t, http.StatusOK, rr.Code) + + var returnedTicket db.Tickets + err = json.Unmarshal(rr.Body.Bytes(), &returnedTicket) + assert.NoError(t, err) + + // Verify that only the provided fields were updated + assert.Equal(t, updateTicket.Description, returnedTicket.Description) + assert.Equal(t, updateTicket.Status, returnedTicket.Status) + // Original fields should remain unchanged + assert.Equal(t, createdTicket.FeatureUUID, returnedTicket.FeatureUUID) + assert.Equal(t, createdTicket.PhaseUUID, returnedTicket.PhaseUUID) + assert.Equal(t, createdTicket.Name, returnedTicket.Name) + }) + + t.Run("should update ticket successfully", func(t *testing.T) { + rr := httptest.NewRecorder() + handler := http.HandlerFunc(tHandler.UpdateTicket) + + updatedTicket := createdTicket + updatedTicket.Name = "Updated Test Ticket" + updatedTicket.Description = "Updated Description" + updatedTicket.Status = db.CompletedTicket + + updateRequest := UpdateTicketRequest{ + Metadata: struct { + Source string `json:"source"` + ID string `json:"id"` + }{ + Source: "test-source", + ID: "test-id", }, + Ticket: &updatedTicket, } requestBody, _ := json.Marshal(updateRequest) rctx := chi.NewRouteContext() rctx.URLParams.Add("uuid", createdTicket.UUID.String()) + req, err := http.NewRequest(http.MethodPost, "/tickets/"+createdTicket.UUID.String(), bytes.NewReader(requestBody)) if err != nil { t.Fatal(err) @@ -284,9 +334,13 @@ func TestUpdateTicket(t *testing.T) { var returnedTicket db.Tickets err = json.Unmarshal(rr.Body.Bytes(), &returnedTicket) assert.NoError(t, err) - assert.Equal(t, updateRequest.Ticket.Description, returnedTicket.Description) - assert.Equal(t, updateRequest.Ticket.Status, returnedTicket.Status) + assert.Equal(t, updatedTicket.Name, returnedTicket.Name) + assert.Equal(t, updatedTicket.Description, returnedTicket.Description) + assert.Equal(t, updatedTicket.Status, returnedTicket.Status) + assert.Equal(t, updatedTicket.FeatureUUID, returnedTicket.FeatureUUID) + assert.Equal(t, updatedTicket.PhaseUUID, returnedTicket.PhaseUUID) }) + } func TestDeleteTicket(t *testing.T) { From 3bf01dad2261f29d545c6d9674dc59b8eaa3d862 Mon Sep 17 00:00:00 2001 From: MahtabBukhari Date: Wed, 4 Dec 2024 13:00:55 +0500 Subject: [PATCH 3/3] second part --- handlers/ticket.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/handlers/ticket.go b/handlers/ticket.go index 03a71bb4e..781490df6 100644 --- a/handlers/ticket.go +++ b/handlers/ticket.go @@ -201,8 +201,8 @@ func (th *ticketHandler) PostTicketDataToStakwork(w http.ResponseWriter, r *http } defer r.Body.Close() - var ticket db.Tickets - if err := json.Unmarshal(body, &ticket); err != nil { + var ticketRequest UpdateTicketRequest + if err := json.Unmarshal(body, &ticketRequest); err != nil { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(TicketResponse{ Success: false, @@ -212,13 +212,22 @@ func (th *ticketHandler) PostTicketDataToStakwork(w http.ResponseWriter, r *http return } + if ticketRequest.Ticket == nil { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(TicketResponse{ + Success: false, + Message: "Validation failed", + Errors: []string{"Ticket data is required"}, + }) + return + } + + ticket := ticketRequest.Ticket var validationErrors []string if ticket.UUID == uuid.Nil { validationErrors = append(validationErrors, "UUID is required") - } else { - if _, err := uuid.Parse(ticket.UUID.String()); err != nil { - validationErrors = append(validationErrors, "Invalid UUID format") - } + } else if _, err := uuid.Parse(ticket.UUID.String()); err != nil { + validationErrors = append(validationErrors, "Invalid UUID format") } if len(validationErrors) > 0 { @@ -295,6 +304,7 @@ func (th *ticketHandler) PostTicketDataToStakwork(w http.ResponseWriter, r *http "productBrief": productBrief, "featureBrief": featureBrief, "examples": "", + "sourceWebsocket": ticketRequest.Metadata.ID, "webhook_url": webhookURL, }, },