@pyreon/core 0.7.12 → 0.7.13
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/package.json +2 -2
- package/src/tests/cx.test.ts +29 -0
- package/src/tests/props.test.ts +94 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/core",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.13",
|
|
4
4
|
"description": "Core component model and lifecycle for Pyreon",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"prepublishOnly": "bun run build"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@pyreon/reactivity": "^0.7.
|
|
52
|
+
"@pyreon/reactivity": "^0.7.13"
|
|
53
53
|
},
|
|
54
54
|
"publishConfig": {
|
|
55
55
|
"access": "public"
|
package/src/tests/cx.test.ts
CHANGED
|
@@ -38,4 +38,33 @@ describe("cx", () => {
|
|
|
38
38
|
expect(cx([])).toBe("")
|
|
39
39
|
expect(cx({})).toBe("")
|
|
40
40
|
})
|
|
41
|
+
|
|
42
|
+
test("object where ALL values are functions returning booleans", () => {
|
|
43
|
+
expect(
|
|
44
|
+
cx({
|
|
45
|
+
active: () => true,
|
|
46
|
+
hidden: () => false,
|
|
47
|
+
bold: () => true,
|
|
48
|
+
italic: () => false,
|
|
49
|
+
}),
|
|
50
|
+
).toBe("active bold")
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test("deeply nested arrays (3+ levels)", () => {
|
|
54
|
+
expect(cx([[["level3", [["level5"]]]]])).toBe("level3 level5")
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test("mixed: string, object with function, deeply nested array", () => {
|
|
58
|
+
expect(cx(["base", { active: () => true }, [["deeply-nested"]]])).toBe(
|
|
59
|
+
"base active deeply-nested",
|
|
60
|
+
)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test("empty string values are filtered", () => {
|
|
64
|
+
expect(cx(["foo", "", "bar", ""])).toBe("foo bar")
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test("number 0 is a valid class name as string", () => {
|
|
68
|
+
expect(cx(0)).toBe("0")
|
|
69
|
+
})
|
|
41
70
|
})
|
package/src/tests/props.test.ts
CHANGED
|
@@ -66,6 +66,100 @@ describe("mergeProps", () => {
|
|
|
66
66
|
})
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
+
describe("mergeProps — edge cases", () => {
|
|
70
|
+
test("mixed getter/static value merging across 3+ sources", () => {
|
|
71
|
+
let dynamicSize = "sm"
|
|
72
|
+
const source1 = { size: "md", variant: "primary" }
|
|
73
|
+
const source2 = Object.defineProperty({} as Record<string, unknown>, "size", {
|
|
74
|
+
get: () => dynamicSize,
|
|
75
|
+
enumerable: true,
|
|
76
|
+
configurable: true,
|
|
77
|
+
})
|
|
78
|
+
const source3 = { color: "red" }
|
|
79
|
+
const result = mergeProps(source1, source2, source3)
|
|
80
|
+
expect(result.size).toBe("sm")
|
|
81
|
+
dynamicSize = "xl"
|
|
82
|
+
expect(result.size).toBe("xl")
|
|
83
|
+
expect((result as Record<string, unknown>).variant).toBe("primary")
|
|
84
|
+
expect((result as Record<string, unknown>).color).toBe("red")
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test("getter returning undefined falling through multiple levels of defaults", () => {
|
|
88
|
+
let level2: string | undefined
|
|
89
|
+
let level1: string | undefined
|
|
90
|
+
const defaults = { theme: "light" }
|
|
91
|
+
const mid = Object.defineProperty({} as Record<string, unknown>, "theme", {
|
|
92
|
+
get: () => level1,
|
|
93
|
+
enumerable: true,
|
|
94
|
+
configurable: true,
|
|
95
|
+
})
|
|
96
|
+
const top = Object.defineProperty({} as Record<string, unknown>, "theme", {
|
|
97
|
+
get: () => level2,
|
|
98
|
+
enumerable: true,
|
|
99
|
+
configurable: true,
|
|
100
|
+
})
|
|
101
|
+
const result = mergeProps(defaults, mid, top)
|
|
102
|
+
// Both getters return undefined — falls back to "light"
|
|
103
|
+
expect(result.theme).toBe("light")
|
|
104
|
+
// Mid-level getter returns value — top still undefined, falls to mid
|
|
105
|
+
level1 = "dark"
|
|
106
|
+
expect(result.theme).toBe("dark")
|
|
107
|
+
// Top-level getter returns value — wins
|
|
108
|
+
level2 = "system"
|
|
109
|
+
expect(result.theme).toBe("system")
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test("mergeProps with no sources (empty call)", () => {
|
|
113
|
+
const result = mergeProps()
|
|
114
|
+
expect(result).toEqual({})
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
test("later source static value overriding earlier getter", () => {
|
|
118
|
+
const dynamic = "from-getter"
|
|
119
|
+
const getterSource = Object.defineProperty({} as Record<string, unknown>, "val", {
|
|
120
|
+
get: () => dynamic,
|
|
121
|
+
enumerable: true,
|
|
122
|
+
configurable: true,
|
|
123
|
+
})
|
|
124
|
+
const staticSource = { val: "static-wins" }
|
|
125
|
+
const result = mergeProps(getterSource, staticSource)
|
|
126
|
+
// Static value should override getter
|
|
127
|
+
expect(result.val).toBe("static-wins")
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test("later source static undefined does not override earlier getter", () => {
|
|
131
|
+
let dynamic = "from-getter"
|
|
132
|
+
const getterSource = Object.defineProperty({} as Record<string, unknown>, "val", {
|
|
133
|
+
get: () => dynamic,
|
|
134
|
+
enumerable: true,
|
|
135
|
+
configurable: true,
|
|
136
|
+
})
|
|
137
|
+
const staticSource = { val: undefined }
|
|
138
|
+
const result = mergeProps(getterSource, staticSource)
|
|
139
|
+
// Static undefined — getter should still be used
|
|
140
|
+
expect(result.val).toBe("from-getter")
|
|
141
|
+
dynamic = "updated"
|
|
142
|
+
expect(result.val).toBe("updated")
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
describe("splitProps — getter reactivity", () => {
|
|
147
|
+
test("preserves getter reactivity through multiple reads", () => {
|
|
148
|
+
let count = 0
|
|
149
|
+
const props = Object.defineProperty({ other: "x" } as Record<string, unknown>, "value", {
|
|
150
|
+
get: () => ++count,
|
|
151
|
+
enumerable: true,
|
|
152
|
+
configurable: true,
|
|
153
|
+
})
|
|
154
|
+
const [own, rest] = splitProps(props, ["value"])
|
|
155
|
+
expect(own.value).toBe(1)
|
|
156
|
+
expect(own.value).toBe(2)
|
|
157
|
+
expect(own.value).toBe(3)
|
|
158
|
+
// rest should not include the getter key
|
|
159
|
+
expect(rest).toEqual({ other: "x" })
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
|
|
69
163
|
describe("createUniqueId", () => {
|
|
70
164
|
test("returns incrementing IDs", () => {
|
|
71
165
|
const id1 = createUniqueId()
|