package bootstrap import "testing" // TestRenderFieldModern locks the v0.23+ ("fields") wire shape for each field // type against what PocketBase expects. func TestRenderFieldModern(t *testing.T) { idByName := map[string]string{"cars": "col_cars"} rel := renderField(fRelation("car", "cars", true, true), "fields", idByName) if rel["collectionId"] != "col_cars" || rel["cascadeDelete"] != true || rel["maxSelect"] != 1 || rel["minSelect"] != 0 || rel["required"] != true { t.Fatalf("relation rendered wrong: %#v", rel) } nonCascade := renderField(fRelation("owner", "users", false, false), "fields", map[string]string{"users": "u"}) if nonCascade["cascadeDelete"] != false { t.Fatalf("non-cascading relation should keep cascadeDelete=false: %#v", nonCascade) } sel := renderField(fSelect("result", []string{"passed", "failed"}, false), "fields", idByName) if sel["maxSelect"] != 1 { t.Fatalf("select maxSelect: %#v", sel) } if vals, ok := sel["values"].([]string); !ok || len(vals) != 2 { t.Fatalf("select values: %#v", sel["values"]) } ad := renderField(fAutodate("created", true, false), "fields", idByName) if ad["onCreate"] != true || ad["onUpdate"] != false { t.Fatalf("autodate: %#v", ad) } file := renderField(attachment(), "fields", idByName) if file["maxSize"] != 10485760 || file["maxSelect"] != 1 { t.Fatalf("file: %#v", file) } if mt, ok := file["mimeTypes"].([]string); !ok || len(mt) != 5 { t.Fatalf("file mimeTypes: %#v", file["mimeTypes"]) } j := renderField(fJSON("params", 10000), "fields", idByName) if j["maxSize"] != 10000 { t.Fatalf("json: %#v", j) } } // TestRenderFieldLegacy checks that the legacy ("schema") layout nests options. func TestRenderFieldLegacy(t *testing.T) { rel := renderField(fRelation("car", "cars", true, true), "schema", map[string]string{"cars": "col_cars"}) opts, ok := rel["options"].(map[string]any) if !ok { t.Fatalf("legacy relation should nest options: %#v", rel) } if opts["collectionId"] != "col_cars" || opts["cascadeDelete"] != true { t.Fatalf("legacy relation options: %#v", opts) } } // TestSameValues covers the select-reconcile comparison (order-insensitive). func TestSameValues(t *testing.T) { if !sameValues([]any{"a", "b"}, []string{"b", "a"}) { t.Fatal("same set in different order should compare equal") } if sameValues([]any{"a"}, []string{"a", "b"}) { t.Fatal("differing lengths should not be equal") } if sameValues([]any{"a", "c"}, []string{"a", "b"}) { t.Fatal("differing members should not be equal") } if sameValues(nil, []string{"a"}) { t.Fatal("nil current should not equal non-empty want") } } // TestSchemaConsistency guards the ordered lists against the schema map. func TestSchemaConsistency(t *testing.T) { for _, name := range createOrder { if _, ok := collectionsSchema[name]; !ok { t.Errorf("createOrder references unknown collection %q", name) } if name == "users" { t.Errorf("users must not be in createOrder (built-in auth collection)") } } for _, name := range reconcileOrder { if _, ok := collectionsSchema[name]; !ok { t.Errorf("reconcileOrder references unknown collection %q", name) } } for name := range indexes { if _, ok := collectionsSchema[name]; !ok { t.Errorf("indexes references unknown collection %q", name) } } }