@tambo-ai/react 0.47.0 → 0.48.0
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/context-helpers/current-interactables-context-helper.d.ts +28 -0
- package/dist/context-helpers/current-interactables-context-helper.d.ts.map +1 -0
- package/dist/context-helpers/current-interactables-context-helper.js +61 -0
- package/dist/context-helpers/current-interactables-context-helper.js.map +1 -0
- package/dist/context-helpers/index.d.ts +1 -0
- package/dist/context-helpers/index.d.ts.map +1 -1
- package/dist/context-helpers/index.js +1 -0
- package/dist/context-helpers/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/__tests__/tambo-mcp-provider.test.d.ts +2 -0
- package/dist/mcp/__tests__/tambo-mcp-provider.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/tambo-mcp-provider.test.js +115 -0
- package/dist/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -0
- package/dist/mcp/tambo-mcp-provider.d.ts +6 -0
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +25 -2
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.d.ts +2 -0
- package/dist/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.d.ts.map +1 -0
- package/dist/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.js +339 -0
- package/dist/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.js.map +1 -0
- package/dist/providers/__tests__/tambo-interactables-additional-context.test.d.ts +2 -0
- package/dist/providers/__tests__/tambo-interactables-additional-context.test.d.ts.map +1 -0
- package/dist/providers/__tests__/tambo-interactables-additional-context.test.js +299 -0
- package/dist/providers/__tests__/tambo-interactables-additional-context.test.js.map +1 -0
- package/dist/providers/tambo-interactable-provider.d.ts +20 -0
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +32 -2
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/context-helpers/current-interactables-context-helper.d.ts +28 -0
- package/esm/context-helpers/current-interactables-context-helper.d.ts.map +1 -0
- package/esm/context-helpers/current-interactables-context-helper.js +56 -0
- package/esm/context-helpers/current-interactables-context-helper.js.map +1 -0
- package/esm/context-helpers/index.d.ts +1 -0
- package/esm/context-helpers/index.d.ts.map +1 -1
- package/esm/context-helpers/index.js +1 -0
- package/esm/context-helpers/index.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/mcp/__tests__/tambo-mcp-provider.test.d.ts +2 -0
- package/esm/mcp/__tests__/tambo-mcp-provider.test.d.ts.map +1 -0
- package/esm/mcp/__tests__/tambo-mcp-provider.test.js +113 -0
- package/esm/mcp/__tests__/tambo-mcp-provider.test.js.map +1 -0
- package/esm/mcp/tambo-mcp-provider.d.ts +6 -0
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +24 -2
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.d.ts +2 -0
- package/esm/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.d.ts.map +1 -0
- package/esm/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.js +334 -0
- package/esm/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.js.map +1 -0
- package/esm/providers/__tests__/tambo-interactables-additional-context.test.d.ts +2 -0
- package/esm/providers/__tests__/tambo-interactables-additional-context.test.d.ts.map +1 -0
- package/esm/providers/__tests__/tambo-interactables-additional-context.test.js +294 -0
- package/esm/providers/__tests__/tambo-interactables-additional-context.test.js.map +1 -0
- package/esm/providers/tambo-interactable-provider.d.ts +20 -0
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +30 -1
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/package.json +8 -8
- package/dist/mcp/mcp-tools-client.d.ts +0 -96
- package/dist/mcp/mcp-tools-client.d.ts.map +0 -1
- package/dist/mcp/mcp-tools-client.js +0 -178
- package/dist/mcp/mcp-tools-client.js.map +0 -1
- package/esm/mcp/mcp-tools-client.d.ts +0 -96
- package/esm/mcp/mcp-tools-client.d.ts.map +0 -1
- package/esm/mcp/mcp-tools-client.js +0 -174
- package/esm/mcp/mcp-tools-client.js.map +0 -1
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { render, waitFor } from "@testing-library/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { useTamboContextHelpers, TamboContextHelpersProvider, } from "../tambo-context-helpers-provider";
|
|
5
|
+
import { TamboInteractableProvider } from "../tambo-interactable-provider";
|
|
6
|
+
import { TamboStubProvider } from "../tambo-stubs";
|
|
7
|
+
import { withTamboInteractable } from "../hoc/with-tambo-interactable";
|
|
8
|
+
function wrapperWithProviders(children) {
|
|
9
|
+
const thread = {
|
|
10
|
+
id: "t-1",
|
|
11
|
+
projectId: "p-1",
|
|
12
|
+
createdAt: new Date().toISOString(),
|
|
13
|
+
updatedAt: new Date().toISOString(),
|
|
14
|
+
messages: [],
|
|
15
|
+
metadata: {},
|
|
16
|
+
};
|
|
17
|
+
return (React.createElement(TamboStubProvider, { thread: thread, registerTool: () => { }, registerTools: () => { }, registerComponent: () => { }, addToolAssociation: () => { } },
|
|
18
|
+
React.createElement(TamboContextHelpersProvider, null, children)));
|
|
19
|
+
}
|
|
20
|
+
describe("Interactables AdditionalContext - Edge Cases & Advanced Scenarios", () => {
|
|
21
|
+
test("handles components without propsSchema gracefully", async () => {
|
|
22
|
+
const SimpleComponent = ({ text }) => (React.createElement("div", null, text));
|
|
23
|
+
const InteractableSimpleComponent = withTamboInteractable(SimpleComponent, {
|
|
24
|
+
componentName: "SimpleComponent",
|
|
25
|
+
description: "A component without schema",
|
|
26
|
+
// No propsSchema provided
|
|
27
|
+
});
|
|
28
|
+
let capturedContexts = [];
|
|
29
|
+
const TestComponent = () => {
|
|
30
|
+
const { getAdditionalContext } = useTamboContextHelpers();
|
|
31
|
+
React.useEffect(() => {
|
|
32
|
+
let mounted = true;
|
|
33
|
+
getAdditionalContext().then((contexts) => {
|
|
34
|
+
if (mounted) {
|
|
35
|
+
capturedContexts = contexts;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return () => {
|
|
39
|
+
mounted = false;
|
|
40
|
+
};
|
|
41
|
+
}, [getAdditionalContext]);
|
|
42
|
+
return React.createElement("div", { "data-testid": "ready" }, "ready");
|
|
43
|
+
};
|
|
44
|
+
const { getByTestId } = render(wrapperWithProviders(React.createElement(TamboInteractableProvider, null,
|
|
45
|
+
React.createElement(InteractableSimpleComponent, { text: "test" }),
|
|
46
|
+
React.createElement(TestComponent, null))));
|
|
47
|
+
await waitFor(() => {
|
|
48
|
+
expect(getByTestId("ready")).toBeInTheDocument();
|
|
49
|
+
const entry = capturedContexts.find((c) => c.name === "interactables");
|
|
50
|
+
expect(entry).toBeDefined();
|
|
51
|
+
const component = entry.context.components[0];
|
|
52
|
+
expect(component.propsSchema).toBe("Not specified");
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
test("handles component unmounting and remounting correctly", async () => {
|
|
56
|
+
const Note = ({ title }) => React.createElement("div", null, title);
|
|
57
|
+
const InteractableNote = withTamboInteractable(Note, {
|
|
58
|
+
componentName: "Note",
|
|
59
|
+
description: "A note",
|
|
60
|
+
propsSchema: z.object({ title: z.string() }),
|
|
61
|
+
});
|
|
62
|
+
let capturedContexts = [];
|
|
63
|
+
const TestComponent = () => {
|
|
64
|
+
const { getAdditionalContext } = useTamboContextHelpers();
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
let mounted = true;
|
|
67
|
+
const interval = setInterval(() => {
|
|
68
|
+
getAdditionalContext().then((contexts) => {
|
|
69
|
+
if (mounted) {
|
|
70
|
+
capturedContexts = contexts;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}, 50);
|
|
74
|
+
return () => {
|
|
75
|
+
mounted = false;
|
|
76
|
+
clearInterval(interval);
|
|
77
|
+
};
|
|
78
|
+
}, [getAdditionalContext]);
|
|
79
|
+
return React.createElement("div", { "data-testid": "ready" }, "ready");
|
|
80
|
+
};
|
|
81
|
+
const Host = () => {
|
|
82
|
+
const [showNote, setShowNote] = React.useState(true);
|
|
83
|
+
React.useEffect(() => {
|
|
84
|
+
// Toggle the note on/off to test unmounting
|
|
85
|
+
const timeout = setTimeout(() => setShowNote(false), 100);
|
|
86
|
+
const timeout2 = setTimeout(() => setShowNote(true), 200);
|
|
87
|
+
return () => {
|
|
88
|
+
clearTimeout(timeout);
|
|
89
|
+
clearTimeout(timeout2);
|
|
90
|
+
};
|
|
91
|
+
}, []);
|
|
92
|
+
return (React.createElement(TamboInteractableProvider, null,
|
|
93
|
+
showNote && React.createElement(InteractableNote, { title: "dynamic note" }),
|
|
94
|
+
React.createElement(TestComponent, null)));
|
|
95
|
+
};
|
|
96
|
+
const { getByTestId } = render(wrapperWithProviders(React.createElement(Host, null)));
|
|
97
|
+
await waitFor(() => {
|
|
98
|
+
expect(getByTestId("ready")).toBeInTheDocument();
|
|
99
|
+
}, { timeout: 1000 });
|
|
100
|
+
// Eventually should show the note again
|
|
101
|
+
await waitFor(() => {
|
|
102
|
+
const entry = capturedContexts.find((c) => c.name === "interactables");
|
|
103
|
+
expect(entry?.context?.components).toHaveLength(1);
|
|
104
|
+
}, { timeout: 1000 });
|
|
105
|
+
});
|
|
106
|
+
test("context helper updates when props change from parent", async () => {
|
|
107
|
+
const Counter = ({ count, label = "Count", }) => (React.createElement("div", null,
|
|
108
|
+
label,
|
|
109
|
+
": ",
|
|
110
|
+
count));
|
|
111
|
+
const InteractableCounter = withTamboInteractable(Counter, {
|
|
112
|
+
componentName: "Counter",
|
|
113
|
+
description: "A counter component",
|
|
114
|
+
propsSchema: z.object({
|
|
115
|
+
count: z.number(),
|
|
116
|
+
label: z.string().optional(),
|
|
117
|
+
}),
|
|
118
|
+
});
|
|
119
|
+
let capturedContexts = [];
|
|
120
|
+
const TestComponent = () => {
|
|
121
|
+
const { getAdditionalContext } = useTamboContextHelpers();
|
|
122
|
+
React.useEffect(() => {
|
|
123
|
+
let mounted = true;
|
|
124
|
+
const interval = setInterval(() => {
|
|
125
|
+
getAdditionalContext().then((contexts) => {
|
|
126
|
+
if (mounted) {
|
|
127
|
+
capturedContexts = contexts;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}, 50);
|
|
131
|
+
return () => {
|
|
132
|
+
mounted = false;
|
|
133
|
+
clearInterval(interval);
|
|
134
|
+
};
|
|
135
|
+
}, [getAdditionalContext]);
|
|
136
|
+
return React.createElement("div", { "data-testid": "ready" }, "ready");
|
|
137
|
+
};
|
|
138
|
+
const Host = () => {
|
|
139
|
+
const [count, setCount] = React.useState(0);
|
|
140
|
+
const [label, setLabel] = React.useState("Items");
|
|
141
|
+
React.useEffect(() => {
|
|
142
|
+
const timeout1 = setTimeout(() => setCount(5), 100);
|
|
143
|
+
const timeout2 = setTimeout(() => setLabel("Updated Items"), 200);
|
|
144
|
+
return () => {
|
|
145
|
+
clearTimeout(timeout1);
|
|
146
|
+
clearTimeout(timeout2);
|
|
147
|
+
};
|
|
148
|
+
}, []);
|
|
149
|
+
return (React.createElement(TamboInteractableProvider, null,
|
|
150
|
+
React.createElement(InteractableCounter, { count: count, label: label }),
|
|
151
|
+
React.createElement(TestComponent, null)));
|
|
152
|
+
};
|
|
153
|
+
const { getByTestId } = render(wrapperWithProviders(React.createElement(Host, null)));
|
|
154
|
+
await waitFor(() => {
|
|
155
|
+
expect(getByTestId("ready")).toBeInTheDocument();
|
|
156
|
+
});
|
|
157
|
+
// Wait for updates to propagate
|
|
158
|
+
await waitFor(() => {
|
|
159
|
+
const entry = capturedContexts.find((c) => c.name === "interactables");
|
|
160
|
+
if (entry?.context?.components?.[0]) {
|
|
161
|
+
const props = entry.context.components[0].props;
|
|
162
|
+
expect(props.count).toBe(5);
|
|
163
|
+
expect(props.label).toBe("Updated Items");
|
|
164
|
+
}
|
|
165
|
+
}, { timeout: 1000 });
|
|
166
|
+
});
|
|
167
|
+
test("multiple providers with nested context helpers work correctly", async () => {
|
|
168
|
+
const Note = ({ title }) => React.createElement("div", null, title);
|
|
169
|
+
const InteractableNote = withTamboInteractable(Note, {
|
|
170
|
+
componentName: "Note",
|
|
171
|
+
description: "A note",
|
|
172
|
+
propsSchema: z.object({ title: z.string() }),
|
|
173
|
+
});
|
|
174
|
+
let outerContexts = [];
|
|
175
|
+
let innerContexts = [];
|
|
176
|
+
const OuterTestComponent = () => {
|
|
177
|
+
const { getAdditionalContext } = useTamboContextHelpers();
|
|
178
|
+
React.useEffect(() => {
|
|
179
|
+
let mounted = true;
|
|
180
|
+
getAdditionalContext().then((contexts) => {
|
|
181
|
+
if (mounted) {
|
|
182
|
+
outerContexts = contexts;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
return () => {
|
|
186
|
+
mounted = false;
|
|
187
|
+
};
|
|
188
|
+
}, [getAdditionalContext]);
|
|
189
|
+
return React.createElement("div", { "data-testid": "outer-ready" }, "outer ready");
|
|
190
|
+
};
|
|
191
|
+
const InnerTestComponent = () => {
|
|
192
|
+
const { getAdditionalContext } = useTamboContextHelpers();
|
|
193
|
+
React.useEffect(() => {
|
|
194
|
+
let mounted = true;
|
|
195
|
+
getAdditionalContext().then((contexts) => {
|
|
196
|
+
if (mounted) {
|
|
197
|
+
innerContexts = contexts;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
return () => {
|
|
201
|
+
mounted = false;
|
|
202
|
+
};
|
|
203
|
+
}, [getAdditionalContext]);
|
|
204
|
+
return React.createElement("div", { "data-testid": "inner-ready" }, "inner ready");
|
|
205
|
+
};
|
|
206
|
+
const { getByTestId } = render(wrapperWithProviders(React.createElement(TamboInteractableProvider, null,
|
|
207
|
+
React.createElement(InteractableNote, { title: "outer note" }),
|
|
208
|
+
React.createElement(OuterTestComponent, null),
|
|
209
|
+
React.createElement(TamboContextHelpersProvider, { contextHelpers: {
|
|
210
|
+
customContext: () => ({ custom: "inner" }),
|
|
211
|
+
} },
|
|
212
|
+
React.createElement(TamboInteractableProvider, null,
|
|
213
|
+
React.createElement(InteractableNote, { title: "inner note" }),
|
|
214
|
+
React.createElement(InnerTestComponent, null))))));
|
|
215
|
+
await waitFor(() => {
|
|
216
|
+
expect(getByTestId("outer-ready")).toBeInTheDocument();
|
|
217
|
+
expect(getByTestId("inner-ready")).toBeInTheDocument();
|
|
218
|
+
});
|
|
219
|
+
await waitFor(() => {
|
|
220
|
+
// Outer context should have outer note
|
|
221
|
+
const outerEntry = outerContexts.find((c) => c.name === "interactables");
|
|
222
|
+
expect(outerEntry?.context?.components).toHaveLength(1);
|
|
223
|
+
expect(outerEntry?.context?.components[0]?.props?.title).toBe("outer note");
|
|
224
|
+
// Inner context should have inner note and custom context
|
|
225
|
+
const innerEntry = innerContexts.find((c) => c.name === "interactables");
|
|
226
|
+
expect(innerEntry?.context?.components).toHaveLength(1);
|
|
227
|
+
expect(innerEntry?.context?.components[0]?.props?.title).toBe("inner note");
|
|
228
|
+
const customEntry = innerContexts.find((c) => c.name === "customContext");
|
|
229
|
+
expect(customEntry?.context).toEqual({ custom: "inner" });
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
test("provider cleanup removes helper when last provider unmounts", async () => {
|
|
233
|
+
const Note = ({ title }) => React.createElement("div", null, title);
|
|
234
|
+
const InteractableNote = withTamboInteractable(Note, {
|
|
235
|
+
componentName: "Note",
|
|
236
|
+
description: "A note",
|
|
237
|
+
propsSchema: z.object({ title: z.string() }),
|
|
238
|
+
});
|
|
239
|
+
let capturedContexts = [];
|
|
240
|
+
const TestComponent = () => {
|
|
241
|
+
const { getAdditionalContext } = useTamboContextHelpers();
|
|
242
|
+
React.useEffect(() => {
|
|
243
|
+
let mounted = true;
|
|
244
|
+
const interval = setInterval(() => {
|
|
245
|
+
getAdditionalContext().then((contexts) => {
|
|
246
|
+
if (mounted) {
|
|
247
|
+
capturedContexts = contexts;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}, 50);
|
|
251
|
+
return () => {
|
|
252
|
+
mounted = false;
|
|
253
|
+
clearInterval(interval);
|
|
254
|
+
};
|
|
255
|
+
}, [getAdditionalContext]);
|
|
256
|
+
return React.createElement("div", { "data-testid": "ready" }, "ready");
|
|
257
|
+
};
|
|
258
|
+
const Host = () => {
|
|
259
|
+
const [showProvider, setShowProvider] = React.useState(true);
|
|
260
|
+
React.useEffect(() => {
|
|
261
|
+
const timeout = setTimeout(() => setShowProvider(false), 200);
|
|
262
|
+
return () => clearTimeout(timeout);
|
|
263
|
+
}, []);
|
|
264
|
+
return (React.createElement(React.Fragment, null,
|
|
265
|
+
showProvider && (React.createElement(TamboInteractableProvider, null,
|
|
266
|
+
React.createElement(InteractableNote, { title: "will disappear" }))),
|
|
267
|
+
React.createElement(TestComponent, null)));
|
|
268
|
+
};
|
|
269
|
+
const { getByTestId } = render(wrapperWithProviders(React.createElement(Host, null)));
|
|
270
|
+
// Initially should have the context
|
|
271
|
+
await waitFor(() => {
|
|
272
|
+
expect(getByTestId("ready")).toBeInTheDocument();
|
|
273
|
+
const entry = capturedContexts.find((c) => c.name === "interactables");
|
|
274
|
+
expect(entry).toBeDefined();
|
|
275
|
+
});
|
|
276
|
+
// After provider unmounts, context should be gone
|
|
277
|
+
await waitFor(() => {
|
|
278
|
+
const entry = capturedContexts.find((c) => c.name === "interactables");
|
|
279
|
+
expect(entry).toBeUndefined();
|
|
280
|
+
}, { timeout: 1000 });
|
|
281
|
+
});
|
|
282
|
+
test("helper error handling doesn't crash the system", async () => {
|
|
283
|
+
const Note = ({ title }) => React.createElement("div", null, title);
|
|
284
|
+
const InteractableNote = withTamboInteractable(Note, {
|
|
285
|
+
componentName: "Note",
|
|
286
|
+
description: "A note",
|
|
287
|
+
propsSchema: z.object({ title: z.string() }),
|
|
288
|
+
});
|
|
289
|
+
// Mock console.error to capture error logs
|
|
290
|
+
const consoleSpy = jest
|
|
291
|
+
.spyOn(console, "error")
|
|
292
|
+
.mockImplementation(() => { });
|
|
293
|
+
let capturedContexts = [];
|
|
294
|
+
const TestComponent = () => {
|
|
295
|
+
const { getAdditionalContext, addContextHelper } = useTamboContextHelpers();
|
|
296
|
+
React.useEffect(() => {
|
|
297
|
+
// Add a helper that throws an error
|
|
298
|
+
addContextHelper("errorHelper", () => {
|
|
299
|
+
throw new Error("Test error in helper");
|
|
300
|
+
});
|
|
301
|
+
}, [addContextHelper]);
|
|
302
|
+
React.useEffect(() => {
|
|
303
|
+
let mounted = true;
|
|
304
|
+
getAdditionalContext()
|
|
305
|
+
.then((contexts) => {
|
|
306
|
+
if (mounted) {
|
|
307
|
+
capturedContexts = contexts;
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
.catch(() => {
|
|
311
|
+
// Should not reach here - errors should be handled gracefully
|
|
312
|
+
});
|
|
313
|
+
return () => {
|
|
314
|
+
mounted = false;
|
|
315
|
+
};
|
|
316
|
+
}, [getAdditionalContext]);
|
|
317
|
+
return React.createElement("div", { "data-testid": "ready" }, "ready");
|
|
318
|
+
};
|
|
319
|
+
const { getByTestId } = render(wrapperWithProviders(React.createElement(TamboInteractableProvider, null,
|
|
320
|
+
React.createElement(InteractableNote, { title: "test" }),
|
|
321
|
+
React.createElement(TestComponent, null))));
|
|
322
|
+
await waitFor(() => {
|
|
323
|
+
expect(getByTestId("ready")).toBeInTheDocument();
|
|
324
|
+
// Should still have the interactables context despite the error
|
|
325
|
+
const entry = capturedContexts.find((c) => c.name === "interactables");
|
|
326
|
+
expect(entry).toBeDefined();
|
|
327
|
+
// Error helper should not be present (filtered out)
|
|
328
|
+
const errorEntry = capturedContexts.find((c) => c.name === "errorHelper");
|
|
329
|
+
expect(errorEntry).toBeUndefined();
|
|
330
|
+
});
|
|
331
|
+
consoleSpy.mockRestore();
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
//# sourceMappingURL=tambo-interactables-additional-context-edge-cases.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tambo-interactables-additional-context-edge-cases.test.js","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-interactables-additional-context-edge-cases.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAEvE,SAAS,oBAAoB,CAAC,QAAyB;IACrD,MAAM,MAAM,GAAG;QACb,EAAE,EAAE,KAAK;QACT,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,EAAE;KACN,CAAC;IAET,OAAO,CACL,oBAAC,iBAAiB,IAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EACtB,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC,EACvB,iBAAiB,EAAE,GAAG,EAAE,GAAE,CAAC,EAC3B,kBAAkB,EAAE,GAAG,EAAE,GAAE,CAAC;QAE5B,oBAAC,2BAA2B,QAAE,QAAQ,CAA+B,CACnD,CACrB,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,mEAAmE,EAAE,GAAG,EAAE;IACjF,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,eAAe,GAA+B,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAChE,iCAAM,IAAI,CAAO,CAClB,CAAC;QAEF,MAAM,2BAA2B,GAAG,qBAAqB,CAAC,eAAe,EAAE;YACzE,aAAa,EAAE,iBAAiB;YAChC,WAAW,EAAE,4BAA4B;YACzC,0BAA0B;SAC3B,CAAC,CAAC;QAEH,IAAI,gBAAgB,GAAU,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,EAAE,oBAAoB,EAAE,GAAG,sBAAsB,EAAE,CAAC;YAE1D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,IAAI,OAAO,GAAG,IAAI,CAAC;gBACnB,oBAAoB,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;oBACvC,IAAI,OAAO,EAAE,CAAC;wBACZ,gBAAgB,GAAG,QAAQ,CAAC;oBAC9B,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,OAAO,GAAG,EAAE;oBACV,OAAO,GAAG,KAAK,CAAC;gBAClB,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAE3B,OAAO,4CAAiB,OAAO,YAAY,CAAC;QAC9C,CAAC,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAC5B,oBAAoB,CAClB,oBAAC,yBAAyB;YACxB,oBAAC,2BAA2B,IAAC,IAAI,EAAC,MAAM,GAAG;YAC3C,oBAAC,aAAa,OAAG,CACS,CAC7B,CACF,CAAC;QAEF,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CACjC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,KAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,IAAI,GAAgC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,iCAAM,KAAK,CAAO,CAAC;QAC5E,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,IAAI,EAAE;YACnD,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,QAAQ;YACrB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;SAC7C,CAAC,CAAC;QAEH,IAAI,gBAAgB,GAAU,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,EAAE,oBAAoB,EAAE,GAAG,sBAAsB,EAAE,CAAC;YAE1D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,IAAI,OAAO,GAAG,IAAI,CAAC;gBACnB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;oBAChC,oBAAoB,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;wBACvC,IAAI,OAAO,EAAE,CAAC;4BACZ,gBAAgB,GAAG,QAAQ,CAAC;wBAC9B,CAAC;oBACH,CAAC,CAAC,CAAC;gBACL,CAAC,EAAE,EAAE,CAAC,CAAC;gBACP,OAAO,GAAG,EAAE;oBACV,OAAO,GAAG,KAAK,CAAC;oBAChB,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAE3B,OAAO,4CAAiB,OAAO,YAAY,CAAC;QAC9C,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAErD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,4CAA4C;gBAC5C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC1D,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC1D,OAAO,GAAG,EAAE;oBACV,YAAY,CAAC,OAAO,CAAC,CAAC;oBACtB,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACzB,CAAC,CAAC;YACJ,CAAC,EAAE,EAAE,CAAC,CAAC;YAEP,OAAO,CACL,oBAAC,yBAAyB;gBACvB,QAAQ,IAAI,oBAAC,gBAAgB,IAAC,KAAK,EAAC,cAAc,GAAG;gBACtD,oBAAC,aAAa,OAAG,CACS,CAC7B,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,oBAAoB,CAAC,oBAAC,IAAI,OAAG,CAAC,CAAC,CAAC;QAE/D,MAAM,OAAO,CACX,GAAG,EAAE;YACH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;QACnD,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;QAEF,wCAAwC;QACxC,MAAM,OAAO,CACX,GAAG,EAAE;YACH,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CACjC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrD,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,OAAO,GAAgD,CAAC,EAC5D,KAAK,EACL,KAAK,GAAG,OAAO,GAChB,EAAE,EAAE,CAAC,CACJ;YACG,KAAK;;YAAI,KAAK,CACX,CACP,CAAC;QAEF,MAAM,mBAAmB,GAAG,qBAAqB,CAAC,OAAO,EAAE;YACzD,aAAa,EAAE,SAAS;YACxB,WAAW,EAAE,qBAAqB;YAClC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;gBACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;gBACjB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC7B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,gBAAgB,GAAU,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,EAAE,oBAAoB,EAAE,GAAG,sBAAsB,EAAE,CAAC;YAE1D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,IAAI,OAAO,GAAG,IAAI,CAAC;gBACnB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;oBAChC,oBAAoB,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;wBACvC,IAAI,OAAO,EAAE,CAAC;4BACZ,gBAAgB,GAAG,QAAQ,CAAC;wBAC9B,CAAC;oBACH,CAAC,CAAC,CAAC;gBACL,CAAC,EAAE,EAAE,CAAC,CAAC;gBACP,OAAO,GAAG,EAAE;oBACV,OAAO,GAAG,KAAK,CAAC;oBAChB,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAE3B,OAAO,4CAAiB,OAAO,YAAY,CAAC;QAC9C,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAElD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBACpD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,GAAG,CAAC,CAAC;gBAClE,OAAO,GAAG,EAAE;oBACV,YAAY,CAAC,QAAQ,CAAC,CAAC;oBACvB,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACzB,CAAC,CAAC;YACJ,CAAC,EAAE,EAAE,CAAC,CAAC;YAEP,OAAO,CACL,oBAAC,yBAAyB;gBACxB,oBAAC,mBAAmB,IAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAI;gBACnD,oBAAC,aAAa,OAAG,CACS,CAC7B,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,oBAAoB,CAAC,oBAAC,IAAI,OAAG,CAAC,CAAC,CAAC;QAE/D,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,gCAAgC;QAChC,MAAM,OAAO,CACX,GAAG,EAAE;YACH,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CACjC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,IAAI,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBAChD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC5B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,IAAI,GAAgC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,iCAAM,KAAK,CAAO,CAAC;QAC5E,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,IAAI,EAAE;YACnD,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,QAAQ;YACrB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;SAC7C,CAAC,CAAC;QAEH,IAAI,aAAa,GAAU,EAAE,CAAC;QAC9B,IAAI,aAAa,GAAU,EAAE,CAAC;QAE9B,MAAM,kBAAkB,GAAG,GAAG,EAAE;YAC9B,MAAM,EAAE,oBAAoB,EAAE,GAAG,sBAAsB,EAAE,CAAC;YAE1D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,IAAI,OAAO,GAAG,IAAI,CAAC;gBACnB,oBAAoB,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;oBACvC,IAAI,OAAO,EAAE,CAAC;wBACZ,aAAa,GAAG,QAAQ,CAAC;oBAC3B,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,OAAO,GAAG,EAAE;oBACV,OAAO,GAAG,KAAK,CAAC;gBAClB,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAE3B,OAAO,4CAAiB,aAAa,kBAAkB,CAAC;QAC1D,CAAC,CAAC;QAEF,MAAM,kBAAkB,GAAG,GAAG,EAAE;YAC9B,MAAM,EAAE,oBAAoB,EAAE,GAAG,sBAAsB,EAAE,CAAC;YAE1D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,IAAI,OAAO,GAAG,IAAI,CAAC;gBACnB,oBAAoB,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;oBACvC,IAAI,OAAO,EAAE,CAAC;wBACZ,aAAa,GAAG,QAAQ,CAAC;oBAC3B,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,OAAO,GAAG,EAAE;oBACV,OAAO,GAAG,KAAK,CAAC;gBAClB,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAE3B,OAAO,4CAAiB,aAAa,kBAAkB,CAAC;QAC1D,CAAC,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAC5B,oBAAoB,CAClB,oBAAC,yBAAyB;YACxB,oBAAC,gBAAgB,IAAC,KAAK,EAAC,YAAY,GAAG;YACvC,oBAAC,kBAAkB,OAAG;YACtB,oBAAC,2BAA2B,IAC1B,cAAc,EAAE;oBACd,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;iBAC3C;gBAED,oBAAC,yBAAyB;oBACxB,oBAAC,gBAAgB,IAAC,KAAK,EAAC,YAAY,GAAG;oBACvC,oBAAC,kBAAkB,OAAG,CACI,CACA,CACJ,CAC7B,CACF,CAAC;QAEF,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACvD,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,uCAAuC;YACvC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CACnC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACxD,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,CAC3D,YAAY,CACb,CAAC;YAEF,0DAA0D;YAC1D,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CACnC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACxD,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,CAC3D,YAAY,CACb,CAAC;YAEF,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CACpC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,IAAI,GAAgC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,iCAAM,KAAK,CAAO,CAAC;QAC5E,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,IAAI,EAAE;YACnD,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,QAAQ;YACrB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;SAC7C,CAAC,CAAC;QAEH,IAAI,gBAAgB,GAAU,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,EAAE,oBAAoB,EAAE,GAAG,sBAAsB,EAAE,CAAC;YAE1D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,IAAI,OAAO,GAAG,IAAI,CAAC;gBACnB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;oBAChC,oBAAoB,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;wBACvC,IAAI,OAAO,EAAE,CAAC;4BACZ,gBAAgB,GAAG,QAAQ,CAAC;wBAC9B,CAAC;oBACH,CAAC,CAAC,CAAC;gBACL,CAAC,EAAE,EAAE,CAAC,CAAC;gBACP,OAAO,GAAG,EAAE;oBACV,OAAO,GAAG,KAAK,CAAC;oBAChB,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAE3B,OAAO,4CAAiB,OAAO,YAAY,CAAC;QAC9C,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAE7D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC9D,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YACrC,CAAC,EAAE,EAAE,CAAC,CAAC;YAEP,OAAO,CACL;gBACG,YAAY,IAAI,CACf,oBAAC,yBAAyB;oBACxB,oBAAC,gBAAgB,IAAC,KAAK,EAAC,gBAAgB,GAAG,CACjB,CAC7B;gBACD,oBAAC,aAAa,OAAG,CAChB,CACJ,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,oBAAoB,CAAC,oBAAC,IAAI,OAAG,CAAC,CAAC,CAAC;QAE/D,oCAAoC;QACpC,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CACjC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,kDAAkD;QAClD,MAAM,OAAO,CACX,GAAG,EAAE;YACH,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CACjC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;QAChC,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,IAAI,GAAgC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,iCAAM,KAAK,CAAO,CAAC;QAC5E,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,IAAI,EAAE;YACnD,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,QAAQ;YACrB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;SAC7C,CAAC,CAAC;QAEH,2CAA2C;QAC3C,MAAM,UAAU,GAAG,IAAI;aACpB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;aACvB,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAEhC,IAAI,gBAAgB,GAAU,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,GAC9C,sBAAsB,EAAE,CAAC;YAE3B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,oCAAoC;gBACpC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE;oBACnC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;gBAC1C,CAAC,CAAC,CAAC;YACL,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;YAEvB,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnB,IAAI,OAAO,GAAG,IAAI,CAAC;gBACnB,oBAAoB,EAAE;qBACnB,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;oBACjB,IAAI,OAAO,EAAE,CAAC;wBACZ,gBAAgB,GAAG,QAAQ,CAAC;oBAC9B,CAAC;gBACH,CAAC,CAAC;qBACD,KAAK,CAAC,GAAG,EAAE;oBACV,8DAA8D;gBAChE,CAAC,CAAC,CAAC;gBACL,OAAO,GAAG,EAAE;oBACV,OAAO,GAAG,KAAK,CAAC;gBAClB,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAE3B,OAAO,4CAAiB,OAAO,YAAY,CAAC;QAC9C,CAAC,CAAC;QAEF,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAC5B,oBAAoB,CAClB,oBAAC,yBAAyB;YACxB,oBAAC,gBAAgB,IAAC,KAAK,EAAC,MAAM,GAAG;YACjC,oBAAC,aAAa,OAAG,CACS,CAC7B,CACF,CAAC;QAEF,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACjD,gEAAgE;YAChE,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CACjC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CACvC,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAE5B,oDAAoD;YACpD,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CACtC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CACrC,CAAC;YACF,MAAM,CAAC,UAAU,CAAC,CAAC,aAAa,EAAE,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,WAAW,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { render, waitFor } from \"@testing-library/react\";\nimport React from \"react\";\nimport { z } from \"zod\";\nimport {\n useTamboContextHelpers,\n TamboContextHelpersProvider,\n} from \"../tambo-context-helpers-provider\";\nimport { TamboInteractableProvider } from \"../tambo-interactable-provider\";\nimport { TamboStubProvider } from \"../tambo-stubs\";\nimport { withTamboInteractable } from \"../hoc/with-tambo-interactable\";\n\nfunction wrapperWithProviders(children: React.ReactNode) {\n const thread = {\n id: \"t-1\",\n projectId: \"p-1\",\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n messages: [],\n metadata: {},\n } as any;\n\n return (\n <TamboStubProvider\n thread={thread}\n registerTool={() => {}}\n registerTools={() => {}}\n registerComponent={() => {}}\n addToolAssociation={() => {}}\n >\n <TamboContextHelpersProvider>{children}</TamboContextHelpersProvider>\n </TamboStubProvider>\n );\n}\n\ndescribe(\"Interactables AdditionalContext - Edge Cases & Advanced Scenarios\", () => {\n test(\"handles components without propsSchema gracefully\", async () => {\n const SimpleComponent: React.FC<{ text: string }> = ({ text }) => (\n <div>{text}</div>\n );\n\n const InteractableSimpleComponent = withTamboInteractable(SimpleComponent, {\n componentName: \"SimpleComponent\",\n description: \"A component without schema\",\n // No propsSchema provided\n });\n\n let capturedContexts: any[] = [];\n const TestComponent = () => {\n const { getAdditionalContext } = useTamboContextHelpers();\n\n React.useEffect(() => {\n let mounted = true;\n getAdditionalContext().then((contexts) => {\n if (mounted) {\n capturedContexts = contexts;\n }\n });\n return () => {\n mounted = false;\n };\n }, [getAdditionalContext]);\n\n return <div data-testid=\"ready\">ready</div>;\n };\n\n const { getByTestId } = render(\n wrapperWithProviders(\n <TamboInteractableProvider>\n <InteractableSimpleComponent text=\"test\" />\n <TestComponent />\n </TamboInteractableProvider>,\n ),\n );\n\n await waitFor(() => {\n expect(getByTestId(\"ready\")).toBeInTheDocument();\n const entry = capturedContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n expect(entry).toBeDefined();\n const component = entry!.context.components[0];\n expect(component.propsSchema).toBe(\"Not specified\");\n });\n });\n\n test(\"handles component unmounting and remounting correctly\", async () => {\n const Note: React.FC<{ title: string }> = ({ title }) => <div>{title}</div>;\n const InteractableNote = withTamboInteractable(Note, {\n componentName: \"Note\",\n description: \"A note\",\n propsSchema: z.object({ title: z.string() }),\n });\n\n let capturedContexts: any[] = [];\n const TestComponent = () => {\n const { getAdditionalContext } = useTamboContextHelpers();\n\n React.useEffect(() => {\n let mounted = true;\n const interval = setInterval(() => {\n getAdditionalContext().then((contexts) => {\n if (mounted) {\n capturedContexts = contexts;\n }\n });\n }, 50);\n return () => {\n mounted = false;\n clearInterval(interval);\n };\n }, [getAdditionalContext]);\n\n return <div data-testid=\"ready\">ready</div>;\n };\n\n const Host = () => {\n const [showNote, setShowNote] = React.useState(true);\n\n React.useEffect(() => {\n // Toggle the note on/off to test unmounting\n const timeout = setTimeout(() => setShowNote(false), 100);\n const timeout2 = setTimeout(() => setShowNote(true), 200);\n return () => {\n clearTimeout(timeout);\n clearTimeout(timeout2);\n };\n }, []);\n\n return (\n <TamboInteractableProvider>\n {showNote && <InteractableNote title=\"dynamic note\" />}\n <TestComponent />\n </TamboInteractableProvider>\n );\n };\n\n const { getByTestId } = render(wrapperWithProviders(<Host />));\n\n await waitFor(\n () => {\n expect(getByTestId(\"ready\")).toBeInTheDocument();\n },\n { timeout: 1000 },\n );\n\n // Eventually should show the note again\n await waitFor(\n () => {\n const entry = capturedContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n expect(entry?.context?.components).toHaveLength(1);\n },\n { timeout: 1000 },\n );\n });\n\n test(\"context helper updates when props change from parent\", async () => {\n const Counter: React.FC<{ count: number; label?: string }> = ({\n count,\n label = \"Count\",\n }) => (\n <div>\n {label}: {count}\n </div>\n );\n\n const InteractableCounter = withTamboInteractable(Counter, {\n componentName: \"Counter\",\n description: \"A counter component\",\n propsSchema: z.object({\n count: z.number(),\n label: z.string().optional(),\n }),\n });\n\n let capturedContexts: any[] = [];\n const TestComponent = () => {\n const { getAdditionalContext } = useTamboContextHelpers();\n\n React.useEffect(() => {\n let mounted = true;\n const interval = setInterval(() => {\n getAdditionalContext().then((contexts) => {\n if (mounted) {\n capturedContexts = contexts;\n }\n });\n }, 50);\n return () => {\n mounted = false;\n clearInterval(interval);\n };\n }, [getAdditionalContext]);\n\n return <div data-testid=\"ready\">ready</div>;\n };\n\n const Host = () => {\n const [count, setCount] = React.useState(0);\n const [label, setLabel] = React.useState(\"Items\");\n\n React.useEffect(() => {\n const timeout1 = setTimeout(() => setCount(5), 100);\n const timeout2 = setTimeout(() => setLabel(\"Updated Items\"), 200);\n return () => {\n clearTimeout(timeout1);\n clearTimeout(timeout2);\n };\n }, []);\n\n return (\n <TamboInteractableProvider>\n <InteractableCounter count={count} label={label} />\n <TestComponent />\n </TamboInteractableProvider>\n );\n };\n\n const { getByTestId } = render(wrapperWithProviders(<Host />));\n\n await waitFor(() => {\n expect(getByTestId(\"ready\")).toBeInTheDocument();\n });\n\n // Wait for updates to propagate\n await waitFor(\n () => {\n const entry = capturedContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n if (entry?.context?.components?.[0]) {\n const props = entry.context.components[0].props;\n expect(props.count).toBe(5);\n expect(props.label).toBe(\"Updated Items\");\n }\n },\n { timeout: 1000 },\n );\n });\n\n test(\"multiple providers with nested context helpers work correctly\", async () => {\n const Note: React.FC<{ title: string }> = ({ title }) => <div>{title}</div>;\n const InteractableNote = withTamboInteractable(Note, {\n componentName: \"Note\",\n description: \"A note\",\n propsSchema: z.object({ title: z.string() }),\n });\n\n let outerContexts: any[] = [];\n let innerContexts: any[] = [];\n\n const OuterTestComponent = () => {\n const { getAdditionalContext } = useTamboContextHelpers();\n\n React.useEffect(() => {\n let mounted = true;\n getAdditionalContext().then((contexts) => {\n if (mounted) {\n outerContexts = contexts;\n }\n });\n return () => {\n mounted = false;\n };\n }, [getAdditionalContext]);\n\n return <div data-testid=\"outer-ready\">outer ready</div>;\n };\n\n const InnerTestComponent = () => {\n const { getAdditionalContext } = useTamboContextHelpers();\n\n React.useEffect(() => {\n let mounted = true;\n getAdditionalContext().then((contexts) => {\n if (mounted) {\n innerContexts = contexts;\n }\n });\n return () => {\n mounted = false;\n };\n }, [getAdditionalContext]);\n\n return <div data-testid=\"inner-ready\">inner ready</div>;\n };\n\n const { getByTestId } = render(\n wrapperWithProviders(\n <TamboInteractableProvider>\n <InteractableNote title=\"outer note\" />\n <OuterTestComponent />\n <TamboContextHelpersProvider\n contextHelpers={{\n customContext: () => ({ custom: \"inner\" }),\n }}\n >\n <TamboInteractableProvider>\n <InteractableNote title=\"inner note\" />\n <InnerTestComponent />\n </TamboInteractableProvider>\n </TamboContextHelpersProvider>\n </TamboInteractableProvider>,\n ),\n );\n\n await waitFor(() => {\n expect(getByTestId(\"outer-ready\")).toBeInTheDocument();\n expect(getByTestId(\"inner-ready\")).toBeInTheDocument();\n });\n\n await waitFor(() => {\n // Outer context should have outer note\n const outerEntry = outerContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n expect(outerEntry?.context?.components).toHaveLength(1);\n expect(outerEntry?.context?.components[0]?.props?.title).toBe(\n \"outer note\",\n );\n\n // Inner context should have inner note and custom context\n const innerEntry = innerContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n expect(innerEntry?.context?.components).toHaveLength(1);\n expect(innerEntry?.context?.components[0]?.props?.title).toBe(\n \"inner note\",\n );\n\n const customEntry = innerContexts.find(\n (c: any) => c.name === \"customContext\",\n );\n expect(customEntry?.context).toEqual({ custom: \"inner\" });\n });\n });\n\n test(\"provider cleanup removes helper when last provider unmounts\", async () => {\n const Note: React.FC<{ title: string }> = ({ title }) => <div>{title}</div>;\n const InteractableNote = withTamboInteractable(Note, {\n componentName: \"Note\",\n description: \"A note\",\n propsSchema: z.object({ title: z.string() }),\n });\n\n let capturedContexts: any[] = [];\n const TestComponent = () => {\n const { getAdditionalContext } = useTamboContextHelpers();\n\n React.useEffect(() => {\n let mounted = true;\n const interval = setInterval(() => {\n getAdditionalContext().then((contexts) => {\n if (mounted) {\n capturedContexts = contexts;\n }\n });\n }, 50);\n return () => {\n mounted = false;\n clearInterval(interval);\n };\n }, [getAdditionalContext]);\n\n return <div data-testid=\"ready\">ready</div>;\n };\n\n const Host = () => {\n const [showProvider, setShowProvider] = React.useState(true);\n\n React.useEffect(() => {\n const timeout = setTimeout(() => setShowProvider(false), 200);\n return () => clearTimeout(timeout);\n }, []);\n\n return (\n <>\n {showProvider && (\n <TamboInteractableProvider>\n <InteractableNote title=\"will disappear\" />\n </TamboInteractableProvider>\n )}\n <TestComponent />\n </>\n );\n };\n\n const { getByTestId } = render(wrapperWithProviders(<Host />));\n\n // Initially should have the context\n await waitFor(() => {\n expect(getByTestId(\"ready\")).toBeInTheDocument();\n const entry = capturedContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n expect(entry).toBeDefined();\n });\n\n // After provider unmounts, context should be gone\n await waitFor(\n () => {\n const entry = capturedContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n expect(entry).toBeUndefined();\n },\n { timeout: 1000 },\n );\n });\n\n test(\"helper error handling doesn't crash the system\", async () => {\n const Note: React.FC<{ title: string }> = ({ title }) => <div>{title}</div>;\n const InteractableNote = withTamboInteractable(Note, {\n componentName: \"Note\",\n description: \"A note\",\n propsSchema: z.object({ title: z.string() }),\n });\n\n // Mock console.error to capture error logs\n const consoleSpy = jest\n .spyOn(console, \"error\")\n .mockImplementation(() => {});\n\n let capturedContexts: any[] = [];\n const TestComponent = () => {\n const { getAdditionalContext, addContextHelper } =\n useTamboContextHelpers();\n\n React.useEffect(() => {\n // Add a helper that throws an error\n addContextHelper(\"errorHelper\", () => {\n throw new Error(\"Test error in helper\");\n });\n }, [addContextHelper]);\n\n React.useEffect(() => {\n let mounted = true;\n getAdditionalContext()\n .then((contexts) => {\n if (mounted) {\n capturedContexts = contexts;\n }\n })\n .catch(() => {\n // Should not reach here - errors should be handled gracefully\n });\n return () => {\n mounted = false;\n };\n }, [getAdditionalContext]);\n\n return <div data-testid=\"ready\">ready</div>;\n };\n\n const { getByTestId } = render(\n wrapperWithProviders(\n <TamboInteractableProvider>\n <InteractableNote title=\"test\" />\n <TestComponent />\n </TamboInteractableProvider>,\n ),\n );\n\n await waitFor(() => {\n expect(getByTestId(\"ready\")).toBeInTheDocument();\n // Should still have the interactables context despite the error\n const entry = capturedContexts.find(\n (c: any) => c.name === \"interactables\",\n );\n expect(entry).toBeDefined();\n\n // Error helper should not be present (filtered out)\n const errorEntry = capturedContexts.find(\n (c: any) => c.name === \"errorHelper\",\n );\n expect(errorEntry).toBeUndefined();\n });\n\n consoleSpy.mockRestore();\n });\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tambo-interactables-additional-context.test.d.ts","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-interactables-additional-context.test.tsx"],"names":[],"mappings":""}
|