1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2024-11-25 09:21:11 +02:00
pocketbase/tools/rest/json_serializer_test.go

196 lines
4.6 KiB
Go

package rest_test
import (
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/labstack/echo/v5"
"github.com/pocketbase/pocketbase/tools/rest"
"github.com/pocketbase/pocketbase/tools/search"
)
func TestSerialize(t *testing.T) {
scenarios := []struct {
name string
serializer rest.Serializer
data any
query string
expected string
}{
{
"empty query",
rest.Serializer{},
map[string]any{"a": 1, "b": 2, "c": "test"},
"",
`{"a":1,"b":2,"c":"test"}`,
},
{
"empty fields",
rest.Serializer{},
map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=",
`{"a":1,"b":2,"c":"test"}`,
},
{
"missing fields",
rest.Serializer{},
map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=missing",
`{}`,
},
{
"non map response",
rest.Serializer{},
"test",
"fields=a,b,test",
`"test"`,
},
{
"non slice of map response",
rest.Serializer{},
[]any{"a", "b", "test"},
"fields=a,test",
`["a","b","test"]`,
},
{
"map with existing and missing fields",
rest.Serializer{},
map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=a, c ,missing", // test individual fields trim
`{"a":1,"c":"test"}`,
},
{
"custom fields param",
rest.Serializer{FieldsParam: "custom"},
map[string]any{"a": 1, "b": 2, "c": "test"},
"custom=a, c ,missing", // test individual fields trim
`{"a":1,"c":"test"}`,
},
{
"slice of maps with existing and missing fields",
rest.Serializer{},
[]any{
map[string]any{"a": 11, "b": 11, "c": "test1"},
map[string]any{"a": 22, "b": 22, "c": "test2"},
},
"fields=a, c ,missing", // test individual fields trim
`[{"a":11,"c":"test1"},{"a":22,"c":"test2"}]`,
},
{
"nested fields with mixed map and any slices",
rest.Serializer{},
map[string]any{
"a": 1,
"b": 2,
"c": "test",
"anySlice": []any{
map[string]any{
"A": []int{1, 2, 3},
"B": []any{"1", "2", 3},
"C": "test",
"D": map[string]any{
"DA": 1,
"DB": 2,
},
},
map[string]any{
"A": "test",
},
},
"mapSlice": []map[string]any{
{
"A": []int{1, 2, 3},
"B": []any{"1", "2", 3},
"C": "test",
"D": []any{
map[string]any{"DA": 1},
},
},
{
"B": []any{"1", "2", 3},
"D": []any{
map[string]any{"DA": 2},
map[string]any{"DA": 3},
map[string]any{"DB": 4}, // will result to empty since there is no DA
},
},
},
"fullMap": []map[string]any{
{
"A": []int{1, 2, 3},
"B": []any{"1", "2", 3},
"C": "test",
},
{
"B": []any{"1", "2", 3},
"D": []any{
map[string]any{"DA": 2},
map[string]any{"DA": 3}, // will result to empty since there is no DA
},
},
},
},
"fields=a, c, anySlice.A, mapSlice.C, mapSlice.D.DA, anySlice.D,fullMap",
`{"a":1,"anySlice":[{"A":[1,2,3],"D":{"DA":1,"DB":2}},{"A":"test"}],"c":"test","fullMap":[{"A":[1,2,3],"B":["1","2",3],"C":"test"},{"B":["1","2",3],"D":[{"DA":2},{"DA":3}]}],"mapSlice":[{"C":"test","D":[{"DA":1}]},{"D":[{"DA":2},{"DA":3},{}]}]}`,
},
{
"SearchResult",
rest.Serializer{},
search.Result{
Page: 1,
PerPage: 10,
TotalItems: 20,
TotalPages: 30,
Items: []any{
map[string]any{"a": 11, "b": 11, "c": "test1"},
map[string]any{"a": 22, "b": 22, "c": "test2"},
},
},
"fields=a,c,missing",
`{"items":[{"a":11,"c":"test1"},{"a":22,"c":"test2"}],"page":1,"perPage":10,"totalItems":20,"totalPages":30}`,
},
{
"*SearchResult",
rest.Serializer{},
&search.Result{
Page: 1,
PerPage: 10,
TotalItems: 20,
TotalPages: 30,
Items: []any{
map[string]any{"a": 11, "b": 11, "c": "test1"},
map[string]any{"a": 22, "b": 22, "c": "test2"},
},
},
"fields=a,c",
`{"items":[{"a":11,"c":"test1"},{"a":22,"c":"test2"}],"page":1,"perPage":10,"totalItems":20,"totalPages":30}`,
},
}
for _, s := range scenarios {
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/", nil)
req.URL.RawQuery = s.query
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
if err := s.serializer.Serialize(c, s.data, ""); err != nil {
t.Errorf("[%s] Serialize failure: %v", s.name, err)
continue
}
rawBody, err := io.ReadAll(rec.Result().Body)
if err != nil {
t.Errorf("[%s] Failed to read request body: %v", s.name, err)
continue
}
if v := strings.TrimSpace(string(rawBody)); v != s.expected {
t.Fatalf("[%s] Expected body\n%v \ngot: \n%v", s.name, s.expected, v)
}
}
}