1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-01-25 06:42:43 +02:00
pocketbase/resolvers/record_field_resolver_test.go

299 lines
9.2 KiB
Go

package resolvers_test
import (
"encoding/json"
"regexp"
"testing"
"github.com/pocketbase/pocketbase/resolvers"
"github.com/pocketbase/pocketbase/tests"
"github.com/pocketbase/pocketbase/tools/list"
)
func TestRecordFieldResolverUpdateQuery(t *testing.T) {
app, _ := tests.NewTestApp()
defer app.Cleanup()
collection, err := app.Dao().FindCollectionByNameOrId("demo4")
if err != nil {
t.Fatal(err)
}
requestData := map[string]any{
"user": map[string]any{
"id": "4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
"profile": map[string]any{
"id": "d13f60a4-5765-48c7-9e1d-3e782340f833",
"name": "test",
},
},
}
scenarios := []struct {
name string
fields []string
expectQuery string
}{
{
"missing field",
[]string{""},
"SELECT `demo4`.* FROM `demo4`",
},
{
"non relation field",
[]string{"title"},
"SELECT `demo4`.* FROM `demo4`",
},
{
"incomplete rel",
[]string{"onerel"},
"SELECT `demo4`.* FROM `demo4`",
},
{
"single rel",
[]string{"onerel.title"},
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `demo4_onerel` ON [[demo4.onerel]] LIKE ('%' || [[demo4_onerel.id]] || '%')",
},
{
"non-relation field + single rel",
[]string{"title", "onerel.title"},
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `demo4_onerel` ON [[demo4.onerel]] LIKE ('%' || [[demo4_onerel.id]] || '%')",
},
{
"nested incomplete rels",
[]string{"manyrels.onerel"},
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `demo4_manyrels` ON [[demo4.manyrels]] LIKE ('%' || [[demo4_manyrels.id]] || '%')",
},
{
"nested complete rels",
[]string{"manyrels.onerel.title"},
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `demo4_manyrels` ON [[demo4.manyrels]] LIKE ('%' || [[demo4_manyrels.id]] || '%') LEFT JOIN `demo4` `demo4_manyrels_onerel` ON [[demo4_manyrels.onerel]] LIKE ('%' || [[demo4_manyrels_onerel.id]] || '%')",
},
{
"repeated nested rels",
[]string{"manyrels.onerel.manyrels.onerel.title"},
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `demo4_manyrels` ON [[demo4.manyrels]] LIKE ('%' || [[demo4_manyrels.id]] || '%') LEFT JOIN `demo4` `demo4_manyrels_onerel` ON [[demo4_manyrels.onerel]] LIKE ('%' || [[demo4_manyrels_onerel.id]] || '%') LEFT JOIN `demo4` `demo4_manyrels_onerel_manyrels` ON [[demo4_manyrels_onerel.manyrels]] LIKE ('%' || [[demo4_manyrels_onerel_manyrels.id]] || '%') LEFT JOIN `demo4` `demo4_manyrels_onerel_manyrels_onerel` ON [[demo4_manyrels_onerel_manyrels.onerel]] LIKE ('%' || [[demo4_manyrels_onerel_manyrels_onerel.id]] || '%')",
},
{
"multiple rels",
[]string{"manyrels.title", "onerel.onefile"},
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `demo4_manyrels` ON [[demo4.manyrels]] LIKE ('%' || [[demo4_manyrels.id]] || '%') LEFT JOIN `demo4` `demo4_onerel` ON [[demo4.onerel]] LIKE ('%' || [[demo4_onerel.id]] || '%')",
},
{
"@collection join",
[]string{"@collection.demo.title", "@collection.demo2.text", "@collection.demo.file"},
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo` `__collection_demo` LEFT JOIN `demo2` `__collection_demo2`",
},
{
"static @request.user.profile fields",
[]string{"@request.user.id", "@request.user.profile.id", "@request.data.demo"},
"SELECT `demo4`.* FROM `demo4`",
},
{
"relational @request.user.profile fields",
[]string{"@request.user.profile.rel.id", "@request.user.profile.rel.name"},
"^" +
regexp.QuoteMeta("SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `profiles` `__user_profiles` ON [[__user_profiles.id]] =") +
" {:.*} " +
regexp.QuoteMeta("LEFT JOIN `profiles` `__user_profiles_rel` ON [[__user_profiles.rel]] LIKE ('%' || [[__user_profiles_rel.id]] || '%')") +
"$",
},
}
for i, s := range scenarios {
query := app.Dao().RecordQuery(collection)
r := resolvers.NewRecordFieldResolver(app.Dao(), collection, requestData)
for _, field := range s.fields {
r.Resolve(field)
}
if err := r.UpdateQuery(query); err != nil {
t.Errorf("(%d) UpdateQuery failed with error %v", i, err)
continue
}
rawQuery := query.Build().SQL()
if !list.ExistInSliceWithRegex(rawQuery, []string{s.expectQuery}) {
t.Errorf("(%d) Expected query\n %v \ngot:\n %v", i, s.expectQuery, rawQuery)
}
}
}
func TestRecordFieldResolverResolveSchemaFields(t *testing.T) {
app, _ := tests.NewTestApp()
defer app.Cleanup()
collection, err := app.Dao().FindCollectionByNameOrId("demo4")
if err != nil {
t.Fatal(err)
}
requestData := map[string]any{
"user": map[string]any{
"id": "4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
"profile": map[string]any{
"id": "d13f60a4-5765-48c7-9e1d-3e782340f833",
},
},
}
r := resolvers.NewRecordFieldResolver(app.Dao(), collection, requestData)
scenarios := []struct {
fieldName string
expectError bool
expectName string
}{
{"", true, ""},
{" ", true, ""},
{"unknown", true, ""},
{"invalid format", true, ""},
{"id", false, "[[demo4.id]]"},
{"created", false, "[[demo4.created]]"},
{"updated", false, "[[demo4.updated]]"},
{"title", false, "[[demo4.title]]"},
{"title.test", true, ""},
{"manyrels", false, "[[demo4.manyrels]]"},
{"manyrels.", true, ""},
{"manyrels.unknown", true, ""},
{"manyrels.title", false, "[[demo4_manyrels.title]]"},
{"manyrels.onerel.manyrels.onefile", false, "[[demo4_manyrels_onerel_manyrels.onefile]]"},
// @request.user.profile relation join:
{"@request.user.profile.rel.name", false, "[[__user_profiles_rel.name]]"},
// @collection fieds:
{"@collect", true, ""},
{"collection.demo4.title", true, ""},
{"@collection", true, ""},
{"@collection.unknown", true, ""},
{"@collection.demo", true, ""},
{"@collection.demo.", true, ""},
{"@collection.demo.title", false, "[[__collection_demo.title]]"},
{"@collection.demo4.title", false, "[[__collection_demo4.title]]"},
{"@collection.demo4.id", false, "[[__collection_demo4.id]]"},
{"@collection.demo4.created", false, "[[__collection_demo4.created]]"},
{"@collection.demo4.updated", false, "[[__collection_demo4.updated]]"},
{"@collection.demo4.manyrels.missing", true, ""},
{"@collection.demo4.manyrels.onerel.manyrels.onerel.onefile", false, "[[__collection_demo4_manyrels_onerel_manyrels_onerel.onefile]]"},
}
for _, s := range scenarios {
name, params, err := r.Resolve(s.fieldName)
hasErr := err != nil
if hasErr != s.expectError {
t.Errorf("(%q) Expected hasErr %v, got %v (%v)", s.fieldName, s.expectError, hasErr, err)
continue
}
if name != s.expectName {
t.Errorf("(%q) Expected name %q, got %q", s.fieldName, s.expectName, name)
}
// params should be empty for non @request fields
if len(params) != 0 {
t.Errorf("(%q) Expected 0 params, got %v", s.fieldName, params)
}
}
}
func TestRecordFieldResolverResolveStaticRequestDataFields(t *testing.T) {
app, _ := tests.NewTestApp()
defer app.Cleanup()
collection, err := app.Dao().FindCollectionByNameOrId("demo4")
if err != nil {
t.Fatal(err)
}
requestData := map[string]any{
"method": "get",
"query": map[string]any{
"a": 123,
},
"data": map[string]any{
"b": 456,
"c": map[string]int{"sub": 1},
},
"user": map[string]any{
"id": "4d0197cc-2b4a-3f83-a26b-d77bc8423d3c",
"profile": map[string]any{
"id": "d13f60a4-5765-48c7-9e1d-3e782340f833",
"name": "test",
},
},
}
r := resolvers.NewRecordFieldResolver(app.Dao(), collection, requestData)
scenarios := []struct {
fieldName string
expectError bool
expectParamValue string // encoded json
}{
{"@request", true, ""},
{"@request.invalid format", true, ""},
{"@request.invalid_format2!", true, ""},
{"@request.missing", true, ""},
{"@request.method", false, `"get"`},
{"@request.query", true, ``},
{"@request.query.a", false, `123`},
{"@request.query.a.missing", false, ``},
{"@request.data", true, ``},
{"@request.data.b", false, `456`},
{"@request.data.b.missing", false, ``},
{"@request.data.c", false, `"{\"sub\":1}"`},
{"@request.user", true, ""},
{"@request.user.id", false, `"4d0197cc-2b4a-3f83-a26b-d77bc8423d3c"`},
{"@request.user.profile", false, `"{\"id\":\"d13f60a4-5765-48c7-9e1d-3e782340f833\",\"name\":\"test\"}"`},
{"@request.user.profile.name", false, `"test"`},
}
for i, s := range scenarios {
name, params, err := r.Resolve(s.fieldName)
hasErr := err != nil
if hasErr != s.expectError {
t.Errorf("(%d) Expected hasErr %v, got %v (%v)", i, s.expectError, hasErr, err)
continue
}
if hasErr {
continue
}
// missing key
// ---
if len(params) == 0 {
if name != "NULL" {
t.Errorf("(%d) Expected 0 placeholder parameters, got %v", i, params)
}
continue
}
// existing key
// ---
if len(params) != 1 {
t.Errorf("(%d) Expected 1 placeholder parameter, got %v", i, params)
continue
}
var paramName string
var paramValue any
for k, v := range params {
paramName = k
paramValue = v
}
if name != ("{:" + paramName + "}") {
t.Errorf("(%d) Expected parameter name %q, got %q", i, paramName, name)
}
encodedParamValue, _ := json.Marshal(paramValue)
if string(encodedParamValue) != s.expectParamValue {
t.Errorf("(%d) Expected params %v, got %v", i, s.expectParamValue, string(encodedParamValue))
}
}
}