Skip to content

Commit b481b81

Browse files
test: takeTopWithMin and minCutoffForTopK
1 parent bd24328 commit b481b81

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { minCutoffForTopK, takeTopWithMin } from './array'
3+
4+
describe('takeTopWithMin and minCutoffForTopK (numbers) - explicit cases', () => {
5+
const id = (x: number) => x
6+
7+
;[
8+
{
9+
name: 'enough ≥ threshold → pure threshold filter',
10+
items: [7, 5, 3, 1],
11+
threshold: 4,
12+
minCount: 2,
13+
expectedTop: [7, 5],
14+
expectedCutoff: 4,
15+
},
16+
{
17+
name: 'not enough ≥ threshold → fallback to top-K',
18+
items: [7, 5, 3, 1],
19+
threshold: 6,
20+
minCount: 2,
21+
expectedTop: [7, 5],
22+
expectedCutoff: 5,
23+
},
24+
{
25+
name: 'duplicates at cutoff (fallback)',
26+
items: [10, 9, 9, 8],
27+
threshold: 9.5,
28+
minCount: 2,
29+
expectedTop: [10, 9],
30+
expectedCutoff: 9,
31+
},
32+
{
33+
name: 'threshold equal to duplicate value',
34+
items: [10, 9, 9, 8],
35+
threshold: 9,
36+
minCount: 2,
37+
expectedTop: [10, 9, 9],
38+
expectedCutoff: 9,
39+
},
40+
{
41+
name: 'minCount = 0 → pure threshold filter',
42+
items: [10, 8, 7],
43+
threshold: 9,
44+
minCount: 0,
45+
expectedTop: [10],
46+
expectedCutoff: 9,
47+
},
48+
{
49+
name: 'fewer items than minCount',
50+
items: [10, 8],
51+
threshold: 9,
52+
minCount: 5,
53+
expectedTop: [10, 8],
54+
expectedCutoff: 8,
55+
},
56+
{
57+
name: 'empty input',
58+
items: [],
59+
threshold: 9,
60+
minCount: 3,
61+
expectedTop: [],
62+
expectedCutoff: 9,
63+
},
64+
{
65+
name: 'negatives and decimals',
66+
items: [-1.2, -3.4, 0.5],
67+
threshold: -2,
68+
minCount: 1,
69+
expectedTop: [0.5, -1.2],
70+
expectedCutoff: -2,
71+
},
72+
].forEach(({ name, items, threshold, minCount, expectedTop, expectedCutoff }) => {
73+
it(name, () => {
74+
const top = takeTopWithMin(items, id, threshold, minCount)
75+
const cutoff = minCutoffForTopK(items, id, threshold, minCount)
76+
expect(top).toEqual(expectedTop)
77+
expect(cutoff).toBe(expectedCutoff)
78+
})
79+
})
80+
})
81+
82+
describe('takeTopWithMin and minCutoffForTopK (objects) - explicit cases', () => {
83+
type Item = { v: number; id: string }
84+
const getValue = (x: Item) => x.v
85+
86+
const items1: Item[] = [
87+
{ v: 10, id: 'a' },
88+
{ v: 9, id: 'b' },
89+
{ v: 9, id: 'c' },
90+
{ v: 8, id: 'd' },
91+
]
92+
93+
const items2: Item[] = [
94+
{ v: 3, id: 'x' },
95+
{ v: 1, id: 'y' },
96+
{ v: 2, id: 'z' },
97+
]
98+
99+
;(
100+
[
101+
{
102+
name: 'duplicates at cutoff (fallback)',
103+
items: items1,
104+
threshold: 9.5,
105+
minCount: 2,
106+
expectedIds: ['a', 'b'],
107+
expectedCutoff: 9,
108+
},
109+
{
110+
name: 'threshold equal to duplicate value',
111+
items: items1,
112+
threshold: 9,
113+
minCount: 2,
114+
expectedIds: ['a', 'b', 'c'],
115+
expectedCutoff: 9,
116+
},
117+
{
118+
name: 'fallback with fewer overall items than minCount',
119+
items: items2,
120+
threshold: 4,
121+
minCount: 5,
122+
expectedIds: ['x', 'z', 'y'],
123+
expectedCutoff: 1,
124+
},
125+
{
126+
name: 'minCount = 0 → pure threshold filter',
127+
items: items2,
128+
threshold: 2,
129+
minCount: 0,
130+
expectedIds: ['x', 'z'],
131+
expectedCutoff: 2,
132+
},
133+
] as const
134+
).forEach(({ name, items, threshold, minCount, expectedIds, expectedCutoff }) => {
135+
it(name, () => {
136+
const top = takeTopWithMin(items, getValue, threshold, minCount)
137+
const cutoff = minCutoffForTopK(items, getValue, threshold, minCount)
138+
expect(top.map((x) => x.id)).toEqual(expectedIds)
139+
expect(cutoff).toBe(expectedCutoff)
140+
})
141+
})
142+
})

0 commit comments

Comments
 (0)