Skip to content

Commit a20e80a

Browse files
committed
Add more tests
1 parent f21b014 commit a20e80a

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

pkg/response/optimize_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package response
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"testing"
67

78
"github.com/stretchr/testify/assert"
@@ -69,6 +70,31 @@ func TestFlatten(t *testing.T) {
6970
"commit.author.date": "2026-01-01",
7071
}, result)
7172
})
73+
74+
t.Run("silently drops nested maps at maxDepth boundary", func(t *testing.T) {
75+
// With defaultMaxDepth=2, depth starts at 1.
76+
// "user" is recursed into at depth=2, but "org" inside it
77+
// is a map at depth=2 where depth < maxDepth is false,
78+
// and the else-if !ok branch also doesn't fire because ok=true.
79+
// Result: "user.org" and its contents are silently lost.
80+
input := map[string]any{
81+
"title": "issue",
82+
"user": map[string]any{
83+
"login": "alice",
84+
"org": map[string]any{
85+
"name": "acme",
86+
},
87+
},
88+
}
89+
result := flattenTo(input, defaultMaxDepth)
90+
91+
assert.Equal(t, "issue", result["title"])
92+
assert.Equal(t, "alice", result["user.login"])
93+
// BUG: org data is silently dropped — neither "user.org" nor
94+
// "user.org.name" appear in the result.
95+
assert.Nil(t, result["user.org"], "nested map at maxDepth is silently dropped")
96+
assert.Nil(t, result["user.org.name"], "nested map contents at maxDepth are lost")
97+
})
7298
}
7399

74100
func TestFilterByFillRate(t *testing.T) {
@@ -156,6 +182,38 @@ func TestOptimizeList_NilInput(t *testing.T) {
156182
assert.Equal(t, "null", string(raw))
157183
}
158184

185+
func TestOptimizeList_NilInput_AsRawMessage(t *testing.T) {
186+
// This mirrors how list_issues embeds OptimizeList output as json.RawMessage.
187+
// When the input slice is nil, OptimizeList returns the bytes "null",
188+
// which produces {"issues":null,...} instead of {"issues":[],...}.
189+
// Consumers expecting an array will break.
190+
optimized, err := OptimizeList[map[string]any](nil)
191+
require.NoError(t, err)
192+
193+
wrapper := map[string]any{
194+
"issues": json.RawMessage(optimized),
195+
"totalCount": 0,
196+
}
197+
198+
out, err := json.Marshal(wrapper)
199+
require.NoError(t, err)
200+
201+
// Parse back and check what "issues" became
202+
var parsed map[string]json.RawMessage
203+
err = json.Unmarshal(out, &parsed)
204+
require.NoError(t, err)
205+
206+
// BUG: "issues" is JSON null, not an empty array
207+
assert.Equal(t, "null", string(parsed["issues"]),
208+
"nil input produces JSON null instead of empty array when embedded as RawMessage")
209+
210+
// This is what a consumer trying to decode an array would see:
211+
var issues []map[string]any
212+
err = json.Unmarshal(parsed["issues"], &issues)
213+
require.NoError(t, err) // unmarshal succeeds but...
214+
assert.Nil(t, issues, "decoded slice is nil, not empty — may cause nil-pointer issues in consumers")
215+
}
216+
159217
func TestOptimizeList_SkipsFillRateBelowMinRows(t *testing.T) {
160218
items := []map[string]any{
161219
{"title": "a", "rare": "x"},
@@ -172,6 +230,72 @@ func TestOptimizeList_SkipsFillRateBelowMinRows(t *testing.T) {
172230
assert.Equal(t, "x", result[0]["rare"])
173231
}
174232

233+
func TestWhitespaceNormalization_DestroysCodeBlocks(t *testing.T) {
234+
// PR/issue bodies often contain markdown with code blocks, bullet lists,
235+
// and intentional line breaks. The whitespace normalization strategy
236+
// collapses all of this into a single line.
237+
body := "## Steps to reproduce\n\n" +
238+
"1. Run the following:\n\n" +
239+
"```go\nfunc main() {\n\tfmt.Println(\"hello\")\n}\n```\n\n" +
240+
"2. Observe the error:\n\n" +
241+
"```\npanic: runtime error\n goroutine 1\n```"
242+
243+
items := []map[string]any{
244+
{
245+
"title": "Bug report",
246+
"body": body,
247+
},
248+
}
249+
250+
raw, err := OptimizeList(items)
251+
require.NoError(t, err)
252+
253+
var result []map[string]any
254+
err = json.Unmarshal(raw, &result)
255+
require.NoError(t, err)
256+
require.Len(t, result, 1)
257+
258+
optimized := result[0]["body"].(string)
259+
260+
assert.Equal(t,
261+
"## Steps to reproduce 1. Run the following: ```go func main() { fmt.Println(\"hello\") } ``` 2. Observe the error: ``` panic: runtime error goroutine 1 ```",
262+
optimized,
263+
"code blocks and markdown structure are flattened into unreadable text",
264+
)
265+
}
266+
267+
func TestFillRateAfterZeroRemoval_DropsLegitimateValues(t *testing.T) {
268+
// This simulates list_branches with 10 branches where 1 is protected.
269+
// Pipeline order: optimizeItem (strips protected:false) → filterByFillRate.
270+
// After optimizeItem, "protected" only appears on 1/10 items.
271+
// Fill rate = 1/10 = 0.1, minCount = int(0.1*10) = 1, and 1 > 1 is false.
272+
// So "protected: true" is removed from the one branch that had it.
273+
274+
items := make([]map[string]any, 10)
275+
for i := range items {
276+
items[i] = map[string]any{
277+
"name": fmt.Sprintf("branch-%d", i),
278+
"protected": false,
279+
}
280+
}
281+
// One branch is actually protected
282+
items[0]["protected"] = true
283+
284+
raw, err := OptimizeList(items)
285+
require.NoError(t, err)
286+
287+
var result []map[string]any
288+
err = json.Unmarshal(raw, &result)
289+
require.NoError(t, err)
290+
require.Len(t, result, 10)
291+
292+
// BUG: The protected branch lost its "protected: true" field.
293+
// optimizeItem stripped "protected: false" from 9 items, then
294+
// filterByFillRate saw "protected" on only 1/10 and removed it.
295+
assert.Nil(t, result[0]["protected"],
296+
"protected:true is lost because zero-value removal deflated the fill rate")
297+
}
298+
175299
func TestPreservedFields(t *testing.T) {
176300
t.Run("keeps preserved URL keys, strips non-preserved", func(t *testing.T) {
177301
cfg := OptimizeListConfig{

0 commit comments

Comments
 (0)