rask-ui 0.1.1 → 0.2.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.
Files changed (212) hide show
  1. package/dist/component.d.ts +17 -0
  2. package/dist/component.d.ts.map +1 -1
  3. package/dist/createAsync.d.ts +23 -0
  4. package/dist/createAsync.d.ts.map +1 -1
  5. package/dist/createAsync.js +23 -0
  6. package/dist/createContext.d.ts +26 -2
  7. package/dist/createContext.d.ts.map +1 -1
  8. package/dist/createContext.js +31 -5
  9. package/dist/createContext.test.d.ts +2 -0
  10. package/dist/createContext.test.d.ts.map +1 -0
  11. package/dist/createContext.test.js +136 -0
  12. package/dist/createMutation.d.ts +23 -0
  13. package/dist/createMutation.d.ts.map +1 -1
  14. package/dist/createMutation.js +23 -0
  15. package/dist/createQuery.d.ts +23 -0
  16. package/dist/createQuery.d.ts.map +1 -1
  17. package/dist/createQuery.js +23 -0
  18. package/dist/createRef.test.d.ts +2 -0
  19. package/dist/createRef.test.d.ts.map +1 -0
  20. package/dist/createRef.test.js +80 -0
  21. package/dist/createState.d.ts +24 -0
  22. package/dist/createState.d.ts.map +1 -1
  23. package/dist/createState.js +24 -0
  24. package/dist/createView.d.ts +54 -0
  25. package/dist/createView.d.ts.map +1 -0
  26. package/dist/createView.js +68 -0
  27. package/dist/createView.test.d.ts +2 -0
  28. package/dist/createView.test.d.ts.map +1 -0
  29. package/dist/createView.test.js +203 -0
  30. package/dist/error.d.ts.map +1 -1
  31. package/dist/error.js +4 -5
  32. package/dist/error.test.d.ts +2 -0
  33. package/dist/error.test.d.ts.map +1 -0
  34. package/dist/error.test.js +144 -0
  35. package/dist/index.d.ts +3 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +3 -2
  38. package/dist/integration.test.d.ts +2 -0
  39. package/dist/integration.test.d.ts.map +1 -0
  40. package/dist/integration.test.js +155 -0
  41. package/dist/jsx-dev-runtime.d.ts +3 -3
  42. package/dist/jsx-dev-runtime.d.ts.map +1 -1
  43. package/dist/jsx-dev-runtime.js +2 -2
  44. package/dist/jsx-runtime.d.ts +1 -4
  45. package/dist/jsx-runtime.d.ts.map +1 -1
  46. package/dist/jsx-runtime.js +3 -14
  47. package/dist/observation.d.ts +1 -0
  48. package/dist/observation.d.ts.map +1 -1
  49. package/dist/observation.js +5 -0
  50. package/dist/test-setup.d.ts +3 -3
  51. package/dist/test-setup.d.ts.map +1 -1
  52. package/dist/test-setup.js +7 -8
  53. package/dist/tests/class.test.d.ts +2 -0
  54. package/dist/tests/class.test.d.ts.map +1 -0
  55. package/dist/tests/class.test.js +143 -0
  56. package/dist/tests/complex-rendering.test.d.ts +2 -0
  57. package/dist/tests/complex-rendering.test.d.ts.map +1 -0
  58. package/dist/tests/complex-rendering.test.js +400 -0
  59. package/dist/tests/component.cleanup.test.d.ts +2 -0
  60. package/dist/tests/component.cleanup.test.d.ts.map +1 -0
  61. package/dist/tests/component.cleanup.test.js +325 -0
  62. package/dist/tests/component.counter.test.d.ts +2 -0
  63. package/dist/tests/component.counter.test.d.ts.map +1 -0
  64. package/dist/tests/component.counter.test.js +124 -0
  65. package/dist/tests/component.interaction.test.d.ts +2 -0
  66. package/dist/tests/component.interaction.test.d.ts.map +1 -0
  67. package/dist/tests/component.interaction.test.js +73 -0
  68. package/dist/tests/component.props.test.d.ts +2 -0
  69. package/dist/tests/component.props.test.d.ts.map +1 -0
  70. package/dist/tests/component.props.test.js +88 -0
  71. package/dist/tests/component.return-types.test.d.ts +2 -0
  72. package/dist/tests/component.return-types.test.d.ts.map +1 -0
  73. package/dist/tests/component.return-types.test.js +357 -0
  74. package/dist/tests/component.state.test.d.ts +2 -0
  75. package/dist/tests/component.state.test.d.ts.map +1 -0
  76. package/dist/tests/component.state.test.js +129 -0
  77. package/dist/tests/component.test.d.ts +2 -0
  78. package/dist/tests/component.test.d.ts.map +1 -0
  79. package/dist/tests/component.test.js +63 -0
  80. package/dist/tests/createAsync.test.d.ts +2 -0
  81. package/dist/tests/createAsync.test.d.ts.map +1 -0
  82. package/dist/tests/createAsync.test.js +110 -0
  83. package/dist/tests/createContext.test.d.ts +2 -0
  84. package/dist/tests/createContext.test.d.ts.map +1 -0
  85. package/dist/tests/createContext.test.js +141 -0
  86. package/dist/tests/createMutation.test.d.ts +2 -0
  87. package/dist/tests/createMutation.test.d.ts.map +1 -0
  88. package/dist/tests/createMutation.test.js +168 -0
  89. package/dist/tests/createQuery.test.d.ts +2 -0
  90. package/dist/tests/createQuery.test.d.ts.map +1 -0
  91. package/dist/tests/createQuery.test.js +156 -0
  92. package/dist/tests/createRef.test.d.ts +2 -0
  93. package/dist/tests/createRef.test.d.ts.map +1 -0
  94. package/dist/tests/createRef.test.js +84 -0
  95. package/dist/tests/createState.test.d.ts +2 -0
  96. package/dist/tests/createState.test.d.ts.map +1 -0
  97. package/dist/tests/createState.test.js +111 -0
  98. package/dist/tests/createView.test.d.ts +2 -0
  99. package/dist/tests/createView.test.d.ts.map +1 -0
  100. package/dist/tests/createView.test.js +203 -0
  101. package/dist/tests/edge-cases.test.d.ts +2 -0
  102. package/dist/tests/edge-cases.test.d.ts.map +1 -0
  103. package/dist/tests/edge-cases.test.js +637 -0
  104. package/dist/tests/error-no-boundary.test.d.ts +2 -0
  105. package/dist/tests/error-no-boundary.test.d.ts.map +1 -0
  106. package/dist/tests/error-no-boundary.test.js +174 -0
  107. package/dist/tests/error.test.d.ts +2 -0
  108. package/dist/tests/error.test.d.ts.map +1 -0
  109. package/dist/tests/error.test.js +199 -0
  110. package/dist/tests/fragment.test.d.ts +2 -0
  111. package/dist/tests/fragment.test.d.ts.map +1 -0
  112. package/dist/tests/fragment.test.js +618 -0
  113. package/dist/tests/integration.test.d.ts +2 -0
  114. package/dist/tests/integration.test.d.ts.map +1 -0
  115. package/dist/tests/integration.test.js +192 -0
  116. package/dist/tests/keys.test.d.ts +2 -0
  117. package/dist/tests/keys.test.d.ts.map +1 -0
  118. package/dist/tests/keys.test.js +293 -0
  119. package/dist/tests/mount.test.d.ts +2 -0
  120. package/dist/tests/mount.test.d.ts.map +1 -0
  121. package/dist/tests/mount.test.js +91 -0
  122. package/dist/tests/observation.test.d.ts +2 -0
  123. package/dist/tests/observation.test.d.ts.map +1 -0
  124. package/dist/tests/observation.test.js +150 -0
  125. package/dist/tests/patch.test.d.ts +2 -0
  126. package/dist/tests/patch.test.d.ts.map +1 -0
  127. package/dist/tests/patch.test.js +498 -0
  128. package/dist/tests/patchChildren.test.d.ts +2 -0
  129. package/dist/tests/patchChildren.test.d.ts.map +1 -0
  130. package/dist/tests/patchChildren.test.js +387 -0
  131. package/dist/tests/primitives.test.d.ts +2 -0
  132. package/dist/tests/primitives.test.d.ts.map +1 -0
  133. package/dist/tests/primitives.test.js +132 -0
  134. package/dist/vdom/AbstractVNode.d.ts +22 -0
  135. package/dist/vdom/AbstractVNode.d.ts.map +1 -0
  136. package/dist/vdom/AbstractVNode.js +106 -0
  137. package/dist/vdom/ComponentVNode.d.ts +48 -0
  138. package/dist/vdom/ComponentVNode.d.ts.map +1 -0
  139. package/dist/vdom/ComponentVNode.js +209 -0
  140. package/dist/vdom/ElementVNode.d.ts +24 -0
  141. package/dist/vdom/ElementVNode.d.ts.map +1 -0
  142. package/dist/vdom/ElementVNode.js +126 -0
  143. package/dist/vdom/FragmentVNode.d.ts +13 -0
  144. package/dist/vdom/FragmentVNode.d.ts.map +1 -0
  145. package/dist/vdom/FragmentVNode.js +34 -0
  146. package/dist/vdom/RootVNode.d.ts +22 -0
  147. package/dist/vdom/RootVNode.d.ts.map +1 -0
  148. package/dist/vdom/RootVNode.js +55 -0
  149. package/dist/vdom/TextVNode.d.ts +11 -0
  150. package/dist/vdom/TextVNode.d.ts.map +1 -0
  151. package/dist/vdom/TextVNode.js +32 -0
  152. package/dist/vdom/class.test.d.ts +2 -0
  153. package/dist/vdom/class.test.d.ts.map +1 -0
  154. package/dist/vdom/class.test.js +143 -0
  155. package/dist/vdom/complex-rendering.test.d.ts +2 -0
  156. package/dist/vdom/complex-rendering.test.d.ts.map +1 -0
  157. package/dist/vdom/complex-rendering.test.js +400 -0
  158. package/dist/vdom/component.cleanup.test.d.ts +2 -0
  159. package/dist/vdom/component.cleanup.test.d.ts.map +1 -0
  160. package/dist/vdom/component.cleanup.test.js +323 -0
  161. package/dist/vdom/component.counter.test.d.ts +2 -0
  162. package/dist/vdom/component.counter.test.d.ts.map +1 -0
  163. package/dist/vdom/component.counter.test.js +124 -0
  164. package/dist/vdom/component.interaction.test.d.ts +2 -0
  165. package/dist/vdom/component.interaction.test.d.ts.map +1 -0
  166. package/dist/vdom/component.interaction.test.js +73 -0
  167. package/dist/vdom/component.props.test.d.ts +2 -0
  168. package/dist/vdom/component.props.test.d.ts.map +1 -0
  169. package/dist/vdom/component.props.test.js +88 -0
  170. package/dist/vdom/component.return-types.test.d.ts +2 -0
  171. package/dist/vdom/component.return-types.test.d.ts.map +1 -0
  172. package/dist/vdom/component.return-types.test.js +357 -0
  173. package/dist/vdom/component.state.test.d.ts +2 -0
  174. package/dist/vdom/component.state.test.d.ts.map +1 -0
  175. package/dist/vdom/component.state.test.js +129 -0
  176. package/dist/vdom/component.test.d.ts +2 -0
  177. package/dist/vdom/component.test.d.ts.map +1 -0
  178. package/dist/vdom/component.test.js +63 -0
  179. package/dist/vdom/dom-utils.d.ts +9 -0
  180. package/dist/vdom/dom-utils.d.ts.map +1 -0
  181. package/dist/vdom/dom-utils.js +74 -0
  182. package/dist/vdom/edge-cases.test.d.ts +2 -0
  183. package/dist/vdom/edge-cases.test.d.ts.map +1 -0
  184. package/dist/vdom/edge-cases.test.js +637 -0
  185. package/dist/vdom/fragment.test.d.ts +2 -0
  186. package/dist/vdom/fragment.test.d.ts.map +1 -0
  187. package/dist/vdom/fragment.test.js +618 -0
  188. package/dist/vdom/index.d.ts +10 -0
  189. package/dist/vdom/index.d.ts.map +1 -0
  190. package/dist/vdom/index.js +26 -0
  191. package/dist/vdom/keys.test.d.ts +2 -0
  192. package/dist/vdom/keys.test.d.ts.map +1 -0
  193. package/dist/vdom/keys.test.js +293 -0
  194. package/dist/vdom/mount.test.d.ts +2 -0
  195. package/dist/vdom/mount.test.d.ts.map +1 -0
  196. package/dist/vdom/mount.test.js +91 -0
  197. package/dist/vdom/patch.test.d.ts +2 -0
  198. package/dist/vdom/patch.test.d.ts.map +1 -0
  199. package/dist/vdom/patch.test.js +498 -0
  200. package/dist/vdom/patchChildren.test.d.ts +2 -0
  201. package/dist/vdom/patchChildren.test.d.ts.map +1 -0
  202. package/dist/vdom/patchChildren.test.js +392 -0
  203. package/dist/vdom/primitives.test.d.ts +2 -0
  204. package/dist/vdom/primitives.test.d.ts.map +1 -0
  205. package/dist/vdom/primitives.test.js +132 -0
  206. package/dist/vdom/types.d.ts +8 -0
  207. package/dist/vdom/types.d.ts.map +1 -0
  208. package/dist/vdom/types.js +1 -0
  209. package/dist/vdom/utils.d.ts +6 -0
  210. package/dist/vdom/utils.d.ts.map +1 -0
  211. package/dist/vdom/utils.js +63 -0
  212. package/package.json +1 -4
@@ -0,0 +1,174 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { jsx } from "../vdom";
3
+ import { renderComponent } from "../test-setup";
4
+ describe("Error handling without ErrorBoundary", () => {
5
+ it("should not infinite loop when component throws during render without ErrorBoundary", async () => {
6
+ let renderCount = 0;
7
+ function ThrowingComponent() {
8
+ renderCount++;
9
+ if (renderCount > 20) {
10
+ throw new Error("Infinite loop detected - rendered more than 20 times!");
11
+ }
12
+ return () => {
13
+ throw new Error("Component throws in render function");
14
+ };
15
+ }
16
+ const { container, unmount } = renderComponent(jsx(ThrowingComponent, {}));
17
+ await new Promise((resolve) => setTimeout(resolve, 50));
18
+ // Should only attempt initialization once, not loop
19
+ expect(renderCount).toBe(1);
20
+ // Should render empty content gracefully
21
+ expect(container.textContent).toBe("");
22
+ unmount();
23
+ });
24
+ it("should not infinite loop when component returns JSX directly without ErrorBoundary", async () => {
25
+ let renderCount = 0;
26
+ function BadComponent() {
27
+ renderCount++;
28
+ if (renderCount > 20) {
29
+ throw new Error("Infinite loop detected - rendered more than 20 times!");
30
+ }
31
+ // Directly return JSX instead of a function
32
+ return jsx("div", { children: "Direct JSX" });
33
+ }
34
+ const { container, unmount } = renderComponent(jsx(BadComponent, {}));
35
+ await new Promise((resolve) => setTimeout(resolve, 50));
36
+ // Should only attempt initialization once, not loop
37
+ expect(renderCount).toBe(1);
38
+ // Should render empty content gracefully (because of error)
39
+ expect(container.textContent).toBe("");
40
+ unmount();
41
+ });
42
+ it("should handle state changes that cause errors without ErrorBoundary", async () => {
43
+ let initCount = 0;
44
+ let renderCount = 0;
45
+ function ComponentWithState() {
46
+ initCount++;
47
+ if (initCount > 20) {
48
+ throw new Error("Infinite loop detected - initialized more than 20 times!");
49
+ }
50
+ return () => {
51
+ renderCount++;
52
+ if (renderCount > 20) {
53
+ throw new Error("Infinite loop detected - rendered more than 20 times!");
54
+ }
55
+ throw new Error("Render error");
56
+ };
57
+ }
58
+ const { container, unmount } = renderComponent(jsx(ComponentWithState, {}));
59
+ await new Promise((resolve) => setTimeout(resolve, 50));
60
+ // Should only initialize once
61
+ expect(initCount).toBe(1);
62
+ // Should render empty without looping
63
+ expect(renderCount).toBeLessThan(20);
64
+ unmount();
65
+ });
66
+ it("should handle nested component returning JSX directly (child error, parent ok)", async () => {
67
+ let parentRenderCount = 0;
68
+ let childInitCount = 0;
69
+ function BadChild() {
70
+ childInitCount++;
71
+ if (childInitCount > 20) {
72
+ throw new Error("Infinite loop detected in child!");
73
+ }
74
+ // Directly return JSX instead of a function
75
+ return jsx("span", { children: "Direct JSX from child" });
76
+ }
77
+ function GoodParent() {
78
+ parentRenderCount++;
79
+ if (parentRenderCount > 20) {
80
+ throw new Error("Infinite loop detected in parent!");
81
+ }
82
+ return () => jsx("div", {
83
+ children: [
84
+ jsx("h1", { children: "Parent" }),
85
+ jsx(BadChild, {}),
86
+ ],
87
+ });
88
+ }
89
+ const { container, unmount } = renderComponent(jsx(GoodParent, {}));
90
+ await new Promise((resolve) => setTimeout(resolve, 50));
91
+ // Parent should initialize once
92
+ expect(parentRenderCount).toBe(1);
93
+ // Child should only attempt to initialize once
94
+ expect(childInitCount).toBe(1);
95
+ // Parent should render but child error shouldn't show
96
+ expect(container.textContent).toContain("Parent");
97
+ expect(container.textContent).not.toContain("Direct JSX");
98
+ unmount();
99
+ });
100
+ it("should handle nested component throwing during render (child error, parent ok)", async () => {
101
+ let parentRenderCount = 0;
102
+ let childInitCount = 0;
103
+ let childRenderAttempts = 0;
104
+ function BadChild() {
105
+ childInitCount++;
106
+ if (childInitCount > 20) {
107
+ throw new Error("Infinite loop detected in child!");
108
+ }
109
+ return () => {
110
+ childRenderAttempts++;
111
+ throw new Error("Child render error");
112
+ };
113
+ }
114
+ function GoodParent() {
115
+ parentRenderCount++;
116
+ if (parentRenderCount > 20) {
117
+ throw new Error("Infinite loop detected in parent!");
118
+ }
119
+ return () => jsx("div", {
120
+ children: [jsx("h1", { children: "Parent" }), jsx(BadChild, {})],
121
+ });
122
+ }
123
+ const { container, unmount } = renderComponent(jsx(GoodParent, {}));
124
+ await new Promise((resolve) => setTimeout(resolve, 50));
125
+ // Parent should initialize once
126
+ expect(parentRenderCount).toBe(1);
127
+ // Child should only initialize once
128
+ expect(childInitCount).toBe(1);
129
+ // Child render should be attempted but parent should still render
130
+ expect(childRenderAttempts).toBeGreaterThan(0);
131
+ expect(childRenderAttempts).toBeLessThan(20);
132
+ expect(container.textContent).toContain("Parent");
133
+ unmount();
134
+ });
135
+ it("should handle multiple nested bad children without looping", async () => {
136
+ let parentRenderCount = 0;
137
+ let child1InitCount = 0;
138
+ let child2InitCount = 0;
139
+ function BadChild1() {
140
+ child1InitCount++;
141
+ if (child1InitCount > 20)
142
+ throw new Error("Child1 loop!");
143
+ return jsx("div", { children: "Direct JSX 1" });
144
+ }
145
+ function BadChild2() {
146
+ child2InitCount++;
147
+ if (child2InitCount > 20)
148
+ throw new Error("Child2 loop!");
149
+ return jsx("span", { children: "Direct JSX 2" });
150
+ }
151
+ function GoodParent() {
152
+ parentRenderCount++;
153
+ if (parentRenderCount > 20)
154
+ throw new Error("Parent loop!");
155
+ return () => jsx("div", {
156
+ children: [
157
+ jsx("h1", { children: "Parent" }),
158
+ jsx(BadChild1, {}),
159
+ jsx(BadChild2, {}),
160
+ ],
161
+ });
162
+ }
163
+ const { container, unmount } = renderComponent(jsx(GoodParent, {}));
164
+ await new Promise((resolve) => setTimeout(resolve, 50));
165
+ // Parent initializes once
166
+ expect(parentRenderCount).toBe(1);
167
+ // Each child initializes once
168
+ expect(child1InitCount).toBe(1);
169
+ expect(child2InitCount).toBe(1);
170
+ // Parent renders successfully despite child errors
171
+ expect(container.textContent).toContain("Parent");
172
+ unmount();
173
+ });
174
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=error.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.test.d.ts","sourceRoot":"","sources":["../../src/tests/error.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,199 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { jsx } from "../vdom";
3
+ import { ErrorBoundary } from "../error";
4
+ import { renderComponent } from "../test-setup";
5
+ describe("ErrorBoundary", () => {
6
+ it("should render children when no error occurs", async () => {
7
+ function SafeChild() {
8
+ return () => jsx("div", { children: "Safe content" });
9
+ }
10
+ function TestComponent() {
11
+ return () => jsx(ErrorBoundary, {
12
+ error: (error) => jsx("div", { children: `Error: ${String(error)}` }),
13
+ children: jsx(SafeChild, {}),
14
+ });
15
+ }
16
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
17
+ await new Promise((resolve) => setTimeout(resolve, 10));
18
+ expect(container.textContent).toContain("Safe content");
19
+ expect(container.textContent).not.toContain("Error:");
20
+ unmount();
21
+ });
22
+ it("should catch errors thrown in child components", async () => {
23
+ function ThrowingChild() {
24
+ return () => {
25
+ throw new Error("Child component error");
26
+ };
27
+ }
28
+ function TestComponent() {
29
+ return () => jsx(ErrorBoundary, {
30
+ error: (error) => jsx("div", { children: `Error: ${String(error)}` }),
31
+ children: jsx(ThrowingChild, {}),
32
+ });
33
+ }
34
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
35
+ await new Promise((resolve) => setTimeout(resolve, 10));
36
+ expect(container.textContent).toContain("Error:");
37
+ expect(container.textContent).toContain("Child component error");
38
+ unmount();
39
+ });
40
+ it("should render custom error UI", async () => {
41
+ function ThrowingChild() {
42
+ return () => {
43
+ throw new Error("Something went wrong");
44
+ };
45
+ }
46
+ function TestComponent() {
47
+ return () => jsx(ErrorBoundary, {
48
+ error: (error) => jsx("div", {
49
+ class: "error-ui",
50
+ children: [
51
+ jsx("h1", { children: "Oops!" }),
52
+ jsx("p", { children: String(error) }),
53
+ ],
54
+ }),
55
+ children: jsx(ThrowingChild, {}),
56
+ });
57
+ }
58
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
59
+ await new Promise((resolve) => setTimeout(resolve, 10));
60
+ const errorUI = document.querySelector(".error-ui");
61
+ expect(errorUI).not.toBeNull();
62
+ expect(errorUI?.querySelector("h1")?.textContent).toBe("Oops!");
63
+ expect(errorUI?.textContent).toContain("Something went wrong");
64
+ unmount();
65
+ });
66
+ it("should handle multiple children", async () => {
67
+ function SafeChild1() {
68
+ return () => jsx("div", { children: "Child 1" });
69
+ }
70
+ function SafeChild2() {
71
+ return () => jsx("div", { children: "Child 2" });
72
+ }
73
+ function TestComponent() {
74
+ return () => jsx(ErrorBoundary, {
75
+ error: (error) => jsx("div", { children: `Error: ${String(error)}` }),
76
+ children: [jsx(SafeChild1, {}), jsx(SafeChild2, {})],
77
+ });
78
+ }
79
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
80
+ await new Promise((resolve) => setTimeout(resolve, 10));
81
+ expect(container.textContent).toContain("Child 1");
82
+ expect(container.textContent).toContain("Child 2");
83
+ unmount();
84
+ });
85
+ it("should catch errors from nested children", async () => {
86
+ function DeepChild() {
87
+ return () => {
88
+ throw new Error("Deep error");
89
+ };
90
+ }
91
+ function MiddleChild() {
92
+ return () => jsx(DeepChild, {});
93
+ }
94
+ function TestComponent() {
95
+ return () => jsx(ErrorBoundary, {
96
+ error: (error) => jsx("div", { children: `Caught: ${String(error)}` }),
97
+ children: jsx(MiddleChild, {}),
98
+ });
99
+ }
100
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
101
+ await new Promise((resolve) => setTimeout(resolve, 10));
102
+ expect(container.textContent).toContain("Caught:");
103
+ expect(container.textContent).toContain("Deep error");
104
+ unmount();
105
+ });
106
+ it("should allow nested error boundaries", async () => {
107
+ function ThrowingChild() {
108
+ return () => {
109
+ throw new Error("Inner error");
110
+ };
111
+ }
112
+ function TestComponent() {
113
+ return () => jsx(ErrorBoundary, {
114
+ error: (error) => jsx("div", { children: `Outer: ${String(error)}` }),
115
+ children: jsx(ErrorBoundary, {
116
+ error: (error) => jsx("div", { children: `Inner: ${String(error)}` }),
117
+ children: jsx(ThrowingChild, {}),
118
+ }),
119
+ });
120
+ }
121
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
122
+ await new Promise((resolve) => setTimeout(resolve, 10));
123
+ // Inner boundary should catch the error
124
+ expect(container.textContent).toContain("Inner:");
125
+ expect(container.textContent).not.toContain("Outer:");
126
+ unmount();
127
+ });
128
+ it("should handle string errors", async () => {
129
+ function ThrowingChild() {
130
+ return () => {
131
+ throw "String error";
132
+ };
133
+ }
134
+ function TestComponent() {
135
+ return () => jsx(ErrorBoundary, {
136
+ error: (error) => jsx("div", { children: `Error: ${String(error)}` }),
137
+ children: jsx(ThrowingChild, {}),
138
+ });
139
+ }
140
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
141
+ await new Promise((resolve) => setTimeout(resolve, 10));
142
+ expect(container.textContent).toContain("String error");
143
+ unmount();
144
+ });
145
+ it("should handle object errors", async () => {
146
+ function ThrowingChild() {
147
+ return () => {
148
+ throw { message: "Custom error object", code: 500 };
149
+ };
150
+ }
151
+ function TestComponent() {
152
+ return () => jsx(ErrorBoundary, {
153
+ error: (error) => jsx("div", {
154
+ children: `Error: ${error.message} (Code: ${error.code})`,
155
+ }),
156
+ children: jsx(ThrowingChild, {}),
157
+ });
158
+ }
159
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
160
+ await new Promise((resolve) => setTimeout(resolve, 10));
161
+ expect(container.textContent).toContain("Custom error object");
162
+ expect(container.textContent).toContain("500");
163
+ unmount();
164
+ });
165
+ it("should switch back to children if error is cleared", async () => {
166
+ // Note: This test demonstrates the current behavior
167
+ // In practice, error clearing would require additional implementation
168
+ function SafeChild() {
169
+ return () => jsx("div", { children: "Safe content" });
170
+ }
171
+ function TestComponent() {
172
+ return () => jsx(ErrorBoundary, {
173
+ error: (error) => jsx("div", { children: `Error: ${String(error)}` }),
174
+ children: jsx(SafeChild, {}),
175
+ });
176
+ }
177
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
178
+ await new Promise((resolve) => setTimeout(resolve, 10));
179
+ expect(container.textContent).toContain("Safe content");
180
+ unmount();
181
+ });
182
+ it("should catch error when component returns JSX directly instead of function", async () => {
183
+ function BadComponent() {
184
+ // Wrong: returning JSX directly
185
+ return jsx("div", { children: "Direct JSX" });
186
+ }
187
+ function TestComponent() {
188
+ return () => jsx(ErrorBoundary, {
189
+ error: (error) => jsx("div", { children: `Error: ${String(error)}` }),
190
+ children: jsx(BadComponent, {}),
191
+ });
192
+ }
193
+ const { container, unmount } = renderComponent(jsx(TestComponent, {}));
194
+ await new Promise((resolve) => setTimeout(resolve, 10));
195
+ expect(container.textContent).toContain("Error:");
196
+ expect(container.textContent).toContain("Component must return a render function");
197
+ unmount();
198
+ });
199
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fragment.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fragment.test.d.ts","sourceRoot":"","sources":["../../src/tests/fragment.test.ts"],"names":[],"mappings":""}