Skip to content

Commit 8ae61b4

Browse files
committed
test: add runtime tests for groupBy with enum and union types
1 parent 4d1e941 commit 8ae61b4

File tree

1 file changed

+173
-1
lines changed

1 file changed

+173
-1
lines changed

test/groupBy.spec.ts

Lines changed: 173 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import { filter, fx, groupBy, pipe, toAsync } from "../src";
1+
import {
2+
entries,
3+
filter,
4+
fromEntries,
5+
fx,
6+
groupBy,
7+
map,
8+
pipe,
9+
reduce,
10+
toArray,
11+
toAsync,
12+
} from "../src";
213
import { AsyncFunctionException } from "../src/_internal/error";
314

415
type Obj = {
@@ -95,4 +106,165 @@ describe("groupBy", function () {
95106
expect(res).toEqual(then2);
96107
});
97108
});
109+
110+
describe("Issue #233 - enum and union types", function () {
111+
enum Status {
112+
Todo = "TODO",
113+
InProgress = "IN_PROGRESS",
114+
Done = "DONE",
115+
}
116+
117+
it("should work with enum types in entries + reduce pattern", function () {
118+
const tasks = [
119+
{ id: 1, status: Status.Todo, priority: 3 },
120+
{ id: 2, status: Status.InProgress, priority: 5 },
121+
{ id: 3, status: Status.Done, priority: 1 },
122+
{ id: 4, status: Status.Todo, priority: 2 },
123+
];
124+
125+
const result = pipe(
126+
tasks,
127+
groupBy((t) => t.status),
128+
entries,
129+
map(
130+
([status, items]) =>
131+
[
132+
status,
133+
reduce((sum, item) => sum + item.priority, 0, items),
134+
] as const,
135+
),
136+
fromEntries,
137+
);
138+
139+
expect(result).toEqual({
140+
[Status.Todo]: 5,
141+
[Status.InProgress]: 5,
142+
[Status.Done]: 1,
143+
});
144+
});
145+
146+
it("should work with string union types", function () {
147+
type Color = "red" | "green" | "blue";
148+
const items: Array<{ name: string; color: Color; value: number }> = [
149+
{ name: "apple", color: "red", value: 10 },
150+
{ name: "grass", color: "green", value: 20 },
151+
{ name: "sky", color: "blue", value: 30 },
152+
{ name: "rose", color: "red", value: 15 },
153+
];
154+
155+
const result = pipe(
156+
items,
157+
groupBy((item) => item.color),
158+
entries,
159+
map(([color, items]) => ({
160+
color,
161+
total: reduce((sum, item) => sum + item.value, 0, items),
162+
count: items.length,
163+
})),
164+
toArray,
165+
);
166+
167+
expect(result).toEqual([
168+
{ color: "red", total: 25, count: 2 },
169+
{ color: "green", total: 20, count: 1 },
170+
{ color: "blue", total: 30, count: 1 },
171+
]);
172+
});
173+
174+
it("should work with string literal types", function () {
175+
const data = [
176+
{ type: "A" as const, amount: 100 },
177+
{ type: "B" as const, amount: 200 },
178+
{ type: "A" as const, amount: 150 },
179+
];
180+
181+
const result = pipe(
182+
data,
183+
groupBy((item) => item.type),
184+
entries,
185+
map(([type, items]) => ({
186+
type,
187+
sum: reduce((acc, cur) => acc + cur.amount, 0, items),
188+
})),
189+
toArray,
190+
);
191+
192+
expect(result).toEqual([
193+
{ type: "A", sum: 250 },
194+
{ type: "B", sum: 200 },
195+
]);
196+
});
197+
198+
it("should handle numeric enum values", function () {
199+
enum NumericStatus {
200+
Pending = 0,
201+
Active = 1,
202+
Completed = 2,
203+
}
204+
205+
const data = [
206+
{ id: 1, status: NumericStatus.Pending },
207+
{ id: 2, status: NumericStatus.Active },
208+
{ id: 3, status: NumericStatus.Pending },
209+
];
210+
211+
const result = groupBy((item) => item.status, data);
212+
213+
expect(result).toEqual({
214+
[NumericStatus.Pending]: [
215+
{ id: 1, status: NumericStatus.Pending },
216+
{ id: 3, status: NumericStatus.Pending },
217+
],
218+
[NumericStatus.Active]: [{ id: 2, status: NumericStatus.Active }],
219+
});
220+
});
221+
222+
it("should handle const assertions", function () {
223+
const CONFIG = {
224+
TYPES: {
225+
ADMIN: "admin",
226+
USER: "user",
227+
GUEST: "guest",
228+
},
229+
} as const;
230+
231+
const users = [
232+
{ name: "Alice", type: CONFIG.TYPES.ADMIN },
233+
{ name: "Bob", type: CONFIG.TYPES.USER },
234+
{ name: "Charlie", type: CONFIG.TYPES.USER },
235+
];
236+
237+
const result = groupBy((user) => user.type, users);
238+
239+
expect(result).toEqual({
240+
[CONFIG.TYPES.ADMIN]: [{ name: "Alice", type: CONFIG.TYPES.ADMIN }],
241+
[CONFIG.TYPES.USER]: [
242+
{ name: "Bob", type: CONFIG.TYPES.USER },
243+
{ name: "Charlie", type: CONFIG.TYPES.USER },
244+
],
245+
});
246+
});
247+
248+
it("should work with async callback and union types", async function () {
249+
type Priority = "low" | "medium" | "high";
250+
const items: Array<{ name: string; priority: Priority }> = [
251+
{ name: "task1", priority: "low" },
252+
{ name: "task2", priority: "high" },
253+
{ name: "task3", priority: "low" },
254+
];
255+
256+
const result = await pipe(
257+
toAsync(items),
258+
groupBy(async (item) => item.priority),
259+
);
260+
261+
expect(result).toEqual({
262+
low: [
263+
{ name: "task1", priority: "low" },
264+
{ name: "task3", priority: "low" },
265+
],
266+
high: [{ name: "task2", priority: "high" }],
267+
});
268+
});
269+
});
98270
});

0 commit comments

Comments
 (0)