修改gin包为ginx
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
package ginx
|
||||
|
||||
import (
|
||||
"code.yun.ink/pkg/responsex"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Error(ctx *gin.Context, err error, ops ...responsex.Option) {
|
||||
responsex.Error(ctx, ctx.Writer, err, ops...)
|
||||
}
|
||||
|
||||
func ErrorWithData(ctx *gin.Context, err error, data any, ops ...responsex.Option) {
|
||||
responsex.ErrorWithData(ctx, ctx.Writer, err, data, ops...)
|
||||
}
|
||||
|
||||
func ErrorStr(ctx *gin.Context, msg string, ops ...responsex.Option) {
|
||||
responsex.ErrorStr(ctx, ctx.Writer, msg, ops...)
|
||||
}
|
||||
|
||||
func Success(ctx *gin.Context, data any, ops ...responsex.Option) {
|
||||
responsex.Success(ctx, ctx.Writer, data, ops...)
|
||||
}
|
||||
|
||||
func SuccessWithPage(ctx *gin.Context, data any, page responsex.Pagination, ops ...responsex.Option) {
|
||||
responsex.SuccessWithPage(ctx, ctx.Writer, data, &page, ops...)
|
||||
}
|
||||
|
||||
func Custom(ctx *gin.Context, ops ...responsex.Option) {
|
||||
responsex.ResponseCtx(ctx, ctx.Writer, ops...)
|
||||
}
|
||||
|
||||
func MsgMapData(ctx *gin.Context, msgKey string, format map[string]string, data any, ops ...responsex.Option) {
|
||||
responsex.FormatMessage(ctx, ctx.Writer, msgKey, format, data, ops...)
|
||||
}
|
||||
|
||||
func MsgKV(ctx *gin.Context, msgKey string, k string, v string, ops ...responsex.Option) {
|
||||
responsex.FormatMessage(ctx, ctx.Writer, msgKey, map[string]string{k: v}, nil, ops...)
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
package ginx_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"code.yun.ink/pkg/responsex"
|
||||
respgin "code.yun.ink/pkg/responsex/ginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gin.SetMode(gin.TestMode)
|
||||
}
|
||||
|
||||
func decodeBody(t *testing.T, w *httptest.ResponseRecorder) map[string]any {
|
||||
t.Helper()
|
||||
var body map[string]any
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
|
||||
t.Fatalf("decode body failed: %v, raw: %s", err, w.Body.String())
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
func newGinCtx(w *httptest.ResponseRecorder) *gin.Context {
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
return c
|
||||
}
|
||||
|
||||
// ---------- Success ----------
|
||||
|
||||
func TestSuccess(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.Success(c, "hello world")
|
||||
|
||||
body := decodeBody(t, w)
|
||||
if body["code"] != float64(200) {
|
||||
t.Errorf("code = %v, want 200", body["code"])
|
||||
}
|
||||
if body["data"] != "hello world" {
|
||||
t.Errorf("data = %v, want hello world", body["data"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuccessWithOptions(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.Success(c, "created",
|
||||
responsex.SetHttpStatusCode(201),
|
||||
responsex.SetHeader("X-Custom", "gin"),
|
||||
)
|
||||
|
||||
if w.Code != 201 {
|
||||
t.Errorf("http status = %d, want 201", w.Code)
|
||||
}
|
||||
if v := w.Header().Get("X-Custom"); v != "gin" {
|
||||
t.Errorf("X-Custom = %q, want gin", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuccessNilData(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.Success(c, nil)
|
||||
|
||||
body := decodeBody(t, w)
|
||||
if _, ok := body["data"]; ok {
|
||||
t.Errorf("data should be omitted for nil")
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Error ----------
|
||||
|
||||
func TestError(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.Error(c, errors.New("gin error"))
|
||||
|
||||
body := decodeBody(t, w)
|
||||
if body["code"] != float64(400) {
|
||||
t.Errorf("code = %v, want 400", body["code"])
|
||||
}
|
||||
if body["message"] != "gin error" {
|
||||
t.Errorf("message = %v, want 'gin error'", body["message"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWithHttpStatus(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.Error(c, errors.New("server error"),
|
||||
responsex.SetHttpStatusCode(500),
|
||||
)
|
||||
|
||||
if w.Code != 500 {
|
||||
t.Errorf("http status = %d, want 500", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWithHeader(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.Error(c, errors.New("bad request"),
|
||||
responsex.SetHttpStatusCode(400),
|
||||
responsex.SetHeaders(map[string]string{
|
||||
"X-Error-Code": "GIN_001",
|
||||
"X-Request-Id": "abc",
|
||||
}),
|
||||
)
|
||||
|
||||
if v := w.Header().Get("X-Error-Code"); v != "GIN_001" {
|
||||
t.Errorf("X-Error-Code = %q, want GIN_001", v)
|
||||
}
|
||||
if v := w.Header().Get("X-Request-Id"); v != "abc" {
|
||||
t.Errorf("X-Request-Id = %q, want abc", v)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- ErrorWithData ----------
|
||||
|
||||
func TestErrorWithData(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.ErrorWithData(c, errors.New("validation error"), map[string]any{
|
||||
"fields": []string{"email", "name"},
|
||||
})
|
||||
|
||||
body := decodeBody(t, w)
|
||||
data, ok := body["data"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("data should be map, got %T", body["data"])
|
||||
}
|
||||
fields, _ := data["fields"].([]any)
|
||||
if len(fields) != 2 {
|
||||
t.Errorf("fields length = %d, want 2", len(fields))
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWithDataAndOptions(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.ErrorWithData(c, errors.New("gone"), "resource",
|
||||
responsex.SetHttpStatusCode(410),
|
||||
)
|
||||
|
||||
if w.Code != 410 {
|
||||
t.Errorf("http status = %d, want 410", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- ErrorStr ----------
|
||||
|
||||
func TestErrorStr(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.ErrorStr(c, "string error")
|
||||
|
||||
body := decodeBody(t, w)
|
||||
if body["message"] == "" {
|
||||
t.Error("message should not be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorStrWithOptions(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.ErrorStr(c, "forbidden",
|
||||
responsex.SetHttpStatusCode(403),
|
||||
responsex.SetHeader("X-Reason", "no-access"),
|
||||
)
|
||||
|
||||
if w.Code != 403 {
|
||||
t.Errorf("http status = %d, want 403", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- SuccessWithPage ----------
|
||||
|
||||
func TestSuccessWithPage(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
page := responsex.Pagination{
|
||||
Page: 1,
|
||||
Size: 10,
|
||||
TotalPage: 3,
|
||||
TotalCount: 30,
|
||||
}
|
||||
|
||||
respgin.SuccessWithPage(c, []string{"a", "b"}, page)
|
||||
|
||||
body := decodeBody(t, w)
|
||||
p, ok := body["pagination"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("pagination should be map, got %T", body["pagination"])
|
||||
}
|
||||
if p["total_count"] != float64(30) {
|
||||
t.Errorf("total_count = %v, want 30", p["total_count"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuccessWithPageAndOptions(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
page := responsex.Pagination{Page: 1, Size: 20, TotalPage: 1, TotalCount: 20}
|
||||
|
||||
respgin.SuccessWithPage(c, []int{1}, page,
|
||||
responsex.SetHeader("X-Total", "20"),
|
||||
)
|
||||
|
||||
if v := w.Header().Get("X-Total"); v != "20" {
|
||||
t.Errorf("X-Total = %q, want 20", v)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- MsgMapData / MsgKV ----------
|
||||
|
||||
func TestMsgKV(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.MsgKV(c, "welcome", "name", "Alice")
|
||||
|
||||
// 仅验证 HTTP 200 正常返回,具体内容由 langx 决定
|
||||
if w.Code != 200 {
|
||||
t.Errorf("http status = %d, want 200", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgKVWithOptions(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.MsgKV(c, "welcome", "name", "Alice",
|
||||
responsex.SetHeader("X-Lang", "zh"),
|
||||
)
|
||||
|
||||
if v := w.Header().Get("X-Lang"); v != "zh" {
|
||||
t.Errorf("X-Lang = %q, want zh", v)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Custom ----------
|
||||
|
||||
func TestCustom(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c := newGinCtx(w)
|
||||
|
||||
respgin.Custom(c,
|
||||
responsex.SetCode(100),
|
||||
responsex.SetMessage("custom gin"),
|
||||
responsex.SetHttpStatusCode(202),
|
||||
)
|
||||
|
||||
if w.Code != 202 {
|
||||
t.Errorf("http status = %d, want 202", w.Code)
|
||||
}
|
||||
body := decodeBody(t, w)
|
||||
if body["code"] != float64(100) {
|
||||
t.Errorf("code = %v, want 100", body["code"])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user