Skip to content
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
19 changes: 9 additions & 10 deletions internal/capability/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package capability
import (
"context"
"encoding/json"
"errors"
"log/slog"
"net/http"
"products/internal"
Expand Down Expand Up @@ -51,7 +50,7 @@ func (h *handler) GetCapability(w http.ResponseWriter, r *http.Request) {
defer cancel()
capability, err := h.service.GetCapability(ctxWithTimeout, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Capability not found"}, http.StatusNotFound)
return
}
Expand All @@ -72,7 +71,7 @@ func (h *handler) GetCapabilitiesByFlow(w http.ResponseWriter, r *http.Request)
defer cancel()
capabilities, err := h.service.GetCapabilitiesByFlow(ctxWithTimeout, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Flow not found"}, http.StatusNotFound)
return
}
Expand All @@ -93,7 +92,7 @@ func (h *handler) GetCapabilitiesByProduct(w http.ResponseWriter, r *http.Reques
defer cancel()
capabilities, err := h.service.GetCapabilitiesByProduct(ctxWithTimeout, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Product not found"}, http.StatusNotFound)
return
}
Expand Down Expand Up @@ -124,7 +123,7 @@ func (h *handler) UpdateCapability(w http.ResponseWriter, r *http.Request) {
defer cancel()
capability, err := h.service.UpdateCapability(ctxWithTimeout, *req)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Capability not found"}, http.StatusNotFound)
return
}
Expand All @@ -145,7 +144,7 @@ func (h *handler) DeleteCapability(w http.ResponseWriter, r *http.Request) {
defer cancel()
err := h.service.DeleteCapability(ctxWithTimout, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Capability not found"}, http.StatusNotFound)
return
}
Expand All @@ -171,10 +170,10 @@ func (h *handler) CreateCapabilityStep(w http.ResponseWriter, r *http.Request) {
defer cancel()
capStep, err := h.service.CreateCapabilityStep(ctxWithTimeout, *req)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error()}, http.StatusNotFound)
return
} else if errors.Is(err, internal.ValidationError{}) {
} else if internal.IsValidationError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error()}, http.StatusBadRequest)
return
}
Expand All @@ -195,7 +194,7 @@ func (h *handler) DeleteCapabilityStep(w http.ResponseWriter, r *http.Request) {
defer cancel()
err := h.service.DeleteCapabilityStep(ctxWithTimeout, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Capability step not found", Instance: strconv.Itoa(id)}, http.StatusNotFound)
return
}
Expand All @@ -216,7 +215,7 @@ func (h *handler) GetCapabilitySteps(w http.ResponseWriter, r *http.Request) {
defer cancel()
steps, err := h.service.GetCapabilitySteps(ctxWithTimeout, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Capability not found"}, http.StatusNotFound)
return
}
Expand Down
14 changes: 7 additions & 7 deletions internal/capability/service_capability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func TestService_CreateCapability(t *testing.T) {
}
},
checkError: func(t *testing.T, err error) {
if !errors.Is(err, internal.NotFoundError{}) {
if !internal.IsNotFoundError(err) {
t.Errorf("expected NotFoundError, got %T", err)
}
},
Expand All @@ -169,7 +169,7 @@ func TestService_CreateCapability(t *testing.T) {
}
},
checkError: func(t *testing.T, err error) {
if !errors.Is(err, internal.NotFoundError{}) {
if !internal.IsNotFoundError(err) {
t.Errorf("expected NotFoundError, got %T", err)
}
},
Expand Down Expand Up @@ -269,7 +269,7 @@ func TestService_GetCapability(t *testing.T) {
}
},
checkError: func(t *testing.T, err error) {
if !errors.Is(err, internal.NotFoundError{}) {
if !internal.IsNotFoundError(err) {
t.Errorf("expected NotFoundError, got %T", err)
}
},
Expand Down Expand Up @@ -366,7 +366,7 @@ func TestService_GetCapabilitiesByProduct(t *testing.T) {
}
},
checkError: func(t *testing.T, err error) {
if !errors.Is(err, internal.NotFoundError{}) {
if !internal.IsNotFoundError(err) {
t.Errorf("expected NotFoundError, got %T", err)
}
},
Expand Down Expand Up @@ -476,7 +476,7 @@ func TestService_GetCapabilitiesByFlow(t *testing.T) {
}
},
checkError: func(t *testing.T, err error) {
if !errors.Is(err, internal.NotFoundError{}) {
if !internal.IsNotFoundError(err) {
t.Errorf("expected NotFoundError, got %T", err)
}
},
Expand Down Expand Up @@ -579,7 +579,7 @@ func TestService_UpdateCapability(t *testing.T) {
}
},
checkError: func(t *testing.T, err error) {
if !errors.Is(err, internal.NotFoundError{}) {
if !internal.IsNotFoundError(err) {
t.Errorf("expected NotFoundError, got %T", err)
}
},
Expand Down Expand Up @@ -675,7 +675,7 @@ func TestService_DeleteCapability(t *testing.T) {
}
},
checkError: func(t *testing.T, err error) {
if !errors.Is(err, internal.NotFoundError{}) {
if !internal.IsNotFoundError(err) {
t.Errorf("expected NotFoundError, got %T", err)
}
},
Expand Down
21 changes: 11 additions & 10 deletions internal/errors.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"errors"
"strconv"
)

Expand All @@ -13,11 +14,6 @@ func (e NotFoundError) Error() string {
return e.itemType + " not found with ID: " + strconv.Itoa(e.id)
}

func (e NotFoundError) Is(target error) bool {
_, ok := target.(NotFoundError)
return ok
}

type ValidationError struct {
msg string
}
Expand All @@ -26,11 +22,6 @@ func (e ValidationError) Error() string {
return e.msg
}

func (e ValidationError) Is(target error) bool {
_, ok := target.(ValidationError)
return ok
}

func NewValidationErr(message string) ValidationError {
return ValidationError{
msg: message,
Expand All @@ -40,3 +31,13 @@ func NewValidationErr(message string) ValidationError {
func NewNotFoundError(id int, itemType string) NotFoundError {
return NotFoundError{id: id, itemType: itemType}
}

func IsNotFoundError(err error) bool {
_, ok := errors.AsType[NotFoundError](err)
return ok
}

func IsValidationError(err error) bool {
_, ok := errors.AsType[ValidationError](err)
return ok
}
77 changes: 77 additions & 0 deletions internal/errors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package internal

import (
"errors"
"fmt"
"testing"
)

func TestIsNotFoundError(t *testing.T) {
t.Run("returns true for NotFoundError", func(t *testing.T) {
err := NewNotFoundError(1, "Product")
if !IsNotFoundError(err) {
t.Errorf("IsNotFoundError(err) = false; want true")
}
})

t.Run("returns true for wrapped NotFoundError", func(t *testing.T) {
err := fmt.Errorf("wrapped: %w", NewNotFoundError(1, "Product"))
if !IsNotFoundError(err) {
t.Errorf("IsNotFoundError(err) = false; want true")
}
})

t.Run("returns false for other errors", func(t *testing.T) {
err := errors.New("some other error")
if IsNotFoundError(err) {
t.Errorf("IsNotFoundError(err) = true; want false")
}
})

t.Run("returns false for nil error", func(t *testing.T) {
if IsNotFoundError(nil) {
t.Errorf("IsNotFoundError(nil) = true; want false")
}
})
}

func TestIsValidationError(t *testing.T) {
t.Run("returns true for ValidationError", func(t *testing.T) {
err := NewValidationErr("invalid input")
if !IsValidationError(err) {
t.Errorf("IsValidationError(err) = false; want true")
}
})

t.Run("returns true for wrapped ValidationError", func(t *testing.T) {
err := fmt.Errorf("wrapped: %w", NewValidationErr("invalid input"))
if !IsValidationError(err) {
t.Errorf("IsValidationError(err) = false; want true")
}
})

t.Run("returns false for other errors", func(t *testing.T) {
err := errors.New("some other error")
if IsValidationError(err) {
t.Errorf("IsValidationError(err) = true; want false")
}
})

t.Run("returns false for nil error", func(t *testing.T) {
if IsValidationError(nil) {
t.Errorf("IsValidationError(nil) = true; want false")
}
})
}

func TestNotFoundError(t *testing.T) {
err := NewNotFoundError(123, "Product")

t.Run("Error message", func(t *testing.T) {
expected := "Product not found with ID: 123"
if err.Error() != expected {
t.Errorf("expected %q, got %q", expected, err.Error())
}
})

}
18 changes: 9 additions & 9 deletions internal/flow/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (h *handler) CreateFlow(w http.ResponseWriter, r *http.Request) {
defer cancel()
flow, err := h.flowService.CreateFlow(contextWithTimeOut, *req, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error()}, http.StatusNotFound)
return
}
Expand All @@ -61,7 +61,7 @@ func (h *handler) GetFlowById(w http.ResponseWriter, r *http.Request) {
defer cancel()
flow, err := h.flowService.GetFlowById(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand All @@ -81,7 +81,7 @@ func (h *handler) GetFlowsByProduct(w http.ResponseWriter, r *http.Request) {
defer cancel()
flows, err := h.flowService.GetFlowsByProduct(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand Down Expand Up @@ -114,7 +114,7 @@ func (h *handler) UpdateFlow(w http.ResponseWriter, r *http.Request) {

flow, err := h.flowService.UpdateFlow(contextWithTimeOut, *req, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand All @@ -137,7 +137,7 @@ func (h *handler) DeleteFlow(w http.ResponseWriter, r *http.Request) {

err := h.flowService.DeleteFlow(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand Down Expand Up @@ -179,7 +179,7 @@ func (h *handler) CreateFlowStep(w http.ResponseWriter, r *http.Request) {
defer cancel()
flowStep, err := h.flowService.CreateFlowStep(contextWithTimeOut, *req)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand Down Expand Up @@ -214,7 +214,7 @@ func (h *handler) DeleteFlowStep(w http.ResponseWriter, r *http.Request) {
defer cancel()
err := h.flowService.DeleteFlowStep(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand All @@ -238,7 +238,7 @@ func (h *handler) GetFlowSteps(w http.ResponseWriter, r *http.Request) {
defer cancel()
flowSteps, err := h.flowService.GetFlowSteps(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand All @@ -258,7 +258,7 @@ func (h *handler) GetFlowPath(w http.ResponseWriter, r *http.Request) {
defer cancel()
flowPath, err := h.flowService.GetFlowPath(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: err.Error(), Instance: r.URL.Path}, http.StatusNotFound)
return
}
Expand Down
10 changes: 4 additions & 6 deletions internal/platform/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package platform
import (
"context"
"encoding/json"
"errors"
"net/http"
"products/internal"
"products/internal/platform/db"
Expand Down Expand Up @@ -67,7 +66,7 @@ func (h *handler) UpdatePlatform(w http.ResponseWriter, r *http.Request) {
defer cancel()
_, err := h.service.UpdatePlatform(contextWithTimeOut, req, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Platform not found"}, http.StatusNotFound)
return
}
Expand All @@ -88,12 +87,11 @@ func (h *handler) DeletePlatform(w http.ResponseWriter, r *http.Request) {
defer cancel()
_, err := h.service.DeletePlatform(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Platform not found"}, http.StatusNotFound)
return
}
logger := internal.LoggerFromContext(r.Context())
logger.Error("Failed to delete platform", "error", err, "platform_id", id)
internal.LoggerFromContext(r.Context()).Error("Failed to delete platform", "error", err, "platform_id", id)
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Internal server error"}, http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -125,7 +123,7 @@ func (h *handler) GetPlatform(w http.ResponseWriter, r *http.Request) {
defer cancel()
platform, err := h.service.GetPlatform(contextWithTimeOut, id)
if err != nil {
if errors.Is(err, internal.NotFoundError{}) {
if internal.IsNotFoundError(err) {
internal.HandleHttpError(w, internal.ErrorEnvelope{Detail: "Platform not found"}, http.StatusNotFound)
return
}
Expand Down
Loading
Loading