@@ -3,9 +3,153 @@ package taxonomy
33import (
44 "testing"
55
6+ "github.com/supermodeltools/cli/internal/archdocs/pssg/config"
67 "github.com/supermodeltools/cli/internal/archdocs/pssg/entity"
78)
89
10+ // ── BuildAll / buildOne / extractValues ───────────────────────────────────────
11+
12+ func TestBuildAll_Basic (t * testing.T ) {
13+ entities := []* entity.Entity {
14+ {Slug : "pasta" , Fields : map [string ]interface {}{"cuisine" : "Italian" }},
15+ {Slug : "ramen" , Fields : map [string ]interface {}{"cuisine" : "Japanese" }},
16+ {Slug : "sushi" , Fields : map [string ]interface {}{"cuisine" : "Japanese" }},
17+ }
18+ tc := config.TaxonomyConfig {Name : "cuisine" , Field : "cuisine" , MinEntities : 1 }
19+ taxes := BuildAll (entities , []config.TaxonomyConfig {tc }, nil )
20+
21+ if len (taxes ) != 1 {
22+ t .Fatalf ("expected 1 taxonomy, got %d" , len (taxes ))
23+ }
24+ tax := taxes [0 ]
25+ if tax .Name != "cuisine" {
26+ t .Errorf ("tax name: got %q, want cuisine" , tax .Name )
27+ }
28+ // 2 unique cuisines: Italian (1 entity), Japanese (2 entities)
29+ if len (tax .Entries ) != 2 {
30+ t .Errorf ("expected 2 entries, got %d" , len (tax .Entries ))
31+ }
32+ }
33+
34+ func TestBuildAll_MinEntitiesFilter (t * testing.T ) {
35+ entities := []* entity.Entity {
36+ {Slug : "pasta" , Fields : map [string ]interface {}{"cuisine" : "Italian" }},
37+ {Slug : "ramen" , Fields : map [string ]interface {}{"cuisine" : "Japanese" }},
38+ {Slug : "sushi" , Fields : map [string ]interface {}{"cuisine" : "Japanese" }},
39+ }
40+ tc := config.TaxonomyConfig {Name : "cuisine" , Field : "cuisine" , MinEntities : 2 }
41+ taxes := BuildAll (entities , []config.TaxonomyConfig {tc }, nil )
42+
43+ // Only Japanese (2 entities) passes the min_entities=2 filter.
44+ if len (taxes [0 ].Entries ) != 1 {
45+ t .Errorf ("expected 1 entry (only Japanese), got %d" , len (taxes [0 ].Entries ))
46+ }
47+ if taxes [0 ].Entries [0 ].Name != "Japanese" {
48+ t .Errorf ("expected Japanese, got %q" , taxes [0 ].Entries [0 ].Name )
49+ }
50+ }
51+
52+ func TestBuildAll_MultiValue (t * testing.T ) {
53+ entities := []* entity.Entity {
54+ {Slug : "pasta" , Fields : map [string ]interface {}{"tags" : []string {"italian" , "pasta" }}},
55+ {Slug : "pizza" , Fields : map [string ]interface {}{"tags" : []string {"italian" , "baked" }}},
56+ }
57+ tc := config.TaxonomyConfig {Name : "tags" , Field : "tags" , MultiValue : true , MinEntities : 1 }
58+ taxes := BuildAll (entities , []config.TaxonomyConfig {tc }, nil )
59+
60+ // Should have 3 unique tags: italian (2), pasta (1), baked (1)
61+ if len (taxes [0 ].Entries ) != 3 {
62+ t .Errorf ("multi-value: expected 3 entries, got %d: %v" , len (taxes [0 ].Entries ), taxes [0 ].Entries )
63+ }
64+ }
65+
66+ func TestBuildAll_Empty (t * testing.T ) {
67+ taxes := BuildAll (nil , nil , nil )
68+ if taxes != nil {
69+ t .Errorf ("nil input: want nil, got %v" , taxes )
70+ }
71+ }
72+
73+ func TestExtractValues_SingleValue (t * testing.T ) {
74+ e := & entity.Entity {Fields : map [string ]interface {}{"cuisine" : "Italian" }}
75+ tc := config.TaxonomyConfig {Field : "cuisine" }
76+ got := extractValues (e , tc , nil )
77+ if len (got ) != 1 || got [0 ] != "Italian" {
78+ t .Errorf ("single value: got %v, want [Italian]" , got )
79+ }
80+ }
81+
82+ func TestExtractValues_Missing (t * testing.T ) {
83+ e := & entity.Entity {Fields : map [string ]interface {}{}}
84+ tc := config.TaxonomyConfig {Field : "cuisine" }
85+ if got := extractValues (e , tc , nil ); got != nil {
86+ t .Errorf ("missing field: want nil, got %v" , got )
87+ }
88+ }
89+
90+ func TestExtractValues_EnrichmentOverride (t * testing.T ) {
91+ e := & entity.Entity {
92+ Slug : "pasta" ,
93+ Fields : map [string ]interface {}{"cuisine" : "Italian" },
94+ }
95+ tc := config.TaxonomyConfig {
96+ Field : "cuisine" ,
97+ EnrichmentOverrideField : "override_cuisine" ,
98+ }
99+ enrichment := map [string ]map [string ]interface {}{
100+ "pasta" : {"override_cuisine" : "Mediterranean" },
101+ }
102+ got := extractValues (e , tc , enrichment )
103+ if len (got ) != 1 || got [0 ] != "Mediterranean" {
104+ t .Errorf ("enrichment override: got %v, want [Mediterranean]" , got )
105+ }
106+ }
107+
108+ // ── getEnrichmentOverrides ────────────────────────────────────────────────────
109+
110+ func TestGetEnrichmentOverrides_SimpleField (t * testing.T ) {
111+ data := map [string ]interface {}{"cuisine" : "Italian" }
112+ got := getEnrichmentOverrides (data , "cuisine" )
113+ if len (got ) != 1 || got [0 ] != "Italian" {
114+ t .Errorf ("simple field: got %v, want [Italian]" , got )
115+ }
116+ }
117+
118+ func TestGetEnrichmentOverrides_SimpleField_Missing (t * testing.T ) {
119+ data := map [string ]interface {}{}
120+ if got := getEnrichmentOverrides (data , "cuisine" ); got != nil {
121+ t .Errorf ("missing field: want nil, got %v" , got )
122+ }
123+ }
124+
125+ func TestGetEnrichmentOverrides_ArrayPath (t * testing.T ) {
126+ data := map [string ]interface {}{
127+ "ingredients" : []interface {}{
128+ map [string ]interface {}{"normalizedName" : "tomato" },
129+ map [string ]interface {}{"normalizedName" : "basil" },
130+ map [string ]interface {}{"normalizedName" : "" }, // empty — should be skipped
131+ },
132+ }
133+ got := getEnrichmentOverrides (data , "ingredients[].normalizedName" )
134+ if len (got ) != 2 || got [0 ] != "tomato" || got [1 ] != "basil" {
135+ t .Errorf ("array path: got %v, want [tomato basil]" , got )
136+ }
137+ }
138+
139+ func TestGetEnrichmentOverrides_ArrayField_Missing (t * testing.T ) {
140+ data := map [string ]interface {}{}
141+ if got := getEnrichmentOverrides (data , "ingredients[].name" ); got != nil {
142+ t .Errorf ("missing array: want nil, got %v" , got )
143+ }
144+ }
145+
146+ func TestGetEnrichmentOverrides_ArrayField_NotArray (t * testing.T ) {
147+ data := map [string ]interface {}{"ingredients" : "not-an-array" }
148+ if got := getEnrichmentOverrides (data , "ingredients[].name" ); got != nil {
149+ t .Errorf ("non-array: want nil, got %v" , got )
150+ }
151+ }
152+
9153// TestGroupByLetterASCII verifies that ASCII entry names are grouped correctly.
10154func TestGroupByLetterASCII (t * testing.T ) {
11155 entries := []Entry {
0 commit comments