@tambo-ai/react 0.43.1 → 0.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/__tests__/use-suggestions.test.js +55 -27
- package/dist/hooks/__tests__/use-suggestions.test.js.map +1 -1
- package/dist/hooks/__tests__/use-tambo-stream-status.test.js +82 -39
- package/dist/hooks/__tests__/use-tambo-stream-status.test.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -3
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-component-state.d.ts.map +1 -1
- package/dist/hooks/use-component-state.js +2 -2
- package/dist/hooks/use-component-state.js.map +1 -1
- package/dist/hooks/use-current-message.d.ts +12 -27
- package/dist/hooks/use-current-message.d.ts.map +1 -1
- package/dist/hooks/use-current-message.js +16 -36
- package/dist/hooks/use-current-message.js.map +1 -1
- package/dist/hooks/use-tambo-stream-status.js +1 -1
- package/dist/hooks/use-tambo-stream-status.js.map +1 -1
- package/dist/hooks/use-thread-input.js +3 -2
- package/dist/hooks/use-thread-input.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/providers/__tests__/tambo-prop-stream-provider.test.js +79 -9
- package/dist/providers/__tests__/tambo-prop-stream-provider.test.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider.test.js +51 -7
- package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +2 -2
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +6 -6
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts +29 -11
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +128 -71
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/util/generate-component.d.ts.map +1 -1
- package/dist/util/generate-component.js +6 -2
- package/dist/util/generate-component.js.map +1 -1
- package/esm/hooks/__tests__/use-suggestions.test.js +55 -27
- package/esm/hooks/__tests__/use-suggestions.test.js.map +1 -1
- package/esm/hooks/__tests__/use-tambo-stream-status.test.js +82 -39
- package/esm/hooks/__tests__/use-tambo-stream-status.test.js.map +1 -1
- package/esm/hooks/index.d.ts +2 -2
- package/esm/hooks/index.d.ts.map +1 -1
- package/esm/hooks/index.js +2 -2
- package/esm/hooks/index.js.map +1 -1
- package/esm/hooks/use-component-state.d.ts.map +1 -1
- package/esm/hooks/use-component-state.js +3 -3
- package/esm/hooks/use-component-state.js.map +1 -1
- package/esm/hooks/use-current-message.d.ts +12 -27
- package/esm/hooks/use-current-message.d.ts.map +1 -1
- package/esm/hooks/use-current-message.js +15 -34
- package/esm/hooks/use-current-message.js.map +1 -1
- package/esm/hooks/use-tambo-stream-status.js +2 -2
- package/esm/hooks/use-tambo-stream-status.js.map +1 -1
- package/esm/hooks/use-thread-input.js +4 -3
- package/esm/hooks/use-thread-input.js.map +1 -1
- package/esm/index.d.ts +2 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +2 -2
- package/esm/index.js.map +1 -1
- package/esm/providers/__tests__/tambo-prop-stream-provider.test.js +80 -10
- package/esm/providers/__tests__/tambo-prop-stream-provider.test.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider.test.js +51 -7
- package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/esm/providers/index.d.ts +1 -1
- package/esm/providers/index.d.ts.map +1 -1
- package/esm/providers/index.js +1 -1
- package/esm/providers/index.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts +2 -2
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +7 -7
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts +29 -11
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +125 -70
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/util/generate-component.d.ts.map +1 -1
- package/esm/util/generate-component.js +6 -2
- package/esm/util/generate-component.js.map +1 -1
- package/package.json +11 -11
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const react_query_1 = require("@tanstack/react-query");
|
|
4
4
|
const react_1 = require("@testing-library/react");
|
|
5
|
+
const generate_component_response_1 = require("../../model/generate-component-response");
|
|
5
6
|
const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
|
|
6
7
|
const tambo_provider_1 = require("../../providers/tambo-provider");
|
|
7
8
|
const tambo_thread_provider_1 = require("../../providers/tambo-thread-provider");
|
|
@@ -38,6 +39,42 @@ describe("useTamboSuggestions", () => {
|
|
|
38
39
|
detailedSuggestion: "Test suggestion 2",
|
|
39
40
|
},
|
|
40
41
|
];
|
|
42
|
+
// Helper function to create mock TamboThreadMessage
|
|
43
|
+
const createMockMessage = (overrides = {}) => ({
|
|
44
|
+
id: "test-message-id",
|
|
45
|
+
componentState: {},
|
|
46
|
+
content: [{ type: "text", text: "Test message" }],
|
|
47
|
+
createdAt: new Date().toISOString(),
|
|
48
|
+
role: "assistant",
|
|
49
|
+
threadId: "test-thread-id",
|
|
50
|
+
...overrides,
|
|
51
|
+
});
|
|
52
|
+
// Helper function to create mock TamboThread
|
|
53
|
+
const createMockThread = (overrides = {}) => ({
|
|
54
|
+
id: "test-thread-id",
|
|
55
|
+
projectId: "test-project-id",
|
|
56
|
+
createdAt: new Date().toISOString(),
|
|
57
|
+
updatedAt: new Date().toISOString(),
|
|
58
|
+
messages: [],
|
|
59
|
+
...overrides,
|
|
60
|
+
});
|
|
61
|
+
// Helper function to create mock CombinedTamboThreadContextProps
|
|
62
|
+
const createMockThreadContext = (overrides = {}) => ({
|
|
63
|
+
thread: createMockThread(),
|
|
64
|
+
switchCurrentThread: jest.fn(),
|
|
65
|
+
startNewThread: jest.fn(),
|
|
66
|
+
updateThreadName: jest.fn(),
|
|
67
|
+
generateThreadName: jest.fn(),
|
|
68
|
+
addThreadMessage: jest.fn(),
|
|
69
|
+
updateThreadMessage: jest.fn(),
|
|
70
|
+
cancel: jest.fn(),
|
|
71
|
+
streaming: false,
|
|
72
|
+
sendThreadMessage: jest.fn(),
|
|
73
|
+
generationStage: generate_component_response_1.GenerationStage.IDLE,
|
|
74
|
+
generationStatusMessage: "",
|
|
75
|
+
isIdle: true,
|
|
76
|
+
...overrides,
|
|
77
|
+
});
|
|
41
78
|
beforeEach(() => {
|
|
42
79
|
jest.mocked(tambo_client_provider_1.useTamboQueryClient).mockReturnValue(new react_query_1.QueryClient());
|
|
43
80
|
jest.mocked(react_query_hooks_1.useTamboMutation).mockImplementation(({ mutationFn }) => ({
|
|
@@ -53,18 +90,15 @@ describe("useTamboSuggestions", () => {
|
|
|
53
90
|
jest.mocked(tambo_provider_1.useTambo).mockReturnValue({
|
|
54
91
|
sendThreadMessage: jest.fn(),
|
|
55
92
|
});
|
|
56
|
-
jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
|
|
57
|
-
thread: {
|
|
58
|
-
id: "test-thread-id",
|
|
93
|
+
jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue(createMockThreadContext({
|
|
94
|
+
thread: createMockThread({
|
|
59
95
|
messages: [
|
|
60
|
-
{
|
|
61
|
-
id: "test-message-id",
|
|
96
|
+
createMockMessage({
|
|
62
97
|
role: "hydra",
|
|
63
|
-
|
|
64
|
-
},
|
|
98
|
+
}),
|
|
65
99
|
],
|
|
66
|
-
},
|
|
67
|
-
});
|
|
100
|
+
}),
|
|
101
|
+
}));
|
|
68
102
|
jest.mocked(use_thread_input_1.useTamboThreadInput).mockReturnValue({
|
|
69
103
|
setValue: jest.fn(),
|
|
70
104
|
value: "",
|
|
@@ -95,18 +129,15 @@ describe("useTamboSuggestions", () => {
|
|
|
95
129
|
},
|
|
96
130
|
},
|
|
97
131
|
});
|
|
98
|
-
jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
|
|
99
|
-
thread: {
|
|
100
|
-
id: "test-thread-id",
|
|
132
|
+
jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue(createMockThreadContext({
|
|
133
|
+
thread: createMockThread({
|
|
101
134
|
messages: [
|
|
102
|
-
{
|
|
103
|
-
id: "test-message-id",
|
|
135
|
+
createMockMessage({
|
|
104
136
|
role: "assistant",
|
|
105
|
-
|
|
106
|
-
},
|
|
137
|
+
}),
|
|
107
138
|
],
|
|
108
|
-
},
|
|
109
|
-
});
|
|
139
|
+
}),
|
|
140
|
+
}));
|
|
110
141
|
// Mock the query result to return the mock suggestions
|
|
111
142
|
jest.mocked(react_query_hooks_1.useTamboQuery).mockReturnValue({
|
|
112
143
|
data: mockSuggestions,
|
|
@@ -136,18 +167,15 @@ describe("useTamboSuggestions", () => {
|
|
|
136
167
|
},
|
|
137
168
|
});
|
|
138
169
|
// Mock the thread to have a non-Tambo message
|
|
139
|
-
jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
|
|
140
|
-
thread: {
|
|
141
|
-
id: "test-thread-id",
|
|
170
|
+
jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue(createMockThreadContext({
|
|
171
|
+
thread: createMockThread({
|
|
142
172
|
messages: [
|
|
143
|
-
{
|
|
144
|
-
id: "test-message-id",
|
|
173
|
+
createMockMessage({
|
|
145
174
|
role: "user",
|
|
146
|
-
|
|
147
|
-
},
|
|
175
|
+
}),
|
|
148
176
|
],
|
|
149
|
-
},
|
|
150
|
-
});
|
|
177
|
+
}),
|
|
178
|
+
}));
|
|
151
179
|
const { result } = (0, react_1.renderHook)(() => (0, use_suggestions_1.useTamboSuggestions)());
|
|
152
180
|
// Wait for the effect to run
|
|
153
181
|
await (0, react_1.act)(async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-suggestions.test.js","sourceRoot":"","sources":["../../../src/hooks/__tests__/use-suggestions.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient, UseQueryResult } from \"@tanstack/react-query\";\nimport { act, renderHook } from \"@testing-library/react\";\nimport { TamboThreadMessage } from \"../../model/generate-component-response\";\nimport {\n useTamboClient,\n useTamboQueryClient,\n} from \"../../providers/tambo-client-provider\";\nimport { TamboContextProps, useTambo } from \"../../providers/tambo-provider\";\nimport {\n TamboThreadContextProps,\n useTamboThread,\n} from \"../../providers/tambo-thread-provider\";\nimport { PartialTamboAI } from \"../../testing/types\";\nimport { useTamboMutation, useTamboQuery } from \"../react-query-hooks\";\nimport { useTamboSuggestions } from \"../use-suggestions\";\nimport { useTamboThreadInput, UseThreadInput } from \"../use-thread-input\";\n\n// Mock the required providers\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n useTamboQueryClient: jest.fn(),\n}));\n\njest.mock(\"../../providers/tambo-provider\", () => ({ useTambo: jest.fn() }));\n\njest.mock(\"../../providers/tambo-thread-provider\", () => ({\n useTamboThread: jest.fn(),\n}));\n\njest.mock(\"../use-thread-input\", () => ({ useTamboThreadInput: jest.fn() }));\n\n// Mock the react-query-hooks\njest.mock(\"../react-query-hooks\", () => ({\n useTamboQuery: jest.fn(),\n useTamboMutation: jest.fn(),\n}));\n\ndescribe(\"useTamboSuggestions\", () => {\n const mockSuggestions: TamboAI.Beta.Threads.Suggestion[] = [\n {\n id: \"suggestion-1\",\n messageId: \"test-message-id\",\n title: \"Test Suggestion 1\",\n detailedSuggestion: \"Test suggestion 1\",\n },\n {\n id: \"suggestion-2\",\n messageId: \"test-message-id\",\n title: \"Test Suggestion 2\",\n detailedSuggestion: \"Test suggestion 2\",\n },\n ];\n\n beforeEach(() => {\n jest.mocked(useTamboQueryClient).mockReturnValue(new QueryClient());\n jest.mocked(useTamboMutation).mockImplementation(\n ({ mutationFn }) =>\n ({\n mutateAsync: mutationFn,\n isLoading: false,\n isError: false,\n error: null,\n }) as any,\n );\n // Setup default mock implementations\n jest.mocked(useTamboClient).mockReturnValue({\n beta: { threads: { suggestions: { generate: jest.fn() } } },\n } satisfies PartialTamboAI as any);\n jest.mocked(useTambo).mockReturnValue({\n sendThreadMessage: jest.fn(),\n } satisfies Partial<TamboContextProps> as any);\n jest.mocked(useTamboThread).mockReturnValue({\n thread: {\n id: \"test-thread-id\",\n messages: [\n {\n id: \"test-message-id\",\n role: \"hydra\",\n content: [{ type: \"text\", text: \"Test message\" }],\n },\n ],\n },\n } as TamboThreadContextProps);\n jest.mocked(useTamboThreadInput).mockReturnValue({\n setValue: jest.fn(),\n value: \"\",\n submit: jest.fn(),\n } satisfies Partial<UseThreadInput> as any);\n // Default query mock returns empty array\n jest.mocked(useTamboQuery).mockReturnValue({\n data: [],\n isLoading: false,\n isError: false,\n error: null,\n } satisfies Partial<UseQueryResult<unknown, unknown>> as any);\n });\n\n it(\"should initialize with empty suggestions and no selected suggestion\", () => {\n const { result } = renderHook(() => useTamboSuggestions());\n\n expect(result.current.suggestions).toEqual([]);\n expect(result.current.selectedSuggestionId).toBeNull();\n });\n\n it(\"should generate suggestions when latest message is from Tambo\", async () => {\n const mockGenerate = jest.fn().mockResolvedValue(mockSuggestions);\n jest.mocked(useTamboClient).mockReturnValue({\n beta: {\n threads: {\n suggestions: {\n generate: mockGenerate,\n list: jest.fn(),\n },\n },\n },\n } satisfies PartialTamboAI as any);\n jest.mocked(useTamboThread).mockReturnValue({\n thread: {\n id: \"test-thread-id\",\n messages: [\n {\n id: \"test-message-id\",\n role: \"assistant\",\n content: [{ type: \"text\", text: \"Test message\" }],\n } as TamboThreadMessage,\n ],\n },\n } as TamboThreadContextProps);\n\n // Mock the query result to return the mock suggestions\n jest.mocked(useTamboQuery).mockReturnValue({\n data: mockSuggestions,\n isLoading: false,\n isError: false,\n error: null,\n } as UseQueryResult<unknown, unknown>);\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n // Wait for the effect to run\n await act(async () => {\n await new Promise((resolve) => setTimeout(resolve, 0));\n });\n\n // Since we're mocking useTamboQuery to return the suggestions directly,\n // the generate function won't be called, so we don't need to check that\n expect(result.current.suggestions).toEqual(mockSuggestions);\n });\n\n it(\"should not generate suggestions when latest message is not from Tambo\", async () => {\n const mockGenerate = jest.fn();\n jest.mocked(useTamboClient).mockReturnValue({\n beta: {\n threads: {\n suggestions: {\n generate: mockGenerate,\n list: jest.fn(),\n },\n },\n },\n } satisfies PartialTamboAI as any);\n // Mock the thread to have a non-Tambo message\n jest.mocked(useTamboThread).mockReturnValue({\n thread: {\n id: \"test-thread-id\",\n messages: [\n {\n id: \"test-message-id\",\n role: \"user\",\n content: [{ type: \"text\", text: \"Test message\" }],\n } as TamboThreadMessage,\n ],\n },\n } as TamboThreadContextProps);\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n // Wait for the effect to run\n await act(async () => {\n await new Promise((resolve) => setTimeout(resolve, 0));\n });\n\n expect(mockGenerate).not.toHaveBeenCalled();\n expect(result.current.suggestions).toEqual([]);\n });\n\n it(\"should accept a suggestion and update input value\", async () => {\n const mockSetValue = jest.fn();\n jest.mocked(useTamboThreadInput).mockReturnValue({\n setValue: mockSetValue,\n value: \"\",\n submit: jest.fn(),\n } satisfies Partial<UseThreadInput> as any);\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n await act(async () => {\n await result.current.accept({\n suggestion: mockSuggestions[0],\n shouldSubmit: false,\n });\n });\n\n expect(mockSetValue).toHaveBeenCalledWith(\"Test suggestion 1\");\n expect(result.current.selectedSuggestionId).toBe(\"suggestion-1\");\n });\n\n it(\"should accept a suggestion and submit it\", async () => {\n const mockSendThreadMessage = jest.fn();\n jest.mocked(useTambo).mockReturnValue({\n sendThreadMessage: mockSendThreadMessage,\n } satisfies Partial<TamboContextProps> as any);\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n await act(async () => {\n await result.current.accept({\n suggestion: mockSuggestions[0],\n shouldSubmit: true,\n });\n });\n\n expect(mockSendThreadMessage).toHaveBeenCalledWith(\"Test suggestion 1\", {\n threadId: \"test-thread-id\",\n });\n expect(result.current.selectedSuggestionId).toBe(\"suggestion-1\");\n });\n\n it(\"should throw error when accepting invalid suggestion\", async () => {\n const invalidSuggestion = {\n id: \"invalid-suggestion\",\n messageId: \"test-message-id\",\n title: \"Invalid Suggestion\",\n detailedSuggestion: \"\", // Empty suggestion should fail validation\n };\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n await act(async () => {\n await expect(\n result.current.accept({\n suggestion: invalidSuggestion,\n shouldSubmit: false,\n }),\n ).rejects.toThrow(\"Message cannot be empty\");\n });\n\n expect(result.current.selectedSuggestionId).toBeNull();\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"use-suggestions.test.js","sourceRoot":"","sources":["../../../src/hooks/__tests__/use-suggestions.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient, UseQueryResult } from \"@tanstack/react-query\";\nimport { act, renderHook } from \"@testing-library/react\";\nimport {\n GenerationStage,\n TamboThreadMessage,\n} from \"../../model/generate-component-response\";\nimport { TamboThread } from \"../../model/tambo-thread\";\nimport {\n useTamboClient,\n useTamboQueryClient,\n} from \"../../providers/tambo-client-provider\";\nimport { TamboContextProps, useTambo } from \"../../providers/tambo-provider\";\nimport {\n CombinedTamboThreadContextProps,\n useTamboThread,\n} from \"../../providers/tambo-thread-provider\";\nimport { PartialTamboAI } from \"../../testing/types\";\nimport { useTamboMutation, useTamboQuery } from \"../react-query-hooks\";\nimport { useTamboSuggestions } from \"../use-suggestions\";\nimport { useTamboThreadInput, UseThreadInput } from \"../use-thread-input\";\n\n// Mock the required providers\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n useTamboQueryClient: jest.fn(),\n}));\n\njest.mock(\"../../providers/tambo-provider\", () => ({ useTambo: jest.fn() }));\n\njest.mock(\"../../providers/tambo-thread-provider\", () => ({\n useTamboThread: jest.fn(),\n}));\n\njest.mock(\"../use-thread-input\", () => ({ useTamboThreadInput: jest.fn() }));\n\n// Mock the react-query-hooks\njest.mock(\"../react-query-hooks\", () => ({\n useTamboQuery: jest.fn(),\n useTamboMutation: jest.fn(),\n}));\n\ndescribe(\"useTamboSuggestions\", () => {\n const mockSuggestions: TamboAI.Beta.Threads.Suggestion[] = [\n {\n id: \"suggestion-1\",\n messageId: \"test-message-id\",\n title: \"Test Suggestion 1\",\n detailedSuggestion: \"Test suggestion 1\",\n },\n {\n id: \"suggestion-2\",\n messageId: \"test-message-id\",\n title: \"Test Suggestion 2\",\n detailedSuggestion: \"Test suggestion 2\",\n },\n ];\n\n // Helper function to create mock TamboThreadMessage\n const createMockMessage = (\n overrides: Partial<TamboThreadMessage> = {},\n ): TamboThreadMessage => ({\n id: \"test-message-id\",\n componentState: {},\n content: [{ type: \"text\", text: \"Test message\" }],\n createdAt: new Date().toISOString(),\n role: \"assistant\",\n threadId: \"test-thread-id\",\n ...overrides,\n });\n\n // Helper function to create mock TamboThread\n const createMockThread = (\n overrides: Partial<TamboThread> = {},\n ): TamboThread => ({\n id: \"test-thread-id\",\n projectId: \"test-project-id\",\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n messages: [],\n ...overrides,\n });\n\n // Helper function to create mock CombinedTamboThreadContextProps\n const createMockThreadContext = (\n overrides: Partial<CombinedTamboThreadContextProps> = {},\n ): CombinedTamboThreadContextProps => ({\n thread: createMockThread(),\n switchCurrentThread: jest.fn(),\n startNewThread: jest.fn(),\n updateThreadName: jest.fn(),\n generateThreadName: jest.fn(),\n addThreadMessage: jest.fn(),\n updateThreadMessage: jest.fn(),\n cancel: jest.fn(),\n streaming: false,\n sendThreadMessage: jest.fn(),\n generationStage: GenerationStage.IDLE,\n generationStatusMessage: \"\",\n isIdle: true,\n ...overrides,\n });\n\n beforeEach(() => {\n jest.mocked(useTamboQueryClient).mockReturnValue(new QueryClient());\n jest.mocked(useTamboMutation).mockImplementation(\n ({ mutationFn }) =>\n ({\n mutateAsync: mutationFn,\n isLoading: false,\n isError: false,\n error: null,\n }) as any,\n );\n // Setup default mock implementations\n jest.mocked(useTamboClient).mockReturnValue({\n beta: { threads: { suggestions: { generate: jest.fn() } } },\n } satisfies PartialTamboAI as any);\n jest.mocked(useTambo).mockReturnValue({\n sendThreadMessage: jest.fn(),\n } satisfies Partial<TamboContextProps> as any);\n jest.mocked(useTamboThread).mockReturnValue(\n createMockThreadContext({\n thread: createMockThread({\n messages: [\n createMockMessage({\n role: \"hydra\",\n }),\n ],\n }),\n }),\n );\n jest.mocked(useTamboThreadInput).mockReturnValue({\n setValue: jest.fn(),\n value: \"\",\n submit: jest.fn(),\n } satisfies Partial<UseThreadInput> as any);\n // Default query mock returns empty array\n jest.mocked(useTamboQuery).mockReturnValue({\n data: [],\n isLoading: false,\n isError: false,\n error: null,\n } satisfies Partial<UseQueryResult<unknown, unknown>> as any);\n });\n\n it(\"should initialize with empty suggestions and no selected suggestion\", () => {\n const { result } = renderHook(() => useTamboSuggestions());\n\n expect(result.current.suggestions).toEqual([]);\n expect(result.current.selectedSuggestionId).toBeNull();\n });\n\n it(\"should generate suggestions when latest message is from Tambo\", async () => {\n const mockGenerate = jest.fn().mockResolvedValue(mockSuggestions);\n jest.mocked(useTamboClient).mockReturnValue({\n beta: {\n threads: {\n suggestions: {\n generate: mockGenerate,\n list: jest.fn(),\n },\n },\n },\n } satisfies PartialTamboAI as any);\n jest.mocked(useTamboThread).mockReturnValue(\n createMockThreadContext({\n thread: createMockThread({\n messages: [\n createMockMessage({\n role: \"assistant\",\n }),\n ],\n }),\n }),\n );\n\n // Mock the query result to return the mock suggestions\n jest.mocked(useTamboQuery).mockReturnValue({\n data: mockSuggestions,\n isLoading: false,\n isError: false,\n error: null,\n } as UseQueryResult<unknown, unknown>);\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n // Wait for the effect to run\n await act(async () => {\n await new Promise((resolve) => setTimeout(resolve, 0));\n });\n\n // Since we're mocking useTamboQuery to return the suggestions directly,\n // the generate function won't be called, so we don't need to check that\n expect(result.current.suggestions).toEqual(mockSuggestions);\n });\n\n it(\"should not generate suggestions when latest message is not from Tambo\", async () => {\n const mockGenerate = jest.fn();\n jest.mocked(useTamboClient).mockReturnValue({\n beta: {\n threads: {\n suggestions: {\n generate: mockGenerate,\n list: jest.fn(),\n },\n },\n },\n } satisfies PartialTamboAI as any);\n // Mock the thread to have a non-Tambo message\n jest.mocked(useTamboThread).mockReturnValue(\n createMockThreadContext({\n thread: createMockThread({\n messages: [\n createMockMessage({\n role: \"user\",\n }),\n ],\n }),\n }),\n );\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n // Wait for the effect to run\n await act(async () => {\n await new Promise((resolve) => setTimeout(resolve, 0));\n });\n\n expect(mockGenerate).not.toHaveBeenCalled();\n expect(result.current.suggestions).toEqual([]);\n });\n\n it(\"should accept a suggestion and update input value\", async () => {\n const mockSetValue = jest.fn();\n jest.mocked(useTamboThreadInput).mockReturnValue({\n setValue: mockSetValue,\n value: \"\",\n submit: jest.fn(),\n } satisfies Partial<UseThreadInput> as any);\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n await act(async () => {\n await result.current.accept({\n suggestion: mockSuggestions[0],\n shouldSubmit: false,\n });\n });\n\n expect(mockSetValue).toHaveBeenCalledWith(\"Test suggestion 1\");\n expect(result.current.selectedSuggestionId).toBe(\"suggestion-1\");\n });\n\n it(\"should accept a suggestion and submit it\", async () => {\n const mockSendThreadMessage = jest.fn();\n jest.mocked(useTambo).mockReturnValue({\n sendThreadMessage: mockSendThreadMessage,\n } satisfies Partial<TamboContextProps> as any);\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n await act(async () => {\n await result.current.accept({\n suggestion: mockSuggestions[0],\n shouldSubmit: true,\n });\n });\n\n expect(mockSendThreadMessage).toHaveBeenCalledWith(\"Test suggestion 1\", {\n threadId: \"test-thread-id\",\n });\n expect(result.current.selectedSuggestionId).toBe(\"suggestion-1\");\n });\n\n it(\"should throw error when accepting invalid suggestion\", async () => {\n const invalidSuggestion = {\n id: \"invalid-suggestion\",\n messageId: \"test-message-id\",\n title: \"Invalid Suggestion\",\n detailedSuggestion: \"\", // Empty suggestion should fail validation\n };\n\n const { result } = renderHook(() => useTamboSuggestions());\n\n await act(async () => {\n await expect(\n result.current.accept({\n suggestion: invalidSuggestion,\n shouldSubmit: false,\n }),\n ).rejects.toThrow(\"Message cannot be empty\");\n });\n\n expect(result.current.selectedSuggestionId).toBeNull();\n });\n});\n"]}
|
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const react_1 = require("@testing-library/react");
|
|
4
4
|
const generate_component_response_1 = require("../../model/generate-component-response");
|
|
5
|
-
const tambo_thread_provider_1 = require("../../providers/tambo-thread-provider");
|
|
6
|
-
const use_current_message_1 = require("../use-current-message");
|
|
7
5
|
const use_tambo_stream_status_1 = require("../use-tambo-stream-status");
|
|
8
6
|
// Mock the required providers
|
|
9
7
|
jest.mock("../../providers/tambo-thread-provider", () => ({
|
|
10
|
-
|
|
8
|
+
useTamboGenerationStage: jest.fn(),
|
|
11
9
|
}));
|
|
12
10
|
jest.mock("../use-current-message", () => ({
|
|
13
11
|
useTamboCurrentMessage: jest.fn(),
|
|
14
12
|
}));
|
|
13
|
+
// Import the mocked functions
|
|
14
|
+
const tambo_thread_provider_1 = require("../../providers/tambo-thread-provider");
|
|
15
|
+
const use_current_message_1 = require("../use-current-message");
|
|
15
16
|
// Mock window for SSR tests
|
|
16
17
|
const originalWindow = global.window;
|
|
17
18
|
// Helper function to create mock ComponentDecisionV2
|
|
@@ -32,15 +33,20 @@ const createMockMessage = (overrides = {}) => ({
|
|
|
32
33
|
threadId: "test-thread",
|
|
33
34
|
...overrides,
|
|
34
35
|
});
|
|
36
|
+
// Get the mocked functions
|
|
37
|
+
const mockUseTamboGenerationStage = jest.mocked(tambo_thread_provider_1.useTamboGenerationStage);
|
|
38
|
+
const mockUseTamboCurrentMessage = jest.mocked(use_current_message_1.useTamboCurrentMessage);
|
|
35
39
|
describe("useTamboStreamStatus", () => {
|
|
36
40
|
beforeEach(() => {
|
|
37
41
|
// Restore window for client-side tests
|
|
38
42
|
global.window = originalWindow;
|
|
39
43
|
// Default mock implementations
|
|
40
|
-
|
|
44
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
41
45
|
generationStage: generate_component_response_1.GenerationStage.IDLE,
|
|
46
|
+
generationStatusMessage: "",
|
|
47
|
+
isIdle: true,
|
|
42
48
|
});
|
|
43
|
-
|
|
49
|
+
mockUseTamboCurrentMessage.mockReturnValue({
|
|
44
50
|
id: "test-message",
|
|
45
51
|
component: {
|
|
46
52
|
props: {},
|
|
@@ -52,10 +58,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
52
58
|
});
|
|
53
59
|
describe("Initial State", () => {
|
|
54
60
|
it("should start with all flags as pending when idle and no props", () => {
|
|
55
|
-
|
|
61
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
56
62
|
generationStage: generate_component_response_1.GenerationStage.IDLE,
|
|
63
|
+
generationStatusMessage: "",
|
|
64
|
+
isIdle: true,
|
|
57
65
|
});
|
|
58
|
-
|
|
66
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
59
67
|
component: createMockComponent({ title: "", body: "" }),
|
|
60
68
|
}));
|
|
61
69
|
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
@@ -82,10 +90,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
82
90
|
});
|
|
83
91
|
describe("Generation vs Props Streaming", () => {
|
|
84
92
|
it("should show generation streaming but props still pending when STREAMING_RESPONSE with no prop content", () => {
|
|
85
|
-
|
|
93
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
86
94
|
generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
|
|
95
|
+
generationStatusMessage: "",
|
|
96
|
+
isIdle: false,
|
|
87
97
|
});
|
|
88
|
-
|
|
98
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
89
99
|
component: createMockComponent({ title: "", body: "" }),
|
|
90
100
|
}));
|
|
91
101
|
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
@@ -99,10 +109,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
99
109
|
expect(result.current.propStatus.body.isStreaming).toBe(false);
|
|
100
110
|
});
|
|
101
111
|
it("should show prop streaming when props receive content during STREAMING_RESPONSE", () => {
|
|
102
|
-
|
|
112
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
103
113
|
generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
|
|
114
|
+
generationStatusMessage: "",
|
|
115
|
+
isIdle: false,
|
|
104
116
|
});
|
|
105
|
-
|
|
117
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
106
118
|
component: createMockComponent({ title: "Hello", body: "" }),
|
|
107
119
|
}));
|
|
108
120
|
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
@@ -119,10 +131,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
119
131
|
describe("Boolean Lifecycle", () => {
|
|
120
132
|
it("should transition through Init -> Streaming -> Success lifecycle", () => {
|
|
121
133
|
// Start with IDLE (Init phase)
|
|
122
|
-
|
|
134
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
123
135
|
generationStage: generate_component_response_1.GenerationStage.IDLE,
|
|
136
|
+
generationStatusMessage: "",
|
|
137
|
+
isIdle: true,
|
|
124
138
|
});
|
|
125
|
-
|
|
139
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
126
140
|
component: createMockComponent({ title: "", body: "" }),
|
|
127
141
|
}));
|
|
128
142
|
const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
@@ -131,10 +145,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
131
145
|
expect(result.current.streamStatus.isStreaming).toBe(false);
|
|
132
146
|
expect(result.current.streamStatus.isSuccess).toBe(false);
|
|
133
147
|
// Phase 2: Streaming - move to STREAMING_RESPONSE with content
|
|
134
|
-
|
|
148
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
135
149
|
generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
|
|
150
|
+
generationStatusMessage: "",
|
|
151
|
+
isIdle: false,
|
|
136
152
|
});
|
|
137
|
-
|
|
153
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
138
154
|
component: createMockComponent({
|
|
139
155
|
title: "Hello World",
|
|
140
156
|
body: "Some content",
|
|
@@ -145,8 +161,10 @@ describe("useTamboStreamStatus", () => {
|
|
|
145
161
|
expect(result.current.streamStatus.isStreaming).toBe(true);
|
|
146
162
|
expect(result.current.streamStatus.isSuccess).toBe(false);
|
|
147
163
|
// Phase 3: Complete - move to COMPLETE
|
|
148
|
-
|
|
164
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
149
165
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
166
|
+
generationStatusMessage: "",
|
|
167
|
+
isIdle: false,
|
|
150
168
|
});
|
|
151
169
|
rerender();
|
|
152
170
|
expect(result.current.streamStatus.isPending).toBe(false);
|
|
@@ -154,11 +172,13 @@ describe("useTamboStreamStatus", () => {
|
|
|
154
172
|
expect(result.current.streamStatus.isSuccess).toBe(true);
|
|
155
173
|
});
|
|
156
174
|
it("should handle error state correctly", () => {
|
|
157
|
-
|
|
175
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
158
176
|
generationStage: generate_component_response_1.GenerationStage.ERROR,
|
|
177
|
+
generationStatusMessage: "",
|
|
178
|
+
isIdle: false,
|
|
159
179
|
});
|
|
160
180
|
const errorMessage = "Generation failed";
|
|
161
|
-
|
|
181
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
162
182
|
component: createMockComponent({ title: "", body: "" }),
|
|
163
183
|
error: errorMessage,
|
|
164
184
|
}));
|
|
@@ -172,10 +192,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
172
192
|
});
|
|
173
193
|
describe("Derivation Rules", () => {
|
|
174
194
|
it("should derive isPending correctly (no generation activity AND all props pending)", () => {
|
|
175
|
-
|
|
195
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
176
196
|
generationStage: generate_component_response_1.GenerationStage.IDLE,
|
|
197
|
+
generationStatusMessage: "",
|
|
198
|
+
isIdle: true,
|
|
177
199
|
});
|
|
178
|
-
|
|
200
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
179
201
|
component: createMockComponent({ title: "", body: "", footer: "" }),
|
|
180
202
|
}));
|
|
181
203
|
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
@@ -186,11 +208,13 @@ describe("useTamboStreamStatus", () => {
|
|
|
186
208
|
expect(result.current.propStatus.footer.isPending).toBe(true);
|
|
187
209
|
});
|
|
188
210
|
it("should derive isStreaming correctly (generation streaming OR any prop streaming)", () => {
|
|
189
|
-
|
|
211
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
190
212
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
213
|
+
generationStatusMessage: "",
|
|
214
|
+
isIdle: false,
|
|
191
215
|
});
|
|
192
216
|
// One prop still streaming
|
|
193
|
-
|
|
217
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
194
218
|
component: createMockComponent({
|
|
195
219
|
title: "Complete Title",
|
|
196
220
|
body: "Still streaming...",
|
|
@@ -202,10 +226,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
202
226
|
});
|
|
203
227
|
it("should derive isSuccess correctly (generation complete AND all props successful)", () => {
|
|
204
228
|
// Step 1: Start with streaming, props empty
|
|
205
|
-
|
|
229
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
206
230
|
generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
|
|
231
|
+
generationStatusMessage: "",
|
|
232
|
+
isIdle: false,
|
|
207
233
|
});
|
|
208
|
-
|
|
234
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
209
235
|
component: createMockComponent({
|
|
210
236
|
title: "",
|
|
211
237
|
body: "",
|
|
@@ -213,7 +239,7 @@ describe("useTamboStreamStatus", () => {
|
|
|
213
239
|
}));
|
|
214
240
|
const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
215
241
|
// Step 2: Simulate streaming in title
|
|
216
|
-
|
|
242
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
217
243
|
component: createMockComponent({
|
|
218
244
|
title: "Complete Title",
|
|
219
245
|
body: "",
|
|
@@ -221,7 +247,7 @@ describe("useTamboStreamStatus", () => {
|
|
|
221
247
|
}));
|
|
222
248
|
rerender();
|
|
223
249
|
// Step 3: Simulate streaming in body
|
|
224
|
-
|
|
250
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
225
251
|
component: createMockComponent({
|
|
226
252
|
title: "Complete Title",
|
|
227
253
|
body: "Complete Body",
|
|
@@ -229,8 +255,10 @@ describe("useTamboStreamStatus", () => {
|
|
|
229
255
|
}));
|
|
230
256
|
rerender();
|
|
231
257
|
// Step 4: Generation complete
|
|
232
|
-
|
|
258
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
233
259
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
260
|
+
generationStatusMessage: "",
|
|
261
|
+
isIdle: false,
|
|
234
262
|
});
|
|
235
263
|
rerender();
|
|
236
264
|
// Now both props should be successful
|
|
@@ -239,10 +267,12 @@ describe("useTamboStreamStatus", () => {
|
|
|
239
267
|
expect(result.current.streamStatus.isSuccess).toBe(true);
|
|
240
268
|
});
|
|
241
269
|
it("should derive isError correctly (generation error OR any prop error)", () => {
|
|
242
|
-
|
|
270
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
243
271
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
272
|
+
generationStatusMessage: "",
|
|
273
|
+
isIdle: false,
|
|
244
274
|
});
|
|
245
|
-
|
|
275
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
246
276
|
component: createMockComponent({
|
|
247
277
|
title: "Good Title",
|
|
248
278
|
body: "Good Body",
|
|
@@ -256,7 +286,7 @@ describe("useTamboStreamStatus", () => {
|
|
|
256
286
|
});
|
|
257
287
|
describe("Type Safety", () => {
|
|
258
288
|
it("should provide strongly typed prop status based on generic", () => {
|
|
259
|
-
|
|
289
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
260
290
|
component: createMockComponent({
|
|
261
291
|
title: "Test",
|
|
262
292
|
description: "Test desc",
|
|
@@ -272,7 +302,7 @@ describe("useTamboStreamStatus", () => {
|
|
|
272
302
|
// expect(result.current.propStatus.nonExistentProp).toBeDefined();
|
|
273
303
|
});
|
|
274
304
|
it("should work without generic type parameter", () => {
|
|
275
|
-
|
|
305
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
276
306
|
component: createMockComponent({ dynamicProp: "value" }),
|
|
277
307
|
}));
|
|
278
308
|
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
@@ -282,13 +312,20 @@ describe("useTamboStreamStatus", () => {
|
|
|
282
312
|
});
|
|
283
313
|
describe("Edge Cases", () => {
|
|
284
314
|
it("should handle missing message gracefully", () => {
|
|
285
|
-
|
|
315
|
+
mockUseTamboCurrentMessage.mockReturnValue({
|
|
316
|
+
id: "test-message",
|
|
317
|
+
role: "user",
|
|
318
|
+
content: [],
|
|
319
|
+
componentState: {},
|
|
320
|
+
createdAt: "",
|
|
321
|
+
threadId: "",
|
|
322
|
+
});
|
|
286
323
|
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
287
324
|
expect(result.current.streamStatus.isPending).toBe(true);
|
|
288
325
|
expect(result.current.propStatus).toEqual({});
|
|
289
326
|
});
|
|
290
327
|
it("should handle missing component props gracefully", () => {
|
|
291
|
-
|
|
328
|
+
mockUseTamboCurrentMessage.mockReturnValue({
|
|
292
329
|
id: "test-message",
|
|
293
330
|
// Missing component property
|
|
294
331
|
});
|
|
@@ -298,30 +335,36 @@ describe("useTamboStreamStatus", () => {
|
|
|
298
335
|
});
|
|
299
336
|
it("should reset prop tracking when generation restarts", () => {
|
|
300
337
|
// Step 1: Complete a message
|
|
301
|
-
|
|
338
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
302
339
|
generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
|
|
340
|
+
generationStatusMessage: "",
|
|
341
|
+
isIdle: false,
|
|
303
342
|
});
|
|
304
|
-
|
|
343
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
305
344
|
component: createMockComponent({ title: "" }),
|
|
306
345
|
}));
|
|
307
346
|
const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
|
|
308
347
|
// Simulate streaming in title
|
|
309
|
-
|
|
348
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
310
349
|
component: createMockComponent({ title: "First Title" }),
|
|
311
350
|
}));
|
|
312
351
|
rerender();
|
|
313
352
|
// Complete generation
|
|
314
|
-
|
|
353
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
315
354
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
355
|
+
generationStatusMessage: "",
|
|
356
|
+
isIdle: false,
|
|
316
357
|
});
|
|
317
358
|
rerender();
|
|
318
359
|
// Should be successful initially
|
|
319
360
|
expect(result.current.propStatus.title.isSuccess).toBe(true);
|
|
320
361
|
// Step 2: Start new generation with a new message ID to trigger reset
|
|
321
|
-
|
|
362
|
+
mockUseTamboGenerationStage.mockReturnValue({
|
|
322
363
|
generationStage: generate_component_response_1.GenerationStage.CHOOSING_COMPONENT,
|
|
364
|
+
generationStatusMessage: "",
|
|
365
|
+
isIdle: false,
|
|
323
366
|
});
|
|
324
|
-
|
|
367
|
+
mockUseTamboCurrentMessage.mockReturnValue(createMockMessage({
|
|
325
368
|
id: "new-message-id", // Different message ID to trigger reset
|
|
326
369
|
component: createMockComponent({ title: "" }),
|
|
327
370
|
}));
|