Skip to content

Commit 3da1d1e

Browse files
fix: api state reflect (#999)
Co-authored-by: Anser Waseem <hafiz.anser.waseem@gmail.com>
1 parent 5ec36d6 commit 3da1d1e

File tree

3 files changed

+117
-6
lines changed

3 files changed

+117
-6
lines changed

.changeset/dirty-otters-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ensembleui/react-framework": patch
3+
---
4+
5+
fix api state reflact issue

packages/framework/src/hooks/useScreenData.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useAtom, useAtomValue } from "jotai";
2-
import { clone } from "lodash-es";
32
import { useCallback, useMemo } from "react";
43
import isEqual from "react-fast-compare";
54
import type { Response, WebSocketConnection } from "../data";
@@ -49,7 +48,7 @@ export const useScreenData = (): {
4948
return;
5049
}
5150
data[name] = response;
52-
setDataAtom(clone(data));
51+
setDataAtom({ [name]: response });
5352
},
5453
[data, setDataAtom],
5554
);

packages/runtime/src/runtime/hooks/__tests__/useInvokeApi.test.tsx

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,22 @@ const BrowserRouterWrapper = ({ children }: BrowserRouterProps) => (
3737
</QueryClientProvider>
3838
);
3939

40+
const logSpy = jest.spyOn(console, "log").mockImplementation(jest.fn());
41+
const errorSpy = jest.spyOn(console, "error").mockImplementation(jest.fn());
42+
4043
beforeEach(() => {
4144
jest.useFakeTimers();
4245
});
4346

4447
afterEach(() => {
48+
logSpy.mockClear();
49+
errorSpy.mockClear();
4550
jest.clearAllMocks();
4651
jest.useRealTimers();
4752
queryClient.clear();
4853
});
4954

5055
test("fetch API cache response for cache expiry", async () => {
51-
const logSpy = jest.spyOn(console, "log");
52-
5356
fetchMock.mockResolvedValue({ body: { data: "foobar" } });
5457

5558
render(
@@ -162,8 +165,6 @@ test("fetch API cache response for unique inputs while cache expiry", async () =
162165
});
163166

164167
test("fetch API without cache", async () => {
165-
const logSpy = jest.spyOn(console, "log");
166-
167168
fetchMock.mockResolvedValue({ body: { data: "foobar" } });
168169

169170
render(
@@ -337,3 +338,109 @@ test("fetch API with force cache clear", async () => {
337338
expect(fetchMock).toHaveBeenCalledTimes(2);
338339
});
339340
});
341+
342+
test("after API fetching using toggle check states", async () => {
343+
fetchMock.mockResolvedValueOnce({ body: { data: "foo" }, isLoading: false });
344+
fetchMock.mockResolvedValueOnce({ body: { data: "bar" }, isLoading: false });
345+
346+
render(
347+
<EnsembleScreen
348+
screen={{
349+
name: "test",
350+
id: "test",
351+
body: {
352+
name: "Column",
353+
properties: {
354+
children: [
355+
{
356+
name: "ToggleButton",
357+
properties: {
358+
id: "toggleButton",
359+
value: "foo",
360+
items: [
361+
{ label: "Foo", value: "foo" },
362+
{ label: "Bar", value: "bar" },
363+
],
364+
onChange: {
365+
executeConditionalAction: {
366+
conditions: [
367+
{
368+
if: `\${value === 'bar'}`,
369+
action: { invokeAPI: { name: "fetchBar" } },
370+
},
371+
],
372+
},
373+
},
374+
},
375+
},
376+
{
377+
name: "Conditional",
378+
properties: {
379+
conditions: [
380+
{
381+
if: `\${toggleButton.value === "foo"}`,
382+
Column: {
383+
children: [
384+
{
385+
LoadingContainer: {
386+
isLoading: `\${fetchFoo.isLoading !== false}`,
387+
widget: {
388+
Text: { text: `\${fetchFoo.body.data}` },
389+
},
390+
},
391+
},
392+
],
393+
},
394+
},
395+
{
396+
elseif: `\${toggleButton.value === "bar"}`,
397+
Column: {
398+
children: [{ Text: { text: `\${fetchFoo.data}` } }],
399+
},
400+
},
401+
],
402+
},
403+
},
404+
{
405+
name: "Button",
406+
properties: {
407+
label: "Verify States",
408+
onTap: { executeCode: "console.log(fetchFoo.isLoading)" },
409+
},
410+
},
411+
],
412+
},
413+
},
414+
apis: [
415+
{ name: "fetchFoo", method: "GET" },
416+
{ name: "fetchBar", method: "GET" },
417+
],
418+
onLoad: { invokeAPI: { name: "fetchFoo" } },
419+
}}
420+
/>,
421+
{
422+
wrapper: BrowserRouterWrapper,
423+
},
424+
);
425+
426+
await waitFor(() => {
427+
expect(fetchMock).toHaveBeenCalledTimes(1);
428+
expect(screen.getByText("Foo")).toBeInTheDocument();
429+
expect(screen.getByText("Bar")).toBeInTheDocument();
430+
});
431+
432+
fireEvent.click(screen.getByText("Bar"));
433+
await waitFor(() => {
434+
expect(fetchMock).toHaveBeenCalledTimes(2);
435+
});
436+
437+
fireEvent.click(screen.getByText("Foo"));
438+
await waitFor(() => {
439+
expect(fetchMock).toHaveBeenCalledTimes(2);
440+
});
441+
442+
fireEvent.click(screen.getByText("Verify States"));
443+
await waitFor(() => {
444+
expect(logSpy).toHaveBeenCalledWith(false);
445+
});
446+
});

0 commit comments

Comments
 (0)