Skip to content

Commit e9398d5

Browse files
committed
fix: multi-root tree rendering
1 parent 0a97255 commit e9398d5

File tree

2 files changed

+194
-1
lines changed

2 files changed

+194
-1
lines changed

__tests__/multiroot.spec.tsx

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import {mount, ReactWrapper} from 'enzyme';
2+
import React, {FC} from 'react';
3+
import {FixedSizeList} from 'react-window';
4+
import {
5+
FixedSizeNodeData,
6+
FixedSizeNodePublicState,
7+
FixedSizeTree,
8+
FixedSizeTreeProps,
9+
FixedSizeTreeState,
10+
Row,
11+
TreeWalker,
12+
TreeWalkerValue,
13+
} from '../src';
14+
import {NodeComponentProps} from '../src/Tree';
15+
import {defaultTree, extractReceivedRecords} from './utils/misc';
16+
17+
type TreeNode = Readonly<{
18+
children?: TreeNode[];
19+
id: string;
20+
name: string;
21+
}>;
22+
23+
type NodeMeta = Readonly<{
24+
nestingLevel: number;
25+
node: TreeNode;
26+
}>;
27+
28+
type ExtendedData = FixedSizeNodeData &
29+
Readonly<{
30+
name: string;
31+
nestingLevel: number;
32+
}>;
33+
34+
describe('Multiroot tree', () => {
35+
const Node: FC<NodeComponentProps<
36+
ExtendedData,
37+
FixedSizeNodePublicState<ExtendedData>
38+
>> = jest.fn(() => null);
39+
40+
let component: ReactWrapper<
41+
FixedSizeTreeProps<ExtendedData>,
42+
FixedSizeTreeState<ExtendedData>,
43+
FixedSizeTree<ExtendedData>
44+
>;
45+
let treeRoots: readonly TreeNode[];
46+
let treeWalkerSpy: jest.Mock;
47+
let isOpenByDefault: boolean;
48+
49+
const getNodeData = (
50+
node: TreeNode,
51+
nestingLevel: number,
52+
): TreeWalkerValue<ExtendedData, NodeMeta> => ({
53+
data: {
54+
id: node.id.toString(),
55+
isOpenByDefault,
56+
name: node.name,
57+
nestingLevel,
58+
},
59+
nestingLevel,
60+
node,
61+
});
62+
63+
function* treeWalker(): ReturnType<TreeWalker<ExtendedData, NodeMeta>> {
64+
for (let i = 0; i < treeRoots.length; i++) {
65+
yield getNodeData(treeRoots[i], 0);
66+
}
67+
68+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
69+
while (true) {
70+
const parentMeta = yield;
71+
72+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
73+
if (parentMeta.node.children) {
74+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
75+
for (let i = 0; i < parentMeta.node.children.length; i++) {
76+
yield getNodeData(
77+
parentMeta.node.children[i],
78+
parentMeta.nestingLevel + 1,
79+
);
80+
}
81+
}
82+
}
83+
}
84+
85+
const mountComponent = (
86+
overriddenProps: Partial<FixedSizeTreeProps<ExtendedData>> = {},
87+
): typeof component =>
88+
mount(
89+
<FixedSizeTree<ExtendedData>
90+
itemSize={30}
91+
treeWalker={treeWalkerSpy}
92+
height={500}
93+
width={500}
94+
{...overriddenProps}
95+
>
96+
{Node}
97+
</FixedSizeTree>,
98+
);
99+
100+
beforeEach(() => {
101+
treeRoots = defaultTree.children;
102+
103+
isOpenByDefault = true;
104+
105+
treeWalkerSpy = jest.fn(treeWalker);
106+
107+
component = mountComponent();
108+
});
109+
110+
it('renders a component', () => {
111+
expect(component).not.toBeUndefined();
112+
});
113+
114+
it('contains a list component', () => {
115+
const list = component.find(FixedSizeList);
116+
expect(list).toHaveLength(1);
117+
expect(list.props()).toMatchObject({
118+
children: Row,
119+
itemCount: 6,
120+
itemData: expect.any(Object),
121+
itemSize: 30,
122+
});
123+
124+
expect(list.prop('itemData')).toMatchObject({
125+
component: Node,
126+
getRecordData: expect.any(Function),
127+
});
128+
129+
expect(extractReceivedRecords(list)).toEqual([
130+
{
131+
data: {
132+
id: 'foo-2',
133+
isOpenByDefault: true,
134+
name: 'Foo #2',
135+
nestingLevel: 0,
136+
},
137+
isOpen: true,
138+
toggle: expect.any(Function),
139+
},
140+
{
141+
data: {
142+
id: 'foo-3',
143+
isOpenByDefault: true,
144+
name: 'Foo #3',
145+
nestingLevel: 1,
146+
},
147+
isOpen: true,
148+
toggle: expect.any(Function),
149+
},
150+
{
151+
data: {
152+
id: 'foo-4',
153+
isOpenByDefault: true,
154+
name: 'Foo #4',
155+
nestingLevel: 1,
156+
},
157+
isOpen: true,
158+
toggle: expect.any(Function),
159+
},
160+
{
161+
data: {
162+
id: 'foo-5',
163+
isOpenByDefault: true,
164+
name: 'Foo #5',
165+
nestingLevel: 0,
166+
},
167+
isOpen: true,
168+
toggle: expect.any(Function),
169+
},
170+
{
171+
data: {
172+
id: 'foo-6',
173+
isOpenByDefault: true,
174+
name: 'Foo #6',
175+
nestingLevel: 1,
176+
},
177+
isOpen: true,
178+
toggle: expect.any(Function),
179+
},
180+
{
181+
data: {
182+
id: 'foo-7',
183+
isOpenByDefault: true,
184+
name: 'Foo #7',
185+
nestingLevel: 1,
186+
},
187+
isOpen: true,
188+
toggle: expect.any(Function),
189+
},
190+
]);
191+
});
192+
});

src/Tree.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,9 @@ const generateNewTree = <
300300
}
301301

302302
currentRecord = visitRecord(currentRecord);
303-
tempRecord = currentRecord;
304303
}
304+
305+
tempRecord = currentRecord;
305306
continue;
306307
}
307308

0 commit comments

Comments
 (0)