rask-ui 0.2.5 → 0.2.7

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 (200) hide show
  1. package/dist/vdom/AbstractVNode.d.ts +20 -1
  2. package/dist/vdom/AbstractVNode.d.ts.map +1 -1
  3. package/dist/vdom/AbstractVNode.js +151 -12
  4. package/dist/vdom/ComponentVNode.d.ts +2 -2
  5. package/dist/vdom/ComponentVNode.d.ts.map +1 -1
  6. package/dist/vdom/ComponentVNode.js +17 -8
  7. package/dist/vdom/ElementVNode.d.ts +6 -9
  8. package/dist/vdom/ElementVNode.d.ts.map +1 -1
  9. package/dist/vdom/ElementVNode.js +103 -34
  10. package/dist/vdom/FragmentVNode.d.ts +2 -2
  11. package/dist/vdom/FragmentVNode.d.ts.map +1 -1
  12. package/dist/vdom/FragmentVNode.js +18 -7
  13. package/dist/vdom/RootVNode.d.ts +2 -2
  14. package/dist/vdom/RootVNode.d.ts.map +1 -1
  15. package/dist/vdom/RootVNode.js +15 -6
  16. package/dist/vdom/dom-utils.d.ts +6 -1
  17. package/dist/vdom/dom-utils.d.ts.map +1 -1
  18. package/dist/vdom/dom-utils.js +20 -1
  19. package/dist/vdom/types.d.ts +12 -0
  20. package/dist/vdom/types.d.ts.map +1 -1
  21. package/package.json +1 -1
  22. package/dist/component.d.ts +0 -38
  23. package/dist/component.d.ts.map +0 -1
  24. package/dist/component.js +0 -130
  25. package/dist/context.d.ts +0 -5
  26. package/dist/context.d.ts.map +0 -1
  27. package/dist/context.js +0 -29
  28. package/dist/createAsync.test.d.ts +0 -2
  29. package/dist/createAsync.test.d.ts.map +0 -1
  30. package/dist/createAsync.test.js +0 -110
  31. package/dist/createAsyncState.d.ts +0 -16
  32. package/dist/createAsyncState.d.ts.map +0 -1
  33. package/dist/createAsyncState.js +0 -24
  34. package/dist/createContext.test.d.ts +0 -2
  35. package/dist/createContext.test.d.ts.map +0 -1
  36. package/dist/createContext.test.js +0 -136
  37. package/dist/createMutation.test.d.ts +0 -2
  38. package/dist/createMutation.test.d.ts.map +0 -1
  39. package/dist/createMutation.test.js +0 -168
  40. package/dist/createQuery.test.d.ts +0 -2
  41. package/dist/createQuery.test.d.ts.map +0 -1
  42. package/dist/createQuery.test.js +0 -156
  43. package/dist/createRef.test.d.ts +0 -2
  44. package/dist/createRef.test.d.ts.map +0 -1
  45. package/dist/createRef.test.js +0 -80
  46. package/dist/createState.test.d.ts +0 -2
  47. package/dist/createState.test.d.ts.map +0 -1
  48. package/dist/createState.test.js +0 -111
  49. package/dist/createView.test.d.ts +0 -2
  50. package/dist/createView.test.d.ts.map +0 -1
  51. package/dist/createView.test.js +0 -203
  52. package/dist/error.test.d.ts +0 -2
  53. package/dist/error.test.d.ts.map +0 -1
  54. package/dist/error.test.js +0 -144
  55. package/dist/integration.test.d.ts +0 -2
  56. package/dist/integration.test.d.ts.map +0 -1
  57. package/dist/integration.test.js +0 -155
  58. package/dist/jsx.d.ts.map +0 -1
  59. package/dist/jsx.js +0 -42
  60. package/dist/observation.test.d.ts +0 -2
  61. package/dist/observation.test.d.ts.map +0 -1
  62. package/dist/observation.test.js +0 -113
  63. package/dist/render-test.d.ts +0 -2
  64. package/dist/render-test.d.ts.map +0 -1
  65. package/dist/render-test.js +0 -21
  66. package/dist/render.d.ts +0 -7
  67. package/dist/render.d.ts.map +0 -1
  68. package/dist/render.js +0 -77
  69. package/dist/suspense.d.ts +0 -25
  70. package/dist/suspense.d.ts.map +0 -1
  71. package/dist/suspense.js +0 -97
  72. package/dist/tests/class.test.d.ts +0 -2
  73. package/dist/tests/class.test.d.ts.map +0 -1
  74. package/dist/tests/class.test.js +0 -185
  75. package/dist/tests/complex-rendering.test.d.ts +0 -2
  76. package/dist/tests/complex-rendering.test.d.ts.map +0 -1
  77. package/dist/tests/complex-rendering.test.js +0 -400
  78. package/dist/tests/component.cleanup.test.d.ts +0 -2
  79. package/dist/tests/component.cleanup.test.d.ts.map +0 -1
  80. package/dist/tests/component.cleanup.test.js +0 -325
  81. package/dist/tests/component.counter.test.d.ts +0 -2
  82. package/dist/tests/component.counter.test.d.ts.map +0 -1
  83. package/dist/tests/component.counter.test.js +0 -124
  84. package/dist/tests/component.interaction.test.d.ts +0 -2
  85. package/dist/tests/component.interaction.test.d.ts.map +0 -1
  86. package/dist/tests/component.interaction.test.js +0 -73
  87. package/dist/tests/component.props.test.d.ts +0 -2
  88. package/dist/tests/component.props.test.d.ts.map +0 -1
  89. package/dist/tests/component.props.test.js +0 -334
  90. package/dist/tests/component.return-types.test.d.ts +0 -2
  91. package/dist/tests/component.return-types.test.d.ts.map +0 -1
  92. package/dist/tests/component.return-types.test.js +0 -357
  93. package/dist/tests/component.state.test.d.ts +0 -2
  94. package/dist/tests/component.state.test.d.ts.map +0 -1
  95. package/dist/tests/component.state.test.js +0 -135
  96. package/dist/tests/component.test.d.ts +0 -2
  97. package/dist/tests/component.test.d.ts.map +0 -1
  98. package/dist/tests/component.test.js +0 -63
  99. package/dist/tests/createAsync.test.d.ts +0 -2
  100. package/dist/tests/createAsync.test.d.ts.map +0 -1
  101. package/dist/tests/createAsync.test.js +0 -110
  102. package/dist/tests/createContext.test.d.ts +0 -2
  103. package/dist/tests/createContext.test.d.ts.map +0 -1
  104. package/dist/tests/createContext.test.js +0 -141
  105. package/dist/tests/createMutation.test.d.ts +0 -2
  106. package/dist/tests/createMutation.test.d.ts.map +0 -1
  107. package/dist/tests/createMutation.test.js +0 -168
  108. package/dist/tests/createQuery.test.d.ts +0 -2
  109. package/dist/tests/createQuery.test.d.ts.map +0 -1
  110. package/dist/tests/createQuery.test.js +0 -156
  111. package/dist/tests/createRef.test.d.ts +0 -2
  112. package/dist/tests/createRef.test.d.ts.map +0 -1
  113. package/dist/tests/createRef.test.js +0 -84
  114. package/dist/tests/createState.test.d.ts +0 -2
  115. package/dist/tests/createState.test.d.ts.map +0 -1
  116. package/dist/tests/createState.test.js +0 -103
  117. package/dist/tests/createView.test.d.ts +0 -2
  118. package/dist/tests/createView.test.d.ts.map +0 -1
  119. package/dist/tests/createView.test.js +0 -203
  120. package/dist/tests/edge-cases.test.d.ts +0 -2
  121. package/dist/tests/edge-cases.test.d.ts.map +0 -1
  122. package/dist/tests/edge-cases.test.js +0 -637
  123. package/dist/tests/error-no-boundary.test.d.ts +0 -2
  124. package/dist/tests/error-no-boundary.test.d.ts.map +0 -1
  125. package/dist/tests/error-no-boundary.test.js +0 -174
  126. package/dist/tests/error.test.d.ts +0 -2
  127. package/dist/tests/error.test.d.ts.map +0 -1
  128. package/dist/tests/error.test.js +0 -199
  129. package/dist/tests/fragment.test.d.ts +0 -2
  130. package/dist/tests/fragment.test.d.ts.map +0 -1
  131. package/dist/tests/fragment.test.js +0 -618
  132. package/dist/tests/integration.test.d.ts +0 -2
  133. package/dist/tests/integration.test.d.ts.map +0 -1
  134. package/dist/tests/integration.test.js +0 -192
  135. package/dist/tests/keys.test.d.ts +0 -2
  136. package/dist/tests/keys.test.d.ts.map +0 -1
  137. package/dist/tests/keys.test.js +0 -293
  138. package/dist/tests/mount.test.d.ts +0 -2
  139. package/dist/tests/mount.test.d.ts.map +0 -1
  140. package/dist/tests/mount.test.js +0 -91
  141. package/dist/tests/observation.test.d.ts +0 -2
  142. package/dist/tests/observation.test.d.ts.map +0 -1
  143. package/dist/tests/observation.test.js +0 -113
  144. package/dist/tests/patch.test.d.ts +0 -2
  145. package/dist/tests/patch.test.d.ts.map +0 -1
  146. package/dist/tests/patch.test.js +0 -498
  147. package/dist/tests/patchChildren.test.d.ts +0 -2
  148. package/dist/tests/patchChildren.test.d.ts.map +0 -1
  149. package/dist/tests/patchChildren.test.js +0 -405
  150. package/dist/tests/primitives.test.d.ts +0 -2
  151. package/dist/tests/primitives.test.d.ts.map +0 -1
  152. package/dist/tests/primitives.test.js +0 -132
  153. package/dist/vdom/class.test.d.ts +0 -2
  154. package/dist/vdom/class.test.d.ts.map +0 -1
  155. package/dist/vdom/class.test.js +0 -143
  156. package/dist/vdom/complex-rendering.test.d.ts +0 -2
  157. package/dist/vdom/complex-rendering.test.d.ts.map +0 -1
  158. package/dist/vdom/complex-rendering.test.js +0 -400
  159. package/dist/vdom/component.cleanup.test.d.ts +0 -2
  160. package/dist/vdom/component.cleanup.test.d.ts.map +0 -1
  161. package/dist/vdom/component.cleanup.test.js +0 -323
  162. package/dist/vdom/component.counter.test.d.ts +0 -2
  163. package/dist/vdom/component.counter.test.d.ts.map +0 -1
  164. package/dist/vdom/component.counter.test.js +0 -124
  165. package/dist/vdom/component.interaction.test.d.ts +0 -2
  166. package/dist/vdom/component.interaction.test.d.ts.map +0 -1
  167. package/dist/vdom/component.interaction.test.js +0 -73
  168. package/dist/vdom/component.props.test.d.ts +0 -2
  169. package/dist/vdom/component.props.test.d.ts.map +0 -1
  170. package/dist/vdom/component.props.test.js +0 -88
  171. package/dist/vdom/component.return-types.test.d.ts +0 -2
  172. package/dist/vdom/component.return-types.test.d.ts.map +0 -1
  173. package/dist/vdom/component.return-types.test.js +0 -357
  174. package/dist/vdom/component.state.test.d.ts +0 -2
  175. package/dist/vdom/component.state.test.d.ts.map +0 -1
  176. package/dist/vdom/component.state.test.js +0 -129
  177. package/dist/vdom/component.test.d.ts +0 -2
  178. package/dist/vdom/component.test.d.ts.map +0 -1
  179. package/dist/vdom/component.test.js +0 -63
  180. package/dist/vdom/edge-cases.test.d.ts +0 -2
  181. package/dist/vdom/edge-cases.test.d.ts.map +0 -1
  182. package/dist/vdom/edge-cases.test.js +0 -637
  183. package/dist/vdom/fragment.test.d.ts +0 -2
  184. package/dist/vdom/fragment.test.d.ts.map +0 -1
  185. package/dist/vdom/fragment.test.js +0 -618
  186. package/dist/vdom/keys.test.d.ts +0 -2
  187. package/dist/vdom/keys.test.d.ts.map +0 -1
  188. package/dist/vdom/keys.test.js +0 -293
  189. package/dist/vdom/mount.test.d.ts +0 -2
  190. package/dist/vdom/mount.test.d.ts.map +0 -1
  191. package/dist/vdom/mount.test.js +0 -91
  192. package/dist/vdom/patch.test.d.ts +0 -2
  193. package/dist/vdom/patch.test.d.ts.map +0 -1
  194. package/dist/vdom/patch.test.js +0 -498
  195. package/dist/vdom/patchChildren.test.d.ts +0 -2
  196. package/dist/vdom/patchChildren.test.d.ts.map +0 -1
  197. package/dist/vdom/patchChildren.test.js +0 -392
  198. package/dist/vdom/primitives.test.d.ts +0 -2
  199. package/dist/vdom/primitives.test.d.ts.map +0 -1
  200. package/dist/vdom/primitives.test.js +0 -132
@@ -1,637 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
- import { jsx, render } from "../vdom/index";
3
- import { Fragment } from "../vdom/FragmentVNode";
4
- import { createState } from "../createState";
5
- describe("VDOM Edge Cases", () => {
6
- describe("Text Node Patching", () => {
7
- it("should patch element to text node", async () => {
8
- const container = document.createElement("div");
9
- let stateFn;
10
- const App = () => {
11
- const state = createState({ showElement: true });
12
- stateFn = state;
13
- return () => jsx("div", {
14
- children: state.showElement
15
- ? [jsx("span", { children: ["Element"] })]
16
- : ["Text"],
17
- });
18
- };
19
- render(jsx(App, {}), container);
20
- const wrapper = container.children[0];
21
- expect(wrapper.children.length).toBe(1);
22
- expect(wrapper.children[0].tagName).toBe("SPAN");
23
- stateFn.showElement = false;
24
- await new Promise((resolve) => setTimeout(resolve, 0));
25
- expect(wrapper.childNodes.length).toBe(1);
26
- expect(wrapper.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
27
- expect(wrapper.textContent).toBe("Text");
28
- });
29
- it("should patch text node to element", async () => {
30
- const container = document.createElement("div");
31
- let stateFn;
32
- const App = () => {
33
- const state = createState({ showText: true });
34
- stateFn = state;
35
- return () => jsx("div", {
36
- children: state.showText
37
- ? ["Text"]
38
- : [jsx("span", { children: ["Element"] })],
39
- });
40
- };
41
- render(jsx(App, {}), container);
42
- const wrapper = container.children[0];
43
- expect(wrapper.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
44
- stateFn.showText = false;
45
- await new Promise((resolve) => setTimeout(resolve, 0));
46
- expect(wrapper.children.length).toBe(1);
47
- expect(wrapper.children[0].tagName).toBe("SPAN");
48
- });
49
- it("should patch text node with different text", async () => {
50
- const container = document.createElement("div");
51
- let stateFn;
52
- const App = () => {
53
- const state = createState({ text: "Old Text" });
54
- stateFn = state;
55
- return () => jsx("div", {
56
- children: [state.text],
57
- });
58
- };
59
- render(jsx(App, {}), container);
60
- const wrapper = container.children[0];
61
- expect(wrapper.textContent).toBe("Old Text");
62
- stateFn.text = "New Text";
63
- await new Promise((resolve) => setTimeout(resolve, 0));
64
- expect(wrapper.textContent).toBe("New Text");
65
- expect(wrapper.childNodes.length).toBe(1);
66
- expect(wrapper.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
67
- });
68
- it("should patch multiple text nodes", async () => {
69
- const container = document.createElement("div");
70
- let stateFn;
71
- const App = () => {
72
- const state = createState({ texts: ["First", "Second"] });
73
- stateFn = state;
74
- return () => jsx("div", {
75
- children: state.texts,
76
- });
77
- };
78
- render(jsx(App, {}), container);
79
- const wrapper = container.children[0];
80
- expect(wrapper.childNodes.length).toBe(2);
81
- stateFn.texts = ["Updated", "Text", "Nodes"];
82
- await new Promise((resolve) => setTimeout(resolve, 0));
83
- expect(wrapper.childNodes.length).toBe(3);
84
- expect(wrapper.childNodes[0].textContent).toBe("Updated");
85
- expect(wrapper.childNodes[1].textContent).toBe("Text");
86
- expect(wrapper.childNodes[2].textContent).toBe("Nodes");
87
- });
88
- });
89
- describe("Mixed Content Patching", () => {
90
- it("should patch mixed elements and text nodes", async () => {
91
- const container = document.createElement("div");
92
- let stateFn;
93
- const App = () => {
94
- const state = createState({ version: 1 });
95
- stateFn = state;
96
- return () => jsx("div", {
97
- children: state.version === 1
98
- ? ["Text", jsx("span", { children: ["Span"] }), "More text"]
99
- : [
100
- jsx("div", { children: ["Div"] }),
101
- "Middle",
102
- jsx("button", { children: ["Button"] }),
103
- ],
104
- });
105
- };
106
- render(jsx(App, {}), container);
107
- const wrapper = container.children[0];
108
- expect(wrapper.childNodes.length).toBe(3);
109
- stateFn.version = 2;
110
- await new Promise((resolve) => setTimeout(resolve, 0));
111
- expect(wrapper.childNodes.length).toBe(3);
112
- expect(wrapper.childNodes[0].tagName).toBe("DIV");
113
- expect(wrapper.childNodes[1].nodeType).toBe(Node.TEXT_NODE);
114
- expect(wrapper.childNodes[1].textContent).toBe("Middle");
115
- expect(wrapper.childNodes[2].tagName).toBe("BUTTON");
116
- });
117
- it("should patch from all text to all elements", async () => {
118
- const container = document.createElement("div");
119
- let stateFn;
120
- const App = () => {
121
- const state = createState({ showElements: false });
122
- stateFn = state;
123
- return () => jsx("div", {
124
- children: state.showElements
125
- ? [
126
- jsx("span", { children: ["A"] }),
127
- jsx("span", { children: ["B"] }),
128
- jsx("span", { children: ["C"] }),
129
- ]
130
- : ["One", "Two", "Three"],
131
- });
132
- };
133
- render(jsx(App, {}), container);
134
- const wrapper = container.children[0];
135
- expect(wrapper.childNodes.length).toBe(3);
136
- expect(wrapper.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
137
- stateFn.showElements = true;
138
- await new Promise((resolve) => setTimeout(resolve, 0));
139
- expect(wrapper.children.length).toBe(3);
140
- expect(wrapper.children[0].tagName).toBe("SPAN");
141
- expect(wrapper.children[1].tagName).toBe("SPAN");
142
- expect(wrapper.children[2].tagName).toBe("SPAN");
143
- });
144
- it("should patch from all elements to all text", async () => {
145
- const container = document.createElement("div");
146
- let stateFn;
147
- const App = () => {
148
- const state = createState({ showElements: true });
149
- stateFn = state;
150
- return () => jsx("div", {
151
- children: state.showElements
152
- ? [
153
- jsx("span", { children: ["A"] }),
154
- jsx("span", { children: ["B"] }),
155
- jsx("span", { children: ["C"] }),
156
- ]
157
- : ["One", "Two", "Three"],
158
- });
159
- };
160
- render(jsx(App, {}), container);
161
- const wrapper = container.children[0];
162
- expect(wrapper.children.length).toBe(3);
163
- stateFn.showElements = false;
164
- await new Promise((resolve) => setTimeout(resolve, 0));
165
- expect(wrapper.childNodes.length).toBe(3);
166
- expect(wrapper.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
167
- expect(wrapper.childNodes[1].nodeType).toBe(Node.TEXT_NODE);
168
- expect(wrapper.childNodes[2].nodeType).toBe(Node.TEXT_NODE);
169
- });
170
- });
171
- describe("Fragment Edge Cases", () => {
172
- it("should patch fragment with text nodes", async () => {
173
- const container = document.createElement("div");
174
- let stateFn;
175
- const App = () => {
176
- const state = createState({ showElement: true });
177
- stateFn = state;
178
- return () => jsx(Fragment, {
179
- children: state.showElement
180
- ? [jsx("span", { children: ["Element"] })]
181
- : ["Text 1", "Text 2"],
182
- });
183
- };
184
- render(jsx(App, {}), container);
185
- expect(container.children.length).toBe(1);
186
- expect(container.children[0].tagName).toBe("SPAN");
187
- stateFn.showElement = false;
188
- await new Promise((resolve) => setTimeout(resolve, 0));
189
- expect(container.childNodes.length).toBe(2);
190
- expect(container.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
191
- expect(container.childNodes[0].textContent).toBe("Text 1");
192
- expect(container.childNodes[1].nodeType).toBe(Node.TEXT_NODE);
193
- expect(container.childNodes[1].textContent).toBe("Text 2");
194
- });
195
- it("should patch fragment with mixed content", async () => {
196
- const container = document.createElement("div");
197
- let stateFn;
198
- const App = () => {
199
- const state = createState({ showMixed: false });
200
- stateFn = state;
201
- return () => jsx(Fragment, {
202
- children: state.showMixed
203
- ? ["Text", jsx("div", { children: ["Element"] }), "More text"]
204
- : [jsx("span", { children: ["A"] })],
205
- });
206
- };
207
- render(jsx(App, {}), container);
208
- stateFn.showMixed = true;
209
- await new Promise((resolve) => setTimeout(resolve, 0));
210
- expect(container.childNodes.length).toBe(3);
211
- expect(container.childNodes[0].nodeType).toBe(Node.TEXT_NODE);
212
- expect(container.childNodes[0].textContent).toBe("Text");
213
- expect(container.childNodes[1].tagName).toBe("DIV");
214
- expect(container.childNodes[2].nodeType).toBe(Node.TEXT_NODE);
215
- expect(container.childNodes[2].textContent).toBe("More text");
216
- });
217
- it("should patch empty fragment to non-empty", async () => {
218
- const container = document.createElement("div");
219
- let stateFn;
220
- const App = () => {
221
- const state = createState({ isEmpty: true });
222
- stateFn = state;
223
- return () => jsx("div", {
224
- children: [
225
- jsx(Fragment, {
226
- children: state.isEmpty
227
- ? []
228
- : [
229
- jsx("span", { children: ["A"] }),
230
- jsx("span", { children: ["B"] }),
231
- ],
232
- }),
233
- ],
234
- });
235
- };
236
- render(jsx(App, {}), container);
237
- const wrapper = container.children[0];
238
- expect(wrapper.childNodes.length).toBe(0);
239
- stateFn.isEmpty = false;
240
- await new Promise((resolve) => setTimeout(resolve, 0));
241
- expect(wrapper.children.length).toBe(2);
242
- expect(wrapper.children[0].textContent).toBe("A");
243
- expect(wrapper.children[1].textContent).toBe("B");
244
- });
245
- it("should patch non-empty fragment to empty", async () => {
246
- const container = document.createElement("div");
247
- let stateFn;
248
- const App = () => {
249
- const state = createState({ isEmpty: false });
250
- stateFn = state;
251
- return () => jsx("div", {
252
- children: [
253
- jsx(Fragment, {
254
- children: state.isEmpty
255
- ? []
256
- : [
257
- jsx("span", { children: ["A"] }),
258
- jsx("span", { children: ["B"] }),
259
- ],
260
- }),
261
- ],
262
- });
263
- };
264
- render(jsx(App, {}), container);
265
- const wrapper = container.children[0];
266
- expect(wrapper.children.length).toBe(2);
267
- stateFn.isEmpty = true;
268
- await new Promise((resolve) => setTimeout(resolve, 0));
269
- expect(wrapper.childNodes.length).toBe(0);
270
- });
271
- });
272
- describe("Property Edge Cases", () => {
273
- it("should patch null attribute to string", async () => {
274
- const container = document.createElement("div");
275
- let stateFn;
276
- const App = () => {
277
- const state = createState({
278
- dataValue: null,
279
- });
280
- stateFn = state;
281
- return () => jsx("div", {
282
- "data-value": state.dataValue,
283
- });
284
- };
285
- render(jsx(App, {}), container);
286
- const div = container.children[0];
287
- expect(div.getAttribute("data-value")).toBeNull();
288
- stateFn.dataValue = "test";
289
- await new Promise((resolve) => setTimeout(resolve, 0));
290
- expect(div.getAttribute("data-value")).toBe("test");
291
- });
292
- it("should patch string attribute to null", async () => {
293
- const container = document.createElement("div");
294
- let stateFn;
295
- const App = () => {
296
- const state = createState({
297
- dataValue: "test",
298
- });
299
- stateFn = state;
300
- return () => jsx("div", {
301
- "data-value": state.dataValue,
302
- });
303
- };
304
- render(jsx(App, {}), container);
305
- const div = container.children[0];
306
- expect(div.getAttribute("data-value")).toBe("test");
307
- stateFn.dataValue = null;
308
- await new Promise((resolve) => setTimeout(resolve, 0));
309
- expect(div.getAttribute("data-value")).toBeNull();
310
- });
311
- it("should remove event listener when patching to null", async () => {
312
- const container = document.createElement("div");
313
- let stateFn;
314
- const handler = vi.fn();
315
- const App = () => {
316
- const state = createState({
317
- doClick: true,
318
- });
319
- stateFn = state;
320
- return () => jsx("button", {
321
- onClick: state.doClick ? handler : null,
322
- });
323
- };
324
- render(jsx(App, {}), container);
325
- const button = container.children[0];
326
- button.click();
327
- expect(handler).toHaveBeenCalledTimes(1);
328
- stateFn.doClick = false;
329
- await new Promise((resolve) => setTimeout(resolve, 0));
330
- button.click();
331
- // Should still be 1, not 2
332
- expect(handler).toHaveBeenCalledTimes(1);
333
- });
334
- it("should handle className changes", async () => {
335
- const container = document.createElement("div");
336
- let stateFn;
337
- const App = () => {
338
- const state = createState({ className: "old-class" });
339
- stateFn = state;
340
- return () => jsx("div", {
341
- className: state.className,
342
- });
343
- };
344
- render(jsx(App, {}), container);
345
- const div = container.children[0];
346
- expect(div.className).toBe("old-class");
347
- stateFn.className = "new-class another-class";
348
- await new Promise((resolve) => setTimeout(resolve, 0));
349
- expect(div.className).toBe("new-class another-class");
350
- });
351
- it("should handle style object changes", async () => {
352
- const container = document.createElement("div");
353
- let stateFn;
354
- const App = () => {
355
- const state = createState({
356
- style: { color: "red", fontSize: "16px" },
357
- });
358
- stateFn = state;
359
- return () => jsx("div", {
360
- style: state.style,
361
- });
362
- };
363
- render(jsx(App, {}), container);
364
- const div = container.children[0];
365
- expect(div.style.color).toBe("red");
366
- expect(div.style.fontSize).toBe("16px");
367
- stateFn.style = { color: "blue", fontWeight: "bold" };
368
- await new Promise((resolve) => setTimeout(resolve, 0));
369
- expect(div.style.color).toBe("blue");
370
- expect(div.style.fontWeight).toBe("bold");
371
- // fontSize should be removed or remain - depends on your implementation
372
- });
373
- });
374
- describe("Keys Edge Cases", () => {
375
- it("should handle keys with mixed text and elements", async () => {
376
- const container = document.createElement("div");
377
- let stateFn;
378
- const App = () => {
379
- const state = createState({ order: "initial" });
380
- stateFn = state;
381
- return () => jsx("div", {
382
- children: state.order === "initial"
383
- ? [
384
- "Text",
385
- jsx("span", { children: ["A"] }, "a"),
386
- jsx("span", { children: ["B"] }, "b"),
387
- ]
388
- : [
389
- jsx("span", { children: ["B"] }, "b"),
390
- "Text",
391
- jsx("span", { children: ["A"] }, "a"),
392
- ],
393
- });
394
- };
395
- render(jsx(App, {}), container);
396
- const wrapper = container.children[0];
397
- const initialSpanA = wrapper.children[0];
398
- const initialSpanB = wrapper.children[1];
399
- stateFn.order = "reordered";
400
- await new Promise((resolve) => setTimeout(resolve, 0));
401
- expect(wrapper.childNodes.length).toBe(3);
402
- expect(wrapper.children[0]).toBe(initialSpanB);
403
- expect(wrapper.children[1]).toBe(initialSpanA);
404
- });
405
- it("should handle duplicate keys gracefully", async () => {
406
- const container = document.createElement("div");
407
- let stateFn;
408
- const App = () => {
409
- const state = createState({ version: 1 });
410
- stateFn = state;
411
- return () => jsx("div", {
412
- children: state.version === 1
413
- ? [
414
- jsx("span", { children: ["A"] }, "key"),
415
- jsx("span", { children: ["B"] }, "key"), // duplicate key
416
- ]
417
- : [
418
- jsx("span", { children: ["C"] }, "key"),
419
- jsx("span", { children: ["D"] }, "other"),
420
- ],
421
- });
422
- };
423
- render(jsx(App, {}), container);
424
- const wrapper = container.children[0];
425
- expect(wrapper.children.length).toBe(2);
426
- stateFn.version = 2;
427
- await new Promise((resolve) => setTimeout(resolve, 0));
428
- // Should handle this without crashing
429
- expect(wrapper.children.length).toBe(2);
430
- });
431
- it("should handle numeric keys", async () => {
432
- const container = document.createElement("div");
433
- let stateFn;
434
- const App = () => {
435
- const state = createState({ reorder: false });
436
- stateFn = state;
437
- return () => jsx("div", {
438
- children: state.reorder
439
- ? [
440
- jsx("span", { children: ["2"] }, "2"),
441
- jsx("span", { children: ["0"] }, "0"),
442
- jsx("span", { children: ["1"] }, "1"),
443
- ]
444
- : [
445
- jsx("span", { children: ["0"] }, "0"),
446
- jsx("span", { children: ["1"] }, "1"),
447
- jsx("span", { children: ["2"] }, "2"),
448
- ],
449
- });
450
- };
451
- render(jsx(App, {}), container);
452
- const wrapper = container.children[0];
453
- const initialChildren = Array.from(wrapper.children);
454
- stateFn.reorder = true;
455
- await new Promise((resolve) => setTimeout(resolve, 0));
456
- const newChildren = Array.from(wrapper.children);
457
- expect(newChildren[0]).toBe(initialChildren[2]);
458
- expect(newChildren[1]).toBe(initialChildren[0]);
459
- expect(newChildren[2]).toBe(initialChildren[1]);
460
- });
461
- });
462
- describe("Empty and Null Cases", () => {
463
- it("should patch from children to no children", async () => {
464
- const container = document.createElement("div");
465
- let stateFn;
466
- const App = () => {
467
- const state = createState({ hasChildren: true });
468
- stateFn = state;
469
- return () => jsx("div", {
470
- children: state.hasChildren
471
- ? [
472
- jsx("span", { children: ["A"] }),
473
- jsx("span", { children: ["B"] }),
474
- ]
475
- : undefined,
476
- });
477
- };
478
- render(jsx(App, {}), container);
479
- const wrapper = container.children[0];
480
- expect(wrapper.children.length).toBe(2);
481
- stateFn.hasChildren = false;
482
- await new Promise((resolve) => setTimeout(resolve, 0));
483
- expect(wrapper.childNodes.length).toBe(0);
484
- });
485
- it("should patch from no children to children", async () => {
486
- const container = document.createElement("div");
487
- let stateFn;
488
- const App = () => {
489
- const state = createState({ hasChildren: false });
490
- stateFn = state;
491
- return () => jsx("div", {
492
- children: state.hasChildren
493
- ? [
494
- jsx("span", { children: ["A"] }),
495
- jsx("span", { children: ["B"] }),
496
- ]
497
- : undefined,
498
- });
499
- };
500
- render(jsx(App, {}), container);
501
- const wrapper = container.children[0];
502
- expect(wrapper.childNodes.length).toBe(0);
503
- stateFn.hasChildren = true;
504
- await new Promise((resolve) => setTimeout(resolve, 0));
505
- expect(wrapper.children.length).toBe(2);
506
- });
507
- it("should handle null and undefined in children array", async () => {
508
- const container = document.createElement("div");
509
- let stateFn;
510
- const App = () => {
511
- const state = createState({ version: 1 });
512
- stateFn = state;
513
- return () => jsx("div", {
514
- children: state.version === 1
515
- ? [null, jsx("span", { children: ["A"] }), undefined]
516
- : [
517
- jsx("span", { children: ["B"] }),
518
- null,
519
- jsx("span", { children: ["C"] }),
520
- ],
521
- });
522
- };
523
- render(jsx(App, {}), container);
524
- const wrapper = container.children[0];
525
- expect(wrapper.children.length).toBe(1);
526
- expect(wrapper.children[0].textContent).toBe("A");
527
- stateFn.version = 2;
528
- await new Promise((resolve) => setTimeout(resolve, 0));
529
- expect(wrapper.children.length).toBe(2);
530
- expect(wrapper.children[0].textContent).toBe("B");
531
- expect(wrapper.children[1].textContent).toBe("C");
532
- });
533
- });
534
- describe("Deeply Nested Patching", () => {
535
- it("should patch deeply nested structure with tag changes", async () => {
536
- const container = document.createElement("div");
537
- let stateFn;
538
- const App = () => {
539
- const state = createState({ version: 1 });
540
- stateFn = state;
541
- return () => jsx("div", {
542
- children: [
543
- jsx("section", {
544
- children: [
545
- jsx("article", {
546
- children: state.version === 1
547
- ? [
548
- jsx("p", {
549
- children: [
550
- jsx("span", { children: ["Deep text"] }),
551
- ],
552
- }),
553
- ]
554
- : [
555
- jsx("div", {
556
- children: [
557
- jsx("strong", { children: ["Updated text"] }),
558
- ],
559
- }),
560
- ],
561
- }),
562
- ],
563
- }),
564
- ],
565
- });
566
- };
567
- render(jsx(App, {}), container);
568
- stateFn.version = 2;
569
- await new Promise((resolve) => setTimeout(resolve, 0));
570
- const wrapper = container.children[0];
571
- const section = wrapper.children[0];
572
- const article = section.children[0];
573
- const div = article.children[0];
574
- expect(div.tagName).toBe("DIV");
575
- expect(div.children[0].tagName).toBe("STRONG");
576
- expect(div.children[0].textContent).toBe("Updated text");
577
- });
578
- it("should patch with alternating fragments and elements", async () => {
579
- const container = document.createElement("div");
580
- let stateFn;
581
- const App = () => {
582
- const state = createState({ version: 1 });
583
- stateFn = state;
584
- return () => jsx("div", {
585
- children: [
586
- jsx(Fragment, {
587
- children: [
588
- jsx("span", {
589
- children: [
590
- jsx(Fragment, {
591
- children: state.version === 1
592
- ? [jsx("em", { children: ["Nested"] })]
593
- : [
594
- jsx("em", { children: ["Updated"] }),
595
- jsx("strong", { children: ["Added"] }),
596
- ],
597
- }),
598
- ],
599
- }),
600
- ],
601
- }),
602
- ],
603
- });
604
- };
605
- render(jsx(App, {}), container);
606
- stateFn.version = 2;
607
- await new Promise((resolve) => setTimeout(resolve, 0));
608
- const wrapper = container.children[0];
609
- const span = wrapper.children[0];
610
- expect(span.children.length).toBe(2);
611
- expect(span.children[0].tagName).toBe("EM");
612
- expect(span.children[0].textContent).toBe("Updated");
613
- expect(span.children[1].tagName).toBe("STRONG");
614
- expect(span.children[1].textContent).toBe("Added");
615
- });
616
- });
617
- describe("Same Node Patching", () => {
618
- it("should handle patching node with itself", async () => {
619
- const container = document.createElement("div");
620
- let stateFn;
621
- const App = () => {
622
- const state = createState({ counter: 0 });
623
- stateFn = state;
624
- return () => jsx("div", {
625
- children: [jsx("span", { children: ["Text"] })],
626
- });
627
- };
628
- render(jsx(App, {}), container);
629
- const wrapper = container.children[0];
630
- const initialContent = wrapper.innerHTML;
631
- // Trigger re-render - should be a no-op since nothing changed
632
- stateFn.counter = 1;
633
- await new Promise((resolve) => setTimeout(resolve, 0));
634
- expect(wrapper.innerHTML).toBe(initialContent);
635
- });
636
- });
637
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=error-no-boundary.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"error-no-boundary.test.d.ts","sourceRoot":"","sources":["../../src/tests/error-no-boundary.test.ts"],"names":[],"mappings":""}