@pyreon/kinetic 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.
Files changed (37) hide show
  1. package/package.json +10 -12
  2. package/src/Collapse.tsx +0 -166
  3. package/src/Stagger.tsx +0 -63
  4. package/src/Transition.tsx +0 -280
  5. package/src/TransitionGroup.tsx +0 -139
  6. package/src/__tests__/Collapse.test.tsx +0 -803
  7. package/src/__tests__/GroupRenderer.test.tsx +0 -434
  8. package/src/__tests__/StaggerRenderer.test.tsx +0 -523
  9. package/src/__tests__/Transition.ssr.test.tsx +0 -183
  10. package/src/__tests__/Transition.test.tsx +0 -403
  11. package/src/__tests__/TransitionItem.test.tsx +0 -514
  12. package/src/__tests__/kinetic-modes.ssr.test.tsx +0 -214
  13. package/src/__tests__/kinetic.browser.test.tsx +0 -327
  14. package/src/__tests__/kinetic.test.tsx +0 -565
  15. package/src/__tests__/presets.test.ts +0 -46
  16. package/src/__tests__/stagger-component-children-hydration.test.tsx +0 -191
  17. package/src/__tests__/top-level-transition-stagger-function-children.test.tsx +0 -141
  18. package/src/__tests__/useAnimationEnd.test.ts +0 -194
  19. package/src/__tests__/useReducedMotion.test.ts +0 -160
  20. package/src/__tests__/useTransitionState.test.ts +0 -132
  21. package/src/__tests__/utils.test.ts +0 -139
  22. package/src/index.ts +0 -15
  23. package/src/jsx-augment.d.ts +0 -12
  24. package/src/kinetic/CollapseRenderer.tsx +0 -216
  25. package/src/kinetic/GroupRenderer.tsx +0 -149
  26. package/src/kinetic/StaggerRenderer.tsx +0 -94
  27. package/src/kinetic/TransitionItem.tsx +0 -250
  28. package/src/kinetic/TransitionRenderer.tsx +0 -230
  29. package/src/kinetic/createKineticComponent.tsx +0 -224
  30. package/src/kinetic/types.ts +0 -149
  31. package/src/kinetic.ts +0 -25
  32. package/src/presets.ts +0 -66
  33. package/src/types.ts +0 -118
  34. package/src/useAnimationEnd.ts +0 -59
  35. package/src/useReducedMotion.ts +0 -28
  36. package/src/useTransitionState.ts +0 -62
  37. package/src/utils.ts +0 -113
@@ -1,565 +0,0 @@
1
- import type { VNode, VNodeChild } from '@pyreon/core'
2
- import { h } from '@pyreon/core'
3
- import { signal } from '@pyreon/reactivity'
4
-
5
- let _reducedMotion = false
6
-
7
- vi.mock('../useReducedMotion', () => ({
8
- useReducedMotion: () => () => _reducedMotion,
9
- }))
10
-
11
- import { kinetic } from '../index'
12
- import { fade, slideUp } from '../presets'
13
-
14
- // Mock rAF for deterministic testing
15
- let rafCallbacks: (() => void)[] = []
16
- const originalRaf = globalThis.requestAnimationFrame
17
- const originalCaf = globalThis.cancelAnimationFrame
18
-
19
- beforeEach(() => {
20
- vi.useFakeTimers()
21
- rafCallbacks = []
22
-
23
- vi.stubGlobal(
24
- 'requestAnimationFrame',
25
- vi.fn((cb: () => void) => {
26
- rafCallbacks.push(cb)
27
- return rafCallbacks.length
28
- }),
29
- )
30
-
31
- vi.stubGlobal('cancelAnimationFrame', vi.fn())
32
- })
33
-
34
- afterEach(() => {
35
- vi.useRealTimers()
36
- vi.stubGlobal('requestAnimationFrame', originalRaf)
37
- vi.stubGlobal('cancelAnimationFrame', originalCaf)
38
- })
39
-
40
- const flushRaf = () => {
41
- const cbs = [...rafCallbacks]
42
- rafCallbacks = []
43
- for (const cb of cbs) cb()
44
- }
45
-
46
- const fireTransitionEnd = (el: HTMLElement) => {
47
- const event = new Event('transitionend', { bubbles: true })
48
- Object.defineProperty(event, 'target', { value: el })
49
- el.dispatchEvent(event)
50
- }
51
-
52
- /**
53
- * Wire up a mock element to the ref found in the VNode tree.
54
- * The kinetic transition mode uses h(tag, { ref: mergedRef, ... })
55
- * which means the ref is directly on the VNode props.
56
- */
57
- const wireRef = (vnode: VNode | null, el: HTMLElement) => {
58
- if (!vnode) return
59
-
60
- const visitNode = (node: VNode) => {
61
- const props = node.props as Record<string, unknown>
62
- if (typeof props?.ref === 'function') {
63
- ;(props.ref as (element: HTMLElement | null) => void)(el)
64
- } else if (props?.ref && typeof props.ref === 'object') {
65
- ;(props.ref as { current: HTMLElement | null }).current = el
66
- }
67
-
68
- // Visit vnode.children (for intrinsic elements)
69
- if (node.children) {
70
- const children = Array.isArray(node.children) ? node.children : [node.children]
71
- for (const child of children) {
72
- if (child && typeof child === 'object' && 'type' in (child as object)) {
73
- visitNode(child as VNode)
74
- }
75
- }
76
- }
77
-
78
- // Visit props.children (for component VNodes like Show)
79
- if (props?.children) {
80
- const pChildren = Array.isArray(props.children) ? props.children : [props.children]
81
- for (const child of pChildren) {
82
- if (child && typeof child === 'object' && 'type' in (child as object)) {
83
- visitNode(child as VNode)
84
- }
85
- }
86
- }
87
-
88
- // Visit fallback on Show
89
- if (
90
- props?.fallback &&
91
- typeof props.fallback === 'object' &&
92
- 'type' in (props.fallback as object)
93
- ) {
94
- visitNode(props.fallback as VNode)
95
- }
96
- }
97
-
98
- visitNode(vnode)
99
- }
100
-
101
- /**
102
- * Resolve the outermost component-type VNode by calling the function.
103
- * kinetic() returns VNodes where type is a component function (e.g. TransitionRenderer).
104
- * We call it once to execute the component and set up watches/refs,
105
- * but do NOT recurse into framework components like Show.
106
- */
107
- const resolveComponent = (vnode: VNodeChild): VNode | null => {
108
- if (!vnode || typeof vnode !== 'object' || !('type' in vnode)) return null
109
- if (typeof vnode.type === 'function') {
110
- const props = vnode.props as Record<string, unknown>
111
- const children = vnode.children
112
- // Call the component function with props (children merged in)
113
- const result = (vnode.type as (p: Record<string, unknown>) => VNodeChild)({
114
- ...props,
115
- ...(children != null ? { children } : {}),
116
- })
117
- if (!result || typeof result !== 'object' || !('type' in result)) return null
118
- return result
119
- }
120
- return vnode
121
- }
122
-
123
- // ─── Transition Mode (default) ────────────────────────────
124
-
125
- describe('kinetic() — transition mode', () => {
126
- it('returns a VNode when show=true', () => {
127
- const FadeDiv = kinetic('div').preset(fade)
128
- const show = signal(true)
129
- const vnode = FadeDiv({ show, children: 'Hello' })
130
- expect(vnode).not.toBeNull()
131
- })
132
-
133
- it('fires onEnter callback when entering', () => {
134
- const onEnter = vi.fn()
135
- const show = signal(false)
136
- const Slide = kinetic('div')
137
- .enter({ opacity: 0, transform: 'translateY(16px)' })
138
- .enterTo({ opacity: 1, transform: 'translateY(0)' })
139
- .enterTransition('all 300ms ease')
140
-
141
- const el = document.createElement('div')
142
- const vnode = resolveComponent(Slide({ show, onEnter, children: 'Hello' }))
143
- wireRef(vnode, el)
144
-
145
- show.set(true)
146
- expect(onEnter).toHaveBeenCalledTimes(1)
147
- })
148
-
149
- it('applies enterStyle on entering', () => {
150
- const show = signal(false)
151
- const Slide = kinetic('div')
152
- .enter({ opacity: 0, transform: 'translateY(16px)' })
153
- .enterTo({ opacity: 1, transform: 'translateY(0)' })
154
- .enterTransition('all 300ms ease')
155
-
156
- const el = document.createElement('div')
157
- const vnode = resolveComponent(Slide({ show, children: 'Hello' }))
158
- wireRef(vnode, el)
159
-
160
- show.set(true)
161
-
162
- expect(el.style.opacity).toBe('0')
163
- expect(el.style.transition).toBe('all 300ms ease')
164
-
165
- flushRaf()
166
- flushRaf()
167
-
168
- expect(el.style.opacity).toBe('1')
169
- })
170
-
171
- it('applies class-based transitions via .enterClass()', () => {
172
- const show = signal(false)
173
- const ClassFade = kinetic('div')
174
- .enterClass({ active: 't-enter', from: 't-from', to: 't-to' })
175
- .leaveClass({ active: 't-leave', from: 't-lfrom', to: 't-lto' })
176
-
177
- const el = document.createElement('div')
178
- const vnode = resolveComponent(ClassFade({ show, children: 'Hello' }))
179
- wireRef(vnode, el)
180
-
181
- show.set(true)
182
-
183
- expect(el.classList.contains('t-enter')).toBe(true)
184
- expect(el.classList.contains('t-from')).toBe(true)
185
-
186
- flushRaf()
187
- flushRaf()
188
-
189
- expect(el.classList.contains('t-from')).toBe(false)
190
- expect(el.classList.contains('t-to')).toBe(true)
191
- })
192
-
193
- it('fires lifecycle callbacks at correct times', () => {
194
- const onEnter = vi.fn()
195
- const onAfterEnter = vi.fn()
196
- const onLeave = vi.fn()
197
- const onAfterLeave = vi.fn()
198
- const show = signal(false)
199
-
200
- const FadeDiv = kinetic('div').preset(fade)
201
- const el = document.createElement('div')
202
- const vnode = resolveComponent(
203
- FadeDiv({ show, onEnter, onAfterEnter, onLeave, onAfterLeave, children: 'Hello' }),
204
- )
205
- wireRef(vnode, el)
206
-
207
- // Enter
208
- show.set(true)
209
- expect(onEnter).toHaveBeenCalledTimes(1)
210
- expect(onAfterEnter).not.toHaveBeenCalled()
211
-
212
- flushRaf()
213
- flushRaf()
214
- fireTransitionEnd(el)
215
-
216
- expect(onAfterEnter).toHaveBeenCalledTimes(1)
217
-
218
- // Leave
219
- show.set(false)
220
- expect(onLeave).toHaveBeenCalledTimes(1)
221
-
222
- flushRaf()
223
- flushRaf()
224
- fireTransitionEnd(el)
225
-
226
- expect(onAfterLeave).toHaveBeenCalledTimes(1)
227
- })
228
-
229
- it('timeout fallback completes transition', () => {
230
- const onAfterEnter = vi.fn()
231
- const show = signal(false)
232
- const FadeDiv = kinetic('div').preset(fade).config({ timeout: 1000 })
233
-
234
- const el = document.createElement('div')
235
- const vnode = resolveComponent(FadeDiv({ show, onAfterEnter, children: 'Hello' }))
236
- wireRef(vnode, el)
237
-
238
- show.set(true)
239
-
240
- flushRaf()
241
- flushRaf()
242
-
243
- vi.advanceTimersByTime(1000)
244
-
245
- expect(onAfterEnter).toHaveBeenCalledTimes(1)
246
- })
247
-
248
- it('appear=true animates on initial mount', () => {
249
- const onEnter = vi.fn()
250
- const show = signal(true)
251
- const FadeDiv = kinetic('div').preset(fade).config({ appear: true }).on({ onEnter })
252
-
253
- const el = document.createElement('div')
254
- const vnode = resolveComponent(FadeDiv({ show, children: 'Hello' }))
255
- wireRef(vnode, el)
256
-
257
- expect(onEnter).toHaveBeenCalledTimes(1)
258
- })
259
- })
260
-
261
- // ─── Chain Immutability ────────────────────────────────────
262
-
263
- describe('kinetic() — chaining', () => {
264
- it('chain is immutable (each method returns new component)', () => {
265
- const Base = kinetic('div')
266
- const WithFade = Base.preset(fade)
267
- const WithSlide = Base.preset(slideUp)
268
-
269
- // WithFade and WithSlide are different components
270
- expect(WithFade).not.toBe(WithSlide)
271
- expect(WithFade).not.toBe(Base)
272
- })
273
-
274
- it('.preset() merges preset properties into config', () => {
275
- const show = signal(false)
276
- const FadeDiv = kinetic('div').preset(fade)
277
-
278
- const el = document.createElement('div')
279
- const vnode = resolveComponent(FadeDiv({ show, children: 'Hello' }))
280
- wireRef(vnode, el)
281
-
282
- show.set(true)
283
-
284
- expect(el.style.opacity).toBe('0')
285
- expect(el.style.transition).toBe('opacity 300ms ease-out')
286
- })
287
-
288
- it('.on() callbacks from chain are used when runtime callbacks not provided', () => {
289
- const onEnter = vi.fn()
290
- const show = signal(false)
291
- const FadeDiv = kinetic('div').preset(fade).on({ onEnter })
292
-
293
- const el = document.createElement('div')
294
- const vnode = resolveComponent(FadeDiv({ show, children: 'Hello' }))
295
- wireRef(vnode, el)
296
-
297
- show.set(true)
298
- expect(onEnter).toHaveBeenCalledTimes(1)
299
- })
300
-
301
- it('runtime props override chain config', () => {
302
- const chainOnEnter = vi.fn()
303
- const runtimeOnEnter = vi.fn()
304
- const show = signal(false)
305
- const FadeDiv = kinetic('div').preset(fade).on({ onEnter: chainOnEnter })
306
-
307
- const el = document.createElement('div')
308
- const vnode = resolveComponent(FadeDiv({ show, onEnter: runtimeOnEnter, children: 'Hello' }))
309
- wireRef(vnode, el)
310
-
311
- show.set(true)
312
-
313
- expect(runtimeOnEnter).toHaveBeenCalledTimes(1)
314
- expect(chainOnEnter).not.toHaveBeenCalled()
315
- })
316
-
317
- it('displayName is set correctly', () => {
318
- const FadeDiv = kinetic('div').preset(fade)
319
- expect(FadeDiv.displayName).toBe('kinetic(div)')
320
- })
321
- })
322
-
323
- // ─── Collapse Mode ─────────────────────────────────────────
324
-
325
- describe('kinetic() — collapse mode', () => {
326
- const mockScrollHeight = (value: number) => {
327
- Object.defineProperty(HTMLElement.prototype, 'scrollHeight', {
328
- configurable: true,
329
- get() {
330
- return value
331
- },
332
- })
333
- }
334
-
335
- beforeEach(() => {
336
- mockScrollHeight(200)
337
- })
338
-
339
- it('fires onEnter on entering and onAfterEnter after transitionend', () => {
340
- const onEnter = vi.fn()
341
- const onAfterEnter = vi.fn()
342
- const show = signal(false)
343
- const Accordion = kinetic('div').collapse()
344
-
345
- const wrapperEl = document.createElement('div')
346
- const contentEl = document.createElement('div')
347
- Object.defineProperty(wrapperEl, 'offsetHeight', {
348
- configurable: true,
349
- get: () => 0,
350
- })
351
-
352
- const vnode = resolveComponent(
353
- Accordion({
354
- show,
355
- onEnter,
356
- onAfterEnter,
357
- // Real h() instead of a mock literal — same VNode shape as
358
- // production, so the test exercises whatever flattening /
359
- // normalisation h() applies (instead of asserting the
360
- // hand-built shape always matches).
361
- children: h('p', null, 'Content'),
362
- }),
363
- )
364
-
365
- // Wire up refs - CollapseRenderer uses h(config.tag, { ref: wrapperRef, ... })
366
- // and inner <div ref={contentRef}>
367
- wireRef(vnode, wrapperEl)
368
-
369
- // Find contentRef in the VNode tree
370
- const findContentRef = (node: VNode | null) => {
371
- if (!node) return
372
- if (node.children) {
373
- const children = Array.isArray(node.children) ? node.children : [node.children]
374
- for (const child of children) {
375
- if (child && typeof child === 'object' && 'type' in (child as object)) {
376
- const cNode = child as VNode
377
- const props = cNode.props as Record<string, unknown>
378
- if (props?.ref && typeof props.ref === 'object' && cNode.type === 'div') {
379
- ;(props.ref as { current: HTMLElement | null }).current = contentEl
380
- }
381
- findContentRef(cNode)
382
- }
383
- }
384
- }
385
- // Check Show props
386
- const props = node.props as Record<string, unknown>
387
- if (props?.children) {
388
- const pc = Array.isArray(props.children) ? props.children : [props.children]
389
- for (const p of pc) {
390
- if (p && typeof p === 'object' && 'type' in (p as object)) {
391
- const pNode = p as VNode
392
- const pProps = pNode.props as Record<string, unknown>
393
- if (pProps?.ref && typeof pProps.ref === 'object') {
394
- ;(pProps.ref as { current: HTMLElement | null }).current = contentEl
395
- }
396
- }
397
- }
398
- }
399
- }
400
- findContentRef(vnode)
401
-
402
- show.set(true)
403
-
404
- expect(onEnter).toHaveBeenCalledTimes(1)
405
-
406
- fireTransitionEnd(wrapperEl)
407
-
408
- expect(onAfterEnter).toHaveBeenCalledTimes(1)
409
- })
410
- })
411
-
412
- // ─── Transition mode — leave with styles ─────────────────────
413
-
414
- describe('kinetic() — transition leave styles', () => {
415
- it('applies leaveStyle and leaveTransition on leaving', () => {
416
- const show = signal(true)
417
- const Slide = kinetic('div')
418
- .enter({ opacity: 0 })
419
- .enterTo({ opacity: 1 })
420
- .enterTransition('opacity 300ms ease')
421
- .leave({ opacity: 1 })
422
- .leaveTo({ opacity: 0 })
423
- .leaveTransition('opacity 200ms ease-in')
424
-
425
- const el = document.createElement('div')
426
- const vnode = resolveComponent(Slide({ show, children: 'Hello' }))
427
- wireRef(vnode, el)
428
-
429
- show.set(false)
430
-
431
- expect(el.style.opacity).toBe('1')
432
- expect(el.style.transition).toBe('opacity 200ms ease-in')
433
-
434
- flushRaf()
435
- flushRaf()
436
-
437
- expect(el.style.opacity).toBe('0')
438
- })
439
- })
440
-
441
- // ─── Config defaults ──────────────────────────────────────
442
-
443
- describe('kinetic() — config defaults and overrides', () => {
444
- it('appear from config is used when runtime appear not provided', () => {
445
- const onEnter = vi.fn()
446
- const show = signal(true)
447
- const FadeDiv = kinetic('div').preset(fade).config({ appear: true })
448
-
449
- const el = document.createElement('div')
450
- const vnode = resolveComponent(FadeDiv({ show, onEnter, children: 'Hello' }))
451
- wireRef(vnode, el)
452
-
453
- expect(onEnter).toHaveBeenCalledTimes(1)
454
- })
455
-
456
- it('runtime appear overrides config appear', () => {
457
- const onEnter = vi.fn()
458
- const show = signal(true)
459
- const FadeDiv = kinetic('div').preset(fade).config({ appear: true })
460
-
461
- const el = document.createElement('div')
462
- const vnode = resolveComponent(FadeDiv({ show, appear: false, onEnter, children: 'Hello' }))
463
- wireRef(vnode, el)
464
-
465
- expect(onEnter).not.toHaveBeenCalled()
466
- })
467
-
468
- it('timeout from config is used as fallback', () => {
469
- const onAfterEnter = vi.fn()
470
- const show = signal(false)
471
- const FadeDiv = kinetic('div').preset(fade).config({ timeout: 200 })
472
-
473
- const el = document.createElement('div')
474
- const vnode = resolveComponent(FadeDiv({ show, onAfterEnter, children: 'Hello' }))
475
- wireRef(vnode, el)
476
-
477
- show.set(true)
478
-
479
- flushRaf()
480
- flushRaf()
481
-
482
- // No transitionend fired — timeout from config (200ms) should fire
483
- vi.advanceTimersByTime(200)
484
-
485
- expect(onAfterEnter).toHaveBeenCalledTimes(1)
486
- })
487
-
488
- it('runtime timeout overrides config timeout', () => {
489
- const onAfterEnter = vi.fn()
490
- const show = signal(false)
491
- const FadeDiv = kinetic('div').preset(fade).config({ timeout: 200 })
492
-
493
- const el = document.createElement('div')
494
- const vnode = resolveComponent(FadeDiv({ show, timeout: 500, onAfterEnter, children: 'Hello' }))
495
- wireRef(vnode, el)
496
-
497
- show.set(true)
498
-
499
- flushRaf()
500
- flushRaf()
501
-
502
- // 200ms from config should NOT trigger since runtime is 500ms
503
- vi.advanceTimersByTime(200)
504
- expect(onAfterEnter).not.toHaveBeenCalled()
505
-
506
- vi.advanceTimersByTime(300)
507
- expect(onAfterEnter).toHaveBeenCalledTimes(1)
508
- })
509
- })
510
-
511
- // ─── DisplayName ───────────────────────────────────────────
512
-
513
- describe('kinetic() — displayName', () => {
514
- it('uses tag string for displayName', () => {
515
- const FadeDiv = kinetic('div').preset(fade)
516
- expect(FadeDiv.displayName).toBe('kinetic(div)')
517
- })
518
- })
519
-
520
- // ─── Reduced Motion ───────────────────────────────────────
521
-
522
- describe('kinetic() — transition reduced motion', () => {
523
- beforeEach(() => {
524
- _reducedMotion = true
525
- })
526
-
527
- afterEach(() => {
528
- _reducedMotion = false
529
- })
530
-
531
- it('reduced motion: entering fires onEnter and onAfterEnter immediately without rAF', () => {
532
- const show = signal(false)
533
- const onEnter = vi.fn()
534
- const onAfterEnter = vi.fn()
535
- const FadeDiv = kinetic('div').preset(fade)
536
-
537
- const el = document.createElement('div')
538
- const vnode = resolveComponent(FadeDiv({ show, onEnter, onAfterEnter, children: 'Hello' }))
539
- wireRef(vnode, el)
540
-
541
- show.set(true)
542
-
543
- expect(onEnter).toHaveBeenCalledTimes(1)
544
- expect(onAfterEnter).toHaveBeenCalledTimes(1)
545
- // No rAF should have been used
546
- expect(rafCallbacks.length).toBe(0)
547
- })
548
-
549
- it('reduced motion: leaving fires onLeave and onAfterLeave immediately without rAF', () => {
550
- const show = signal(true)
551
- const onLeave = vi.fn()
552
- const onAfterLeave = vi.fn()
553
- const FadeDiv = kinetic('div').preset(fade)
554
-
555
- const el = document.createElement('div')
556
- const vnode = resolveComponent(FadeDiv({ show, onLeave, onAfterLeave, children: 'Hello' }))
557
- wireRef(vnode, el)
558
-
559
- show.set(false)
560
-
561
- expect(onLeave).toHaveBeenCalledTimes(1)
562
- expect(onAfterLeave).toHaveBeenCalledTimes(1)
563
- expect(rafCallbacks.length).toBe(0)
564
- })
565
- })
@@ -1,46 +0,0 @@
1
- import { fade, presets, scaleIn, slideDown, slideLeft, slideRight, slideUp } from '../presets'
2
-
3
- describe('presets', () => {
4
- const allPresets = {
5
- fade,
6
- scaleIn,
7
- slideUp,
8
- slideDown,
9
- slideLeft,
10
- slideRight,
11
- }
12
-
13
- it.each(Object.entries(allPresets))('%s has all required style properties', (_, preset) => {
14
- expect(preset.enterStyle).toBeDefined()
15
- expect(preset.enterToStyle).toBeDefined()
16
- expect(preset.enterTransition).toBeDefined()
17
- expect(preset.leaveStyle).toBeDefined()
18
- expect(preset.leaveToStyle).toBeDefined()
19
- expect(preset.leaveTransition).toBeDefined()
20
- })
21
-
22
- it.each(Object.entries(allPresets))('%s has non-empty transition strings', (_, preset) => {
23
- expect(typeof preset.enterTransition).toBe('string')
24
- expect((preset.enterTransition as string).length).toBeGreaterThan(0)
25
- expect(typeof preset.leaveTransition).toBe('string')
26
- expect((preset.leaveTransition as string).length).toBeGreaterThan(0)
27
- })
28
-
29
- it('presets object contains all expected presets', () => {
30
- expect(Object.keys(presets)).toEqual([
31
- 'fade',
32
- 'scaleIn',
33
- 'slideUp',
34
- 'slideDown',
35
- 'slideLeft',
36
- 'slideRight',
37
- ])
38
- })
39
-
40
- it('presets are plain objects (no side effects)', () => {
41
- for (const preset of Object.values(presets)) {
42
- expect(typeof preset).toBe('object')
43
- expect(preset).not.toBeInstanceOf(Array)
44
- }
45
- })
46
- })