@pyreon/styler 0.24.5 → 0.24.6
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 +5 -7
- package/src/ThemeProvider.ts +0 -65
- package/src/__tests__/ThemeProvider.test.ts +0 -67
- package/src/__tests__/benchmark.bench.ts +0 -200
- package/src/__tests__/composition-chain.test.ts +0 -537
- package/src/__tests__/css.test.ts +0 -70
- package/src/__tests__/dev-gate-treeshake.test.ts +0 -85
- package/src/__tests__/forward.test.ts +0 -282
- package/src/__tests__/globalStyle.test.ts +0 -72
- package/src/__tests__/hash.test.ts +0 -70
- package/src/__tests__/hybrid-injection.test.ts +0 -225
- package/src/__tests__/index.ts +0 -14
- package/src/__tests__/inject-rules.browser.test.ts +0 -40
- package/src/__tests__/insertion-effect.test.ts +0 -119
- package/src/__tests__/integration-dom.test.ts +0 -58
- package/src/__tests__/integration.test.ts +0 -179
- package/src/__tests__/keyframes.test.ts +0 -68
- package/src/__tests__/memory-growth.test.ts +0 -220
- package/src/__tests__/native-marker.test.ts +0 -9
- package/src/__tests__/p3-features.test.ts +0 -316
- package/src/__tests__/resolve-cache.test.ts +0 -94
- package/src/__tests__/resolve.test.ts +0 -308
- package/src/__tests__/shared.test.ts +0 -133
- package/src/__tests__/sheet-advanced.test.ts +0 -659
- package/src/__tests__/sheet-split-atrules.test.ts +0 -410
- package/src/__tests__/sheet.test.ts +0 -250
- package/src/__tests__/static-styler-resolve-cost.test.ts +0 -160
- package/src/__tests__/styled-reactive.test.ts +0 -74
- package/src/__tests__/styled-ssr.test.ts +0 -75
- package/src/__tests__/styled.test.ts +0 -511
- package/src/__tests__/styler.browser.test.tsx +0 -194
- package/src/__tests__/theme.test.ts +0 -33
- package/src/__tests__/useCSS.test.ts +0 -172
- package/src/css.ts +0 -13
- package/src/env.d.ts +0 -6
- package/src/forward.ts +0 -308
- package/src/globalStyle.ts +0 -53
- package/src/hash.ts +0 -28
- package/src/index.ts +0 -15
- package/src/keyframes.ts +0 -36
- package/src/manifest.ts +0 -332
- package/src/resolve.ts +0 -225
- package/src/shared.ts +0 -22
- package/src/sheet.ts +0 -635
- package/src/styled.tsx +0 -503
- package/src/tests/manifest-snapshot.test.ts +0 -51
- package/src/useCSS.ts +0 -20
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest"
|
|
2
|
-
import { css } from "../css"
|
|
3
|
-
import { CSSResult, normalizeCSS, resolve, resolveValue } from "../resolve"
|
|
4
|
-
import { isDynamic } from "../shared"
|
|
5
|
-
|
|
6
|
-
// Helper to create a TemplateStringsArray
|
|
7
|
-
const tsa = (strings: readonly string[]): TemplateStringsArray => {
|
|
8
|
-
const arr = [...strings] as string[] & { raw: readonly string[] }
|
|
9
|
-
arr.raw = strings
|
|
10
|
-
return arr
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
describe("resolve", () => {
|
|
14
|
-
describe("primitive interpolations", () => {
|
|
15
|
-
it("resolves strings", () => {
|
|
16
|
-
const result = resolve(tsa(["color: ", ";"]), ["red"], {})
|
|
17
|
-
expect(result).toBe("color: red;")
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it("resolves numbers", () => {
|
|
21
|
-
const result = resolve(tsa(["flex: ", ";"]), [1], {})
|
|
22
|
-
expect(result).toBe("flex: 1;")
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it("resolves null as empty string", () => {
|
|
26
|
-
const result = resolve(tsa(["a", "b"]), [null], {})
|
|
27
|
-
expect(result).toBe("ab")
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it("resolves undefined as empty string", () => {
|
|
31
|
-
const result = resolve(tsa(["a", "b"]), [undefined], {})
|
|
32
|
-
expect(result).toBe("ab")
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it("resolves false as empty string", () => {
|
|
36
|
-
const result = resolve(tsa(["a", "b"]), [false], {})
|
|
37
|
-
expect(result).toBe("ab")
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it("resolves true as empty string", () => {
|
|
41
|
-
const result = resolve(tsa(["a", "b"]), [true], {})
|
|
42
|
-
expect(result).toBe("ab")
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
describe("function interpolations", () => {
|
|
47
|
-
it("calls functions with props and uses return value", () => {
|
|
48
|
-
const fn = (props: Record<string, unknown>) => props.color as string
|
|
49
|
-
const result = resolve(tsa(["color: ", ";"]), [fn], { color: "blue" })
|
|
50
|
-
expect(result).toBe("color: blue;")
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it("resolves nested function results recursively", () => {
|
|
54
|
-
const fn = () => () => "red"
|
|
55
|
-
const result = resolve(tsa(["color: ", ";"]), [fn], {})
|
|
56
|
-
expect(result).toBe("color: red;")
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it("handles functions returning null", () => {
|
|
60
|
-
const fn = () => null
|
|
61
|
-
const result = resolve(tsa(["a", "b"]), [fn], {})
|
|
62
|
-
expect(result).toBe("ab")
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it("handles functions returning false (conditional)", () => {
|
|
66
|
-
const fn = (props: Record<string, unknown>) => (props.active ? "color: red;" : false)
|
|
67
|
-
const result = resolve(tsa(["", ""]), [fn], { active: false })
|
|
68
|
-
expect(result).toBe("")
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it("uses empty object when no props provided", () => {
|
|
72
|
-
const fn = (props: Record<string, unknown>) =>
|
|
73
|
-
Object.keys(props).length === 0 ? "empty" : "has-props"
|
|
74
|
-
const result = resolve(tsa(["", ""]), [fn], {})
|
|
75
|
-
expect(result).toBe("empty")
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
describe("CSSResult interpolations", () => {
|
|
80
|
-
it("resolves nested CSSResult", () => {
|
|
81
|
-
const inner = css`color: red;`
|
|
82
|
-
const result = resolveValue(inner, {})
|
|
83
|
-
expect(result).toBe("color: red;")
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it("resolves deeply nested CSSResults", () => {
|
|
87
|
-
const inner1 = css`color: red;`
|
|
88
|
-
const inner2 = css`${inner1} display: flex;`
|
|
89
|
-
const result = resolveValue(inner2, {})
|
|
90
|
-
expect(result).toBe("color: red; display: flex;")
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it("resolves CSSResult with function interpolations", () => {
|
|
94
|
-
const inner = css`color: ${((p: Record<string, unknown>) => p.color) as any};`
|
|
95
|
-
const result = resolveValue(inner, { color: "green" })
|
|
96
|
-
expect(result).toBe("color: green;")
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
describe("array interpolations", () => {
|
|
101
|
-
it("resolves arrays of values", () => {
|
|
102
|
-
const result = resolve(tsa(["", ""]), [["a", "b", "c"]], {})
|
|
103
|
-
expect(result).toBe("abc")
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
it("resolves arrays with CSSResults", () => {
|
|
107
|
-
const inner = css`color: red;`
|
|
108
|
-
const result = resolveValue([inner, " display: flex;"], {})
|
|
109
|
-
expect(result).toBe("color: red; display: flex;")
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
describe("combined patterns", () => {
|
|
114
|
-
it("handles multiple interpolation types", () => {
|
|
115
|
-
const result = resolve(
|
|
116
|
-
tsa(["display: ", "; color: ", "; flex: ", ";"]),
|
|
117
|
-
["flex", "red", 1],
|
|
118
|
-
{},
|
|
119
|
-
)
|
|
120
|
-
expect(result).toBe("display: flex; color: red; flex: 1;")
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
it("handles conditional CSS with logical AND (truthy)", () => {
|
|
124
|
-
const condition = true
|
|
125
|
-
const conditionalCss = condition && css`color: red;`
|
|
126
|
-
const result = resolveValue(conditionalCss, {})
|
|
127
|
-
expect(result).toBe("color: red;")
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it("handles conditional CSS with logical AND (falsy)", () => {
|
|
131
|
-
const condition = false
|
|
132
|
-
const conditionalCss = condition && css`color: red;`
|
|
133
|
-
const result = resolveValue(conditionalCss, {})
|
|
134
|
-
expect(result).toBe("")
|
|
135
|
-
})
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
describe("CSSResult", () => {
|
|
140
|
-
it("stores strings and values as readonly properties", () => {
|
|
141
|
-
const strings = ["color: ", ";"] as unknown as TemplateStringsArray
|
|
142
|
-
const values = ["red"]
|
|
143
|
-
const result = new CSSResult(strings, values)
|
|
144
|
-
expect(result.strings).toBe(strings)
|
|
145
|
-
expect(result.values).toBe(values)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it("toString resolves with empty props", () => {
|
|
149
|
-
const result = css`color: red;`
|
|
150
|
-
expect(result.toString()).toBe("color: red;")
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
describe("normalizeCSS", () => {
|
|
155
|
-
describe("comment stripping", () => {
|
|
156
|
-
it("strips CSS block comments", () => {
|
|
157
|
-
expect(normalizeCSS("/* comment */ color: red;")).toBe("color: red;")
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it("strips multiple block comments", () => {
|
|
161
|
-
expect(normalizeCSS("/* BASE */ color: red; /* HOVER */ font-size: 1rem;")).toBe(
|
|
162
|
-
"color: red; font-size: 1rem;",
|
|
163
|
-
)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
it("strips multiline block comments", () => {
|
|
167
|
-
expect(normalizeCSS("/* --------\n BASE STATE\n -------- */\nheight: 3rem;")).toBe(
|
|
168
|
-
"height: 3rem;",
|
|
169
|
-
)
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
it("strips JS-style line comments", () => {
|
|
173
|
-
expect(normalizeCSS("// this is not valid CSS\ncolor: red;")).toBe("color: red;")
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
it("preserves :// in URLs", () => {
|
|
177
|
-
expect(normalizeCSS("background: url(https://example.com/img.png);")).toContain(
|
|
178
|
-
"https://example.com/img.png",
|
|
179
|
-
)
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
it("strips line comments but preserves URL protocols", () => {
|
|
183
|
-
const result = normalizeCSS("// comment\nbackground: url(https://example.com/img.png);")
|
|
184
|
-
expect(result).toContain("https://example.com/img.png")
|
|
185
|
-
expect(result).not.toContain("// comment")
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
it("handles unterminated block comment", () => {
|
|
189
|
-
expect(normalizeCSS("color: red; /* never closed")).toBe("color: red;")
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it("handles unterminated line comment", () => {
|
|
193
|
-
expect(normalizeCSS("color: red;\n// trailing comment")).toBe("color: red;")
|
|
194
|
-
})
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
describe("whitespace handling", () => {
|
|
198
|
-
it("collapses whitespace", () => {
|
|
199
|
-
expect(normalizeCSS(" color: red; font-size: 1rem; ")).toBe(
|
|
200
|
-
"color: red; font-size: 1rem;",
|
|
201
|
-
)
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
it("converts tabs and newlines to spaces", () => {
|
|
205
|
-
expect(normalizeCSS("color:\tred;\nfont-size:\t1rem;")).toBe("color: red; font-size: 1rem;")
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
it("collapses multiple spaces", () => {
|
|
209
|
-
expect(normalizeCSS("color: red;")).toBe("color: red;")
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
it("trims leading and trailing whitespace", () => {
|
|
213
|
-
expect(normalizeCSS(" color: red; ")).toBe("color: red;")
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
it("handles carriage returns", () => {
|
|
217
|
-
expect(normalizeCSS("color: red;\r\nfont-size: 1rem;")).toBe("color: red; font-size: 1rem;")
|
|
218
|
-
})
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
describe("semicolon handling", () => {
|
|
222
|
-
it("removes redundant semicolons after {", () => {
|
|
223
|
-
expect(normalizeCSS(".foo {; color: red; }")).toBe(".foo { color: red; }")
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
it("removes redundant semicolons after }", () => {
|
|
227
|
-
expect(normalizeCSS(".foo { color: red; }; .bar { }")).toBe(".foo { color: red; } .bar { }")
|
|
228
|
-
})
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
describe("edge cases", () => {
|
|
232
|
-
it("returns empty string for empty input", () => {
|
|
233
|
-
expect(normalizeCSS("")).toBe("")
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
it("returns empty string for whitespace-only input", () => {
|
|
237
|
-
expect(normalizeCSS(" \n\t ")).toBe("")
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
it("handles CSS with braces", () => {
|
|
241
|
-
expect(normalizeCSS(".foo { color: red; }")).toBe(".foo { color: red; }")
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
it("handles @media rules", () => {
|
|
245
|
-
const result = normalizeCSS("@media (min-width: 48em) { color: blue; }")
|
|
246
|
-
expect(result).toContain("@media")
|
|
247
|
-
expect(result).toContain("color: blue;")
|
|
248
|
-
})
|
|
249
|
-
})
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
// Behavioural lock-in for the CSSResult._staticResolved cache (ported from
|
|
253
|
-
// vitus-labs `754cd203` + lock-in `60fc25c1`). Common pattern: a shared
|
|
254
|
-
// static snippet interpolated into many dynamic components. Without this
|
|
255
|
-
// cache the snippet's resolve work was paid once per dynamic render of
|
|
256
|
-
// every consumer; with it, the resolve fires once per snippet, total.
|
|
257
|
-
describe("CSSResult._staticResolved cache", () => {
|
|
258
|
-
it("populates _staticResolved on first resolveValue of a known-static CSSResult", () => {
|
|
259
|
-
const inner = css`color: red;`
|
|
260
|
-
// Pre-classify as static via isDynamic (the same call shared.ts makes
|
|
261
|
-
// at styled-component creation time).
|
|
262
|
-
isDynamic(inner)
|
|
263
|
-
expect(inner._isDynamic).toBe(false)
|
|
264
|
-
expect(inner._staticResolved).toBe(undefined)
|
|
265
|
-
|
|
266
|
-
resolveValue(inner, {})
|
|
267
|
-
expect(inner._staticResolved).toBe("color: red;")
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
it("returns cached _staticResolved on subsequent resolveValue calls", () => {
|
|
271
|
-
const inner = css`padding: 12px;`
|
|
272
|
-
isDynamic(inner)
|
|
273
|
-
resolveValue(inner, {})
|
|
274
|
-
expect(inner._staticResolved).toBe("padding: 12px;")
|
|
275
|
-
|
|
276
|
-
// Mutate values to a sentinel that would change the resolved output if
|
|
277
|
-
// recomputed. The cache MUST return the prior result.
|
|
278
|
-
;(inner as unknown as { values: unknown[] }).values = ["SENTINEL"]
|
|
279
|
-
expect(resolveValue(inner, {})).toBe("padding: 12px;")
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
it("does NOT cache dynamic CSSResults (props vary per call)", () => {
|
|
283
|
-
const dyn = css`color: ${(p: Record<string, unknown>) => p.c as string};`
|
|
284
|
-
isDynamic(dyn)
|
|
285
|
-
expect(dyn._isDynamic).toBe(true)
|
|
286
|
-
|
|
287
|
-
// Resolve twice with different props; cache should not be populated.
|
|
288
|
-
resolveValue(dyn, { c: "red" })
|
|
289
|
-
expect(dyn._staticResolved).toBe(undefined)
|
|
290
|
-
resolveValue(dyn, { c: "blue" })
|
|
291
|
-
expect(dyn._staticResolved).toBe(undefined)
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
it("skips cache when _isDynamic is undefined (not yet classified)", () => {
|
|
295
|
-
// Construct a CSSResult directly without going through isDynamic.
|
|
296
|
-
// resolveValue's cache check is `_isDynamic === false` (strict), so an
|
|
297
|
-
// unclassified CSSResult falls through to the regular resolve path
|
|
298
|
-
// — the regular path takes the SECOND branch (`return resolve(...)`)
|
|
299
|
-
// and does NOT populate the cache.
|
|
300
|
-
const tpl = Object.assign(["color: ", ";"], {
|
|
301
|
-
raw: ["color: ", ";"],
|
|
302
|
-
}) as unknown as TemplateStringsArray
|
|
303
|
-
const r = new CSSResult(tpl, ["red"])
|
|
304
|
-
expect(r._isDynamic).toBe(undefined)
|
|
305
|
-
expect(resolveValue(r, {})).toBe("color: red;")
|
|
306
|
-
expect(r._staticResolved).toBe(undefined) // cache stays unpopulated
|
|
307
|
-
})
|
|
308
|
-
})
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { css } from '../css'
|
|
3
|
-
import { CSSResult } from '../resolve'
|
|
4
|
-
import { isDynamic } from '../shared'
|
|
5
|
-
|
|
6
|
-
describe('isDynamic', () => {
|
|
7
|
-
it('returns true for function values', () => {
|
|
8
|
-
expect(isDynamic(() => 'red')).toBe(true)
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it('returns false for string values', () => {
|
|
12
|
-
expect(isDynamic('color: red;')).toBe(false)
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('returns false for number values', () => {
|
|
16
|
-
expect(isDynamic(42)).toBe(false)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('returns false for null and undefined', () => {
|
|
20
|
-
expect(isDynamic(null)).toBe(false)
|
|
21
|
-
expect(isDynamic(undefined)).toBe(false)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('returns false for boolean values', () => {
|
|
25
|
-
expect(isDynamic(true)).toBe(false)
|
|
26
|
-
expect(isDynamic(false)).toBe(false)
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('returns true for arrays containing functions', () => {
|
|
30
|
-
expect(isDynamic(['a', () => 'b'])).toBe(true)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('returns false for arrays of static values', () => {
|
|
34
|
-
expect(isDynamic(['a', 'b', 42])).toBe(false)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('returns true for CSSResult with dynamic values', () => {
|
|
38
|
-
const result = css`
|
|
39
|
-
color: ${() => 'red'};
|
|
40
|
-
`
|
|
41
|
-
expect(isDynamic(result)).toBe(true)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('returns false for CSSResult with only static values', () => {
|
|
45
|
-
const result = css`
|
|
46
|
-
color: ${'red'};
|
|
47
|
-
`
|
|
48
|
-
expect(isDynamic(result)).toBe(false)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('returns true for nested dynamic CSSResult', () => {
|
|
52
|
-
const inner = css`
|
|
53
|
-
color: ${() => 'red'};
|
|
54
|
-
`
|
|
55
|
-
const outer = css`
|
|
56
|
-
${inner}
|
|
57
|
-
`
|
|
58
|
-
expect(isDynamic(outer)).toBe(true)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('returns false for nested static CSSResult', () => {
|
|
62
|
-
const inner = css`
|
|
63
|
-
color: red;
|
|
64
|
-
`
|
|
65
|
-
const outer = css`
|
|
66
|
-
${inner}
|
|
67
|
-
`
|
|
68
|
-
expect(isDynamic(outer)).toBe(false)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('detects deeply nested dynamic values', () => {
|
|
72
|
-
const deep = css`
|
|
73
|
-
color: ${() => 'red'};
|
|
74
|
-
`
|
|
75
|
-
const mid = css`
|
|
76
|
-
${deep}
|
|
77
|
-
`
|
|
78
|
-
const outer = css`
|
|
79
|
-
${mid}
|
|
80
|
-
`
|
|
81
|
-
expect(isDynamic(outer)).toBe(true)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('handles arrays inside CSSResult', () => {
|
|
85
|
-
const result = new CSSResult(
|
|
86
|
-
Object.assign(['', ''], { raw: ['', ''] }) as TemplateStringsArray,
|
|
87
|
-
[['a', () => 'b']],
|
|
88
|
-
)
|
|
89
|
-
expect(isDynamic(result)).toBe(true)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
// Behavioural lock-in for the CSSResult._isDynamic memoization (ported
|
|
93
|
-
// from vitus-labs `c483cabc` + lock-in `60fc25c1`). Without these tests
|
|
94
|
-
// a future regression that removed the cache would only show up as a
|
|
95
|
-
// perf regression, never as a test failure.
|
|
96
|
-
describe('CSSResult _isDynamic memoization', () => {
|
|
97
|
-
it('populates _isDynamic on first call for dynamic templates', () => {
|
|
98
|
-
const r = css`color: ${() => 'red'};`
|
|
99
|
-
expect(r._isDynamic).toBe(undefined)
|
|
100
|
-
isDynamic(r)
|
|
101
|
-
expect(r._isDynamic).toBe(true)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('populates _isDynamic on first call for static templates', () => {
|
|
105
|
-
const r = css`color: ${'red'};`
|
|
106
|
-
expect(r._isDynamic).toBe(undefined)
|
|
107
|
-
isDynamic(r)
|
|
108
|
-
expect(r._isDynamic).toBe(false)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
it('returns cached result on subsequent calls without rescanning values', () => {
|
|
112
|
-
const r = css`color: ${() => 'red'};`
|
|
113
|
-
const first = isDynamic(r)
|
|
114
|
-
expect(first).toBe(true)
|
|
115
|
-
expect(r._isDynamic).toBe(true)
|
|
116
|
-
|
|
117
|
-
// Mutate values to a sentinel that would invert the answer if rescanned.
|
|
118
|
-
// The memoized path must NOT consult `values` again — it should return
|
|
119
|
-
// the cached `_isDynamic` directly.
|
|
120
|
-
;(r as unknown as { values: unknown[] }).values = ['static-only']
|
|
121
|
-
expect(isDynamic(r)).toBe(true) // still uses cached value, not rescan
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('memoizes nested CSSResults independently', () => {
|
|
125
|
-
const inner = css`color: ${() => 'red'};`
|
|
126
|
-
const outer = css`${inner}`
|
|
127
|
-
isDynamic(outer)
|
|
128
|
-
// Recursing through outer populates inner too.
|
|
129
|
-
expect(inner._isDynamic).toBe(true)
|
|
130
|
-
expect(outer._isDynamic).toBe(true)
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
})
|