From b4c13af6bc9f1cb3161afad2326badd779c344e1 Mon Sep 17 00:00:00 2001 From: Jonas Lammler Date: Thu, 5 Nov 2026 13:43:25 +0100 Subject: [PATCH 1/3] chore(exp): add mockutil.NewErrorRequest helper Co-authored-by: Winni Neessen --- hcloud/exp/mockutil/http.go | 24 ++++++++++++++++++++++++ hcloud/exp/mockutil/http_test.go | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/hcloud/exp/mockutil/http.go b/hcloud/exp/mockutil/http.go index 763a0776..9ffe037e 100644 --- a/hcloud/exp/mockutil/http.go +++ b/hcloud/exp/mockutil/http.go @@ -202,3 +202,27 @@ func validateJSONSyntax(raw string) error { return fmt.Errorf("%w %s", err, b.String()) } + +// NewErrorRequest returns a new generic error request for the given HTTP method and +// path and status. +func NewErrorRequest(method string, path string, status int, errorCode, errorMessage string) Request { + jsonRaw := `{ + "error": { + "code": "` + errorCode + `", + "message": "` + errorMessage + `", + "details": null + } + }` + + return Request{ + Method: method, Path: path, + Status: status, + JSONRaw: jsonRaw, + } +} + +// NotFoundRequest returns a generic `Not found` (404) request for the given HTTP method +// and path. +func NotFoundRequest(method string, path string) Request { + return NewErrorRequest(method, path, http.StatusNotFound, "not_found", "entity not found") +} diff --git a/hcloud/exp/mockutil/http_test.go b/hcloud/exp/mockutil/http_test.go index ed91602d..6d0a76fe 100644 --- a/hcloud/exp/mockutil/http_test.go +++ b/hcloud/exp/mockutil/http_test.go @@ -116,3 +116,22 @@ func TestValidateJSONSyntax(t *testing.T) { 5 | "meta": { "pagination": { "page": 1 }}`, ) } + +func TestNewErrorRequest(t *testing.T) { + t.Run("server error", func(t *testing.T) { + r := NewErrorRequest(http.MethodPost, "/path", 500, "server_error", "server error") + assert.Equal(t, "POST", r.Method) + assert.Equal(t, "/path", r.Path) + assert.Equal(t, 500, r.Status) + assert.JSONEq(t, `{ "error": {"code": "server_error", "details": null, "message": "server error" }}`, r.JSONRaw) + }) + + t.Run("not found", func(t *testing.T) { + r := NotFoundRequest(http.MethodPost, "/path") + assert.Equal(t, "POST", r.Method) + assert.Equal(t, "/path", r.Path) + assert.Equal(t, 404, r.Status) + assert.JSONEq(t, `{ "error": {"code": "not_found", "details": null, "message": "entity not found" }}`, r.JSONRaw) + }) + +} From fc017ee789f14a6dbe6cc1430d4de9398ef336da Mon Sep 17 00:00:00 2001 From: Jonas Lammler Date: Thu, 5 Nov 2026 13:47:20 +0100 Subject: [PATCH 2/3] fix: add server error helper --- hcloud/exp/mockutil/http.go | 6 ++++++ hcloud/exp/mockutil/http_test.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hcloud/exp/mockutil/http.go b/hcloud/exp/mockutil/http.go index 9ffe037e..9d5b7c43 100644 --- a/hcloud/exp/mockutil/http.go +++ b/hcloud/exp/mockutil/http.go @@ -226,3 +226,9 @@ func NewErrorRequest(method string, path string, status int, errorCode, errorMes func NotFoundRequest(method string, path string) Request { return NewErrorRequest(method, path, http.StatusNotFound, "not_found", "entity not found") } + +// ServerErrorRequest returns a generic `Internal Server Error` (500) request for the +// given HTTP method and path. +func ServerErrorRequest(method string, path string) Request { + return NewErrorRequest(method, path, http.StatusInternalServerError, "server_error", "server error") +} diff --git a/hcloud/exp/mockutil/http_test.go b/hcloud/exp/mockutil/http_test.go index 6d0a76fe..9f45fc49 100644 --- a/hcloud/exp/mockutil/http_test.go +++ b/hcloud/exp/mockutil/http_test.go @@ -119,7 +119,7 @@ func TestValidateJSONSyntax(t *testing.T) { func TestNewErrorRequest(t *testing.T) { t.Run("server error", func(t *testing.T) { - r := NewErrorRequest(http.MethodPost, "/path", 500, "server_error", "server error") + r := ServerErrorRequest(http.MethodPost, "/path") assert.Equal(t, "POST", r.Method) assert.Equal(t, "/path", r.Path) assert.Equal(t, 500, r.Status) From d92633fef9a1f16b3896fb04e5a5e6ccc5f7cd15 Mon Sep 17 00:00:00 2001 From: Jonas Lammler Date: Thu, 5 Nov 2026 13:53:17 +0100 Subject: [PATCH 3/3] fix: use map instead of raw string --- hcloud/exp/mockutil/http.go | 18 ++++++++---------- hcloud/exp/mockutil/http_test.go | 5 ++--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/hcloud/exp/mockutil/http.go b/hcloud/exp/mockutil/http.go index 9d5b7c43..c50cafb3 100644 --- a/hcloud/exp/mockutil/http.go +++ b/hcloud/exp/mockutil/http.go @@ -206,18 +206,16 @@ func validateJSONSyntax(raw string) error { // NewErrorRequest returns a new generic error request for the given HTTP method and // path and status. func NewErrorRequest(method string, path string, status int, errorCode, errorMessage string) Request { - jsonRaw := `{ - "error": { - "code": "` + errorCode + `", - "message": "` + errorMessage + `", - "details": null - } - }` - return Request{ Method: method, Path: path, - Status: status, - JSONRaw: jsonRaw, + Status: status, + JSON: map[string]any{ + "error": map[string]any{ + "code": errorCode, + "message": errorMessage, + "details": nil, + }, + }, } } diff --git a/hcloud/exp/mockutil/http_test.go b/hcloud/exp/mockutil/http_test.go index 9f45fc49..51ee1fe2 100644 --- a/hcloud/exp/mockutil/http_test.go +++ b/hcloud/exp/mockutil/http_test.go @@ -123,7 +123,7 @@ func TestNewErrorRequest(t *testing.T) { assert.Equal(t, "POST", r.Method) assert.Equal(t, "/path", r.Path) assert.Equal(t, 500, r.Status) - assert.JSONEq(t, `{ "error": {"code": "server_error", "details": null, "message": "server error" }}`, r.JSONRaw) + assert.Equal(t, map[string]any{"error": map[string]any{"code": "server_error", "message": "server error", "details": nil}}, r.JSON) }) t.Run("not found", func(t *testing.T) { @@ -131,7 +131,6 @@ func TestNewErrorRequest(t *testing.T) { assert.Equal(t, "POST", r.Method) assert.Equal(t, "/path", r.Path) assert.Equal(t, 404, r.Status) - assert.JSONEq(t, `{ "error": {"code": "not_found", "details": null, "message": "entity not found" }}`, r.JSONRaw) + assert.Equal(t, map[string]any{"error": map[string]any{"code": "not_found", "message": "entity not found", "details": nil}}, r.JSON) }) - }