@object-ui/react 3.1.5 → 3.3.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/CHANGELOG.md +25 -0
- package/README.md +28 -3
- package/dist/SchemaRenderer.js +2 -2
- package/dist/components/form/FieldFactory.js +5 -2
- package/dist/context/AppShellContext.d.ts +26 -0
- package/dist/context/AppShellContext.js +67 -0
- package/dist/context/index.d.ts +1 -7
- package/dist/context/index.js +1 -7
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useDataRefresh.d.ts +36 -0
- package/dist/hooks/useDataRefresh.js +50 -0
- package/dist/hooks/useDiscovery.d.ts +12 -0
- package/dist/hooks/useDiscovery.js +6 -0
- package/dist/hooks/usePerformanceBudget.js +1 -1
- package/package.json +32 -9
- package/.turbo/turbo-build.log +0 -4
- package/src/LazyPluginLoader.tsx +0 -174
- package/src/SchemaRenderer.tsx +0 -266
- package/src/__tests__/LazyPluginLoader.test.tsx +0 -176
- package/src/__tests__/SchemaRenderer.aria.test.tsx +0 -118
- package/src/__tests__/SchemaRenderer.debug.test.tsx +0 -69
- package/src/__tests__/SchemaRenderer.errorBoundary.test.tsx +0 -114
- package/src/__tests__/SchemaRenderer.expressions.test.tsx +0 -131
- package/src/__tests__/SchemaRendererProvider.smoke.test.tsx +0 -132
- package/src/__tests__/ThemeProvider.test.tsx +0 -451
- package/src/__tests__/useNavigationOverlay.test.ts +0 -578
- package/src/__tests__/useOffline.test.ts +0 -198
- package/src/__tests__/usePageTransition.test.ts +0 -214
- package/src/__tests__/usePageVariables.test.tsx +0 -334
- package/src/__tests__/usePerformance.test.ts +0 -137
- package/src/__tests__/useViewData.test.tsx +0 -422
- package/src/__tests__/view-switching.test.tsx +0 -456
- package/src/components/form/FieldFactory.tsx +0 -509
- package/src/components/form/FormRenderer.test.tsx +0 -744
- package/src/components/form/FormRenderer.tsx +0 -258
- package/src/components/form/README.md +0 -352
- package/src/components/form/index.ts +0 -12
- package/src/context/ActionContext.tsx +0 -213
- package/src/context/DndContext.tsx +0 -260
- package/src/context/NotificationContext.tsx +0 -280
- package/src/context/SchemaRendererContext.tsx +0 -48
- package/src/context/ThemeContext.tsx +0 -325
- package/src/context/__tests__/ActionContext.test.tsx +0 -174
- package/src/context/__tests__/DndContext.test.tsx +0 -150
- package/src/context/__tests__/NotificationContext.test.tsx +0 -176
- package/src/context/__tests__/useDataScope.test.tsx +0 -91
- package/src/context/index.ts +0 -13
- package/src/hooks/__tests__/useActionEngine.test.ts +0 -170
- package/src/hooks/__tests__/useActionRunner.test.ts +0 -153
- package/src/hooks/__tests__/useAnimation.test.ts +0 -82
- package/src/hooks/__tests__/useColumnSummary.test.ts +0 -93
- package/src/hooks/__tests__/useCrudShortcuts.test.ts +0 -85
- package/src/hooks/__tests__/useDebugMode.test.ts +0 -83
- package/src/hooks/__tests__/useDensityMode.test.ts +0 -81
- package/src/hooks/__tests__/useDiscovery.test.tsx +0 -149
- package/src/hooks/__tests__/useDynamicApp.test.ts +0 -161
- package/src/hooks/__tests__/useETagCache.test.ts +0 -153
- package/src/hooks/__tests__/useExpression.test.ts +0 -86
- package/src/hooks/__tests__/useFocusTrap.test.ts +0 -294
- package/src/hooks/__tests__/useKeyboardShortcuts.test.ts +0 -144
- package/src/hooks/__tests__/usePageTransition.test.ts +0 -158
- package/src/hooks/__tests__/usePerformanceBudget.test.ts +0 -157
- package/src/hooks/__tests__/useReducedMotion.test.ts +0 -104
- package/src/hooks/__tests__/useSchemaPersistence.test.ts +0 -220
- package/src/hooks/__tests__/useViewSharing.test.ts +0 -121
- package/src/hooks/__tests__/useViewTransition.test.ts +0 -61
- package/src/hooks/index.ts +0 -35
- package/src/hooks/useActionEngine.ts +0 -84
- package/src/hooks/useActionRunner.ts +0 -119
- package/src/hooks/useAnimation.ts +0 -117
- package/src/hooks/useClientNotifications.ts +0 -251
- package/src/hooks/useColumnSummary.ts +0 -87
- package/src/hooks/useCrudShortcuts.ts +0 -126
- package/src/hooks/useDebugMode.ts +0 -95
- package/src/hooks/useDensityMode.ts +0 -102
- package/src/hooks/useDiscovery.ts +0 -154
- package/src/hooks/useDynamicApp.ts +0 -142
- package/src/hooks/useETagCache.ts +0 -404
- package/src/hooks/useExpression.ts +0 -56
- package/src/hooks/useFocusManagement.ts +0 -248
- package/src/hooks/useFocusTrap.ts +0 -138
- package/src/hooks/useGlobalUndo.ts +0 -98
- package/src/hooks/useKeyboardShortcuts.ts +0 -119
- package/src/hooks/useNavigationOverlay.ts +0 -190
- package/src/hooks/useOffline.ts +0 -301
- package/src/hooks/usePageTransition.ts +0 -187
- package/src/hooks/usePageVariables.tsx +0 -157
- package/src/hooks/usePerformance.ts +0 -246
- package/src/hooks/usePerformanceBudget.ts +0 -313
- package/src/hooks/useReducedMotion.ts +0 -53
- package/src/hooks/useSchemaPersistence.ts +0 -222
- package/src/hooks/useViewData.ts +0 -201
- package/src/hooks/useViewSharing.ts +0 -140
- package/src/hooks/useViewTransition.ts +0 -144
- package/src/index.ts +0 -41
- package/src/spec-bridge/SpecBridge.ts +0 -64
- package/src/spec-bridge/__tests__/P1SpecBridge.test.ts +0 -855
- package/src/spec-bridge/__tests__/SpecBridge.test.ts +0 -550
- package/src/spec-bridge/bridges/dashboard.ts +0 -180
- package/src/spec-bridge/bridges/form-view.ts +0 -109
- package/src/spec-bridge/bridges/list-view.ts +0 -187
- package/src/spec-bridge/bridges/page.ts +0 -136
- package/src/spec-bridge/index.ts +0 -14
- package/src/spec-bridge/types.ts +0 -38
- package/src/utils/i18n.ts +0 -10
- package/tsconfig.json +0 -17
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -2
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI — useOffline Tests
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
10
|
-
import { renderHook, act } from '@testing-library/react';
|
|
11
|
-
import { useOffline } from '../hooks/useOffline';
|
|
12
|
-
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// Helpers
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
|
|
17
|
-
const QUEUE_KEY = 'objectui-offline-queue';
|
|
18
|
-
|
|
19
|
-
function mockOnlineStatus(online: boolean) {
|
|
20
|
-
Object.defineProperty(navigator, 'onLine', {
|
|
21
|
-
value: online,
|
|
22
|
-
configurable: true,
|
|
23
|
-
writable: true,
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function triggerOnline() {
|
|
28
|
-
mockOnlineStatus(true);
|
|
29
|
-
window.dispatchEvent(new Event('online'));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function triggerOffline() {
|
|
33
|
-
mockOnlineStatus(false);
|
|
34
|
-
window.dispatchEvent(new Event('offline'));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
// Tests
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
|
|
41
|
-
describe('useOffline', () => {
|
|
42
|
-
beforeEach(() => {
|
|
43
|
-
mockOnlineStatus(true);
|
|
44
|
-
localStorage.removeItem(QUEUE_KEY);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
afterEach(() => {
|
|
48
|
-
vi.restoreAllMocks();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should default to online with empty queue', () => {
|
|
52
|
-
const { result } = renderHook(() => useOffline());
|
|
53
|
-
expect(result.current.isOnline).toBe(true);
|
|
54
|
-
expect(result.current.enabled).toBe(true);
|
|
55
|
-
expect(result.current.syncState).toBe('idle');
|
|
56
|
-
expect(result.current.pendingCount).toBe(0);
|
|
57
|
-
expect(result.current.showIndicator).toBe(false);
|
|
58
|
-
expect(result.current.strategy).toBe('network_first');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should detect offline status', () => {
|
|
62
|
-
const { result } = renderHook(() => useOffline());
|
|
63
|
-
expect(result.current.isOnline).toBe(true);
|
|
64
|
-
|
|
65
|
-
act(() => {
|
|
66
|
-
triggerOffline();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
expect(result.current.isOnline).toBe(false);
|
|
70
|
-
expect(result.current.showIndicator).toBe(true);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should detect coming back online', () => {
|
|
74
|
-
mockOnlineStatus(false);
|
|
75
|
-
const { result } = renderHook(() => useOffline());
|
|
76
|
-
expect(result.current.isOnline).toBe(false);
|
|
77
|
-
|
|
78
|
-
act(() => {
|
|
79
|
-
triggerOnline();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
expect(result.current.isOnline).toBe(true);
|
|
83
|
-
expect(result.current.showIndicator).toBe(false);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should queue mutations', () => {
|
|
87
|
-
const { result } = renderHook(() => useOffline());
|
|
88
|
-
|
|
89
|
-
act(() => {
|
|
90
|
-
result.current.queueMutation({
|
|
91
|
-
operation: 'create',
|
|
92
|
-
resource: 'users',
|
|
93
|
-
data: { name: 'Alice' },
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
expect(result.current.pendingCount).toBe(1);
|
|
98
|
-
|
|
99
|
-
act(() => {
|
|
100
|
-
result.current.queueMutation({
|
|
101
|
-
operation: 'update',
|
|
102
|
-
resource: 'users',
|
|
103
|
-
data: { id: '1', name: 'Bob' },
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
expect(result.current.pendingCount).toBe(2);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('should clear the mutation queue', () => {
|
|
111
|
-
const { result } = renderHook(() => useOffline());
|
|
112
|
-
|
|
113
|
-
act(() => {
|
|
114
|
-
result.current.queueMutation({ operation: 'create', resource: 'users' });
|
|
115
|
-
result.current.queueMutation({ operation: 'delete', resource: 'users' });
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
expect(result.current.pendingCount).toBe(2);
|
|
119
|
-
|
|
120
|
-
act(() => {
|
|
121
|
-
result.current.clearQueue();
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
expect(result.current.pendingCount).toBe(0);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should enforce queueMaxSize', () => {
|
|
128
|
-
const { result } = renderHook(() => useOffline({ queueMaxSize: 2 }));
|
|
129
|
-
|
|
130
|
-
act(() => {
|
|
131
|
-
result.current.queueMutation({ operation: 'create', resource: 'a' });
|
|
132
|
-
result.current.queueMutation({ operation: 'create', resource: 'b' });
|
|
133
|
-
result.current.queueMutation({ operation: 'create', resource: 'c' });
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
expect(result.current.pendingCount).toBe(2);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('should respect custom config values', () => {
|
|
140
|
-
const { result } = renderHook(() =>
|
|
141
|
-
useOffline({
|
|
142
|
-
strategy: 'cache_first',
|
|
143
|
-
offlineIndicator: false,
|
|
144
|
-
offlineMessage: 'Custom message',
|
|
145
|
-
}),
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
expect(result.current.strategy).toBe('cache_first');
|
|
149
|
-
expect(result.current.offlineMessage).toBe('Custom message');
|
|
150
|
-
|
|
151
|
-
act(() => {
|
|
152
|
-
triggerOffline();
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// offlineIndicator is false, so showIndicator should be false even when offline
|
|
156
|
-
expect(result.current.showIndicator).toBe(false);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('should not queue mutations when disabled', () => {
|
|
160
|
-
const { result } = renderHook(() => useOffline({ enabled: false }));
|
|
161
|
-
|
|
162
|
-
act(() => {
|
|
163
|
-
result.current.queueMutation({ operation: 'create', resource: 'users' });
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
expect(result.current.pendingCount).toBe(0);
|
|
167
|
-
expect(result.current.enabled).toBe(false);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it('should sync mutations', async () => {
|
|
171
|
-
const { result } = renderHook(() => useOffline());
|
|
172
|
-
|
|
173
|
-
act(() => {
|
|
174
|
-
result.current.queueMutation({ operation: 'create', resource: 'users' });
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
expect(result.current.pendingCount).toBe(1);
|
|
178
|
-
|
|
179
|
-
await act(async () => {
|
|
180
|
-
await result.current.sync();
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
expect(result.current.pendingCount).toBe(0);
|
|
184
|
-
expect(result.current.syncState).toBe('idle');
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it('should persist queue to localStorage', () => {
|
|
188
|
-
const { result } = renderHook(() => useOffline());
|
|
189
|
-
|
|
190
|
-
act(() => {
|
|
191
|
-
result.current.queueMutation({ operation: 'create', resource: 'users' });
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
const stored = JSON.parse(localStorage.getItem(QUEUE_KEY) || '[]');
|
|
195
|
-
expect(stored).toHaveLength(1);
|
|
196
|
-
expect(stored[0].resource).toBe('users');
|
|
197
|
-
});
|
|
198
|
-
});
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI — usePageTransition Tests
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
10
|
-
import { renderHook } from '@testing-library/react';
|
|
11
|
-
import { usePageTransition } from '../hooks/usePageTransition';
|
|
12
|
-
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// matchMedia mock helper
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
|
|
17
|
-
function mockMatchMedia(reducedMotion: boolean) {
|
|
18
|
-
const listeners: Array<(e: MediaQueryListEvent) => void> = [];
|
|
19
|
-
const mql = {
|
|
20
|
-
matches: reducedMotion,
|
|
21
|
-
media: '(prefers-reduced-motion: reduce)',
|
|
22
|
-
addEventListener: (_: string, cb: (e: MediaQueryListEvent) => void) => {
|
|
23
|
-
listeners.push(cb);
|
|
24
|
-
},
|
|
25
|
-
removeEventListener: (_: string, cb: (e: MediaQueryListEvent) => void) => {
|
|
26
|
-
const idx = listeners.indexOf(cb);
|
|
27
|
-
if (idx >= 0) listeners.splice(idx, 1);
|
|
28
|
-
},
|
|
29
|
-
addListener: vi.fn(),
|
|
30
|
-
removeListener: vi.fn(),
|
|
31
|
-
onchange: null,
|
|
32
|
-
dispatchEvent: vi.fn(),
|
|
33
|
-
} as unknown as MediaQueryList;
|
|
34
|
-
|
|
35
|
-
Object.defineProperty(window, 'matchMedia', {
|
|
36
|
-
writable: true,
|
|
37
|
-
configurable: true,
|
|
38
|
-
value: vi.fn().mockReturnValue(mql),
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
return { mql, listeners };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
// Tests
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
|
|
48
|
-
describe('usePageTransition', () => {
|
|
49
|
-
beforeEach(() => {
|
|
50
|
-
mockMatchMedia(false);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
afterEach(() => {
|
|
54
|
-
vi.restoreAllMocks();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('should return inactive result for default (none) type', () => {
|
|
58
|
-
const { result } = renderHook(() => usePageTransition());
|
|
59
|
-
|
|
60
|
-
expect(result.current.isActive).toBe(false);
|
|
61
|
-
expect(result.current.type).toBe('none');
|
|
62
|
-
expect(result.current.enterClassName).toBe('');
|
|
63
|
-
expect(result.current.exitClassName).toBe('');
|
|
64
|
-
expect(result.current.enterStyle).toEqual({});
|
|
65
|
-
expect(result.current.exitStyle).toEqual({});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should generate fade transition classes', () => {
|
|
69
|
-
const { result } = renderHook(() =>
|
|
70
|
-
usePageTransition({ type: 'fade', duration: 200 }),
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
expect(result.current.isActive).toBe(true);
|
|
74
|
-
expect(result.current.enterClassName).toContain('animate-in');
|
|
75
|
-
expect(result.current.enterClassName).toContain('fade-in');
|
|
76
|
-
expect(result.current.exitClassName).toContain('animate-out');
|
|
77
|
-
expect(result.current.exitClassName).toContain('fade-out');
|
|
78
|
-
expect(result.current.enterStyle.animationDuration).toBe('200ms');
|
|
79
|
-
expect(result.current.duration).toBe(200);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('should generate slide_up transition classes', () => {
|
|
83
|
-
const { result } = renderHook(() =>
|
|
84
|
-
usePageTransition({ type: 'slide_up' }),
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
expect(result.current.isActive).toBe(true);
|
|
88
|
-
expect(result.current.enterClassName).toContain('slide-in-from-bottom');
|
|
89
|
-
expect(result.current.exitClassName).toContain('slide-out-to-top');
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('should generate slide_down transition classes', () => {
|
|
93
|
-
const { result } = renderHook(() =>
|
|
94
|
-
usePageTransition({ type: 'slide_down' }),
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
expect(result.current.enterClassName).toContain('slide-in-from-top');
|
|
98
|
-
expect(result.current.exitClassName).toContain('slide-out-to-bottom');
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should generate slide_left transition classes', () => {
|
|
102
|
-
const { result } = renderHook(() =>
|
|
103
|
-
usePageTransition({ type: 'slide_left' }),
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
expect(result.current.enterClassName).toContain('slide-in-from-right');
|
|
107
|
-
expect(result.current.exitClassName).toContain('slide-out-to-left');
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('should generate slide_right transition classes', () => {
|
|
111
|
-
const { result } = renderHook(() =>
|
|
112
|
-
usePageTransition({ type: 'slide_right' }),
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
expect(result.current.enterClassName).toContain('slide-in-from-left');
|
|
116
|
-
expect(result.current.exitClassName).toContain('slide-out-to-right');
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should generate scale transition classes', () => {
|
|
120
|
-
const { result } = renderHook(() =>
|
|
121
|
-
usePageTransition({ type: 'scale' }),
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
expect(result.current.enterClassName).toContain('zoom-in');
|
|
125
|
-
expect(result.current.exitClassName).toContain('zoom-out');
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('should generate rotate transition classes', () => {
|
|
129
|
-
const { result } = renderHook(() =>
|
|
130
|
-
usePageTransition({ type: 'rotate' }),
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
expect(result.current.enterClassName).toContain('spin-in');
|
|
134
|
-
expect(result.current.exitClassName).toContain('spin-out');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should generate flip transition classes', () => {
|
|
138
|
-
const { result } = renderHook(() =>
|
|
139
|
-
usePageTransition({ type: 'flip' }),
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
expect(result.current.isActive).toBe(true);
|
|
143
|
-
expect(result.current.enterClassName).toContain('fade-in');
|
|
144
|
-
expect(result.current.exitClassName).toContain('fade-out');
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should apply custom easing', () => {
|
|
148
|
-
const { result } = renderHook(() =>
|
|
149
|
-
usePageTransition({ type: 'fade', easing: 'spring' }),
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
expect(result.current.enterStyle.animationTimingFunction).toBe(
|
|
153
|
-
'cubic-bezier(0.34, 1.56, 0.64, 1)',
|
|
154
|
-
);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should apply custom duration', () => {
|
|
158
|
-
const { result } = renderHook(() =>
|
|
159
|
-
usePageTransition({ type: 'fade', duration: 500 }),
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
expect(result.current.enterStyle.animationDuration).toBe('500ms');
|
|
163
|
-
expect(result.current.duration).toBe(500);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('should use default duration of 300ms', () => {
|
|
167
|
-
const { result } = renderHook(() =>
|
|
168
|
-
usePageTransition({ type: 'fade' }),
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
expect(result.current.duration).toBe(300);
|
|
172
|
-
expect(result.current.enterStyle.animationDuration).toBe('300ms');
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('should disable transitions when reduced motion is preferred', () => {
|
|
176
|
-
mockMatchMedia(true);
|
|
177
|
-
|
|
178
|
-
const { result } = renderHook(() =>
|
|
179
|
-
usePageTransition({ type: 'fade', duration: 200 }),
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
expect(result.current.isActive).toBe(false);
|
|
183
|
-
expect(result.current.enterClassName).toBe('');
|
|
184
|
-
expect(result.current.exitClassName).toBe('');
|
|
185
|
-
expect(result.current.enterStyle).toEqual({});
|
|
186
|
-
expect(result.current.exitStyle).toEqual({});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
it('should set animationFillMode to both', () => {
|
|
190
|
-
const { result } = renderHook(() =>
|
|
191
|
-
usePageTransition({ type: 'fade' }),
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
expect(result.current.enterStyle.animationFillMode).toBe('both');
|
|
195
|
-
expect(result.current.exitStyle.animationFillMode).toBe('both');
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('should support all easing values', () => {
|
|
199
|
-
const easings = [
|
|
200
|
-
{ input: 'linear' as const, expected: 'linear' },
|
|
201
|
-
{ input: 'ease' as const, expected: 'ease' },
|
|
202
|
-
{ input: 'ease_in' as const, expected: 'ease-in' },
|
|
203
|
-
{ input: 'ease_out' as const, expected: 'ease-out' },
|
|
204
|
-
{ input: 'ease_in_out' as const, expected: 'ease-in-out' },
|
|
205
|
-
];
|
|
206
|
-
|
|
207
|
-
for (const { input, expected } of easings) {
|
|
208
|
-
const { result } = renderHook(() =>
|
|
209
|
-
usePageTransition({ type: 'fade', easing: input }),
|
|
210
|
-
);
|
|
211
|
-
expect(result.current.enterStyle.animationTimingFunction).toBe(expected);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
});
|