package llm import ( "strings" "testing" ) func TestExtractJSON_Variants(t *testing.T) { cases := []struct { name string in string want string okErr bool // true means "expect not-found" }{ {"raw", `{"a":1}`, `{"a":1}`, false}, {"with prose", "Here:\n{\"a\":1}\nend", `{"a":1}`, false}, {"markdown fence", "```json\n{\"a\":1}\n```", `{"a":1}`, false}, {"plain fence", "```\n{\"a\":1}\n```", `{"a":1}`, false}, {"array", `[1,2,3]`, `[1,2,3]`, false}, {"nested braces in strings", `{"k":"a{b}c","v":1}`, `{"k":"a{b}c","v":1}`, false}, {"no JSON", "I cannot help with that.", "", true}, {"truncated", `{"a":1,`, "", true}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { got, ok := ExtractJSON(tc.in) if tc.okErr && ok { t.Fatalf("ExtractJSON should have failed; got %q", got) } if !tc.okErr && !ok { t.Fatalf("ExtractJSON unexpectedly failed for %q", tc.in) } if !tc.okErr && got != tc.want { t.Errorf("got=%q want=%q", got, tc.want) } }) } } func TestAppendSchemaInstruction_KeepsExistingSystem(t *testing.T) { out := AppendSchemaInstruction("be terse", ShapeExpandTerms, nil) if !strings.HasPrefix(out, "be terse") { t.Errorf("rider must follow original system: %q", out) } if !strings.Contains(out, "JSON Schema") { t.Errorf("rider must reference JSON Schema: %q", out) } if !strings.Contains(out, "terms") { t.Errorf("rider must embed shape property name: %q", out) } } func TestAppendSchemaInstruction_Freeform(t *testing.T) { if out := AppendSchemaInstruction("base", ShapeFreeform, nil); out != "base" { t.Errorf("ShapeFreeform must leave the prompt untouched: %q", out) } } func TestAppendSchemaInstruction_EmptyPrompt(t *testing.T) { out := AppendSchemaInstruction("", ShapeRerankOrder, nil) if strings.HasPrefix(out, "\n") { t.Errorf("empty prompt must not leave a leading separator: %q", out) } if !strings.Contains(out, "order") { t.Errorf("rider must embed shape property name: %q", out) } } func TestSnippet_TruncatesLong(t *testing.T) { long := strings.Repeat("x", 1000) out := Snippet([]byte(long)) if len(out) < 100 { t.Errorf("Snippet=%d chars; want a truncated payload", len(out)) } if !strings.HasSuffix(out, "…") { t.Error("long Snippet must end with the truncation marker") } } func TestSnippet_ShortUnchanged(t *testing.T) { if out := Snippet([]byte(" short ")); out != "short" { t.Errorf("Snippet must trim and pass short input through: %q", out) } }