| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | package core_test | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2024-11-24 18:41:57 +08:00
										 |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 	"slices" | 
					
						
							| 
									
										
										
										
											2024-11-24 18:41:57 +08:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/pocketbase/pocketbase/core" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestNewFieldsList(t *testing.T) { | 
					
						
							|  |  |  | 	fields := core.NewFieldsList( | 
					
						
							|  |  |  | 		&core.TextField{Id: "id1", Name: "test1"}, | 
					
						
							|  |  |  | 		&core.TextField{Name: "test2"}, | 
					
						
							|  |  |  | 		&core.TextField{Id: "id1", Name: "test1_new"}, // should replace the original id1 field
 | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(fields) != 2 { | 
					
						
							|  |  |  | 		t.Fatalf("Expected 2 fields, got %d (%v)", len(fields), fields) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, f := range fields { | 
					
						
							|  |  |  | 		if f.GetId() == "" { | 
					
						
							|  |  |  | 			t.Fatalf("Expected field id to be set, found empty id for field %v", f) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if fields[0].GetName() != "test1_new" { | 
					
						
							|  |  |  | 		t.Fatalf("Expected field with name test1_new, got %s", fields[0].GetName()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if fields[1].GetName() != "test2" { | 
					
						
							|  |  |  | 		t.Fatalf("Expected field with name test2, got %s", fields[1].GetName()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListClone(t *testing.T) { | 
					
						
							|  |  |  | 	f1 := &core.TextField{Name: "test1"} | 
					
						
							|  |  |  | 	f2 := &core.EmailField{Name: "test2"} | 
					
						
							|  |  |  | 	s1 := core.NewFieldsList(f1, f2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s2, err := s1.Clone() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s1Str := s1.String() | 
					
						
							|  |  |  | 	s2Str := s2.String() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if s1Str != s2Str { | 
					
						
							|  |  |  | 		t.Fatalf("Expected the cloned list to be equal, got \n%v\nVS\n%v", s1, s2) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// change in one list shouldn't result to change in the other
 | 
					
						
							|  |  |  | 	// (aka. check if it is a deep clone)
 | 
					
						
							|  |  |  | 	s1[0].SetName("test1_update") | 
					
						
							|  |  |  | 	if s2[0].GetName() != "test1" { | 
					
						
							|  |  |  | 		t.Fatalf("Expected s2 field name to not change, got %q", s2[0].GetName()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListFieldNames(t *testing.T) { | 
					
						
							|  |  |  | 	f1 := &core.TextField{Name: "test1"} | 
					
						
							|  |  |  | 	f2 := &core.EmailField{Name: "test2"} | 
					
						
							|  |  |  | 	testFieldsList := core.NewFieldsList(f1, f2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result := testFieldsList.FieldNames() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := []string{f1.Name, f2.Name} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(result) != len(expected) { | 
					
						
							|  |  |  | 		t.Fatalf("Expected %d slice elements, got %d\n%v", len(expected), len(result), result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, name := range expected { | 
					
						
							|  |  |  | 		if !slices.Contains(result, name) { | 
					
						
							|  |  |  | 			t.Fatalf("Missing name %q in %v", name, result) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListAsMap(t *testing.T) { | 
					
						
							|  |  |  | 	f1 := &core.TextField{Name: "test1"} | 
					
						
							|  |  |  | 	f2 := &core.EmailField{Name: "test2"} | 
					
						
							|  |  |  | 	testFieldsList := core.NewFieldsList(f1, f2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result := testFieldsList.AsMap() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expectedIndexes := []string{f1.Name, f2.Name} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(result) != len(expectedIndexes) { | 
					
						
							|  |  |  | 		t.Fatalf("Expected %d map elements, got %d\n%v", len(expectedIndexes), len(result), result) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, index := range expectedIndexes { | 
					
						
							|  |  |  | 		if _, ok := result[index]; !ok { | 
					
						
							|  |  |  | 			t.Fatalf("Missing index %q", index) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListGetById(t *testing.T) { | 
					
						
							|  |  |  | 	f1 := &core.TextField{Id: "id1", Name: "test1"} | 
					
						
							|  |  |  | 	f2 := &core.EmailField{Id: "id2", Name: "test2"} | 
					
						
							|  |  |  | 	testFieldsList := core.NewFieldsList(f1, f2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// missing field id
 | 
					
						
							|  |  |  | 	result1 := testFieldsList.GetById("test1") | 
					
						
							|  |  |  | 	if result1 != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Found unexpected field %v", result1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// existing field id
 | 
					
						
							|  |  |  | 	result2 := testFieldsList.GetById("id2") | 
					
						
							|  |  |  | 	if result2 == nil || result2.GetId() != "id2" { | 
					
						
							|  |  |  | 		t.Fatalf("Cannot find field with id %q, got %v ", "id2", result2) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListGetByName(t *testing.T) { | 
					
						
							|  |  |  | 	f1 := &core.TextField{Id: "id1", Name: "test1"} | 
					
						
							|  |  |  | 	f2 := &core.EmailField{Id: "id2", Name: "test2"} | 
					
						
							|  |  |  | 	testFieldsList := core.NewFieldsList(f1, f2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// missing field name
 | 
					
						
							|  |  |  | 	result1 := testFieldsList.GetByName("id1") | 
					
						
							|  |  |  | 	if result1 != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Found unexpected field %v", result1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// existing field name
 | 
					
						
							|  |  |  | 	result2 := testFieldsList.GetByName("test2") | 
					
						
							|  |  |  | 	if result2 == nil || result2.GetName() != "test2" { | 
					
						
							|  |  |  | 		t.Fatalf("Cannot find field with name %q, got %v ", "test2", result2) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListRemove(t *testing.T) { | 
					
						
							|  |  |  | 	testFieldsList := core.NewFieldsList( | 
					
						
							|  |  |  | 		&core.TextField{Id: "id1", Name: "test1"}, | 
					
						
							|  |  |  | 		&core.TextField{Id: "id2", Name: "test2"}, | 
					
						
							|  |  |  | 		&core.TextField{Id: "id3", Name: "test3"}, | 
					
						
							|  |  |  | 		&core.TextField{Id: "id4", Name: "test4"}, | 
					
						
							|  |  |  | 		&core.TextField{Id: "id5", Name: "test5"}, | 
					
						
							|  |  |  | 		&core.TextField{Id: "id6", Name: "test6"}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// remove by id
 | 
					
						
							|  |  |  | 	testFieldsList.RemoveById("id2") | 
					
						
							|  |  |  | 	testFieldsList.RemoveById("test3") // should do nothing
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// remove by name
 | 
					
						
							|  |  |  | 	testFieldsList.RemoveByName("test5") | 
					
						
							|  |  |  | 	testFieldsList.RemoveByName("id6") // should do nothing
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := []string{"test1", "test3", "test4", "test6"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(testFieldsList) != len(expected) { | 
					
						
							|  |  |  | 		t.Fatalf("Expected %d, got %d\n%v", len(expected), len(testFieldsList), testFieldsList) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, name := range expected { | 
					
						
							|  |  |  | 		if f := testFieldsList.GetByName(name); f == nil { | 
					
						
							|  |  |  | 			t.Fatalf("Missing field %q", name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListAdd(t *testing.T) { | 
					
						
							|  |  |  | 	f0 := &core.TextField{} | 
					
						
							|  |  |  | 	f1 := &core.TextField{Name: "test1"} | 
					
						
							|  |  |  | 	f2 := &core.TextField{Id: "f2Id", Name: "test2"} | 
					
						
							|  |  |  | 	f3 := &core.TextField{Id: "f3Id", Name: "test3"} | 
					
						
							|  |  |  | 	testFieldsList := core.NewFieldsList(f0, f1, f2, f3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f2New := &core.EmailField{Id: "f2Id", Name: "test2_new"} | 
					
						
							|  |  |  | 	f4 := &core.URLField{Name: "test4"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	testFieldsList.Add(f2New) | 
					
						
							|  |  |  | 	testFieldsList.Add(f4) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(testFieldsList) != 5 { | 
					
						
							|  |  |  | 		t.Fatalf("Expected %d, got %d\n%v", 5, len(testFieldsList), testFieldsList) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check if each field has id
 | 
					
						
							|  |  |  | 	for _, f := range testFieldsList { | 
					
						
							|  |  |  | 		if f.GetId() == "" { | 
					
						
							|  |  |  | 			t.Fatalf("Expected field id to be set, found empty id for field %v", f) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check if f2 field was replaced
 | 
					
						
							|  |  |  | 	if f := testFieldsList.GetById("f2Id"); f == nil || f.Type() != core.FieldTypeEmail { | 
					
						
							|  |  |  | 		t.Fatalf("Expected f2 field to be replaced, found %v", f) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check if f4 was added
 | 
					
						
							|  |  |  | 	if f := testFieldsList.GetByName("test4"); f == nil || f.GetName() != "test4" { | 
					
						
							|  |  |  | 		t.Fatalf("Expected f4 field to be added, found %v", f) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-09 22:11:14 +08:00
										 |  |  | func TestFieldsListAddMarshaledJSON(t *testing.T) { | 
					
						
							|  |  |  | 	t.Parallel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scenarios := []struct { | 
					
						
							|  |  |  | 		name           string | 
					
						
							|  |  |  | 		raw            []byte | 
					
						
							|  |  |  | 		expectError    bool | 
					
						
							|  |  |  | 		expectedFields map[string]string | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"nil", | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			map[string]string{"abc": core.FieldTypeNumber}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"empty array", | 
					
						
							|  |  |  | 			[]byte(`[]`), | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			map[string]string{"abc": core.FieldTypeNumber}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"empty object", | 
					
						
							|  |  |  | 			[]byte(`{}`), | 
					
						
							|  |  |  | 			true, | 
					
						
							|  |  |  | 			map[string]string{"abc": core.FieldTypeNumber}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"array with empty object", | 
					
						
							|  |  |  | 			[]byte(`[{}]`), | 
					
						
							|  |  |  | 			true, | 
					
						
							|  |  |  | 			map[string]string{"abc": core.FieldTypeNumber}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"single object with invalid type", | 
					
						
							|  |  |  | 			[]byte(`{"type":"missing","name":"test"}`), | 
					
						
							|  |  |  | 			true, | 
					
						
							|  |  |  | 			map[string]string{"abc": core.FieldTypeNumber}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"single object with valid type", | 
					
						
							|  |  |  | 			[]byte(`{"type":"text","name":"test"}`), | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			map[string]string{ | 
					
						
							|  |  |  | 				"abc":  core.FieldTypeNumber, | 
					
						
							|  |  |  | 				"test": core.FieldTypeText, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"array of object with valid types", | 
					
						
							|  |  |  | 			[]byte(`[{"type":"text","name":"test1"},{"type":"url","name":"test2"}]`), | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			map[string]string{ | 
					
						
							|  |  |  | 				"abc":   core.FieldTypeNumber, | 
					
						
							|  |  |  | 				"test1": core.FieldTypeText, | 
					
						
							|  |  |  | 				"test2": core.FieldTypeURL, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"fields with duplicated ids should replace existing fields", | 
					
						
							|  |  |  | 			[]byte(`[{"type":"text","name":"test1"},{"type":"url","name":"test2"},{"type":"text","name":"abc2", "id":"abc_id"}]`), | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			map[string]string{ | 
					
						
							|  |  |  | 				"abc2":  core.FieldTypeText, | 
					
						
							|  |  |  | 				"test1": core.FieldTypeText, | 
					
						
							|  |  |  | 				"test2": core.FieldTypeURL, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, s := range scenarios { | 
					
						
							|  |  |  | 		t.Run(s.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			testList := core.NewFieldsList(&core.NumberField{Name: "abc", Id: "abc_id"}) | 
					
						
							|  |  |  | 			err := testList.AddMarshaledJSON(s.raw) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hasErr := err != nil | 
					
						
							|  |  |  | 			if hasErr != s.expectError { | 
					
						
							|  |  |  | 				t.Fatalf("Expected hasErr %v, got %v", s.expectError, hasErr) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if len(s.expectedFields) != len(testList) { | 
					
						
							|  |  |  | 				t.Fatalf("Expected %d fields, got %d", len(s.expectedFields), len(testList)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for fieldName, typ := range s.expectedFields { | 
					
						
							|  |  |  | 				f := testList.GetByName(fieldName) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if f == nil { | 
					
						
							|  |  |  | 					t.Errorf("Missing expected field %q", fieldName) | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if f.Type() != typ { | 
					
						
							|  |  |  | 					t.Errorf("Expect field %q to has type %q, got %q", fieldName, typ, f.Type()) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-24 18:41:57 +08:00
										 |  |  | func TestFieldsListAddAt(t *testing.T) { | 
					
						
							|  |  |  | 	scenarios := []struct { | 
					
						
							|  |  |  | 		position int | 
					
						
							|  |  |  | 		expected []string | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{-2, []string{"test1", "test2_new", "test3", "test4"}}, | 
					
						
							|  |  |  | 		{-1, []string{"test1", "test2_new", "test3", "test4"}}, | 
					
						
							|  |  |  | 		{0, []string{"test2_new", "test4", "test1", "test3"}}, | 
					
						
							|  |  |  | 		{1, []string{"test1", "test2_new", "test4", "test3"}}, | 
					
						
							|  |  |  | 		{2, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 		{3, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 		{4, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 		{5, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, s := range scenarios { | 
					
						
							|  |  |  | 		t.Run(strconv.Itoa(s.position), func(t *testing.T) { | 
					
						
							|  |  |  | 			f1 := &core.TextField{Id: "f1Id", Name: "test1"} | 
					
						
							|  |  |  | 			f2 := &core.TextField{Id: "f2Id", Name: "test2"} | 
					
						
							|  |  |  | 			f3 := &core.TextField{Id: "f3Id", Name: "test3"} | 
					
						
							|  |  |  | 			testFieldsList := core.NewFieldsList(f1, f2, f3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			f2New := &core.EmailField{Id: "f2Id", Name: "test2_new"} | 
					
						
							|  |  |  | 			f4 := &core.URLField{Name: "test4"} | 
					
						
							|  |  |  | 			testFieldsList.AddAt(s.position, f2New, f4) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rawNames, err := json.Marshal(testFieldsList.FieldNames()) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rawExpected, err := json.Marshal(s.expected) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if !bytes.Equal(rawNames, rawExpected) { | 
					
						
							|  |  |  | 				t.Fatalf("Expected fields\n%s\ngot\n%s", rawExpected, rawNames) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListAddMarshaledJSONAt(t *testing.T) { | 
					
						
							|  |  |  | 	scenarios := []struct { | 
					
						
							|  |  |  | 		position int | 
					
						
							|  |  |  | 		expected []string | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{-2, []string{"test1", "test2_new", "test3", "test4"}}, | 
					
						
							|  |  |  | 		{-1, []string{"test1", "test2_new", "test3", "test4"}}, | 
					
						
							|  |  |  | 		{0, []string{"test2_new", "test4", "test1", "test3"}}, | 
					
						
							|  |  |  | 		{1, []string{"test1", "test2_new", "test4", "test3"}}, | 
					
						
							|  |  |  | 		{2, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 		{3, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 		{4, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 		{5, []string{"test1", "test3", "test2_new", "test4"}}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, s := range scenarios { | 
					
						
							|  |  |  | 		t.Run(strconv.Itoa(s.position), func(t *testing.T) { | 
					
						
							|  |  |  | 			f1 := &core.TextField{Id: "f1Id", Name: "test1"} | 
					
						
							|  |  |  | 			f2 := &core.TextField{Id: "f2Id", Name: "test2"} | 
					
						
							|  |  |  | 			f3 := &core.TextField{Id: "f3Id", Name: "test3"} | 
					
						
							|  |  |  | 			testFieldsList := core.NewFieldsList(f1, f2, f3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err := testFieldsList.AddMarshaledJSONAt(s.position, []byte(`[ | 
					
						
							|  |  |  | 				{"id":"f2Id", "name":"test2_new", "type": "text"}, | 
					
						
							|  |  |  | 				{"name": "test4", "type": "text"} | 
					
						
							|  |  |  | 			]`)) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rawNames, err := json.Marshal(testFieldsList.FieldNames()) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rawExpected, err := json.Marshal(s.expected) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if !bytes.Equal(rawNames, rawExpected) { | 
					
						
							|  |  |  | 				t.Fatalf("Expected fields\n%s\ngot\n%s", rawExpected, rawNames) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-30 00:23:19 +08:00
										 |  |  | func TestFieldsListStringAndValue(t *testing.T) { | 
					
						
							|  |  |  | 	t.Run("empty list", func(t *testing.T) { | 
					
						
							|  |  |  | 		testFieldsList := core.NewFieldsList() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		str := testFieldsList.String() | 
					
						
							|  |  |  | 		if str != "[]" { | 
					
						
							|  |  |  | 			t.Fatalf("Expected empty slice, got\n%q", str) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		v, err := testFieldsList.Value() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if v != str { | 
					
						
							|  |  |  | 			t.Fatalf("Expected String and Value to match") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("list with fields", func(t *testing.T) { | 
					
						
							|  |  |  | 		testFieldsList := core.NewFieldsList( | 
					
						
							|  |  |  | 			&core.TextField{Id: "f1id", Name: "test1"}, | 
					
						
							|  |  |  | 			&core.BoolField{Id: "f2id", Name: "test2"}, | 
					
						
							|  |  |  | 			&core.URLField{Id: "f3id", Name: "test3"}, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		str := testFieldsList.String() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		v, err := testFieldsList.Value() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if v != str { | 
					
						
							|  |  |  | 			t.Fatalf("Expected String and Value to match") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		expectedParts := []string{ | 
					
						
							|  |  |  | 			`"type":"bool"`, | 
					
						
							|  |  |  | 			`"type":"url"`, | 
					
						
							|  |  |  | 			`"type":"text"`, | 
					
						
							|  |  |  | 			`"id":"f1id"`, | 
					
						
							|  |  |  | 			`"id":"f2id"`, | 
					
						
							|  |  |  | 			`"id":"f3id"`, | 
					
						
							|  |  |  | 			`"name":"test1"`, | 
					
						
							|  |  |  | 			`"name":"test2"`, | 
					
						
							|  |  |  | 			`"name":"test3"`, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, part := range expectedParts { | 
					
						
							|  |  |  | 			if !strings.Contains(str, part) { | 
					
						
							|  |  |  | 				t.Fatalf("Missing %q in\nn%v", part, str) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListScan(t *testing.T) { | 
					
						
							|  |  |  | 	scenarios := []struct { | 
					
						
							|  |  |  | 		name        string | 
					
						
							|  |  |  | 		data        any | 
					
						
							|  |  |  | 		expectError bool | 
					
						
							|  |  |  | 		expectJSON  string | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{"nil", nil, false, "[]"}, | 
					
						
							|  |  |  | 		{"empty string", "", false, "[]"}, | 
					
						
							|  |  |  | 		{"empty byte", []byte{}, false, "[]"}, | 
					
						
							|  |  |  | 		{"empty string array", "[]", false, "[]"}, | 
					
						
							|  |  |  | 		{"invalid string", "invalid", true, "[]"}, | 
					
						
							|  |  |  | 		{"non-string", 123, true, "[]"}, | 
					
						
							|  |  |  | 		{"item with no field type", `[{}]`, true, "[]"}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"unknown field type", | 
					
						
							|  |  |  | 			`[{"id":"123","name":"test1","type":"unknown"},{"id":"456","name":"test2","type":"bool"}]`, | 
					
						
							|  |  |  | 			true, | 
					
						
							|  |  |  | 			`[]`, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"only the minimum field options", | 
					
						
							|  |  |  | 			`[{"id":"123","name":"test1","type":"text","required":true},{"id":"456","name":"test2","type":"bool"}]`, | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			`[{"autogeneratePattern":"","hidden":false,"id":"123","max":0,"min":0,"name":"test1","pattern":"","presentable":false,"primaryKey":false,"required":true,"system":false,"type":"text"},{"hidden":false,"id":"456","name":"test2","presentable":false,"required":false,"system":false,"type":"bool"}]`, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"all field options", | 
					
						
							|  |  |  | 			`[{"autogeneratePattern":"","hidden":true,"id":"123","max":12,"min":0,"name":"test1","pattern":"","presentable":true,"primaryKey":false,"required":true,"system":false,"type":"text"},{"hidden":false,"id":"456","name":"test2","presentable":false,"required":false,"system":true,"type":"bool"}]`, | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			`[{"autogeneratePattern":"","hidden":true,"id":"123","max":12,"min":0,"name":"test1","pattern":"","presentable":true,"primaryKey":false,"required":true,"system":false,"type":"text"},{"hidden":false,"id":"456","name":"test2","presentable":false,"required":false,"system":true,"type":"bool"}]`, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, s := range scenarios { | 
					
						
							|  |  |  | 		t.Run(s.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			testFieldsList := core.FieldsList{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err := testFieldsList.Scan(s.data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hasErr := err != nil | 
					
						
							|  |  |  | 			if hasErr != s.expectError { | 
					
						
							|  |  |  | 				t.Fatalf("Expected hasErr %v, got %v (%v)", s.expectError, hasErr, err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			str := testFieldsList.String() | 
					
						
							|  |  |  | 			if str != s.expectJSON { | 
					
						
							|  |  |  | 				t.Fatalf("Expected\n%v\ngot\n%v", s.expectJSON, str) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestFieldsListJSON(t *testing.T) { | 
					
						
							|  |  |  | 	scenarios := []struct { | 
					
						
							|  |  |  | 		name        string | 
					
						
							|  |  |  | 		data        string | 
					
						
							|  |  |  | 		expectError bool | 
					
						
							|  |  |  | 		expectJSON  string | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{"empty string", "", true, "[]"}, | 
					
						
							|  |  |  | 		{"invalid string", "invalid", true, "[]"}, | 
					
						
							|  |  |  | 		{"empty string array", "[]", false, "[]"}, | 
					
						
							|  |  |  | 		{"item with no field type", `[{}]`, true, "[]"}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"unknown field type", | 
					
						
							|  |  |  | 			`[{"id":"123","name":"test1","type":"unknown"},{"id":"456","name":"test2","type":"bool"}]`, | 
					
						
							|  |  |  | 			true, | 
					
						
							|  |  |  | 			`[]`, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"only the minimum field options", | 
					
						
							|  |  |  | 			`[{"id":"123","name":"test1","type":"text","required":true},{"id":"456","name":"test2","type":"bool"}]`, | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			`[{"autogeneratePattern":"","hidden":false,"id":"123","max":0,"min":0,"name":"test1","pattern":"","presentable":false,"primaryKey":false,"required":true,"system":false,"type":"text"},{"hidden":false,"id":"456","name":"test2","presentable":false,"required":false,"system":false,"type":"bool"}]`, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"all field options", | 
					
						
							|  |  |  | 			`[{"autogeneratePattern":"","hidden":true,"id":"123","max":12,"min":0,"name":"test1","pattern":"","presentable":true,"primaryKey":false,"required":true,"system":false,"type":"text"},{"hidden":false,"id":"456","name":"test2","presentable":false,"required":false,"system":true,"type":"bool"}]`, | 
					
						
							|  |  |  | 			false, | 
					
						
							|  |  |  | 			`[{"autogeneratePattern":"","hidden":true,"id":"123","max":12,"min":0,"name":"test1","pattern":"","presentable":true,"primaryKey":false,"required":true,"system":false,"type":"text"},{"hidden":false,"id":"456","name":"test2","presentable":false,"required":false,"system":true,"type":"bool"}]`, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, s := range scenarios { | 
					
						
							|  |  |  | 		t.Run(s.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			testFieldsList := core.FieldsList{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err := testFieldsList.UnmarshalJSON([]byte(s.data)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hasErr := err != nil | 
					
						
							|  |  |  | 			if hasErr != s.expectError { | 
					
						
							|  |  |  | 				t.Fatalf("Expected hasErr %v, got %v (%v)", s.expectError, hasErr, err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			raw, err := testFieldsList.MarshalJSON() | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				t.Fatal(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			str := string(raw) | 
					
						
							|  |  |  | 			if str != s.expectJSON { | 
					
						
							|  |  |  | 				t.Fatalf("Expected\n%v\ngot\n%v", s.expectJSON, str) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |