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,293 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { jsx, render } from "./index";
3
+ import { createState } from "../createState";
4
+ const waitForUpdate = () => new Promise((resolve) => setTimeout(resolve, 10));
5
+ describe("VDOM Keys", () => {
6
+ it("should preserve elements when reordering with keys", async () => {
7
+ const container = document.createElement("div");
8
+ let stateFn;
9
+ const App = () => {
10
+ const state = createState({ order: ["a", "b", "c"] });
11
+ stateFn = state;
12
+ return () => jsx("ul", {
13
+ children: state.order.map((key) => jsx("li", { children: `Item ${key.toUpperCase()}` }, key)),
14
+ });
15
+ };
16
+ render(jsx(App, {}), container);
17
+ const ul = container.children[0];
18
+ const initialChildren = Array.from(ul.children);
19
+ // Store references to the original DOM elements
20
+ const itemA = initialChildren[0];
21
+ const itemB = initialChildren[1];
22
+ const itemC = initialChildren[2];
23
+ expect(itemA.textContent).toBe("Item A");
24
+ expect(itemB.textContent).toBe("Item B");
25
+ expect(itemC.textContent).toBe("Item C");
26
+ // Reorder to C, A, B
27
+ stateFn.order = ["c", "a", "b"];
28
+ await waitForUpdate();
29
+ const newChildren = Array.from(ul.children);
30
+ // Verify elements were reordered, not recreated
31
+ // The DOM elements should be the same instances, just moved
32
+ expect(newChildren[0]).toBe(itemC); // C is now first
33
+ expect(newChildren[1]).toBe(itemA); // A is now second
34
+ expect(newChildren[2]).toBe(itemB); // B is now third
35
+ expect(newChildren[0].textContent).toBe("Item C");
36
+ expect(newChildren[1].textContent).toBe("Item A");
37
+ expect(newChildren[2].textContent).toBe("Item B");
38
+ });
39
+ it("should not preserve elements when reordering without keys", async () => {
40
+ const container = document.createElement("div");
41
+ let stateFn;
42
+ const App = () => {
43
+ const state = createState({ items: ["Item A", "Item B", "Item C"] });
44
+ stateFn = state;
45
+ return () => jsx("ul", {
46
+ children: state.items.map((text) => jsx("li", { children: text })),
47
+ });
48
+ };
49
+ render(jsx(App, {}), container);
50
+ const ul = container.children[0];
51
+ const initialChildren = Array.from(ul.children);
52
+ // Store references to the original DOM elements
53
+ const itemA = initialChildren[0];
54
+ const itemB = initialChildren[1];
55
+ const itemC = initialChildren[2];
56
+ // Reorder to C, A, B
57
+ stateFn.items = ["Item C", "Item A", "Item B"];
58
+ await waitForUpdate();
59
+ const newChildren = Array.from(ul.children);
60
+ // Without keys, the DOM elements are reused in place and just updated
61
+ // So the DOM nodes remain the same, but their content is changed
62
+ expect(newChildren[0]).toBe(itemA); // Same DOM node, but content changed to "Item C"
63
+ expect(newChildren[1]).toBe(itemB); // Same DOM node, but content changed to "Item A"
64
+ expect(newChildren[2]).toBe(itemC); // Same DOM node, but content changed to "Item B"
65
+ expect(newChildren[0].textContent).toBe("Item C");
66
+ expect(newChildren[1].textContent).toBe("Item A");
67
+ expect(newChildren[2].textContent).toBe("Item B");
68
+ });
69
+ it("should preserve element state when reordering with keys", async () => {
70
+ const container = document.createElement("div");
71
+ let stateFn;
72
+ const App = () => {
73
+ const state = createState({
74
+ order: ["first", "second", "third"],
75
+ values: { first: "First", second: "Second", third: "Third" },
76
+ });
77
+ stateFn = state;
78
+ return () => jsx("div", {
79
+ children: state.order.map((key) => jsx("input", { value: state.values[key] }, key)),
80
+ });
81
+ };
82
+ render(jsx(App, {}), container);
83
+ const div = container.children[0];
84
+ const initialInputs = Array.from(div.children);
85
+ // User "types" in the inputs (simulating user interaction)
86
+ initialInputs[0].value = "Modified First";
87
+ initialInputs[1].value = "Modified Second";
88
+ initialInputs[2].value = "Modified Third";
89
+ // Store references
90
+ const input1 = initialInputs[0];
91
+ const input2 = initialInputs[1];
92
+ const input3 = initialInputs[2];
93
+ // Reorder to third, first, second
94
+ stateFn.order = ["third", "first", "second"];
95
+ await waitForUpdate();
96
+ const newInputs = Array.from(div.children);
97
+ // Verify elements were moved (not recreated) so user modifications are preserved
98
+ expect(newInputs[0]).toBe(input3);
99
+ expect(newInputs[1]).toBe(input1);
100
+ expect(newInputs[2]).toBe(input2);
101
+ // The user's modifications should be preserved because the DOM elements were moved
102
+ expect(newInputs[0].value).toBe("Modified Third");
103
+ expect(newInputs[1].value).toBe("Modified First");
104
+ expect(newInputs[2].value).toBe("Modified Second");
105
+ });
106
+ it("should handle adding new items with keys", async () => {
107
+ const container = document.createElement("div");
108
+ let stateFn;
109
+ const App = () => {
110
+ const state = createState({ items: ["a", "b"] });
111
+ stateFn = state;
112
+ return () => jsx("ul", {
113
+ children: state.items.map((key) => jsx("li", { children: `Item ${key.toUpperCase()}` }, key)),
114
+ });
115
+ };
116
+ render(jsx(App, {}), container);
117
+ const ul = container.children[0];
118
+ const initialChildren = Array.from(ul.children);
119
+ expect(ul.children.length).toBe(2);
120
+ // Store references
121
+ const itemA = initialChildren[0];
122
+ const itemB = initialChildren[1];
123
+ // Add a new item in the middle
124
+ stateFn.items = ["a", "c", "b"];
125
+ await waitForUpdate();
126
+ const newChildren = Array.from(ul.children);
127
+ expect(ul.children.length).toBe(3);
128
+ // Original elements should be preserved
129
+ expect(newChildren[0]).toBe(itemA);
130
+ expect(newChildren[2]).toBe(itemB);
131
+ // New element in the middle
132
+ expect(newChildren[1]).not.toBe(itemA);
133
+ expect(newChildren[1]).not.toBe(itemB);
134
+ expect(newChildren[1].textContent).toBe("Item C");
135
+ });
136
+ it("should handle removing items with keys", async () => {
137
+ const container = document.createElement("div");
138
+ let stateFn;
139
+ const App = () => {
140
+ const state = createState({ items: ["a", "b", "c"] });
141
+ stateFn = state;
142
+ return () => jsx("ul", {
143
+ children: state.items.map((key) => jsx("li", { children: `Item ${key.toUpperCase()}` }, key)),
144
+ });
145
+ };
146
+ render(jsx(App, {}), container);
147
+ const ul = container.children[0];
148
+ const initialChildren = Array.from(ul.children);
149
+ expect(ul.children.length).toBe(3);
150
+ // Store references
151
+ const itemA = initialChildren[0];
152
+ const itemC = initialChildren[2];
153
+ // Remove the middle item
154
+ stateFn.items = ["a", "c"];
155
+ await waitForUpdate();
156
+ const newChildren = Array.from(ul.children);
157
+ expect(ul.children.length).toBe(2);
158
+ // Remaining elements should be preserved
159
+ expect(newChildren[0]).toBe(itemA);
160
+ expect(newChildren[1]).toBe(itemC);
161
+ });
162
+ it("should handle replacing all items with different keys", async () => {
163
+ const container = document.createElement("div");
164
+ let stateFn;
165
+ const App = () => {
166
+ const state = createState({ items: ["a", "b", "c"] });
167
+ stateFn = state;
168
+ return () => jsx("ul", {
169
+ children: state.items.map((key) => jsx("li", { children: `Item ${key.toUpperCase()}` }, key)),
170
+ });
171
+ };
172
+ render(jsx(App, {}), container);
173
+ const ul = container.children[0];
174
+ const initialChildren = Array.from(ul.children);
175
+ // Store references
176
+ const itemA = initialChildren[0];
177
+ const itemB = initialChildren[1];
178
+ const itemC = initialChildren[2];
179
+ // Replace all items with new keys
180
+ stateFn.items = ["x", "y", "z"];
181
+ await waitForUpdate();
182
+ const newChildren = Array.from(ul.children);
183
+ expect(ul.children.length).toBe(3);
184
+ // All elements should be new instances
185
+ expect(newChildren[0]).not.toBe(itemA);
186
+ expect(newChildren[1]).not.toBe(itemB);
187
+ expect(newChildren[2]).not.toBe(itemC);
188
+ expect(newChildren[0].textContent).toBe("Item X");
189
+ expect(newChildren[1].textContent).toBe("Item Y");
190
+ expect(newChildren[2].textContent).toBe("Item Z");
191
+ });
192
+ it("should handle complex reordering scenario with keys", async () => {
193
+ const container = document.createElement("div");
194
+ let stateFn;
195
+ const App = () => {
196
+ const state = createState({ items: ["a", "b", "c", "d", "e"] });
197
+ stateFn = state;
198
+ return () => jsx("ul", {
199
+ children: state.items.map((key) => jsx("li", { children: key.toUpperCase() }, key)),
200
+ });
201
+ };
202
+ render(jsx(App, {}), container);
203
+ const ul = container.children[0];
204
+ const initialChildren = Array.from(ul.children);
205
+ const [itemA, itemB, itemC, itemD, itemE] = initialChildren;
206
+ // Complex reorder: remove C, add F, reorder to [E, A, F, D, B]
207
+ stateFn.items = ["e", "a", "f", "d", "b"];
208
+ await waitForUpdate();
209
+ const newChildren = Array.from(ul.children);
210
+ expect(ul.children.length).toBe(5);
211
+ // Verify preserved elements are in correct positions
212
+ expect(newChildren[0]).toBe(itemE);
213
+ expect(newChildren[1]).toBe(itemA);
214
+ expect(newChildren[3]).toBe(itemD);
215
+ expect(newChildren[4]).toBe(itemB);
216
+ // F is new
217
+ expect(newChildren[2]).not.toBe(itemA);
218
+ expect(newChildren[2]).not.toBe(itemB);
219
+ expect(newChildren[2]).not.toBe(itemC);
220
+ expect(newChildren[2]).not.toBe(itemD);
221
+ expect(newChildren[2]).not.toBe(itemE);
222
+ expect(newChildren[2].textContent).toBe("F");
223
+ // C should not be in the list
224
+ expect(newChildren.includes(itemC)).toBe(false);
225
+ });
226
+ it("should handle nested elements with keys", async () => {
227
+ const container = document.createElement("div");
228
+ let stateFn;
229
+ const App = () => {
230
+ const state = createState({ order: ["section1", "section2"] });
231
+ stateFn = state;
232
+ return () => jsx("div", {
233
+ children: state.order.map((key) => {
234
+ const num = key === "section1" ? "1" : "2";
235
+ return jsx("section", {
236
+ children: [
237
+ jsx("h2", { children: `Section ${num}` }),
238
+ jsx("p", { children: `Content ${num}` }),
239
+ ],
240
+ }, key);
241
+ }),
242
+ });
243
+ };
244
+ render(jsx(App, {}), container);
245
+ const div = container.children[0];
246
+ const initialSections = Array.from(div.children);
247
+ const section1 = initialSections[0];
248
+ const section2 = initialSections[1];
249
+ // Reorder sections
250
+ stateFn.order = ["section2", "section1"];
251
+ await waitForUpdate();
252
+ const newSections = Array.from(div.children);
253
+ // Verify sections were moved, not recreated
254
+ expect(newSections[0]).toBe(section2);
255
+ expect(newSections[1]).toBe(section1);
256
+ expect(newSections[0].children[0].textContent).toBe("Section 2");
257
+ expect(newSections[1].children[0].textContent).toBe("Section 1");
258
+ });
259
+ it("should handle mixed keys and non-keyed elements", async () => {
260
+ const container = document.createElement("div");
261
+ let stateFn;
262
+ const App = () => {
263
+ const state = createState({
264
+ items: [
265
+ { key: "a", text: "Item A" },
266
+ { text: "Item B" },
267
+ { key: "c", text: "Item C" },
268
+ ],
269
+ });
270
+ stateFn = state;
271
+ return () => jsx("ul", {
272
+ children: state.items.map((item) => jsx("li", { children: item.text }, item.key)),
273
+ });
274
+ };
275
+ render(jsx(App, {}), container);
276
+ const ul = container.children[0];
277
+ expect(ul.children.length).toBe(3);
278
+ expect(ul.children[0].textContent).toBe("Item A");
279
+ expect(ul.children[1].textContent).toBe("Item B");
280
+ expect(ul.children[2].textContent).toBe("Item C");
281
+ // Reorder with mixed keys
282
+ stateFn.items = [
283
+ { key: "c", text: "Item C" },
284
+ { text: "Item B Modified" },
285
+ { key: "a", text: "Item A" },
286
+ ];
287
+ await waitForUpdate();
288
+ expect(ul.children.length).toBe(3);
289
+ expect(ul.children[0].textContent).toBe("Item C");
290
+ expect(ul.children[1].textContent).toBe("Item B Modified");
291
+ expect(ul.children[2].textContent).toBe("Item A");
292
+ });
293
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mount.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.test.d.ts","sourceRoot":"","sources":["../../src/vdom/mount.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,91 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { jsx, render } from "./index";
3
+ describe("VDOM Mount", () => {
4
+ it("should render a single element to the DOM", () => {
5
+ // Create a container element
6
+ const container = document.createElement("div");
7
+ // Create a vnode using jsx
8
+ const vnode = jsx("div", { id: "test" });
9
+ // Render the vnode to the container
10
+ render(vnode, container);
11
+ // Assert that the element was created and appended
12
+ expect(container.children.length).toBe(1);
13
+ expect(container.children[0].tagName).toBe("DIV");
14
+ });
15
+ it("should render an element with multiple children", () => {
16
+ // Create a container element
17
+ const container = document.createElement("div");
18
+ // Create child vnodes
19
+ const child1 = jsx("span", { id: "child1" });
20
+ const child2 = jsx("span", { id: "child2" });
21
+ const child3 = jsx("div", { id: "child3" });
22
+ // Create parent vnode with children
23
+ const parentVNode = jsx("div", {
24
+ id: "parent",
25
+ children: [child1, child2, child3],
26
+ });
27
+ // Render the parent vnode
28
+ render(parentVNode, container);
29
+ // Verify parent was rendered
30
+ expect(container.children.length).toBe(1);
31
+ expect(container.children[0].tagName).toBe("DIV");
32
+ // Verify children were rendered
33
+ const parent = container.children[0];
34
+ expect(parent.children.length).toBe(3);
35
+ expect(parent.children[0].tagName).toBe("SPAN");
36
+ expect(parent.children[1].tagName).toBe("SPAN");
37
+ expect(parent.children[2].tagName).toBe("DIV");
38
+ });
39
+ it("should render element with data and aria attributes", () => {
40
+ // Create a container element
41
+ const container = document.createElement("div");
42
+ // Create vnode with data and aria attributes
43
+ const vnode = jsx("div", {
44
+ "data-testid": "test-component",
45
+ "data-value": "123",
46
+ "aria-label": "Test element",
47
+ "aria-hidden": "true",
48
+ });
49
+ // Render the vnode
50
+ render(vnode, container);
51
+ // Verify attributes were set
52
+ const div = container.children[0];
53
+ expect(div.getAttribute("data-testid")).toBe("test-component");
54
+ expect(div.getAttribute("data-value")).toBe("123");
55
+ expect(div.getAttribute("aria-label")).toBe("Test element");
56
+ expect(div.getAttribute("aria-hidden")).toBe("true");
57
+ });
58
+ it("should render element with properties", () => {
59
+ // Create a container element
60
+ const container = document.createElement("div");
61
+ // Create vnode with properties
62
+ const vnode = jsx("div", {
63
+ className: "test-class",
64
+ textContent: "Hello World",
65
+ });
66
+ // Render the vnode
67
+ render(vnode, container);
68
+ // Verify properties were set
69
+ const div = container.children[0];
70
+ expect(div.className).toBe("test-class");
71
+ expect(div.textContent).toBe("Hello World");
72
+ });
73
+ it("should render element with event listener", () => {
74
+ // Create a container element
75
+ const container = document.createElement("div");
76
+ // Create mock click handler
77
+ const handleClick = vi.fn();
78
+ // Create vnode with event listener
79
+ const vnode = jsx("button", {
80
+ onClick: handleClick,
81
+ });
82
+ // Render the vnode
83
+ render(vnode, container);
84
+ // Get the button element
85
+ const button = container.children[0];
86
+ // Trigger click event
87
+ button.click();
88
+ // Verify event handler was called
89
+ expect(handleClick).toHaveBeenCalledTimes(1);
90
+ });
91
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=patch.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.test.d.ts","sourceRoot":"","sources":["../../src/vdom/patch.test.tsx"],"names":[],"mappings":""}