From c7bbb26ac0abd2d0fad581cb1107a9f77ba04083 Mon Sep 17 00:00:00 2001 From: MauritsBrinkman Date: Tue, 17 Jun 2025 15:19:44 +0100 Subject: [PATCH] test: add useStream onStop callback tests --- libs/sdk-js/src/tests/stream.test.tsx | 234 +++++++++++++++++++++++--- 1 file changed, 210 insertions(+), 24 deletions(-) diff --git a/libs/sdk-js/src/tests/stream.test.tsx b/libs/sdk-js/src/tests/stream.test.tsx index 6184b411f..a5588d805 100644 --- a/libs/sdk-js/src/tests/stream.test.tsx +++ b/libs/sdk-js/src/tests/stream.test.tsx @@ -74,12 +74,7 @@ function TestChatComponent() { {isLoading ? "Loading..." : "Not loading"} {error ?
{String(error)}
: null} - + + + ); + } + + render(); + + // Start a stream and stop it + await user.click(screen.getByTestId("submit")); + await user.click(screen.getByTestId("stop")); + + // Verify onStop was called with mutate function + expect(onStopCallback).toHaveBeenCalledTimes(1); + expect(onStopCallback).toHaveBeenCalledWith( + expect.objectContaining({ + mutate: expect.any(Function), + }), + ); + }); + + it("mutate function updates stream values immediately", async () => { + function TestComponent() { + const { submit, stop, values } = useStream({ + assistantId: "test-assistant", + apiKey: "test-api-key", + onStop: ({ mutate }) => { + mutate((prev) => ({ + ...prev, + stoppedByUser: true, + customMessage: "Stream stopped", + })); + }, + }); + + return ( +
+
+ {(values as any).stoppedByUser ? "Stopped" : "Not stopped"} +
+
+ {(values as any).customMessage || "No message"} +
+ + +
+ ); + } + + render(); + + // Initial state + expect(screen.getByTestId("stopped-status")).toHaveTextContent( + "Not stopped", + ); + expect(screen.getByTestId("custom-message")).toHaveTextContent( + "No message", + ); + + // Start and stop stream + await user.click(screen.getByTestId("submit")); + await user.click(screen.getByTestId("stop")); + + // Verify state was updated immediately + await waitFor(() => { + expect(screen.getByTestId("stopped-status")).toHaveTextContent("Stopped"); + expect(screen.getByTestId("custom-message")).toHaveTextContent( + "Stream stopped", + ); + }); + }); + + it("handles functional updates correctly", async () => { + function TestComponent() { + const { submit, stop, values } = useStream({ + assistantId: "test-assistant", + apiKey: "test-api-key", + initialValues: { + counter: 5, + items: ["item1", "item2"], + }, + onStop: ({ mutate }) => { + mutate((prev: any) => ({ + ...prev, + counter: (prev.counter || 0) + 10, + items: [...(prev.items || []), "stopped"], + })); + }, + }); + + return ( +
+
{(values as any).counter}
+
{(values as any).items?.join(", ")}
+ + +
+ ); + } + + render(); + + // Initial state + expect(screen.getByTestId("counter")).toHaveTextContent("5"); + expect(screen.getByTestId("items")).toHaveTextContent("item1, item2"); + + // Start and stop stream + await user.click(screen.getByTestId("submit")); + await user.click(screen.getByTestId("stop")); + + // Verify functional update was applied correctly + await waitFor(() => { + expect(screen.getByTestId("counter")).toHaveTextContent("15"); + expect(screen.getByTestId("items")).toHaveTextContent( + "item1, item2, stopped", + ); + }); + }); + + it("is not called when stream completes naturally", async () => { + const onStopCallback = vi.fn(); + + function TestComponent() { + const { submit } = useStream({ + assistantId: "test-assistant", + apiKey: "test-api-key", + onStop: onStopCallback, + }); + + return ( +
+ +
+ ); + } + + render(); + + // Start a stream and let it complete naturally + await user.click(screen.getByTestId("submit")); + + // Wait for stream to complete naturally + await waitFor(() => { + expect(onStopCallback).not.toHaveBeenCalled(); + }); + }); +});