package llm import "testing" func TestExtractJSONObject(t *testing.T) { tests := []struct { name string in string want string }{ {"plain", `{"a":1}`, `{"a":1}`}, {"with prose", "Конечно, вот:\n{\"a\":1}\nготово", `{"a":1}`}, {"fenced json", "```json\n{\"a\":1}\n```", `{"a":1}`}, {"fenced bare", "```\n{\"a\":1}\n```", `{"a":1}`}, {"nested", `{"a":{"b":2},"c":3}`, `{"a":{"b":2},"c":3}`}, {"brace in string", `{"path":"a{b}c","n":1}`, `{"path":"a{b}c","n":1}`}, {"escaped quote in string", `{"q":"he said \"hi\" {x}"}`, `{"q":"he said \"hi\" {x}"}`}, {"trailing after object", `{"a":1} extra {ignored}`, `{"a":1}`}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := ExtractJSONObject(tt.in) if err != nil { t.Fatalf("ExtractJSONObject(%q): %v", tt.in, err) } if got != tt.want { t.Errorf("ExtractJSONObject(%q) = %q, want %q", tt.in, got, tt.want) } }) } } func TestExtractJSONObject_Errors(t *testing.T) { for _, in := range []string{"", "no json here", "just text", `{"unbalanced":1`} { if _, err := ExtractJSONObject(in); err == nil { t.Errorf("ExtractJSONObject(%q): want error", in) } } }