test(handlers): cover upstream error mapping to API response codes

This commit is contained in:
Noooste
2026-04-20 00:23:55 +02:00
parent cfa13be75b
commit b8061e5109
3 changed files with 94 additions and 0 deletions
+35
View File
@@ -12,6 +12,7 @@ import (
"testing"
"time"
"Noooste/garage-ui/internal/apierr"
"Noooste/garage-ui/internal/models"
"Noooste/garage-ui/internal/services/mocks"
@@ -426,3 +427,37 @@ func TestUpdateBucketWebsite_Disable(t *testing.T) {
t.Fatalf("status = %d", resp.StatusCode)
}
}
func TestDeleteBucket_UpstreamBucketNotEmpty(t *testing.T) {
app, admin := newBucketsTestApp(t)
admin.GetBucketInfoByAliasFn = func(_ context.Context, _ string) (*models.GarageBucketInfo, error) {
return &models.GarageBucketInfo{ID: "id-1"}, nil
}
admin.DeleteBucketFn = func(_ context.Context, _ string) error {
return &apierr.UpstreamError{
HTTPStatus: 409,
Code: "BucketNotEmpty",
Message: "Tried to delete a non-empty bucket",
Source: "garage",
}
}
resp, err := app.Test(httptest.NewRequest(http.MethodDelete, "/buckets/alpha", nil))
if err != nil {
t.Fatalf("app.Test: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusConflict {
t.Fatalf("status = %d, want 409", resp.StatusCode)
}
var body models.APIResponse
decodeJSON(t, resp.Body, &body)
if body.Error == nil {
t.Fatal("error missing from response body")
}
if body.Error.Code != models.ErrCodeBucketNotEmpty {
t.Errorf("code = %q, want %s", body.Error.Code, models.ErrCodeBucketNotEmpty)
}
if body.Error.Message != "Tried to delete a non-empty bucket" {
t.Errorf("message = %q", body.Error.Message)
}
}
+30
View File
@@ -13,6 +13,7 @@ import (
"testing"
"time"
"Noooste/garage-ui/internal/apierr"
"Noooste/garage-ui/internal/models"
"Noooste/garage-ui/internal/services"
"Noooste/garage-ui/internal/services/mocks"
@@ -868,3 +869,32 @@ func TestCreateDirectory_ServiceError500(t *testing.T) {
t.Fatalf("status = %d, want 500", resp.StatusCode)
}
}
func TestDeleteObject_UpstreamNoSuchKey(t *testing.T) {
app, s3 := newObjectsTestApp(t)
s3.ObjectExistsFn = func(_ context.Context, _, _ string) (bool, error) { return true, nil }
s3.DeleteObjectFn = func(_ context.Context, _, _ string) error {
return &apierr.UpstreamError{
HTTPStatus: 404,
Code: "NoSuchKey",
Message: "The specified key does not exist",
Source: "s3",
}
}
resp, err := app.Test(httptest.NewRequest(http.MethodDelete, "/buckets/b1/objects/foo.txt", nil))
if err != nil {
t.Fatalf("app.Test: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusNotFound {
t.Fatalf("status = %d, want 404", resp.StatusCode)
}
var body models.APIResponse
decodeJSON(t, resp.Body, &body)
if body.Error == nil || body.Error.Code != models.ErrCodeObjectNotFound {
t.Fatalf("error = %+v, want code %s", body.Error, models.ErrCodeObjectNotFound)
}
if body.Error.Message != "The specified key does not exist" {
t.Errorf("message = %q", body.Error.Message)
}
}
+29
View File
@@ -11,6 +11,7 @@ import (
"testing"
"time"
"Noooste/garage-ui/internal/apierr"
"Noooste/garage-ui/internal/models"
"Noooste/garage-ui/internal/services/mocks"
@@ -365,3 +366,31 @@ func TestUpdateUser_AdminError500(t *testing.T) {
t.Fatalf("status = %d, want 500", resp.StatusCode)
}
}
func TestDeleteUser_UpstreamAccessDenied(t *testing.T) {
app, admin := newUsersTestApp(t)
admin.DeleteKeyFn = func(_ context.Context, _ string) error {
return &apierr.UpstreamError{
HTTPStatus: 403,
Code: "AccessDenied",
Message: "permission denied",
Source: "garage",
}
}
resp, err := app.Test(httptest.NewRequest(http.MethodDelete, "/users/abc", nil))
if err != nil {
t.Fatalf("app.Test: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusForbidden {
t.Fatalf("status = %d, want 403", resp.StatusCode)
}
var body models.APIResponse
decodeJSON(t, resp.Body, &body)
if body.Error == nil || body.Error.Code != models.ErrCodeForbidden {
t.Fatalf("error = %+v, want code %s", body.Error, models.ErrCodeForbidden)
}
if body.Error.Message != "permission denied" {
t.Errorf("message = %q", body.Error.Message)
}
}