rask-ui 0.1.1 → 0.2.1
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/README.md +923 -185
- package/dist/component.d.ts +17 -0
- package/dist/component.d.ts.map +1 -1
- package/dist/createAsync.d.ts +23 -0
- package/dist/createAsync.d.ts.map +1 -1
- package/dist/createAsync.js +23 -0
- package/dist/createContext.d.ts +26 -2
- package/dist/createContext.d.ts.map +1 -1
- package/dist/createContext.js +31 -5
- package/dist/createContext.test.d.ts +2 -0
- package/dist/createContext.test.d.ts.map +1 -0
- package/dist/createContext.test.js +136 -0
- package/dist/createMutation.d.ts +23 -0
- package/dist/createMutation.d.ts.map +1 -1
- package/dist/createMutation.js +23 -0
- package/dist/createQuery.d.ts +23 -0
- package/dist/createQuery.d.ts.map +1 -1
- package/dist/createQuery.js +23 -0
- package/dist/createRef.test.d.ts +2 -0
- package/dist/createRef.test.d.ts.map +1 -0
- package/dist/createRef.test.js +80 -0
- package/dist/createState.d.ts +24 -0
- package/dist/createState.d.ts.map +1 -1
- package/dist/createState.js +24 -0
- package/dist/createView.d.ts +54 -0
- package/dist/createView.d.ts.map +1 -0
- package/dist/createView.js +68 -0
- package/dist/createView.test.d.ts +2 -0
- package/dist/createView.test.d.ts.map +1 -0
- package/dist/createView.test.js +203 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +4 -5
- package/dist/error.test.d.ts +2 -0
- package/dist/error.test.d.ts.map +1 -0
- package/dist/error.test.js +144 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/integration.test.d.ts +2 -0
- package/dist/integration.test.d.ts.map +1 -0
- package/dist/integration.test.js +155 -0
- package/dist/jsx-dev-runtime.d.ts +3 -3
- package/dist/jsx-dev-runtime.d.ts.map +1 -1
- package/dist/jsx-dev-runtime.js +2 -2
- package/dist/jsx-runtime.d.ts +1 -4
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx-runtime.js +3 -14
- package/dist/observation.d.ts +1 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +5 -0
- package/dist/test-setup.d.ts +3 -3
- package/dist/test-setup.d.ts.map +1 -1
- package/dist/test-setup.js +7 -8
- package/dist/tests/class.test.d.ts +2 -0
- package/dist/tests/class.test.d.ts.map +1 -0
- package/dist/tests/class.test.js +185 -0
- package/dist/tests/complex-rendering.test.d.ts +2 -0
- package/dist/tests/complex-rendering.test.d.ts.map +1 -0
- package/dist/tests/complex-rendering.test.js +400 -0
- package/dist/tests/component.cleanup.test.d.ts +2 -0
- package/dist/tests/component.cleanup.test.d.ts.map +1 -0
- package/dist/tests/component.cleanup.test.js +325 -0
- package/dist/tests/component.counter.test.d.ts +2 -0
- package/dist/tests/component.counter.test.d.ts.map +1 -0
- package/dist/tests/component.counter.test.js +124 -0
- package/dist/tests/component.interaction.test.d.ts +2 -0
- package/dist/tests/component.interaction.test.d.ts.map +1 -0
- package/dist/tests/component.interaction.test.js +73 -0
- package/dist/tests/component.props.test.d.ts +2 -0
- package/dist/tests/component.props.test.d.ts.map +1 -0
- package/dist/tests/component.props.test.js +334 -0
- package/dist/tests/component.return-types.test.d.ts +2 -0
- package/dist/tests/component.return-types.test.d.ts.map +1 -0
- package/dist/tests/component.return-types.test.js +357 -0
- package/dist/tests/component.state.test.d.ts +2 -0
- package/dist/tests/component.state.test.d.ts.map +1 -0
- package/dist/tests/component.state.test.js +135 -0
- package/dist/tests/component.test.d.ts +2 -0
- package/dist/tests/component.test.d.ts.map +1 -0
- package/dist/tests/component.test.js +63 -0
- package/dist/tests/createAsync.test.d.ts +2 -0
- package/dist/tests/createAsync.test.d.ts.map +1 -0
- package/dist/tests/createAsync.test.js +110 -0
- package/dist/tests/createContext.test.d.ts +2 -0
- package/dist/tests/createContext.test.d.ts.map +1 -0
- package/dist/tests/createContext.test.js +141 -0
- package/dist/tests/createMutation.test.d.ts +2 -0
- package/dist/tests/createMutation.test.d.ts.map +1 -0
- package/dist/tests/createMutation.test.js +168 -0
- package/dist/tests/createQuery.test.d.ts +2 -0
- package/dist/tests/createQuery.test.d.ts.map +1 -0
- package/dist/tests/createQuery.test.js +156 -0
- package/dist/tests/createRef.test.d.ts +2 -0
- package/dist/tests/createRef.test.d.ts.map +1 -0
- package/dist/tests/createRef.test.js +84 -0
- package/dist/tests/createState.test.d.ts +2 -0
- package/dist/tests/createState.test.d.ts.map +1 -0
- package/dist/tests/createState.test.js +103 -0
- package/dist/tests/createView.test.d.ts +2 -0
- package/dist/tests/createView.test.d.ts.map +1 -0
- package/dist/tests/createView.test.js +203 -0
- package/dist/tests/edge-cases.test.d.ts +2 -0
- package/dist/tests/edge-cases.test.d.ts.map +1 -0
- package/dist/tests/edge-cases.test.js +637 -0
- package/dist/tests/error-no-boundary.test.d.ts +2 -0
- package/dist/tests/error-no-boundary.test.d.ts.map +1 -0
- package/dist/tests/error-no-boundary.test.js +174 -0
- package/dist/tests/error.test.d.ts +2 -0
- package/dist/tests/error.test.d.ts.map +1 -0
- package/dist/tests/error.test.js +199 -0
- package/dist/tests/fragment.test.d.ts +2 -0
- package/dist/tests/fragment.test.d.ts.map +1 -0
- package/dist/tests/fragment.test.js +618 -0
- package/dist/tests/integration.test.d.ts +2 -0
- package/dist/tests/integration.test.d.ts.map +1 -0
- package/dist/tests/integration.test.js +192 -0
- package/dist/tests/keys.test.d.ts +2 -0
- package/dist/tests/keys.test.d.ts.map +1 -0
- package/dist/tests/keys.test.js +293 -0
- package/dist/tests/mount.test.d.ts +2 -0
- package/dist/tests/mount.test.d.ts.map +1 -0
- package/dist/tests/mount.test.js +91 -0
- package/dist/tests/observation.test.d.ts +2 -0
- package/dist/tests/observation.test.d.ts.map +1 -0
- package/dist/tests/observation.test.js +150 -0
- package/dist/tests/patch.test.d.ts +2 -0
- package/dist/tests/patch.test.d.ts.map +1 -0
- package/dist/tests/patch.test.js +498 -0
- package/dist/tests/patchChildren.test.d.ts +2 -0
- package/dist/tests/patchChildren.test.d.ts.map +1 -0
- package/dist/tests/patchChildren.test.js +387 -0
- package/dist/tests/primitives.test.d.ts +2 -0
- package/dist/tests/primitives.test.d.ts.map +1 -0
- package/dist/tests/primitives.test.js +132 -0
- package/dist/vdom/AbstractVNode.d.ts +22 -0
- package/dist/vdom/AbstractVNode.d.ts.map +1 -0
- package/dist/vdom/AbstractVNode.js +106 -0
- package/dist/vdom/ComponentVNode.d.ts +48 -0
- package/dist/vdom/ComponentVNode.d.ts.map +1 -0
- package/dist/vdom/ComponentVNode.js +209 -0
- package/dist/vdom/ElementVNode.d.ts +24 -0
- package/dist/vdom/ElementVNode.d.ts.map +1 -0
- package/dist/vdom/ElementVNode.js +126 -0
- package/dist/vdom/FragmentVNode.d.ts +13 -0
- package/dist/vdom/FragmentVNode.d.ts.map +1 -0
- package/dist/vdom/FragmentVNode.js +34 -0
- package/dist/vdom/RootVNode.d.ts +22 -0
- package/dist/vdom/RootVNode.d.ts.map +1 -0
- package/dist/vdom/RootVNode.js +55 -0
- package/dist/vdom/TextVNode.d.ts +11 -0
- package/dist/vdom/TextVNode.d.ts.map +1 -0
- package/dist/vdom/TextVNode.js +32 -0
- package/dist/vdom/class.test.d.ts +2 -0
- package/dist/vdom/class.test.d.ts.map +1 -0
- package/dist/vdom/class.test.js +143 -0
- package/dist/vdom/complex-rendering.test.d.ts +2 -0
- package/dist/vdom/complex-rendering.test.d.ts.map +1 -0
- package/dist/vdom/complex-rendering.test.js +400 -0
- package/dist/vdom/component.cleanup.test.d.ts +2 -0
- package/dist/vdom/component.cleanup.test.d.ts.map +1 -0
- package/dist/vdom/component.cleanup.test.js +323 -0
- package/dist/vdom/component.counter.test.d.ts +2 -0
- package/dist/vdom/component.counter.test.d.ts.map +1 -0
- package/dist/vdom/component.counter.test.js +124 -0
- package/dist/vdom/component.interaction.test.d.ts +2 -0
- package/dist/vdom/component.interaction.test.d.ts.map +1 -0
- package/dist/vdom/component.interaction.test.js +73 -0
- package/dist/vdom/component.props.test.d.ts +2 -0
- package/dist/vdom/component.props.test.d.ts.map +1 -0
- package/dist/vdom/component.props.test.js +88 -0
- package/dist/vdom/component.return-types.test.d.ts +2 -0
- package/dist/vdom/component.return-types.test.d.ts.map +1 -0
- package/dist/vdom/component.return-types.test.js +357 -0
- package/dist/vdom/component.state.test.d.ts +2 -0
- package/dist/vdom/component.state.test.d.ts.map +1 -0
- package/dist/vdom/component.state.test.js +129 -0
- package/dist/vdom/component.test.d.ts +2 -0
- package/dist/vdom/component.test.d.ts.map +1 -0
- package/dist/vdom/component.test.js +63 -0
- package/dist/vdom/dom-utils.d.ts +9 -0
- package/dist/vdom/dom-utils.d.ts.map +1 -0
- package/dist/vdom/dom-utils.js +84 -0
- package/dist/vdom/edge-cases.test.d.ts +2 -0
- package/dist/vdom/edge-cases.test.d.ts.map +1 -0
- package/dist/vdom/edge-cases.test.js +637 -0
- package/dist/vdom/fragment.test.d.ts +2 -0
- package/dist/vdom/fragment.test.d.ts.map +1 -0
- package/dist/vdom/fragment.test.js +618 -0
- package/dist/vdom/index.d.ts +10 -0
- package/dist/vdom/index.d.ts.map +1 -0
- package/dist/vdom/index.js +26 -0
- package/dist/vdom/keys.test.d.ts +2 -0
- package/dist/vdom/keys.test.d.ts.map +1 -0
- package/dist/vdom/keys.test.js +293 -0
- package/dist/vdom/mount.test.d.ts +2 -0
- package/dist/vdom/mount.test.d.ts.map +1 -0
- package/dist/vdom/mount.test.js +91 -0
- package/dist/vdom/patch.test.d.ts +2 -0
- package/dist/vdom/patch.test.d.ts.map +1 -0
- package/dist/vdom/patch.test.js +498 -0
- package/dist/vdom/patchChildren.test.d.ts +2 -0
- package/dist/vdom/patchChildren.test.d.ts.map +1 -0
- package/dist/vdom/patchChildren.test.js +392 -0
- package/dist/vdom/primitives.test.d.ts +2 -0
- package/dist/vdom/primitives.test.d.ts.map +1 -0
- package/dist/vdom/primitives.test.js +132 -0
- package/dist/vdom/types.d.ts +8 -0
- package/dist/vdom/types.d.ts.map +1 -0
- package/dist/vdom/types.js +1 -0
- package/dist/vdom/utils.d.ts +6 -0
- package/dist/vdom/utils.d.ts.map +1 -0
- package/dist/vdom/utils.js +63 -0
- package/package.json +4 -6
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { jsx, render } from "../vdom";
|
|
3
|
+
import { createState } from "../createState";
|
|
4
|
+
describe("Component Props", () => {
|
|
5
|
+
it("should pass string props to component", () => {
|
|
6
|
+
const container = document.createElement("div");
|
|
7
|
+
const MyComponent = (props) => {
|
|
8
|
+
return () => jsx("div", { children: props.message });
|
|
9
|
+
};
|
|
10
|
+
render(jsx(MyComponent, { message: "Hello Props" }), container);
|
|
11
|
+
expect(container.children[0].textContent).toBe("Hello Props");
|
|
12
|
+
});
|
|
13
|
+
it("should pass number props to component", () => {
|
|
14
|
+
const container = document.createElement("div");
|
|
15
|
+
const MyComponent = (props) => {
|
|
16
|
+
return () => jsx("div", { children: String(props.count) });
|
|
17
|
+
};
|
|
18
|
+
render(jsx(MyComponent, { count: 42 }), container);
|
|
19
|
+
expect(container.children[0].textContent).toBe("42");
|
|
20
|
+
});
|
|
21
|
+
it("should pass object props to component", () => {
|
|
22
|
+
const container = document.createElement("div");
|
|
23
|
+
const MyComponent = (props) => {
|
|
24
|
+
return () => jsx("div", {
|
|
25
|
+
children: `${props.user.name} is ${props.user.age}`,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
render(jsx(MyComponent, { user: { name: "Alice", age: 25 } }), container);
|
|
29
|
+
expect(container.children[0].textContent).toBe("Alice is 25");
|
|
30
|
+
});
|
|
31
|
+
it("should pass array props to component", () => {
|
|
32
|
+
const container = document.createElement("div");
|
|
33
|
+
const MyComponent = (props) => {
|
|
34
|
+
return () => jsx("ul", {
|
|
35
|
+
children: props.items.map((item) => jsx("li", { children: item })),
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
render(jsx(MyComponent, { items: ["apple", "banana", "cherry"] }), container);
|
|
39
|
+
const ul = container.children[0];
|
|
40
|
+
expect(ul.children).toHaveLength(3);
|
|
41
|
+
expect(ul.children[0].textContent).toBe("apple");
|
|
42
|
+
expect(ul.children[1].textContent).toBe("banana");
|
|
43
|
+
expect(ul.children[2].textContent).toBe("cherry");
|
|
44
|
+
});
|
|
45
|
+
it("should pass function props to component", () => {
|
|
46
|
+
const container = document.createElement("div");
|
|
47
|
+
const handleClick = () => "clicked";
|
|
48
|
+
const MyComponent = (props) => {
|
|
49
|
+
return () => jsx("button", {
|
|
50
|
+
children: props.onClick(),
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
render(jsx(MyComponent, { onClick: handleClick }), container);
|
|
54
|
+
expect(container.children[0].textContent).toBe("clicked");
|
|
55
|
+
});
|
|
56
|
+
it("should pass multiple props to component", () => {
|
|
57
|
+
const container = document.createElement("div");
|
|
58
|
+
const MyComponent = (props) => {
|
|
59
|
+
return () => jsx("div", {
|
|
60
|
+
children: `${props.title}: ${props.count} (${props.isActive ? "active" : "inactive"})`,
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
render(jsx(MyComponent, { title: "Counter", count: 5, isActive: true }), container);
|
|
64
|
+
expect(container.children[0].textContent).toBe("Counter: 5 (active)");
|
|
65
|
+
});
|
|
66
|
+
it("should handle optional props", () => {
|
|
67
|
+
const container1 = document.createElement("div");
|
|
68
|
+
const container2 = document.createElement("div");
|
|
69
|
+
const MyComponent = (props) => {
|
|
70
|
+
return () => jsx("div", {
|
|
71
|
+
children: props.message || "Default message",
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
render(jsx(MyComponent, {}), container1);
|
|
75
|
+
expect(container1.children[0].textContent).toBe("Default message");
|
|
76
|
+
render(jsx(MyComponent, { message: "Custom message" }), container2);
|
|
77
|
+
expect(container2.children[0].textContent).toBe("Custom message");
|
|
78
|
+
});
|
|
79
|
+
it("should pass props from parent to child component", () => {
|
|
80
|
+
const container = document.createElement("div");
|
|
81
|
+
const ChildComponent = (props) => {
|
|
82
|
+
return () => jsx("div", { children: props.message });
|
|
83
|
+
};
|
|
84
|
+
const ParentComponent = (props) => {
|
|
85
|
+
return () => jsx("div", {
|
|
86
|
+
children: jsx(ChildComponent, { message: props.text }),
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
render(jsx(ParentComponent, { text: "Hello from parent" }), container);
|
|
90
|
+
expect(container.children[0].children[0].textContent).toBe("Hello from parent");
|
|
91
|
+
});
|
|
92
|
+
it("should pass props through multiple levels of nesting", () => {
|
|
93
|
+
const container = document.createElement("div");
|
|
94
|
+
const GrandchildComponent = (props) => {
|
|
95
|
+
return () => jsx("span", { children: props.value });
|
|
96
|
+
};
|
|
97
|
+
const ChildComponent = (props) => {
|
|
98
|
+
return () => jsx("div", {
|
|
99
|
+
children: jsx(GrandchildComponent, { value: props.data }),
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
const ParentComponent = (props) => {
|
|
103
|
+
return () => jsx("div", {
|
|
104
|
+
children: jsx(ChildComponent, { data: props.info }),
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
render(jsx(ParentComponent, { info: "Deep nested value" }), container);
|
|
108
|
+
const span = container.querySelector("span");
|
|
109
|
+
expect(span?.textContent).toBe("Deep nested value");
|
|
110
|
+
});
|
|
111
|
+
it("should update nested component when parent props change", async () => {
|
|
112
|
+
const container = document.createElement("div");
|
|
113
|
+
const ChildComponent = (props) => {
|
|
114
|
+
return () => jsx("div", { children: String(props.count) });
|
|
115
|
+
};
|
|
116
|
+
const ParentComponent = () => {
|
|
117
|
+
const state = createState({ value: 5 });
|
|
118
|
+
return () => jsx("div", {
|
|
119
|
+
children: [
|
|
120
|
+
jsx(ChildComponent, { count: state.value }),
|
|
121
|
+
jsx("button", {
|
|
122
|
+
onclick: () => (state.value = 10),
|
|
123
|
+
children: "Update",
|
|
124
|
+
}),
|
|
125
|
+
],
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
render(jsx(ParentComponent, {}), container);
|
|
129
|
+
expect(container.children[0].children[0].textContent).toBe("5");
|
|
130
|
+
// Trigger update
|
|
131
|
+
container.querySelector("button").click();
|
|
132
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
133
|
+
expect(container.children[0].children[0].textContent).toBe("10");
|
|
134
|
+
});
|
|
135
|
+
it("should correctly update props in nested components with state changes", async () => {
|
|
136
|
+
const container = document.createElement("div");
|
|
137
|
+
const ChildComponent = (props) => {
|
|
138
|
+
return () => jsx("div", { children: `${props.message}: ${props.count}` });
|
|
139
|
+
};
|
|
140
|
+
const ParentComponent = () => {
|
|
141
|
+
const state = createState({ count: 0 });
|
|
142
|
+
return () => jsx("div", {
|
|
143
|
+
children: [
|
|
144
|
+
jsx(ChildComponent, { message: "Count", count: state.count }),
|
|
145
|
+
jsx("button", {
|
|
146
|
+
onclick: () => state.count++,
|
|
147
|
+
children: "Increment",
|
|
148
|
+
}),
|
|
149
|
+
],
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
render(jsx(ParentComponent, {}), container);
|
|
153
|
+
// Check initial state
|
|
154
|
+
const childDiv = container.querySelector(":scope > div > div");
|
|
155
|
+
expect(childDiv.textContent).toBe("Count: 0");
|
|
156
|
+
// Simulate button click
|
|
157
|
+
const button = container.querySelector("button");
|
|
158
|
+
button.click();
|
|
159
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
160
|
+
// Check updated state - THIS is where the bug would show
|
|
161
|
+
// If old props are used instead of new props, this will fail
|
|
162
|
+
expect(childDiv.textContent).toBe("Count: 1");
|
|
163
|
+
});
|
|
164
|
+
it("should pass updated object props to nested components", async () => {
|
|
165
|
+
const container = document.createElement("div");
|
|
166
|
+
const ChildComponent = (props) => {
|
|
167
|
+
return () => jsx("div", { children: `${props.user.name} - ${props.user.age}` });
|
|
168
|
+
};
|
|
169
|
+
const ParentComponent = () => {
|
|
170
|
+
const state = createState({
|
|
171
|
+
userData: { name: "Alice", age: 25 },
|
|
172
|
+
});
|
|
173
|
+
return () => jsx("div", {
|
|
174
|
+
children: [
|
|
175
|
+
jsx(ChildComponent, { user: state.userData }),
|
|
176
|
+
jsx("button", {
|
|
177
|
+
onclick: () => {
|
|
178
|
+
state.userData.name = "Bob";
|
|
179
|
+
state.userData.age = 30;
|
|
180
|
+
},
|
|
181
|
+
children: "Update",
|
|
182
|
+
}),
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
render(jsx(ParentComponent, {}), container);
|
|
187
|
+
expect(container.children[0].children[0].textContent).toBe("Alice - 25");
|
|
188
|
+
// Trigger update
|
|
189
|
+
container.querySelector("button").click();
|
|
190
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
191
|
+
expect(container.children[0].children[0].textContent).toBe("Bob - 30");
|
|
192
|
+
});
|
|
193
|
+
it("should correctly update props in deeply nested components on state change", async () => {
|
|
194
|
+
const container = document.createElement("div");
|
|
195
|
+
const DeepChild = (props) => {
|
|
196
|
+
return () => jsx("span", { children: String(props.value) });
|
|
197
|
+
};
|
|
198
|
+
const MiddleChild = (props) => {
|
|
199
|
+
return () => jsx("div", {
|
|
200
|
+
children: jsx(DeepChild, { value: props.data }),
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
const ParentComponent = () => {
|
|
204
|
+
const state = createState({ value: 100 });
|
|
205
|
+
return () => jsx("div", {
|
|
206
|
+
children: [
|
|
207
|
+
jsx(MiddleChild, { data: state.value }),
|
|
208
|
+
jsx("button", {
|
|
209
|
+
onclick: () => (state.value += 50),
|
|
210
|
+
children: "Update",
|
|
211
|
+
}),
|
|
212
|
+
],
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
render(jsx(ParentComponent, {}), container);
|
|
216
|
+
// Check initial state
|
|
217
|
+
const span = container.querySelector("span");
|
|
218
|
+
expect(span.textContent).toBe("100");
|
|
219
|
+
// Trigger update
|
|
220
|
+
const button = container.querySelector("button");
|
|
221
|
+
button.click();
|
|
222
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
223
|
+
// THIS is the critical test - ensures new props propagate correctly
|
|
224
|
+
expect(span.textContent).toBe("150");
|
|
225
|
+
});
|
|
226
|
+
it("should handle multiple nested components receiving different updated props", async () => {
|
|
227
|
+
const container = document.createElement("div");
|
|
228
|
+
const ChildA = (props) => {
|
|
229
|
+
return () => jsx("div", { class: "child-a", children: props.value });
|
|
230
|
+
};
|
|
231
|
+
const ChildB = (props) => {
|
|
232
|
+
return () => jsx("div", { class: "child-b", children: props.value });
|
|
233
|
+
};
|
|
234
|
+
const ParentComponent = () => {
|
|
235
|
+
const state = createState({ valueA: "A1", valueB: "B1" });
|
|
236
|
+
return () => jsx("div", {
|
|
237
|
+
children: [
|
|
238
|
+
jsx(ChildA, { value: state.valueA }),
|
|
239
|
+
jsx(ChildB, { value: state.valueB }),
|
|
240
|
+
jsx("button", {
|
|
241
|
+
class: "btn-a",
|
|
242
|
+
onclick: () => (state.valueA = "A2"),
|
|
243
|
+
children: "Update A",
|
|
244
|
+
}),
|
|
245
|
+
jsx("button", {
|
|
246
|
+
class: "btn-b",
|
|
247
|
+
onclick: () => (state.valueB = "B2"),
|
|
248
|
+
children: "Update B",
|
|
249
|
+
}),
|
|
250
|
+
],
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
render(jsx(ParentComponent, {}), container);
|
|
254
|
+
const childA = container.querySelector(".child-a");
|
|
255
|
+
const childB = container.querySelector(".child-b");
|
|
256
|
+
expect(childA.textContent).toBe("A1");
|
|
257
|
+
expect(childB.textContent).toBe("B1");
|
|
258
|
+
// Update only A
|
|
259
|
+
container.querySelector(".btn-a").click();
|
|
260
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
261
|
+
expect(childA.textContent).toBe("A2");
|
|
262
|
+
expect(childB.textContent).toBe("B1"); // B should remain unchanged
|
|
263
|
+
// Update only B
|
|
264
|
+
container.querySelector(".btn-b").click();
|
|
265
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
266
|
+
expect(childA.textContent).toBe("A2"); // A should remain unchanged
|
|
267
|
+
expect(childB.textContent).toBe("B2");
|
|
268
|
+
});
|
|
269
|
+
it("should pass array of props to nested components and update correctly", async () => {
|
|
270
|
+
const container = document.createElement("div");
|
|
271
|
+
const ItemComponent = (props) => {
|
|
272
|
+
return () => jsx("li", { children: `${props.index}: ${props.item}` });
|
|
273
|
+
};
|
|
274
|
+
const ListComponent = (props) => {
|
|
275
|
+
return () => jsx("ul", {
|
|
276
|
+
children: props.items.map((item, index) => jsx(ItemComponent, { item, index, key: index })),
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
const ParentComponent = () => {
|
|
280
|
+
const state = createState({ items: ["apple", "banana"] });
|
|
281
|
+
return () => jsx("div", {
|
|
282
|
+
children: [
|
|
283
|
+
jsx(ListComponent, { items: state.items }),
|
|
284
|
+
jsx("button", {
|
|
285
|
+
onclick: () => state.items.push("cherry"),
|
|
286
|
+
children: "Add",
|
|
287
|
+
}),
|
|
288
|
+
],
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
render(jsx(ParentComponent, {}), container);
|
|
292
|
+
const ul = container.querySelector("ul");
|
|
293
|
+
expect(ul.children.length).toBe(2);
|
|
294
|
+
expect(ul.children[0].textContent).toBe("0: apple");
|
|
295
|
+
expect(ul.children[1].textContent).toBe("1: banana");
|
|
296
|
+
// Add item
|
|
297
|
+
container.querySelector("button").click();
|
|
298
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
299
|
+
expect(ul.children.length).toBe(3);
|
|
300
|
+
expect(ul.children[2].textContent).toBe("2: cherry");
|
|
301
|
+
});
|
|
302
|
+
it("should maintain correct prop values when sibling components update", async () => {
|
|
303
|
+
const container = document.createElement("div");
|
|
304
|
+
const DisplayComponent = (props) => {
|
|
305
|
+
return () => jsx("div", {
|
|
306
|
+
class: props.label.toLowerCase().replace(/\s/g, "-"),
|
|
307
|
+
children: `${props.label}: ${props.value}`,
|
|
308
|
+
});
|
|
309
|
+
};
|
|
310
|
+
const ParentComponent = () => {
|
|
311
|
+
const state = createState({ countA: 0, countB: 100 });
|
|
312
|
+
return () => jsx("div", {
|
|
313
|
+
children: [
|
|
314
|
+
jsx(DisplayComponent, { label: "Counter A", value: state.countA }),
|
|
315
|
+
jsx(DisplayComponent, { label: "Counter B", value: state.countB }),
|
|
316
|
+
jsx("button", {
|
|
317
|
+
class: "update-a",
|
|
318
|
+
onclick: () => state.countA++,
|
|
319
|
+
children: "Inc A",
|
|
320
|
+
}),
|
|
321
|
+
],
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
render(jsx(ParentComponent, {}), container);
|
|
325
|
+
const displayA = container.querySelector(".counter-a");
|
|
326
|
+
const displayB = container.querySelector(".counter-b");
|
|
327
|
+
// Update A
|
|
328
|
+
container.querySelector(".update-a").click();
|
|
329
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
330
|
+
// Ensure A updated and B kept its value (didn't get stale/wrong props)
|
|
331
|
+
expect(displayA?.textContent).toContain("1");
|
|
332
|
+
expect(displayB?.textContent).toContain("100");
|
|
333
|
+
});
|
|
334
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.return-types.test.d.ts","sourceRoot":"","sources":["../../src/tests/component.return-types.test.ts"],"names":[],"mappings":""}
|