package llmjson import "testing" func TestUnmarshalToleratesEllipsisAndCommas(t *testing.T) { raw := []byte(`{ "nodes": [ {"label": "a", "url": "https://example.com/a"}, ..., {"label": "b"}, ], "edges": [...] }`) var out struct { Nodes []struct { Label string `json:"label"` URL string `json:"url"` } `json:"nodes"` Edges []any `json:"edges"` } if err := Unmarshal(raw, &out); err != nil { t.Fatalf("Unmarshal error: %v", err) } if len(out.Nodes) != 2 { t.Fatalf("nodes = %d, want 2", len(out.Nodes)) } if out.Nodes[0].URL != "https://example.com/a" { t.Fatalf("url mutated: %q", out.Nodes[0].URL) } } func TestSanitizeReturnsNilWhenValid(t *testing.T) { if got := Sanitize([]byte(`{"a":1}`)); got != nil { t.Fatalf("expected nil for clean json, got %q", got) } } func TestSanitizeEscapesNewlinesInsideStrings(t *testing.T) { raw := []byte(`{"examples":"第一行 第二行","identity":"觀察者"}`) cleaned := Sanitize(raw) if cleaned == nil { t.Fatal("expected sanitized output") } var out struct { Examples string `json:"examples"` Identity string `json:"identity"` } if err := Unmarshal(raw, &out); err != nil { t.Fatalf("Unmarshal error: %v", err) } if out.Examples != "第一行\n第二行" { t.Fatalf("examples = %q", out.Examples) } if out.Identity != "觀察者" { t.Fatalf("identity = %q", out.Identity) } } func TestSanitizeKeepsDotsInsideStrings(t *testing.T) { raw := []byte(`{"note":"see ... and https://a.b/c", "list":[1, ...]}`) cleaned := Sanitize(raw) if cleaned == nil { t.Fatal("expected sanitized output") } var out struct { Note string `json:"note"` List []int `json:"list"` } if err := Unmarshal(raw, &out); err != nil { t.Fatalf("Unmarshal error: %v", err) } if out.Note != "see ... and https://a.b/c" { t.Fatalf("string content mutated: %q", out.Note) } if len(out.List) != 1 || out.List[0] != 1 { t.Fatalf("list = %v, want [1]", out.List) } }