@pie-lib/drag 3.1.1-next.0 → 3.1.1-next.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.
@@ -0,0 +1,313 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { DragProvider } from '../drag-provider';
4
+
5
+ jest.mock('@dnd-kit/core', () => ({
6
+ DndContext: ({ children, onDragStart, onDragEnd, sensors, collisionDetection, modifiers, autoScroll }) => (
7
+ <div
8
+ data-testid="dnd-context"
9
+ data-has-sensors={!!sensors}
10
+ data-has-collision-detection={!!collisionDetection}
11
+ data-has-modifiers={!!modifiers}
12
+ data-has-auto-scroll={!!autoScroll}
13
+ data-on-drag-start={typeof onDragStart === 'function' ? 'function' : 'undefined'}
14
+ data-on-drag-end={typeof onDragEnd === 'function' ? 'function' : 'undefined'}
15
+ >
16
+ {children}
17
+ </div>
18
+ ),
19
+ PointerSensor: 'PointerSensor',
20
+ KeyboardSensor: 'KeyboardSensor',
21
+ useSensor: jest.fn((sensor, config) => ({ sensor, config })),
22
+ useSensors: jest.fn((...sensors) => sensors),
23
+ }));
24
+
25
+ describe('DragProvider', () => {
26
+ const defaultProps = {
27
+ children: <div data-testid="test-child">Test Content</div>,
28
+ };
29
+
30
+ beforeEach(() => {
31
+ jest.clearAllMocks();
32
+ });
33
+
34
+ describe('rendering', () => {
35
+ it('should render children correctly', () => {
36
+ render(<DragProvider {...defaultProps} />);
37
+ expect(screen.getByTestId('test-child')).toBeInTheDocument();
38
+ expect(screen.getByText('Test Content')).toBeInTheDocument();
39
+ });
40
+
41
+ it('should render multiple children', () => {
42
+ render(
43
+ <DragProvider>
44
+ <div data-testid="child-1">Child 1</div>
45
+ <div data-testid="child-2">Child 2</div>
46
+ </DragProvider>,
47
+ );
48
+ expect(screen.getByTestId('child-1')).toBeInTheDocument();
49
+ expect(screen.getByTestId('child-2')).toBeInTheDocument();
50
+ });
51
+
52
+ it('should wrap children in DndContext', () => {
53
+ render(<DragProvider {...defaultProps} />);
54
+ const dndContext = screen.getByTestId('dnd-context');
55
+ expect(dndContext).toBeInTheDocument();
56
+ expect(dndContext).toContainElement(screen.getByTestId('test-child'));
57
+ });
58
+
59
+ it('should render with complex children', () => {
60
+ render(
61
+ <DragProvider>
62
+ <div>
63
+ <span data-testid="nested">Nested</span>
64
+ <ul>
65
+ <li data-testid="list-item">Item</li>
66
+ </ul>
67
+ </div>
68
+ </DragProvider>,
69
+ );
70
+ expect(screen.getByTestId('nested')).toBeInTheDocument();
71
+ expect(screen.getByTestId('list-item')).toBeInTheDocument();
72
+ });
73
+ });
74
+
75
+ describe('DndContext props', () => {
76
+ it('should pass sensors to DndContext', () => {
77
+ render(<DragProvider {...defaultProps} />);
78
+ const dndContext = screen.getByTestId('dnd-context');
79
+ expect(dndContext).toHaveAttribute('data-has-sensors', 'true');
80
+ });
81
+
82
+ it('should pass onDragStart handler to DndContext', () => {
83
+ const onDragStart = jest.fn();
84
+ render(<DragProvider {...defaultProps} onDragStart={onDragStart} />);
85
+ const dndContext = screen.getByTestId('dnd-context');
86
+ expect(dndContext).toHaveAttribute('data-on-drag-start', 'function');
87
+ });
88
+
89
+ it('should pass onDragEnd handler to DndContext', () => {
90
+ const onDragEnd = jest.fn();
91
+ render(<DragProvider {...defaultProps} onDragEnd={onDragEnd} />);
92
+ const dndContext = screen.getByTestId('dnd-context');
93
+ expect(dndContext).toHaveAttribute('data-on-drag-end', 'function');
94
+ });
95
+
96
+ it('should pass collisionDetection to DndContext', () => {
97
+ const collisionDetection = jest.fn();
98
+ render(<DragProvider {...defaultProps} collisionDetection={collisionDetection} />);
99
+ const dndContext = screen.getByTestId('dnd-context');
100
+ expect(dndContext).toHaveAttribute('data-has-collision-detection', 'true');
101
+ });
102
+
103
+ it('should pass modifiers to DndContext', () => {
104
+ const modifiers = [jest.fn()];
105
+ render(<DragProvider {...defaultProps} modifiers={modifiers} />);
106
+ const dndContext = screen.getByTestId('dnd-context');
107
+ expect(dndContext).toHaveAttribute('data-has-modifiers', 'true');
108
+ });
109
+
110
+ it('should pass autoScroll to DndContext', () => {
111
+ const autoScroll = { enabled: true };
112
+ render(<DragProvider {...defaultProps} autoScroll={autoScroll} />);
113
+ const dndContext = screen.getByTestId('dnd-context');
114
+ expect(dndContext).toHaveAttribute('data-has-auto-scroll', 'true');
115
+ });
116
+
117
+ it('should pass all props to DndContext', () => {
118
+ const onDragStart = jest.fn();
119
+ const onDragEnd = jest.fn();
120
+ const collisionDetection = jest.fn();
121
+ const modifiers = [jest.fn()];
122
+ const autoScroll = { enabled: true };
123
+
124
+ render(
125
+ <DragProvider
126
+ {...defaultProps}
127
+ onDragStart={onDragStart}
128
+ onDragEnd={onDragEnd}
129
+ collisionDetection={collisionDetection}
130
+ modifiers={modifiers}
131
+ autoScroll={autoScroll}
132
+ />,
133
+ );
134
+
135
+ const dndContext = screen.getByTestId('dnd-context');
136
+ expect(dndContext).toHaveAttribute('data-on-drag-start', 'function');
137
+ expect(dndContext).toHaveAttribute('data-on-drag-end', 'function');
138
+ expect(dndContext).toHaveAttribute('data-has-collision-detection', 'true');
139
+ expect(dndContext).toHaveAttribute('data-has-modifiers', 'true');
140
+ expect(dndContext).toHaveAttribute('data-has-auto-scroll', 'true');
141
+ });
142
+ });
143
+
144
+ describe('optional props', () => {
145
+ it('should work without onDragStart', () => {
146
+ expect(() => {
147
+ render(<DragProvider {...defaultProps} />);
148
+ }).not.toThrow();
149
+ });
150
+
151
+ it('should work without onDragEnd', () => {
152
+ expect(() => {
153
+ render(<DragProvider {...defaultProps} />);
154
+ }).not.toThrow();
155
+ });
156
+
157
+ it('should work without collisionDetection', () => {
158
+ render(<DragProvider {...defaultProps} />);
159
+ const dndContext = screen.getByTestId('dnd-context');
160
+ expect(dndContext).toHaveAttribute('data-has-collision-detection', 'false');
161
+ });
162
+
163
+ it('should work without modifiers', () => {
164
+ render(<DragProvider {...defaultProps} />);
165
+ const dndContext = screen.getByTestId('dnd-context');
166
+ expect(dndContext).toHaveAttribute('data-has-modifiers', 'false');
167
+ });
168
+
169
+ it('should work without autoScroll', () => {
170
+ render(<DragProvider {...defaultProps} />);
171
+ const dndContext = screen.getByTestId('dnd-context');
172
+ expect(dndContext).toHaveAttribute('data-has-auto-scroll', 'false');
173
+ });
174
+ });
175
+
176
+ describe('sensors setup', () => {
177
+ it('should initialize PointerSensor with activation constraint', () => {
178
+ const { useSensor } = require('@dnd-kit/core');
179
+ render(<DragProvider {...defaultProps} />);
180
+
181
+ expect(useSensor).toHaveBeenCalledWith('PointerSensor', { activationConstraint: { distance: 8 } });
182
+ });
183
+
184
+ it('should initialize KeyboardSensor', () => {
185
+ const { useSensor } = require('@dnd-kit/core');
186
+ render(<DragProvider {...defaultProps} />);
187
+
188
+ expect(useSensor).toHaveBeenCalledWith('KeyboardSensor');
189
+ });
190
+
191
+ it('should combine sensors with useSensors', () => {
192
+ const { useSensors } = require('@dnd-kit/core');
193
+ render(<DragProvider {...defaultProps} />);
194
+
195
+ expect(useSensors).toHaveBeenCalled();
196
+ });
197
+ });
198
+
199
+ describe('re-rendering', () => {
200
+ it('should update children when they change', () => {
201
+ const { rerender } = render(<DragProvider {...defaultProps} />);
202
+ expect(screen.getByText('Test Content')).toBeInTheDocument();
203
+
204
+ rerender(
205
+ <DragProvider>
206
+ <div data-testid="new-child">New Content</div>
207
+ </DragProvider>,
208
+ );
209
+ expect(screen.getByText('New Content')).toBeInTheDocument();
210
+ expect(screen.queryByText('Test Content')).not.toBeInTheDocument();
211
+ });
212
+
213
+ it('should update handlers when they change', () => {
214
+ const onDragStart1 = jest.fn();
215
+ const onDragStart2 = jest.fn();
216
+
217
+ const { rerender } = render(<DragProvider {...defaultProps} onDragStart={onDragStart1} />);
218
+
219
+ rerender(<DragProvider {...defaultProps} onDragStart={onDragStart2} />);
220
+
221
+ // Should still have the handler attribute
222
+ const dndContext = screen.getByTestId('dnd-context');
223
+ expect(dndContext).toHaveAttribute('data-on-drag-start', 'function');
224
+ });
225
+ });
226
+
227
+ describe('edge cases', () => {
228
+ it('should handle fragment children', () => {
229
+ render(
230
+ <DragProvider>
231
+ <>
232
+ <div data-testid="fragment-child-1">First</div>
233
+ <div data-testid="fragment-child-2">Second</div>
234
+ </>
235
+ </DragProvider>,
236
+ );
237
+ expect(screen.getByTestId('fragment-child-1')).toBeInTheDocument();
238
+ expect(screen.getByTestId('fragment-child-2')).toBeInTheDocument();
239
+ });
240
+
241
+ it('should handle null children within array', () => {
242
+ render(
243
+ <DragProvider>
244
+ {[
245
+ <div key="1" data-testid="valid-child">
246
+ Valid
247
+ </div>,
248
+ null,
249
+ <div key="2" data-testid="another-valid">
250
+ Another
251
+ </div>,
252
+ ]}
253
+ </DragProvider>,
254
+ );
255
+ expect(screen.getByTestId('valid-child')).toBeInTheDocument();
256
+ expect(screen.getByTestId('another-valid')).toBeInTheDocument();
257
+ });
258
+
259
+ it('should handle empty modifiers array', () => {
260
+ render(<DragProvider {...defaultProps} modifiers={[]} />);
261
+ const dndContext = screen.getByTestId('dnd-context');
262
+ expect(dndContext).toHaveAttribute('data-has-modifiers', 'true');
263
+ });
264
+
265
+ it('should handle multiple modifier functions', () => {
266
+ const modifiers = [jest.fn(), jest.fn(), jest.fn()];
267
+ render(<DragProvider {...defaultProps} modifiers={modifiers} />);
268
+ const dndContext = screen.getByTestId('dnd-context');
269
+ expect(dndContext).toHaveAttribute('data-has-modifiers', 'true');
270
+ });
271
+ });
272
+
273
+ describe('prop types validation', () => {
274
+ // Suppress console errors for prop type validation tests
275
+ const originalError = console.error;
276
+ beforeAll(() => {
277
+ console.error = jest.fn();
278
+ });
279
+ afterAll(() => {
280
+ console.error = originalError;
281
+ });
282
+
283
+ it('should accept valid children prop', () => {
284
+ expect(() => {
285
+ render(<DragProvider {...defaultProps} />);
286
+ }).not.toThrow();
287
+ });
288
+
289
+ it('should accept function props for callbacks', () => {
290
+ expect(() => {
291
+ render(<DragProvider {...defaultProps} onDragStart={jest.fn()} onDragEnd={jest.fn()} />);
292
+ }).not.toThrow();
293
+ });
294
+
295
+ it('should accept function prop for collisionDetection', () => {
296
+ expect(() => {
297
+ render(<DragProvider {...defaultProps} collisionDetection={jest.fn()} />);
298
+ }).not.toThrow();
299
+ });
300
+
301
+ it('should accept array of functions for modifiers', () => {
302
+ expect(() => {
303
+ render(<DragProvider {...defaultProps} modifiers={[jest.fn(), jest.fn()]} />);
304
+ }).not.toThrow();
305
+ });
306
+
307
+ it('should accept object for autoScroll', () => {
308
+ expect(() => {
309
+ render(<DragProvider {...defaultProps} autoScroll={{ enabled: true }} />);
310
+ }).not.toThrow();
311
+ });
312
+ });
313
+ });