@@ -47,7 +47,7 @@ func TestFlatten(t *testing.T) {
4747
4848 for _ , tc := range tests {
4949 t .Run (tc .name , func (t * testing.T ) {
50- result := flattenTo (tc .input , maxFlattenDepth )
50+ result := flattenTo (tc .input , defaultMaxDepth )
5151 assert .Equal (t , tc .expected , result )
5252 })
5353 }
@@ -72,11 +72,10 @@ func TestFlatten(t *testing.T) {
7272}
7373
7474func TestTrimArrayFields (t * testing.T ) {
75- original := collectionFieldExtractors
76- defer func () { collectionFieldExtractors = original }()
77-
78- collectionFieldExtractors = map [string ][]string {
79- "reviewers" : {"login" , "state" },
75+ cfg := OptimizeListConfig {
76+ collectionExtractors : map [string ][]string {
77+ "reviewers" : {"login" , "state" },
78+ },
8079 }
8180
8281 result := optimizeItem (map [string ]any {
@@ -85,7 +84,7 @@ func TestTrimArrayFields(t *testing.T) {
8584 map [string ]any {"login" : "bob" , "state" : "changes_requested" , "id" : float64 (2 )},
8685 },
8786 "title" : "Fix bug" ,
88- })
87+ }, cfg )
8988
9089 expected := []any {
9190 map [string ]any {"login" : "alice" , "state" : "approved" },
@@ -96,6 +95,8 @@ func TestTrimArrayFields(t *testing.T) {
9695}
9796
9897func TestFilterByFillRate (t * testing.T ) {
98+ cfg := OptimizeListConfig {}
99+
99100 items := []map [string ]any {
100101 {"title" : "a" , "body" : "text" , "milestone" : "v1" },
101102 {"title" : "b" , "body" : "text" },
@@ -109,7 +110,7 @@ func TestFilterByFillRate(t *testing.T) {
109110 {"title" : "j" , "body" : "text" },
110111 }
111112
112- result := filterByFillRate (items , 0.1 )
113+ result := filterByFillRate (items , 0.1 , cfg )
113114
114115 for _ , item := range result {
115116 assert .Contains (t , item , "title" )
@@ -119,145 +120,144 @@ func TestFilterByFillRate(t *testing.T) {
119120}
120121
121122func TestFilterByFillRate_PreservesFields (t * testing.T ) {
122- original := preservedFields
123- defer func () { preservedFields = original }()
124-
125- preservedFields = map [string ]bool {"html_url" : true }
123+ cfg := OptimizeListConfig {
124+ preservedFields : map [string ]bool {"html_url" : true },
125+ }
126126
127127 items := make ([]map [string ]any , 10 )
128128 for i := range items {
129129 items [i ] = map [string ]any {"title" : "x" }
130130 }
131131 items [0 ]["html_url" ] = "https://github.com/repo/1"
132132
133- result := filterByFillRate (items , 0.1 )
133+ result := filterByFillRate (items , 0.1 , cfg )
134134 assert .Contains (t , result [0 ], "html_url" )
135135}
136136
137- func TestOptimizeItems (t * testing.T ) {
138- tests := []struct {
139- name string
140- items []map [string ]any
141- expected []map [string ]any
142- }{
137+ func TestOptimizeList_AllStrategies (t * testing.T ) {
138+ items := []map [string ]any {
143139 {
144- name : "applies all strategies in sequence" ,
145- items : []map [string ]any {
146- {
147- "title" : "Fix bug" ,
148- "body" : "line1\n \n line2" ,
149- "url" : "https://api.github.com/repos/1" ,
150- "html_url" : "https://github.com/repo/1" ,
151- "avatar_url" : "https://avatars.githubusercontent.com/1" ,
152- "draft" : false ,
153- "merged_at" : nil ,
154- "labels" : []any {map [string ]any {"name" : "bug" }},
155- "user" : map [string ]any {
156- "login" : "user" ,
157- "avatar_url" : "https://avatars.githubusercontent.com/1" ,
158- },
159- },
160- },
161- expected : []map [string ]any {
162- {
163- "title" : "Fix bug" ,
164- "body" : "line1 line2" ,
165- "html_url" : "https://github.com/repo/1" ,
166- "draft" : false ,
167- "labels" : "bug" ,
168- "user.login" : "user" ,
169- },
140+ "title" : "Fix bug" ,
141+ "body" : "line1\n \n line2" ,
142+ "url" : "https://api.github.com/repos/1" ,
143+ "html_url" : "https://github.com/repo/1" ,
144+ "avatar_url" : "https://avatars.githubusercontent.com/1" ,
145+ "draft" : false ,
146+ "merged_at" : nil ,
147+ "labels" : []any {map [string ]any {"name" : "bug" }},
148+ "user" : map [string ]any {
149+ "login" : "user" ,
150+ "avatar_url" : "https://avatars.githubusercontent.com/1" ,
170151 },
171152 },
172- {
173- name : "nil input" ,
174- items : nil ,
175- expected : nil ,
176- },
177153 }
178154
179- for _ , tc := range tests {
180- t .Run (tc .name , func (t * testing.T ) {
181- result := OptimizeItems (tc .items , maxFlattenDepth )
182- assert .Equal (t , tc .expected , result )
183- })
184- }
155+ raw , err := OptimizeList (items ,
156+ WithPreservedFields (map [string ]bool {"html_url" : true , "draft" : true }),
157+ WithCollectionExtractors (map [string ][]string {"labels" : {"name" }}),
158+ )
159+ require .NoError (t , err )
160+
161+ var result []map [string ]any
162+ err = json .Unmarshal (raw , & result )
163+ require .NoError (t , err )
164+ require .Len (t , result , 1 )
165+
166+ assert .Equal (t , "Fix bug" , result [0 ]["title" ])
167+ assert .Equal (t , "line1 line2" , result [0 ]["body" ])
168+ assert .Equal (t , "https://github.com/repo/1" , result [0 ]["html_url" ])
169+ assert .Equal (t , false , result [0 ]["draft" ])
170+ assert .Equal (t , "bug" , result [0 ]["labels" ])
171+ assert .Equal (t , "user" , result [0 ]["user.login" ])
172+ assert .Nil (t , result [0 ]["url" ])
173+ assert .Nil (t , result [0 ]["avatar_url" ])
174+ assert .Nil (t , result [0 ]["merged_at" ])
185175}
186176
187- func TestOptimizeItems_SkipsFillRateBelowMinRows (t * testing.T ) {
177+ func TestOptimizeList_NilInput (t * testing.T ) {
178+ raw , err := OptimizeList [map [string ]any ](nil )
179+ require .NoError (t , err )
180+ assert .Equal (t , "null" , string (raw ))
181+ }
182+
183+ func TestOptimizeList_SkipsFillRateBelowMinRows (t * testing.T ) {
188184 items := []map [string ]any {
189185 {"title" : "a" , "rare" : "x" },
190186 {"title" : "b" },
191187 }
192188
193- result := OptimizeItems (items , maxFlattenDepth )
189+ raw , err := OptimizeList (items )
190+ require .NoError (t , err )
191+
192+ var result []map [string ]any
193+ err = json .Unmarshal (raw , & result )
194+ require .NoError (t , err )
195+
194196 assert .Equal (t , "x" , result [0 ]["rare" ])
195197}
196198
197199func TestPreservedFields (t * testing.T ) {
198- original := preservedFields
199- defer func () { preservedFields = original }()
200-
201- preservedFields = map [ string ] bool {
202- "html_url" : true ,
203- "clone_url" : true ,
204- }
200+ t . Run ( "keeps preserved URL keys, strips non-preserved" , func ( t * testing. T ) {
201+ cfg := OptimizeListConfig {
202+ preservedFields : map [ string ] bool {
203+ "html_url" : true ,
204+ "clone_url" : true ,
205+ } ,
206+ }
205207
206- result := optimizeItem (map [string ]any {
207- "html_url" : "https://github.com/repo/1" ,
208- "clone_url" : "https://github.com/repo/1.git" ,
209- "avatar_url" : "https://avatars.githubusercontent.com/1" ,
210- "user.html_url" : "https://github.com/user" ,
211- "user.clone_url" : "https://github.com/user.git" ,
208+ result := optimizeItem (map [string ]any {
209+ "html_url" : "https://github.com/repo/1" ,
210+ "clone_url" : "https://github.com/repo/1.git" ,
211+ "avatar_url" : "https://avatars.githubusercontent.com/1" ,
212+ "user.html_url" : "https://github.com/user" ,
213+ "user.clone_url" : "https://github.com/user.git" ,
214+ }, cfg )
215+
216+ assert .Contains (t , result , "html_url" )
217+ assert .Contains (t , result , "clone_url" )
218+ assert .NotContains (t , result , "avatar_url" )
219+ assert .NotContains (t , result , "user.html_url" )
220+ assert .NotContains (t , result , "user.clone_url" )
212221 })
213222
214- assert .Contains (t , result , "html_url" )
215- assert .Contains (t , result , "clone_url" )
216- assert .NotContains (t , result , "avatar_url" )
217- assert .NotContains (t , result , "user.html_url" )
218- assert .NotContains (t , result , "user.clone_url" )
219- }
220-
221- func TestPreservedFields_ProtectsZeroValues (t * testing.T ) {
222- original := preservedFields
223- defer func () { preservedFields = original }()
223+ t .Run ("protects zero values" , func (t * testing.T ) {
224+ cfg := OptimizeListConfig {
225+ preservedFields : map [string ]bool {"draft" : true },
226+ }
224227
225- preservedFields = map [string ]bool {"draft" : true }
228+ result := optimizeItem (map [string ]any {
229+ "draft" : false ,
230+ "body" : "" ,
231+ }, cfg )
226232
227- result := optimizeItem (map [string ]any {
228- "draft" : false ,
229- "body" : "" ,
233+ assert .Contains (t , result , "draft" )
234+ assert .NotContains (t , result , "body" )
230235 })
231236
232- assert .Contains (t , result , "draft" )
233- assert .NotContains (t , result , "body" )
234- }
235-
236- func TestPreservedFields_ProtectsFromCollectionSummarization (t * testing.T ) {
237- original := preservedFields
238- defer func () { preservedFields = original }()
237+ t .Run ("protects from collection summarization" , func (t * testing.T ) {
238+ cfg := OptimizeListConfig {
239+ preservedFields : map [string ]bool {"assignees" : true },
240+ }
239241
240- preservedFields = map [string ]bool {"assignees" : true }
242+ assignees := []any {
243+ map [string ]any {"login" : "alice" , "id" : float64 (1 )},
244+ map [string ]any {"login" : "bob" , "id" : float64 (2 )},
245+ }
241246
242- assignees := [ ]any {
243- map [ string ] any { "login " : "alice" , "id" : float64 ( 1 )} ,
244- map [string ]any {"login " : "bob" , "id" : float64 ( 2 ) },
245- }
247+ result := optimizeItem ( map [ string ]any {
248+ "assignees " : assignees ,
249+ "comments" : [] any { map [string ]any {"id " : "1" }, map [ string ] any { "id" : "2" } },
250+ }, cfg )
246251
247- result := optimizeItem (map [string ]any {
248- "assignees" : assignees ,
249- "comments" : []any {map [string ]any {"id" : "1" }, map [string ]any {"id" : "2" }},
252+ assert .Equal (t , assignees , result ["assignees" ])
253+ assert .Equal (t , "[2 items]" , result ["comments" ])
250254 })
251-
252- assert .Equal (t , assignees , result ["assignees" ])
253- assert .Equal (t , "[2 items]" , result ["comments" ])
254255}
255256
256257func TestCollectionFieldExtractors_SurviveFillRate (t * testing.T ) {
257- original := collectionFieldExtractors
258- defer func () { collectionFieldExtractors = original }()
259-
260- collectionFieldExtractors = map [string ][]string {"labels" : {"name" }}
258+ cfg := OptimizeListConfig {
259+ collectionExtractors : map [string ][]string {"labels" : {"name" }},
260+ }
261261
262262 items := []map [string ]any {
263263 {"title" : "PR 1" , "labels" : "bug" },
@@ -266,86 +266,7 @@ func TestCollectionFieldExtractors_SurviveFillRate(t *testing.T) {
266266 {"title" : "PR 4" },
267267 }
268268
269- result := filterByFillRate (items , defaultFillRateThreshold )
269+ result := filterByFillRate (items , defaultFillRateThreshold , cfg )
270270
271271 assert .Contains (t , result [0 ], "labels" )
272272}
273-
274- func TestMarshalItems_PlainSlice (t * testing.T ) {
275- type commit struct {
276- SHA string `json:"sha"`
277- Message string `json:"message"`
278- URL string `json:"url"`
279- }
280-
281- data := []commit {
282- {SHA : "abc123" , Message : "fix bug" , URL : "https://api.github.com/commits/abc123" },
283- {SHA : "def456" , Message : "add feature" , URL : "https://api.github.com/commits/def456" },
284- {SHA : "ghi789" , Message : "update docs" , URL : "https://api.github.com/commits/ghi789" },
285- }
286-
287- raw , err := MarshalItems (data )
288- require .NoError (t , err )
289-
290- var result []map [string ]any
291- err = json .Unmarshal (raw , & result )
292- require .NoError (t , err )
293-
294- for _ , item := range result {
295- assert .NotEmpty (t , item ["sha" ])
296- assert .NotEmpty (t , item ["message" ])
297- assert .Nil (t , item ["url" ])
298- }
299- }
300-
301- func TestMarshalItems_WrappedObject (t * testing.T ) {
302- data := map [string ]any {
303- "issues" : []any {
304- map [string ]any {
305- "title" : "bug report" ,
306- "url" : "https://api.github.com/issues/1" ,
307- "html_url" : "https://github.com/issues/1" ,
308- "draft" : false ,
309- },
310- map [string ]any {
311- "title" : "feature request" ,
312- "url" : "https://api.github.com/issues/2" ,
313- "html_url" : "https://github.com/issues/2" ,
314- "draft" : false ,
315- },
316- map [string ]any {
317- "title" : "docs update" ,
318- "url" : "https://api.github.com/issues/3" ,
319- "html_url" : "https://github.com/issues/3" ,
320- "draft" : false ,
321- },
322- },
323- "totalCount" : 100 ,
324- "pageInfo" : map [string ]any {
325- "hasNextPage" : true ,
326- "endCursor" : "abc123" ,
327- },
328- }
329-
330- raw , err := MarshalItems (data )
331- require .NoError (t , err )
332-
333- var result map [string ]any
334- err = json .Unmarshal (raw , & result )
335- require .NoError (t , err )
336-
337- assert .NotNil (t , result ["totalCount" ])
338- assert .NotNil (t , result ["pageInfo" ])
339-
340- issues , ok := result ["issues" ].([]any )
341- require .True (t , ok )
342- require .Len (t , issues , 3 )
343-
344- for _ , issue := range issues {
345- m := issue .(map [string ]any )
346- assert .NotEmpty (t , m ["title" ])
347- assert .NotEmpty (t , m ["html_url" ])
348- assert .Nil (t , m ["url" ])
349- assert .Equal (t , false , m ["draft" ])
350- }
351- }
0 commit comments