Skip to content

Commit 7d0b463

Browse files
committed
test dropdown items update when ensemble storage changes
1 parent 032728c commit 7d0b463

2 files changed

Lines changed: 108 additions & 3 deletions

File tree

packages/runtime/src/widgets/Form/Dropdown.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
EnsembleAction,
1414
Expression,
1515
} from "@ensembleui/react-framework";
16-
import { get, isEmpty, isNull, isObject, isString } from "lodash-es";
16+
import { get, isArray, isEmpty, isNull, isObject, isString } from "lodash-es";
1717
import { WidgetRegistry } from "../../registry";
1818
import type {
1919
EnsembleWidgetProps,
@@ -145,7 +145,7 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
145145
const options = useMemo(() => {
146146
let dropdownOptions: React.ReactNode[] | null = null;
147147

148-
if (values?.items) {
148+
if (values?.items && isArray(values.items)) {
149149
const tempOptions = values.items.map((item) => {
150150
if (item.type === "group") {
151151
// Render a group item with sub-items
@@ -166,7 +166,7 @@ const Dropdown: React.FC<DropdownProps> = (props) => {
166166
}
167167
return (
168168
<Select.Option
169-
className={`${values.id || ""}_option`}
169+
className={`${values?.id || ""}_option`}
170170
key={item.value}
171171
value={item.value}
172172
>

packages/runtime/src/widgets/Form/__tests__/Dropdown.test.tsx

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,5 +198,110 @@ describe("Dropdown Widget", () => {
198198
);
199199
});
200200
});
201+
202+
test("dropdown items update when ensemble storage changes", async () => {
203+
render(
204+
<Form
205+
children={[
206+
{
207+
name: "Dropdown",
208+
properties: {
209+
id: "dynamicItems",
210+
label: "Dynamic Items",
211+
items: `\${ensemble.storage.get('dropdownItems')}`,
212+
},
213+
},
214+
{
215+
name: "Button",
216+
properties: {
217+
label: "Add Item",
218+
onTap: {
219+
executeCode: `
220+
const currentItems = ensemble.storage.get('dropdownItems') || [];
221+
ensemble.storage.set('dropdownItems', [
222+
...currentItems,
223+
{ label: 'New Item', value: 'newItem' }
224+
]);
225+
`,
226+
},
227+
},
228+
},
229+
{
230+
name: "Button",
231+
properties: {
232+
label: "Remove Item",
233+
onTap: {
234+
executeCode: `
235+
const currentItems = ensemble.storage.get('dropdownItems') || [];
236+
const filteredItems = currentItems.filter(item => item.value !== 'newItem');
237+
ensemble.storage.set('dropdownItems', filteredItems);
238+
`,
239+
},
240+
},
241+
},
242+
{
243+
name: "Button",
244+
properties: {
245+
label: "Set Initial Items",
246+
onTap: {
247+
executeCode: `
248+
ensemble.storage.set('dropdownItems', [
249+
{ label: 'Initial Item 1', value: 'initial1' },
250+
{ label: 'Initial Item 2', value: 'initial2' }
251+
]);
252+
`,
253+
},
254+
},
255+
},
256+
...defaultFormButton,
257+
]}
258+
id="form"
259+
/>,
260+
{ wrapper: FormTestWrapper },
261+
);
262+
263+
const dropdown = screen.getByRole("combobox");
264+
const setInitialButton = screen.getByText("Set Initial Items");
265+
const addItemButton = screen.getByText("Add Item");
266+
const removeItemButton = screen.getByText("Remove Item");
267+
268+
// Set initial items
269+
fireEvent.click(setInitialButton);
270+
271+
// Open dropdown to see initial items
272+
userEvent.click(dropdown);
273+
await waitFor(() => {
274+
expect(screen.getByTitle("Initial Item 1")).toBeInTheDocument();
275+
expect(screen.getByTitle("Initial Item 2")).toBeInTheDocument();
276+
});
277+
278+
// Close dropdown
279+
userEvent.click(dropdown);
280+
281+
// Add a new item
282+
fireEvent.click(addItemButton);
283+
284+
// Open dropdown to verify new item was added
285+
userEvent.click(dropdown);
286+
await waitFor(() => {
287+
expect(screen.getByTitle("Initial Item 1")).toBeInTheDocument();
288+
expect(screen.getByTitle("Initial Item 2")).toBeInTheDocument();
289+
expect(screen.getByTitle("New Item")).toBeInTheDocument();
290+
});
291+
292+
// Close dropdown
293+
userEvent.click(dropdown);
294+
295+
// Remove the new item
296+
fireEvent.click(removeItemButton);
297+
298+
// Open dropdown to verify item was removed
299+
userEvent.click(dropdown);
300+
await waitFor(() => {
301+
expect(screen.getByTitle("Initial Item 1")).toBeInTheDocument();
302+
expect(screen.getByTitle("Initial Item 2")).toBeInTheDocument();
303+
expect(screen.queryByText("New Item")).not.toBeInTheDocument();
304+
});
305+
});
201306
});
202307
/* eslint-enable react/no-children-prop */

0 commit comments

Comments
 (0)