|
| 1 | +import { GroupingHelper, updateGroupOffsets } from '../m_grouping_expanded'; |
| 2 | +import type { DataItem, GroupInfoData, GroupItemData } from '../types'; |
| 3 | + |
| 4 | +export interface GroupConfig { |
| 5 | + key: string; |
| 6 | + count: number; |
| 7 | + serverCount?: number; |
| 8 | +} |
| 9 | + |
| 10 | +/** |
| 11 | + * Test helper that simulates the grid's expand/collapse flow for grouped data. |
| 12 | + * |
| 13 | + * Constructed from a configuration array — each entry generates a group |
| 14 | + * with `count` leaf items (ids like `"A0"`, `"A1"`, …). |
| 15 | + * When `serverCount` is provided it is used as the group's total instead of |
| 16 | + * the visible leaf count, mirroring the real server-side paging scenario. |
| 17 | + * |
| 18 | + * - `collapse(path)` — nullifies `group.items` and registers the group as collapsed. |
| 19 | + * - `expand(path)` — restores the saved children and marks the group as expanded. |
| 20 | + * |
| 21 | + * After each operation all group offsets are recalculated via `updateGroupOffsets`, |
| 22 | + * exactly matching the `changeRowExpand` flow in the production code. |
| 23 | + */ |
| 24 | + |
| 25 | +export class GroupingTestHelper { |
| 26 | + public readonly grouping: GroupingHelper; |
| 27 | + |
| 28 | + public readonly items: DataItem[]; |
| 29 | + |
| 30 | + private readonly groupsByKey: Map<string, GroupItemData>; |
| 31 | + |
| 32 | + private readonly leafCounts: Map<string, number>; |
| 33 | + |
| 34 | + /** Saved children snapshots so expand can restore them. */ |
| 35 | + private readonly savedChildren = new Map<string, GroupItemData[] | null>(); |
| 36 | + |
| 37 | + constructor(groups: GroupConfig[]) { |
| 38 | + this.grouping = new GroupingHelper({ option: (): undefined => undefined }); |
| 39 | + this.groupsByKey = new Map(); |
| 40 | + this.leafCounts = new Map(); |
| 41 | + |
| 42 | + // Initialize group items |
| 43 | + this.items = groups.map(({ key, count, serverCount }) => { |
| 44 | + const items = Array.from({ length: count }, (_, i) => ({ id: `${key}${i}` })); |
| 45 | + const group = { key, items } as unknown as GroupItemData; |
| 46 | + this.groupsByKey.set(key, group); |
| 47 | + this.leafCounts.set(key, serverCount ?? count); |
| 48 | + |
| 49 | + return group; |
| 50 | + }); |
| 51 | + } |
| 52 | + |
| 53 | + public collapse(path: string[]): void { |
| 54 | + const key = path[0]; |
| 55 | + const group = this.groupsByKey.get(key); |
| 56 | + const count = this.leafCounts.get(key) ?? 0; |
| 57 | + |
| 58 | + this.simulateChangeRowExpand(path, count); |
| 59 | + |
| 60 | + if (group) { |
| 61 | + this.savedChildren.set(key, group.items); |
| 62 | + group.items = null; |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + public expand(path: string[]): void { |
| 67 | + const groupInfo = this.grouping.findGroupInfo(path); |
| 68 | + const count = groupInfo ? groupInfo.count : 0; |
| 69 | + |
| 70 | + this.simulateChangeRowExpand(path, count); |
| 71 | + |
| 72 | + const key = path[0]; |
| 73 | + const group = this.groupsByKey.get(key); |
| 74 | + if (group) { |
| 75 | + group.items = this.savedChildren.get(key) ?? []; |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + private simulateChangeRowExpand( |
| 80 | + path: unknown[], |
| 81 | + count: number, |
| 82 | + ): void { |
| 83 | + const groupInfo = this.grouping.findGroupInfo(path); |
| 84 | + |
| 85 | + const pendingGroupInfo: GroupInfoData = { |
| 86 | + offset: groupInfo ? groupInfo.offset : -1, |
| 87 | + path: groupInfo ? groupInfo.path : path, |
| 88 | + isExpanded: groupInfo ? !groupInfo.isExpanded : false, |
| 89 | + count, |
| 90 | + }; |
| 91 | + |
| 92 | + updateGroupOffsets(this.grouping, this.items, [], 0, pendingGroupInfo); |
| 93 | + |
| 94 | + if (groupInfo) { |
| 95 | + groupInfo.isExpanded = !groupInfo.isExpanded; |
| 96 | + groupInfo.count = count; |
| 97 | + } else if (pendingGroupInfo.offset >= 0) { |
| 98 | + this.grouping.addGroupInfo(pendingGroupInfo); |
| 99 | + } |
| 100 | + } |
| 101 | +} |
0 commit comments