Files
ai-agent/internal/pkg/httpx/response_test.go
T

127 lines
3.4 KiB
Go
Raw Normal View History

package httpx
import (
"code.tczkiot.com/wlw/ai-agent/internal/pkg/errorsx"
"code.tczkiot.com/wlw/ai-agent/internal/pkg/i18nx"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/mlogclub/simple/sqls"
"github.com/mlogclub/simple/web"
)
func TestWriteJSONWrapsCommonResultTypes(t *testing.T) {
gin.SetMode(gin.TestMode)
tests := []struct {
name string
input any
wantStatus int
want web.JsonResult
}{
{
name: "nil becomes success",
input: nil,
wantStatus: http.StatusOK,
want: *web.JsonSuccess(),
},
{
name: "plain value becomes data",
input: map[string]any{"id": float64(1)},
wantStatus: http.StatusOK,
want: *web.JsonData(map[string]any{"id": float64(1)}),
},
{
name: "error becomes json error",
input: errors.New("boom"),
wantStatus: http.StatusOK,
want: *web.JsonError(errors.New("boom")),
},
{
name: "page data becomes page result",
input: PageData([]any{"a"}, &sqls.Paging{Page: 1, Limit: 20, Total: 1}),
wantStatus: http.StatusOK,
want: *web.JsonPageData([]any{"a"}, &sqls.Paging{Page: 1, Limit: 20, Total: 1}),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx, recorder := testContext()
WriteJSON(ctx, tt.input)
if recorder.Code != tt.wantStatus {
t.Fatalf("status = %d, want %d", recorder.Code, tt.wantStatus)
}
var got web.JsonResult
if err := json.Unmarshal(recorder.Body.Bytes(), &got); err != nil {
t.Fatalf("decode response: %v", err)
}
if got.Success != tt.want.Success || got.ErrorCode != tt.want.ErrorCode || got.Message != tt.want.Message {
t.Fatalf("result = %+v, want %+v", got, tt.want)
}
})
}
}
func TestWriteJSONLocalizesI18nErrors(t *testing.T) {
2026-05-25 12:06:15 +08:00
gin.SetMode(gin.TestMode)
ctx, recorder := testContext()
i18nx.SetLocale(ctx, i18nx.LocaleEnUS)
WriteJSON(ctx, errorsx.InvalidParamI18n("error.e0116"))
2026-05-25 12:06:15 +08:00
var got web.JsonResult
if err := json.Unmarshal(recorder.Body.Bytes(), &got); err != nil {
t.Fatalf("decode response: %v", err)
}
if got.Message != "Conversation not found." {
t.Fatalf("message = %q, want %q", got.Message, "Conversation not found.")
}
}
func TestWriteJSONUsesSnakeCaseCursorFields(t *testing.T) {
gin.SetMode(gin.TestMode)
ctx, recorder := testContext()
WriteJSON(ctx, CursorData([]string{"a"}, "next", true))
var body map[string]any
if err := json.Unmarshal(recorder.Body.Bytes(), &body); err != nil {
t.Fatalf("decode response: %v", err)
}
data, ok := body["data"].(map[string]any)
if !ok {
t.Fatalf("data = %#v, want object", body["data"])
}
if got := data["has_more"]; got != true {
t.Fatalf("has_more = %#v, want true", got)
}
if _, exists := data["hasMore"]; exists {
t.Fatalf("camelCase hasMore should not be exposed: %s", recorder.Body.String())
}
}
func TestWriteHttpStatusJSONUsesProvidedStatus(t *testing.T) {
gin.SetMode(gin.TestMode)
ctx, recorder := testContext()
WriteHttpStatusJSON(ctx, http.StatusUnauthorized, web.JsonErrorMsg("unauthorized"))
if recorder.Code != http.StatusUnauthorized {
t.Fatalf("status = %d, want %d", recorder.Code, http.StatusUnauthorized)
}
}
func testContext() (*gin.Context, *httptest.ResponseRecorder) {
recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.Request = httptest.NewRequest(http.MethodGet, "/", nil)
return ctx, recorder
}