package classifier import ( "testing" ) func TestParseTier1Response_Clean(t *testing.T) { raw := `{"channel": "tech", "platforms": [], "duplicate_of": null, "rationale": "GPU launch story"}` result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if result.Channel != "tech" { t.Errorf("channel = %q, want tech", result.Channel) } if len(result.Platforms) != 0 { t.Errorf("platforms = %v, want empty", result.Platforms) } if result.DuplicateOf != nil { t.Errorf("duplicate_of = %v, want nil", result.DuplicateOf) } } func TestParseTier1Response_WithPlatforms(t *testing.T) { raw := `{"channel":"gaming","platforms":["nintendo-switch","pc"],"duplicate_of":null,"rationale":"Switch 2 launch"}` result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if result.Channel != "gaming" { t.Errorf("channel = %q", result.Channel) } if len(result.Platforms) != 2 { t.Fatalf("platforms = %v, want 2", result.Platforms) } if result.Platforms[0] != "nintendo-switch" || result.Platforms[1] != "pc" { t.Errorf("platforms = %v", result.Platforms) } } func TestParseTier1Response_WithDuplicate(t *testing.T) { raw := `{"channel":"politics","platforms":[],"duplicate_of":"guid-abc-123","rationale":"same event"}` result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if result.DuplicateOf == nil || *result.DuplicateOf != "guid-abc-123" { t.Errorf("duplicate_of = %v", result.DuplicateOf) } } func TestParseTier1Response_InvalidChannel(t *testing.T) { raw := `{"channel":"sports","platforms":[],"duplicate_of":null,"rationale":"test"}` _, err := ParseTier1Response(raw) if err == nil { t.Error("expected error for invalid channel") } } func TestParseTier1Response_FiltersInvalidPlatforms(t *testing.T) { raw := `{"channel":"gaming","platforms":["nintendo-switch","fake-platform","pc","also-fake"],"duplicate_of":null,"rationale":"test"}` result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if len(result.Platforms) != 2 { t.Fatalf("platforms = %v, want [nintendo-switch pc]", result.Platforms) } } func TestParseTier2Response_PostTrue(t *testing.T) { raw := `{"post":true,"channel":"politics","platforms":[],"duplicate_of":null,"rationale":"major world event"}` result, err := ParseTier2Response(raw) if err != nil { t.Fatal(err) } if !result.Post { t.Error("post = false, want true") } if result.Channel != "politics" { t.Errorf("channel = %q", result.Channel) } } func TestParseTier2Response_PostFalse(t *testing.T) { raw := `{"post":false,"platforms":[],"duplicate_of":null,"rationale":"local news"}` result, err := ParseTier2Response(raw) if err != nil { t.Fatal(err) } if result.Post { t.Error("post = true, want false") } } func TestRepairJSON_MarkdownFences(t *testing.T) { raw := "```json\n{\"channel\": \"tech\", \"platforms\": [], \"duplicate_of\": null, \"rationale\": \"test\"}\n```" result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if result.Channel != "tech" { t.Errorf("channel = %q", result.Channel) } } func TestRepairJSON_ThinkBlocks(t *testing.T) { raw := "I need to classify this as tech because it's about GPUs\n{\"channel\": \"tech\", \"platforms\": [], \"duplicate_of\": null, \"rationale\": \"GPU story\"}" result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if result.Channel != "tech" { t.Errorf("channel = %q", result.Channel) } } func TestRepairJSON_TrailingCommas(t *testing.T) { raw := `{"channel": "politics", "platforms": [], "duplicate_of": null, "rationale": "test",}` result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if result.Channel != "politics" { t.Errorf("channel = %q", result.Channel) } } func TestRepairJSON_TrailingCommaInArray(t *testing.T) { raw := `{"channel": "gaming", "platforms": ["pc", "xbox",], "duplicate_of": null, "rationale": "test"}` result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if len(result.Platforms) != 2 { t.Errorf("platforms = %v", result.Platforms) } } func TestRepairJSON_CombinedIssues(t *testing.T) { raw := "reasoning here\n```json\n{\"channel\": \"tech\", \"platforms\": [],\"duplicate_of\": null, \"rationale\": \"test\",}\n```" result, err := ParseTier1Response(raw) if err != nil { t.Fatal(err) } if result.Channel != "tech" { t.Errorf("channel = %q", result.Channel) } } func TestRepairJSON_GarbageInput(t *testing.T) { _, err := ParseTier1Response("I think this should go to tech because reasons") if err == nil { t.Error("expected error for garbage input") } }