Skip to content

Commit ec03041

Browse files
authored
fix: templatedata re-render issue in collapsible (#1010)
templatedata re-render issue in collapsible
1 parent 361f64a commit ec03041

File tree

3 files changed

+171
-1
lines changed

3 files changed

+171
-1
lines changed

.changeset/ninety-birds-kneel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ensembleui/react-runtime": patch
3+
---
4+
5+
Fix template data re-render issue in collapsible

packages/runtime/src/widgets/Collapsible.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,13 @@ const CollapseItem = ({
8686

8787
useEffect(() => {
8888
setEvaluatedKeys((prev) => {
89+
if (currentIndex === 0) {
90+
return [key];
91+
}
8992
prev[currentIndex] = key;
9093
return [...prev];
9194
});
92-
}, [key, setEvaluatedKeys]);
95+
}, [key, currentIndex, setEvaluatedKeys]);
9396

9497
return null;
9598
};
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
2+
import "@testing-library/jest-dom";
3+
import { BrowserRouter } from "react-router-dom";
4+
import { EnsembleScreen } from "../../runtime/screen";
5+
import "../index";
6+
7+
describe("Collapsible Widget", () => {
8+
test("test collapsible widget", async () => {
9+
render(
10+
<EnsembleScreen
11+
screen={{
12+
name: "test_collapsible",
13+
id: "test_collapsible",
14+
body: {
15+
name: "Column",
16+
properties: {
17+
children: [
18+
{
19+
name: "Collapsible",
20+
properties: {
21+
"item-template": {
22+
data: "[{ id: '1', name: 'Apple'}, { id: '2', name: 'Mango'},{ id: '3', name: 'Banana'}]",
23+
name: "fruit",
24+
template: {
25+
name: "CollapsibleItem",
26+
properties: {
27+
key: `\${fruit.id}`,
28+
label: { Text: { text: `\${fruit.id}` } },
29+
children: { Text: { text: `\${fruit.name}` } },
30+
},
31+
},
32+
},
33+
},
34+
},
35+
],
36+
},
37+
},
38+
}}
39+
/>,
40+
{ wrapper: BrowserRouter },
41+
);
42+
43+
await waitFor(() => {
44+
expect(screen.getByText("1")).toBeVisible();
45+
expect(screen.getByText("2")).toBeVisible();
46+
expect(screen.getByText("3")).toBeVisible();
47+
expect(screen.queryByText("Apple")).not.toBeInTheDocument();
48+
expect(screen.queryByText("Mango")).not.toBeInTheDocument();
49+
expect(screen.queryByText("Banana")).not.toBeInTheDocument();
50+
});
51+
52+
fireEvent.click(screen.getByText("2"));
53+
fireEvent.click(screen.getByText("3"));
54+
55+
await waitFor(() => {
56+
expect(screen.queryByText("Apple")).not.toBeInTheDocument();
57+
expect(screen.queryByText("Mango")).toBeVisible();
58+
expect(screen.queryByText("Banana")).toBeVisible();
59+
});
60+
61+
fireEvent.click(screen.getByText("1"));
62+
fireEvent.click(screen.getByText("3"));
63+
64+
await waitFor(() => {
65+
expect(screen.queryByText("Apple")).toBeVisible();
66+
expect(screen.queryByText("Mango")).toBeVisible();
67+
expect(screen.queryByText("Banana")).not.toBeVisible();
68+
});
69+
});
70+
71+
test("test collapsible widget data change conditionally", async () => {
72+
render(
73+
<EnsembleScreen
74+
screen={{
75+
name: "test_collapsible",
76+
id: "test_collapsible",
77+
body: {
78+
name: "Column",
79+
properties: {
80+
children: [
81+
{
82+
name: "Collapsible",
83+
properties: {
84+
"item-template": {
85+
data: `\${ensemble.storage.get('fruits')}`,
86+
name: "fruit",
87+
template: {
88+
name: "CollapsibleItem",
89+
properties: {
90+
key: `\${fruit.id}`,
91+
label: { Text: { text: `\${fruit.id}` } },
92+
children: { Text: { text: `\${fruit.name}` } },
93+
},
94+
},
95+
},
96+
},
97+
},
98+
{
99+
name: "Button",
100+
properties: {
101+
label: "Set Fruits",
102+
onTap: {
103+
executeCode: {
104+
body: "ensemble.storage.set('fruits', [{ id: '4', name: 'Strawberry'},{ id: '5', name: 'Avocado'}])",
105+
},
106+
},
107+
},
108+
},
109+
],
110+
},
111+
},
112+
onLoad: {
113+
executeCode: {
114+
body: `ensemble.storage.set('fruits', [{ id: '1', name: 'Apple'},{ id: '2', name: 'Mango'},{ id: '3', name: 'Banana'}])`,
115+
},
116+
},
117+
}}
118+
/>,
119+
{ wrapper: BrowserRouter },
120+
);
121+
122+
await waitFor(() => {
123+
expect(screen.getByText("1")).toBeVisible();
124+
expect(screen.getByText("2")).toBeVisible();
125+
expect(screen.getByText("3")).toBeVisible();
126+
expect(screen.queryByText("Apple")).not.toBeInTheDocument();
127+
expect(screen.queryByText("Mango")).not.toBeInTheDocument();
128+
expect(screen.queryByText("Banana")).not.toBeInTheDocument();
129+
});
130+
131+
fireEvent.click(screen.getByText("Set Fruits"));
132+
133+
await waitFor(() => {
134+
expect(screen.queryByText("1")).not.toBeInTheDocument();
135+
expect(screen.queryByText("2")).not.toBeInTheDocument();
136+
expect(screen.queryByText("3")).not.toBeInTheDocument();
137+
expect(screen.queryByText("Apple")).not.toBeInTheDocument();
138+
expect(screen.queryByText("Mango")).not.toBeInTheDocument();
139+
expect(screen.queryByText("Banana")).not.toBeInTheDocument();
140+
141+
expect(screen.getByText("4")).toBeVisible();
142+
expect(screen.getByText("5")).toBeVisible();
143+
expect(screen.queryByText("Strawberry")).not.toBeInTheDocument();
144+
expect(screen.queryByText("Avocado")).not.toBeInTheDocument();
145+
});
146+
147+
fireEvent.click(screen.getByText("4"));
148+
fireEvent.click(screen.getByText("5"));
149+
150+
await waitFor(() => {
151+
expect(screen.queryByText("Strawberry")).toBeVisible();
152+
expect(screen.queryByText("Avocado")).toBeVisible();
153+
});
154+
155+
fireEvent.click(screen.getByText("4"));
156+
157+
await waitFor(() => {
158+
expect(screen.queryByText("Strawberry")).not.toBeVisible();
159+
expect(screen.queryByText("Avocado")).toBeVisible();
160+
});
161+
});
162+
});

0 commit comments

Comments
 (0)