@copilotkit/react-core 1.54.1 → 1.55.0-next.8
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/CHANGELOG.md +127 -116
- package/dist/copilotkit-B3Mb1yVE.cjs +7975 -0
- package/dist/copilotkit-B3Mb1yVE.cjs.map +1 -0
- package/dist/copilotkit-DBzgOMby.d.cts +2182 -0
- package/dist/copilotkit-DBzgOMby.d.cts.map +1 -0
- package/dist/copilotkit-DNYSFuz5.mjs +7562 -0
- package/dist/copilotkit-DNYSFuz5.mjs.map +1 -0
- package/dist/copilotkit-Dy5w3qEV.d.mts +2182 -0
- package/dist/copilotkit-Dy5w3qEV.d.mts.map +1 -0
- package/dist/index.cjs +27 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +4 -5
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1941 -35
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/index.cjs +77 -7
- package/dist/v2/index.css +1 -2
- package/dist/v2/index.d.cts +6 -4
- package/dist/v2/index.d.mts +6 -4
- package/dist/v2/index.mjs +7 -4
- package/dist/v2/index.umd.js +5725 -24
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +37 -9
- package/scripts/scope-preflight.mjs +101 -0
- package/src/components/CopilotListeners.tsx +2 -6
- package/src/components/copilot-provider/copilot-messages.tsx +1 -1
- package/src/components/copilot-provider/copilotkit-props.tsx +1 -1
- package/src/components/copilot-provider/copilotkit.tsx +4 -4
- package/src/context/copilot-messages-context.tsx +1 -1
- package/src/hooks/__tests__/use-coagent-config.test.ts +2 -2
- package/src/hooks/__tests__/use-coagent-state-render.e2e.test.tsx +2 -2
- package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +3 -7
- package/src/hooks/__tests__/use-frontend-tool-available.test.tsx +1 -1
- package/src/hooks/__tests__/use-frontend-tool-remount.e2e.test.tsx +4 -4
- package/src/hooks/use-agent-nodename.ts +1 -1
- package/src/hooks/use-coagent-state-render-bridge.tsx +1 -4
- package/src/hooks/use-coagent.ts +1 -1
- package/src/hooks/use-configure-chat-suggestions.tsx +2 -2
- package/src/hooks/use-copilot-chat-suggestions.tsx +2 -2
- package/src/hooks/use-copilot-chat_internal.ts +2 -2
- package/src/hooks/use-copilot-readable.ts +1 -1
- package/src/hooks/use-frontend-tool.ts +2 -2
- package/src/hooks/use-human-in-the-loop.ts +2 -2
- package/src/hooks/use-langgraph-interrupt.ts +2 -5
- package/src/hooks/use-lazy-tool-renderer.tsx +1 -1
- package/src/hooks/use-render-tool-call.ts +1 -1
- package/src/lib/copilot-task.ts +1 -1
- package/src/setupTests.ts +18 -14
- package/src/v2/__tests__/A2UIMessageRenderer.test.tsx +176 -0
- package/src/v2/__tests__/globalSetup.ts +14 -0
- package/src/v2/__tests__/setup.ts +93 -0
- package/src/v2/__tests__/utils/test-helpers.tsx +470 -0
- package/src/v2/a2ui/A2UIMessageRenderer.tsx +206 -0
- package/src/v2/components/CopilotKitInspector.tsx +50 -0
- package/src/v2/components/MCPAppsActivityRenderer.tsx +785 -0
- package/src/v2/components/WildcardToolCallRender.tsx +86 -0
- package/src/v2/components/__tests__/license-warning-banner.test.tsx +46 -0
- package/src/v2/components/chat/CopilotChat.tsx +431 -0
- package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +375 -0
- package/src/v2/components/chat/CopilotChatAudioRecorder.tsx +350 -0
- package/src/v2/components/chat/CopilotChatInput.tsx +1302 -0
- package/src/v2/components/chat/CopilotChatMessageView.tsx +556 -0
- package/src/v2/components/chat/CopilotChatReasoningMessage.tsx +252 -0
- package/src/v2/components/chat/CopilotChatSuggestionPill.tsx +59 -0
- package/src/v2/components/chat/CopilotChatSuggestionView.tsx +133 -0
- package/src/v2/components/chat/CopilotChatToggleButton.tsx +171 -0
- package/src/v2/components/chat/CopilotChatToolCallsView.tsx +40 -0
- package/src/v2/components/chat/CopilotChatUserMessage.tsx +388 -0
- package/src/v2/components/chat/CopilotChatView.tsx +598 -0
- package/src/v2/components/chat/CopilotModalHeader.tsx +129 -0
- package/src/v2/components/chat/CopilotPopup.tsx +81 -0
- package/src/v2/components/chat/CopilotPopupView.tsx +317 -0
- package/src/v2/components/chat/CopilotSidebar.tsx +76 -0
- package/src/v2/components/chat/CopilotSidebarView.tsx +255 -0
- package/src/v2/components/chat/__tests__/CopilotChat.e2e.test.tsx +1113 -0
- package/src/v2/components/chat/__tests__/CopilotChat.onError.test.tsx +73 -0
- package/src/v2/components/chat/__tests__/CopilotChat.slots.e2e.test.tsx +432 -0
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +150 -0
- package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.slots.e2e.test.tsx +624 -0
- package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.test.tsx +702 -0
- package/src/v2/components/chat/__tests__/CopilotChatCssClasses.test.tsx +107 -0
- package/src/v2/components/chat/__tests__/CopilotChatInput.slots.e2e.test.tsx +929 -0
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +986 -0
- package/src/v2/components/chat/__tests__/CopilotChatMessageView.slots.e2e.test.tsx +1004 -0
- package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.tsx +169 -0
- package/src/v2/components/chat/__tests__/CopilotChatSuggestionView.slots.e2e.test.tsx +530 -0
- package/src/v2/components/chat/__tests__/CopilotChatToolRendering.e2e.test.tsx +782 -0
- package/src/v2/components/chat/__tests__/CopilotChatToolRerenders.e2e.test.tsx +2413 -0
- package/src/v2/components/chat/__tests__/CopilotChatUserMessage.slots.e2e.test.tsx +621 -0
- package/src/v2/components/chat/__tests__/CopilotChatView.onClick.e2e.test.tsx +853 -0
- package/src/v2/components/chat/__tests__/CopilotChatView.slots.e2e.test.tsx +1050 -0
- package/src/v2/components/chat/__tests__/CopilotModalHeader.slots.e2e.test.tsx +484 -0
- package/src/v2/components/chat/__tests__/CopilotPopupView.slots.e2e.test.tsx +612 -0
- package/src/v2/components/chat/__tests__/CopilotSidebarView.slots.e2e.test.tsx +502 -0
- package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +1011 -0
- package/src/v2/components/chat/__tests__/setup.ts +1 -0
- package/src/v2/components/chat/index.ts +79 -0
- package/src/v2/components/index.ts +7 -0
- package/src/v2/components/license-warning-banner.tsx +198 -0
- package/src/v2/components/ui/button.tsx +123 -0
- package/src/v2/components/ui/dropdown-menu.tsx +258 -0
- package/src/v2/components/ui/tooltip.tsx +60 -0
- package/src/v2/hooks/__tests__/standard-schema-types.test.tsx +152 -0
- package/src/v2/hooks/__tests__/standard-schema.test.tsx +282 -0
- package/src/v2/hooks/__tests__/use-agent-context-timing.e2e.test.tsx +132 -0
- package/src/v2/hooks/__tests__/use-agent-context.test.tsx +401 -0
- package/src/v2/hooks/__tests__/use-agent-error-state.test.tsx +44 -0
- package/src/v2/hooks/__tests__/use-agent-stability.test.tsx +205 -0
- package/src/v2/hooks/__tests__/use-agent.e2e.test.tsx +148 -0
- package/src/v2/hooks/__tests__/use-component.test.tsx +123 -0
- package/src/v2/hooks/__tests__/use-configure-suggestions.e2e.test.tsx +696 -0
- package/src/v2/hooks/__tests__/use-default-render-tool.test.tsx +153 -0
- package/src/v2/hooks/__tests__/use-frontend-tool-available.test.tsx +167 -0
- package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.tsx +2129 -0
- package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.tsx +1261 -0
- package/src/v2/hooks/__tests__/use-interrupt.test.tsx +397 -0
- package/src/v2/hooks/__tests__/use-katex-styles.test.tsx +56 -0
- package/src/v2/hooks/__tests__/use-keyboard-height.test.tsx +192 -0
- package/src/v2/hooks/__tests__/use-render-tool.test.tsx +259 -0
- package/src/v2/hooks/__tests__/use-suggestions.e2e.test.tsx +524 -0
- package/src/v2/hooks/__tests__/use-threads.test.tsx +433 -0
- package/src/v2/hooks/__tests__/zod-regression.test.tsx +311 -0
- package/src/v2/hooks/index.ts +18 -0
- package/src/v2/hooks/use-agent-context.tsx +45 -0
- package/src/v2/hooks/use-agent.tsx +155 -0
- package/src/v2/hooks/use-component.tsx +89 -0
- package/src/v2/hooks/use-configure-suggestions.tsx +187 -0
- package/src/v2/hooks/use-default-render-tool.tsx +254 -0
- package/src/v2/hooks/use-frontend-tool.tsx +43 -0
- package/src/v2/hooks/use-human-in-the-loop.tsx +81 -0
- package/src/v2/hooks/use-interrupt.tsx +305 -0
- package/src/v2/hooks/use-keyboard-height.tsx +67 -0
- package/src/v2/hooks/use-render-activity-message.tsx +73 -0
- package/src/v2/hooks/use-render-custom-messages.tsx +93 -0
- package/src/v2/hooks/use-render-tool-call.tsx +175 -0
- package/src/v2/hooks/use-render-tool.tsx +181 -0
- package/src/v2/hooks/use-suggestions.tsx +91 -0
- package/src/v2/hooks/use-threads.tsx +256 -0
- package/src/v2/hooks/useKatexStyles.ts +27 -0
- package/src/v2/index.css +1 -1
- package/src/v2/index.ts +18 -2
- package/src/v2/lib/__tests__/completePartialMarkdown.test.ts +495 -0
- package/src/v2/lib/__tests__/renderSlot.test.tsx +588 -0
- package/src/v2/lib/react-core.ts +156 -0
- package/src/v2/lib/slots.tsx +143 -0
- package/src/v2/lib/transcription-client.ts +184 -0
- package/src/v2/lib/utils.ts +8 -0
- package/src/v2/providers/CopilotChatConfigurationProvider.tsx +162 -0
- package/src/v2/providers/CopilotKitProvider.tsx +600 -0
- package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.tsx +546 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.license.test.tsx +101 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.onError.test.tsx +69 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.renderCustomMessages.e2e.test.tsx +881 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.stability.test.tsx +740 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.test.tsx +642 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.wildcard.test.tsx +294 -0
- package/src/v2/providers/index.ts +14 -0
- package/src/v2/styles/globals.css +230 -0
- package/src/v2/types/__tests__/defineToolCallRenderer.test.tsx +525 -0
- package/src/v2/types/defineToolCallRenderer.ts +65 -0
- package/src/v2/types/frontend-tool.ts +8 -0
- package/src/v2/types/human-in-the-loop.ts +33 -0
- package/src/v2/types/index.ts +7 -0
- package/src/v2/types/interrupt.ts +15 -0
- package/src/v2/types/react-activity-message-renderer.ts +27 -0
- package/src/v2/types/react-custom-message-renderer.ts +17 -0
- package/src/v2/types/react-tool-call-renderer.ts +32 -0
- package/tsdown.config.ts +34 -10
- package/vitest.config.mjs +4 -3
- package/LICENSE +0 -21
- package/dist/copilotkit-BRPQ2sqS.d.cts +0 -670
- package/dist/copilotkit-BRPQ2sqS.d.cts.map +0 -1
- package/dist/copilotkit-C94ayZbs.cjs +0 -2161
- package/dist/copilotkit-C94ayZbs.cjs.map +0 -1
- package/dist/copilotkit-CwZMFmSK.d.mts +0 -670
- package/dist/copilotkit-CwZMFmSK.d.mts.map +0 -1
- package/dist/copilotkit-Yh_Ld_FX.mjs +0 -2031
- package/dist/copilotkit-Yh_Ld_FX.mjs.map +0 -1
- package/dist/v2/index.css.map +0 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { render, act } from "@testing-library/react";
|
|
3
|
+
import React, { useState } from "react";
|
|
4
|
+
import type { Theme } from "@copilotkit/a2ui-renderer";
|
|
5
|
+
|
|
6
|
+
vi.mock("../providers", () => ({
|
|
7
|
+
useCopilotKit: vi.fn(() => ({
|
|
8
|
+
copilotkit: {
|
|
9
|
+
properties: {},
|
|
10
|
+
setProperties: vi.fn(),
|
|
11
|
+
runAgent: vi.fn().mockResolvedValue(undefined),
|
|
12
|
+
},
|
|
13
|
+
})),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
describe("A2UIMessageRenderer rendering integration", () => {
|
|
17
|
+
it("should render A2UI surface content via React renderer", async () => {
|
|
18
|
+
const { createA2UIMessageRenderer } =
|
|
19
|
+
await import("../a2ui/A2UIMessageRenderer.js");
|
|
20
|
+
const renderer = createA2UIMessageRenderer({
|
|
21
|
+
theme: {} as Theme,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const content = {
|
|
25
|
+
operations: [
|
|
26
|
+
{
|
|
27
|
+
beginRendering: {
|
|
28
|
+
surfaceId: "test-surface",
|
|
29
|
+
root: "root",
|
|
30
|
+
styles: {},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
surfaceUpdate: {
|
|
35
|
+
surfaceId: "test-surface",
|
|
36
|
+
components: [
|
|
37
|
+
{ id: "root", text: { literalString: "Hello World" } },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const RenderComponent = renderer.render as React.FC<any>;
|
|
45
|
+
const TestWrapper = () => (
|
|
46
|
+
<RenderComponent content={content} agent={null} />
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
let container: HTMLElement;
|
|
50
|
+
await act(async () => {
|
|
51
|
+
const result = render(<TestWrapper />);
|
|
52
|
+
container = result.container;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const surfaceElement = container!.querySelector(
|
|
56
|
+
"[data-surface-id='test-surface']",
|
|
57
|
+
);
|
|
58
|
+
expect(surfaceElement).not.toBeNull();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should update surface when operations change", async () => {
|
|
62
|
+
const { createA2UIMessageRenderer } =
|
|
63
|
+
await import("../a2ui/A2UIMessageRenderer.js");
|
|
64
|
+
const renderer = createA2UIMessageRenderer({
|
|
65
|
+
theme: {} as Theme,
|
|
66
|
+
});
|
|
67
|
+
const RenderComponent = renderer.render as React.FC<any>;
|
|
68
|
+
|
|
69
|
+
let setContent: (content: any) => void;
|
|
70
|
+
const TestWrapper = () => {
|
|
71
|
+
const [content, _setContent] = useState({
|
|
72
|
+
operations: [
|
|
73
|
+
{ beginRendering: { surfaceId: "test", root: "root", styles: {} } },
|
|
74
|
+
{
|
|
75
|
+
surfaceUpdate: {
|
|
76
|
+
surfaceId: "test",
|
|
77
|
+
components: [{ id: "root", text: { literalString: "Initial" } }],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
});
|
|
82
|
+
setContent = _setContent;
|
|
83
|
+
return <RenderComponent content={content} agent={null} />;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
let container: HTMLElement;
|
|
87
|
+
await act(async () => {
|
|
88
|
+
const result = render(<TestWrapper />);
|
|
89
|
+
container = result.container;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const surfaceElement = container!.querySelector("[data-surface-id='test']");
|
|
93
|
+
expect(surfaceElement).not.toBeNull();
|
|
94
|
+
|
|
95
|
+
await act(async () => {
|
|
96
|
+
setContent({
|
|
97
|
+
operations: [
|
|
98
|
+
{ beginRendering: { surfaceId: "test", root: "root", styles: {} } },
|
|
99
|
+
{
|
|
100
|
+
surfaceUpdate: {
|
|
101
|
+
surfaceId: "test",
|
|
102
|
+
components: [{ id: "root", text: { literalString: "Updated" } }],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const updatedSurface = container!.querySelector("[data-surface-id='test']");
|
|
110
|
+
expect(updatedSurface).not.toBeNull();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should return null when no operations are provided", async () => {
|
|
114
|
+
const { createA2UIMessageRenderer } =
|
|
115
|
+
await import("../a2ui/A2UIMessageRenderer.js");
|
|
116
|
+
const renderer = createA2UIMessageRenderer({
|
|
117
|
+
theme: {} as Theme,
|
|
118
|
+
});
|
|
119
|
+
const RenderComponent = renderer.render as React.FC<any>;
|
|
120
|
+
|
|
121
|
+
const TestWrapper = () => (
|
|
122
|
+
<RenderComponent content={{ operations: [] }} agent={null} />
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
let container: HTMLElement;
|
|
126
|
+
await act(async () => {
|
|
127
|
+
const result = render(<TestWrapper />);
|
|
128
|
+
container = result.container;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(container!.querySelector("[data-surface-id]")).toBeNull();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("should render multiple surfaces independently", async () => {
|
|
135
|
+
const { createA2UIMessageRenderer } =
|
|
136
|
+
await import("../a2ui/A2UIMessageRenderer.js");
|
|
137
|
+
const renderer = createA2UIMessageRenderer({
|
|
138
|
+
theme: {} as Theme,
|
|
139
|
+
});
|
|
140
|
+
const RenderComponent = renderer.render as React.FC<any>;
|
|
141
|
+
|
|
142
|
+
const content = {
|
|
143
|
+
operations: [
|
|
144
|
+
{ beginRendering: { surfaceId: "s1", root: "r1", styles: {} } },
|
|
145
|
+
{ beginRendering: { surfaceId: "s2", root: "r2", styles: {} } },
|
|
146
|
+
{
|
|
147
|
+
surfaceUpdate: {
|
|
148
|
+
surfaceId: "s1",
|
|
149
|
+
components: [{ id: "r1", text: { literalString: "Surface 1" } }],
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
surfaceUpdate: {
|
|
154
|
+
surfaceId: "s2",
|
|
155
|
+
components: [{ id: "r2", text: { literalString: "Surface 2" } }],
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const TestWrapper = () => (
|
|
162
|
+
<RenderComponent content={content} agent={null} />
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
let container: HTMLElement;
|
|
166
|
+
await act(async () => {
|
|
167
|
+
const result = render(<TestWrapper />);
|
|
168
|
+
container = result.container;
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const surface1 = container!.querySelector("[data-surface-id='s1']");
|
|
172
|
+
const surface2 = container!.querySelector("[data-surface-id='s2']");
|
|
173
|
+
expect(surface1).not.toBeNull();
|
|
174
|
+
expect(surface2).not.toBeNull();
|
|
175
|
+
});
|
|
176
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs once in Node before test workers start.
|
|
3
|
+
* Ensures `window` exists on globalThis so any code that runs during module
|
|
4
|
+
* resolution (e.g. when Vitest discovers tests) does not throw "window is not defined".
|
|
5
|
+
* CI can load test files in the main process before jsdom is available in workers.
|
|
6
|
+
*/
|
|
7
|
+
export default function globalSetup() {
|
|
8
|
+
if (
|
|
9
|
+
typeof globalThis !== "undefined" &&
|
|
10
|
+
typeof (globalThis as any).window === "undefined"
|
|
11
|
+
) {
|
|
12
|
+
(globalThis as any).window = globalThis as any;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Test setup file for Vitest
|
|
2
|
+
// Add any global test configuration here
|
|
3
|
+
import { afterEach, vi } from "vitest";
|
|
4
|
+
import { cleanup } from "@testing-library/react";
|
|
5
|
+
import React from "react";
|
|
6
|
+
|
|
7
|
+
// Mock ResizeObserver which is not available in jsdom
|
|
8
|
+
global.ResizeObserver = class ResizeObserver {
|
|
9
|
+
constructor(callback: ResizeObserverCallback) {
|
|
10
|
+
// Store callback for potential future use
|
|
11
|
+
this.callback = callback;
|
|
12
|
+
}
|
|
13
|
+
callback: ResizeObserverCallback;
|
|
14
|
+
observe() {}
|
|
15
|
+
unobserve() {}
|
|
16
|
+
disconnect() {}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Mock scrollIntoView which is not available in jsdom
|
|
20
|
+
HTMLElement.prototype.scrollIntoView = vi.fn();
|
|
21
|
+
|
|
22
|
+
// Ensure we cleanup between tests to avoid lingering handles
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
cleanup();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Mock canvas getContext used by audio recorder during tests
|
|
28
|
+
HTMLCanvasElement.prototype.getContext = function (contextId: any) {
|
|
29
|
+
if (contextId === "2d") {
|
|
30
|
+
return {
|
|
31
|
+
fillRect: () => {},
|
|
32
|
+
clearRect: () => {},
|
|
33
|
+
getImageData: () => ({ data: [] }),
|
|
34
|
+
putImageData: () => {},
|
|
35
|
+
createImageData: () => ({ data: [] }),
|
|
36
|
+
setTransform: () => {},
|
|
37
|
+
drawImage: () => {},
|
|
38
|
+
save: () => {},
|
|
39
|
+
restore: () => {},
|
|
40
|
+
beginPath: () => {},
|
|
41
|
+
closePath: () => {},
|
|
42
|
+
moveTo: () => {},
|
|
43
|
+
lineTo: () => {},
|
|
44
|
+
stroke: () => {},
|
|
45
|
+
translate: () => {},
|
|
46
|
+
scale: () => {},
|
|
47
|
+
rotate: () => {},
|
|
48
|
+
arc: () => {},
|
|
49
|
+
fill: () => {},
|
|
50
|
+
measureText: (text: string) => ({ width: text.length * 8 }),
|
|
51
|
+
transform: () => {},
|
|
52
|
+
rect: () => {},
|
|
53
|
+
clip: () => {},
|
|
54
|
+
} as unknown as CanvasRenderingContext2D;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
} as any;
|
|
58
|
+
|
|
59
|
+
// Simplify Radix tooltip behavior to avoid act() noise in jsdom
|
|
60
|
+
vi.mock("@radix-ui/react-tooltip", async () => {
|
|
61
|
+
const forward = (
|
|
62
|
+
renderFn: React.ForwardRefRenderFunction<HTMLElement, any>,
|
|
63
|
+
) => React.forwardRef(renderFn);
|
|
64
|
+
|
|
65
|
+
const SimpleProvider: React.FC<{ children?: React.ReactNode }> = ({
|
|
66
|
+
children,
|
|
67
|
+
}) => React.createElement(React.Fragment, null, children);
|
|
68
|
+
|
|
69
|
+
const SimplePortal: React.FC<{ children?: React.ReactNode }> = ({
|
|
70
|
+
children,
|
|
71
|
+
}) => React.createElement(React.Fragment, null, children);
|
|
72
|
+
|
|
73
|
+
const createWrapper = () =>
|
|
74
|
+
forward(
|
|
75
|
+
({ children, asChild, sideOffset: _sideOffset, ...rest }: any, ref) => {
|
|
76
|
+
if (asChild && React.isValidElement(children)) {
|
|
77
|
+
return React.cloneElement(children, { ref, ...rest });
|
|
78
|
+
}
|
|
79
|
+
return React.createElement("div", { ref, ...rest }, children);
|
|
80
|
+
},
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const passthrough = createWrapper();
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
Provider: SimpleProvider,
|
|
87
|
+
Root: passthrough,
|
|
88
|
+
Trigger: passthrough,
|
|
89
|
+
Content: passthrough,
|
|
90
|
+
Portal: SimplePortal,
|
|
91
|
+
Arrow: () => null,
|
|
92
|
+
};
|
|
93
|
+
});
|