package schema import ( "encoding/json" "testing" ) type SimpleParams struct { Name string `json:"name" description:"The name"` Age int `json:"age" description:"The age"` } type OptionalParams struct { Required string `json:"required" description:"A required field"` Optional *string `json:"optional,omitempty" description:"An optional field"` } type EnumParams struct { Color string `json:"color" description:"The color" enum:"red,green,blue"` } type NestedParams struct { Inner SimpleParams `json:"inner" description:"Nested object"` } type ArrayParams struct { Items []string `json:"items" description:"A list of items"` } type EmbeddedBase struct { ID string `json:"id" description:"The ID"` } type EmbeddedParams struct { EmbeddedBase Name string `json:"name" description:"The name"` } func TestFromStruct_Simple(t *testing.T) { s := FromStruct(SimpleParams{}) if s["type"] != "object" { t.Errorf("expected type=object, got %v", s["type"]) } props, ok := s["properties"].(map[string]any) if !ok { t.Fatal("expected properties to be map[string]any") } if len(props) != 2 { t.Errorf("expected 2 properties, got %d", len(props)) } nameSchema, ok := props["name"].(map[string]any) if !ok { t.Fatal("expected name property to be map[string]any") } if nameSchema["type"] != "string" { t.Errorf("expected name type=string, got %v", nameSchema["type"]) } if nameSchema["description"] != "The name" { t.Errorf("expected name description='The name', got %v", nameSchema["description"]) } ageSchema, ok := props["age"].(map[string]any) if !ok { t.Fatal("expected age property to be map[string]any") } if ageSchema["type"] != "integer" { t.Errorf("expected age type=integer, got %v", ageSchema["type"]) } required, ok := s["required"].([]string) if !ok { t.Fatal("expected required to be []string") } if len(required) != 2 { t.Errorf("expected 2 required fields, got %d", len(required)) } } func TestFromStruct_Optional(t *testing.T) { s := FromStruct(OptionalParams{}) required, ok := s["required"].([]string) if !ok { t.Fatal("expected required to be []string") } // Only "required" field should be required, not "optional" if len(required) != 1 { t.Errorf("expected 1 required field, got %d: %v", len(required), required) } if required[0] != "required" { t.Errorf("expected required field 'required', got %v", required[0]) } } func TestFromStruct_Enum(t *testing.T) { s := FromStruct(EnumParams{}) props := s["properties"].(map[string]any) colorSchema := props["color"].(map[string]any) if colorSchema["type"] != "string" { t.Errorf("expected enum type=string, got %v", colorSchema["type"]) } enums, ok := colorSchema["enum"].([]string) if !ok { t.Fatal("expected enum to be []string") } if len(enums) != 3 { t.Errorf("expected 3 enum values, got %d", len(enums)) } } func TestFromStruct_Nested(t *testing.T) { s := FromStruct(NestedParams{}) props := s["properties"].(map[string]any) innerSchema := props["inner"].(map[string]any) if innerSchema["type"] != "object" { t.Errorf("expected nested type=object, got %v", innerSchema["type"]) } innerProps := innerSchema["properties"].(map[string]any) if len(innerProps) != 2 { t.Errorf("expected 2 inner properties, got %d", len(innerProps)) } } func TestFromStruct_Array(t *testing.T) { s := FromStruct(ArrayParams{}) props := s["properties"].(map[string]any) itemsSchema := props["items"].(map[string]any) if itemsSchema["type"] != "array" { t.Errorf("expected array type=array, got %v", itemsSchema["type"]) } items := itemsSchema["items"].(map[string]any) if items["type"] != "string" { t.Errorf("expected items type=string, got %v", items["type"]) } } func TestFromStruct_Embedded(t *testing.T) { s := FromStruct(EmbeddedParams{}) props := s["properties"].(map[string]any) // Should have both ID from embedded and Name if len(props) != 2 { t.Errorf("expected 2 properties (flattened), got %d", len(props)) } if _, ok := props["id"]; !ok { t.Error("expected 'id' property from embedded struct") } if _, ok := props["name"]; !ok { t.Error("expected 'name' property") } } func TestFromStruct_ValidJSON(t *testing.T) { s := FromStruct(SimpleParams{}) data, err := json.Marshal(s) if err != nil { t.Fatalf("schema should be valid JSON: %v", err) } var parsed map[string]any if err := json.Unmarshal(data, &parsed); err != nil { t.Fatalf("schema should round-trip through JSON: %v", err) } }