@object-ui/plugin-view 3.3.0 → 3.3.2

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.
@@ -1,705 +0,0 @@
1
- /**
2
- * ObjectUI
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 } from 'vitest';
10
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
11
- import { ObjectView } from '../ObjectView';
12
- import type { ObjectViewSchema, DataSource } from '@object-ui/types';
13
-
14
- // Mock @object-ui/react to avoid circular dependency issues
15
- vi.mock('@object-ui/react', () => ({
16
- SchemaRenderer: ({ schema }: any) => (
17
- <div data-testid="schema-renderer" data-schema-type={schema?.type}>
18
- {schema?.type}
19
- </div>
20
- ),
21
- SchemaRendererContext: null,
22
- }));
23
-
24
- // Mock @object-ui/plugin-grid
25
- vi.mock('@object-ui/plugin-grid', () => ({
26
- ObjectGrid: ({ schema, onRowClick }: any) => (
27
- <div data-testid="object-grid" data-object={schema?.objectName}>
28
- <button data-testid="grid-row" onClick={() => onRowClick?.({ id: '1', name: 'Test' })}>
29
- Row 1
30
- </button>
31
- </div>
32
- ),
33
- }));
34
-
35
- // Mock @object-ui/plugin-form
36
- vi.mock('@object-ui/plugin-form', () => ({
37
- ObjectForm: ({ schema }: any) => (
38
- <div data-testid="object-form" data-mode={schema?.mode}>
39
- Form ({schema?.mode})
40
- </div>
41
- ),
42
- }));
43
-
44
- const createMockDataSource = (overrides: Partial<DataSource> = {}): DataSource => ({
45
- find: vi.fn().mockResolvedValue([]),
46
- findOne: vi.fn().mockResolvedValue(null),
47
- create: vi.fn().mockResolvedValue({}),
48
- update: vi.fn().mockResolvedValue({}),
49
- delete: vi.fn().mockResolvedValue({}),
50
- getObjectSchema: vi.fn().mockResolvedValue({
51
- label: 'Contacts',
52
- fields: {
53
- name: { label: 'Name', type: 'text' },
54
- email: { label: 'Email', type: 'text' },
55
- status: {
56
- label: 'Status',
57
- type: 'select',
58
- options: [
59
- { label: 'Active', value: 'active' },
60
- { label: 'Inactive', value: 'inactive' },
61
- ],
62
- },
63
- created_at: { label: 'Created', type: 'date' },
64
- },
65
- }),
66
- ...overrides,
67
- } as DataSource);
68
-
69
- describe('ObjectView', () => {
70
- let mockDataSource: DataSource;
71
-
72
- beforeEach(() => {
73
- vi.clearAllMocks();
74
- mockDataSource = createMockDataSource();
75
- });
76
-
77
- // ============================
78
- // Basic Rendering
79
- // ============================
80
- describe('Basic Rendering', () => {
81
- it('should render with minimal schema', () => {
82
- const schema: ObjectViewSchema = {
83
- type: 'object-view',
84
- objectName: 'contacts',
85
- };
86
-
87
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
88
-
89
- // Should render the grid by default
90
- expect(screen.getByTestId('object-grid')).toBeDefined();
91
- });
92
-
93
- it('should render title and description', () => {
94
- const schema: ObjectViewSchema = {
95
- type: 'object-view',
96
- objectName: 'contacts',
97
- title: 'Contact List',
98
- description: 'Manage your contacts',
99
- };
100
-
101
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
102
-
103
- expect(screen.getByText('Contact List')).toBeDefined();
104
- expect(screen.getByText('Manage your contacts')).toBeDefined();
105
- });
106
-
107
- it('should not render search box (delegated to ListView toolbar)', () => {
108
- const schema: ObjectViewSchema = {
109
- type: 'object-view',
110
- objectName: 'contacts',
111
- };
112
-
113
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
114
-
115
- expect(screen.queryByPlaceholderText(/search/i)).toBeNull();
116
- });
117
-
118
- it('should not render search box when showSearch is false', () => {
119
- const schema: ObjectViewSchema = {
120
- type: 'object-view',
121
- objectName: 'contacts',
122
- showSearch: false,
123
- };
124
-
125
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
126
-
127
- expect(screen.queryByPlaceholderText(/search/i)).toBeNull();
128
- });
129
-
130
- it('should render create button by default', () => {
131
- const schema: ObjectViewSchema = {
132
- type: 'object-view',
133
- objectName: 'contacts',
134
- };
135
-
136
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
137
-
138
- expect(screen.getByText('Create')).toBeDefined();
139
- });
140
-
141
- it('should hide create button when showCreate is false', () => {
142
- const schema: ObjectViewSchema = {
143
- type: 'object-view',
144
- objectName: 'contacts',
145
- showCreate: false,
146
- };
147
-
148
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
149
-
150
- expect(screen.queryByText('Create')).toBeNull();
151
- });
152
- });
153
-
154
- // ============================
155
- // Named List Views
156
- // ============================
157
- describe('Named List Views', () => {
158
- it('should render named view tabs when listViews has multiple entries', () => {
159
- const schema: ObjectViewSchema = {
160
- type: 'object-view',
161
- objectName: 'contacts',
162
- listViews: {
163
- all: { label: 'All Contacts', type: 'grid' },
164
- active: { label: 'Active', type: 'grid', filter: [['status', '=', 'active']] },
165
- },
166
- defaultListView: 'all',
167
- };
168
-
169
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
170
-
171
- expect(screen.getByText('All Contacts')).toBeDefined();
172
- expect(screen.getByText('Active')).toBeDefined();
173
- });
174
-
175
- it('should not render tabs when only one named view exists', () => {
176
- const schema: ObjectViewSchema = {
177
- type: 'object-view',
178
- objectName: 'contacts',
179
- listViews: {
180
- all: { label: 'All Contacts', type: 'grid' },
181
- },
182
- };
183
-
184
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
185
-
186
- // Should not show tabs for a single view
187
- expect(screen.queryByRole('tablist')).toBeNull();
188
- });
189
-
190
- it('should default to first named view when defaultListView is not set', () => {
191
- const schema: ObjectViewSchema = {
192
- type: 'object-view',
193
- objectName: 'contacts',
194
- listViews: {
195
- all: { label: 'All Contacts', type: 'grid' },
196
- active: { label: 'Active', type: 'grid' },
197
- },
198
- };
199
-
200
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
201
-
202
- // The grid should be rendered (first view is grid type)
203
- expect(screen.getByTestId('object-grid')).toBeDefined();
204
- });
205
- });
206
-
207
- // ============================
208
- // Default View Type
209
- // ============================
210
- describe('Default View Type', () => {
211
- it('should render grid by default when no defaultViewType set', () => {
212
- const schema: ObjectViewSchema = {
213
- type: 'object-view',
214
- objectName: 'contacts',
215
- };
216
-
217
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
218
-
219
- expect(screen.getByTestId('object-grid')).toBeDefined();
220
- });
221
- });
222
-
223
- // ============================
224
- // Navigation Config
225
- // ============================
226
- describe('Navigation Config', () => {
227
- it('should not navigate when mode is none', () => {
228
- const onRowClick = vi.fn();
229
- const schema: ObjectViewSchema = {
230
- type: 'object-view',
231
- objectName: 'contacts',
232
- navigation: { mode: 'none' },
233
- };
234
-
235
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
236
-
237
- // Click a grid row
238
- fireEvent.click(screen.getByTestId('grid-row'));
239
-
240
- // onRowClick should not be called (mode is none)
241
- expect(onRowClick).not.toHaveBeenCalled();
242
- });
243
-
244
- it('should not navigate when preventNavigation is true', () => {
245
- const onRowClick = vi.fn();
246
- const schema: ObjectViewSchema = {
247
- type: 'object-view',
248
- objectName: 'contacts',
249
- navigation: { mode: 'page', preventNavigation: true },
250
- };
251
-
252
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
253
-
254
- fireEvent.click(screen.getByTestId('grid-row'));
255
-
256
- expect(onRowClick).not.toHaveBeenCalled();
257
- });
258
-
259
- it('should open in new window when mode is new_window', () => {
260
- const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null);
261
-
262
- const schema: ObjectViewSchema = {
263
- type: 'object-view',
264
- objectName: 'contacts',
265
- navigation: { mode: 'new_window' },
266
- };
267
-
268
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
269
-
270
- fireEvent.click(screen.getByTestId('grid-row'));
271
-
272
- expect(openSpy).toHaveBeenCalledWith('/contacts/1', '_blank');
273
- openSpy.mockRestore();
274
- });
275
-
276
- it('should call onNavigate for page mode', () => {
277
- const onNavigate = vi.fn();
278
- const schema: ObjectViewSchema = {
279
- type: 'object-view',
280
- objectName: 'contacts',
281
- navigation: { mode: 'page' },
282
- onNavigate,
283
- };
284
-
285
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
286
-
287
- fireEvent.click(screen.getByTestId('grid-row'));
288
-
289
- expect(onNavigate).toHaveBeenCalledWith('1', 'view');
290
- });
291
-
292
- it('should open form in view mode when split navigation mode is clicked', () => {
293
- const schema: ObjectViewSchema = {
294
- type: 'object-view',
295
- objectName: 'contacts',
296
- navigation: { mode: 'split' },
297
- };
298
-
299
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
300
-
301
- fireEvent.click(screen.getByTestId('grid-row'));
302
-
303
- // Split mode renders NavigationOverlay with split panels including a close button
304
- expect(screen.getByTestId('object-form')).toBeDefined();
305
- expect(screen.getByLabelText('Close panel')).toBeDefined();
306
- });
307
-
308
- it('should open form in view mode when popover navigation mode is clicked', () => {
309
- const schema: ObjectViewSchema = {
310
- type: 'object-view',
311
- objectName: 'contacts',
312
- navigation: { mode: 'popover' },
313
- };
314
-
315
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
316
-
317
- fireEvent.click(screen.getByTestId('grid-row'));
318
-
319
- // Popover mode renders NavigationOverlay Dialog fallback (no popoverTrigger)
320
- expect(screen.getByTestId('object-form')).toBeDefined();
321
- expect(screen.getByRole('dialog')).toBeDefined();
322
- });
323
-
324
- it('should close split panel and return to normal view', () => {
325
- const schema: ObjectViewSchema = {
326
- type: 'object-view',
327
- objectName: 'contacts',
328
- navigation: { mode: 'split' },
329
- };
330
-
331
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
332
-
333
- // Open split panel
334
- fireEvent.click(screen.getByTestId('grid-row'));
335
- expect(screen.getByLabelText('Close panel')).toBeDefined();
336
-
337
- // Close split panel
338
- fireEvent.click(screen.getByLabelText('Close panel'));
339
-
340
- // Form should be gone, grid should remain
341
- expect(screen.queryByLabelText('Close panel')).toBeNull();
342
- expect(screen.getByTestId('object-grid')).toBeDefined();
343
- });
344
- });
345
-
346
- // ============================
347
- // CRUD Operations
348
- // ============================
349
- describe('CRUD Operations', () => {
350
- it('should hide create button when operations.create is false', () => {
351
- const schema: ObjectViewSchema = {
352
- type: 'object-view',
353
- objectName: 'contacts',
354
- operations: { create: false, read: true, update: true, delete: true },
355
- };
356
-
357
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
358
-
359
- expect(screen.queryByText('Create')).toBeNull();
360
- });
361
- });
362
-
363
- // ============================
364
- // Data Source Integration
365
- // ============================
366
- describe('Data Source Integration', () => {
367
- it('should fetch object schema on mount', async () => {
368
- const schema: ObjectViewSchema = {
369
- type: 'object-view',
370
- objectName: 'contacts',
371
- };
372
-
373
- render(<ObjectView schema={schema} dataSource={mockDataSource} />);
374
-
375
- await waitFor(() => {
376
- expect(mockDataSource.getObjectSchema).toHaveBeenCalledWith('contacts');
377
- });
378
- });
379
- });
380
-
381
- // ============================
382
- // View Switcher (prop-based views)
383
- // ============================
384
- describe('View Switcher (prop-based)', () => {
385
- it('should not render view switcher with single view prop', () => {
386
- const schema: ObjectViewSchema = {
387
- type: 'object-view',
388
- objectName: 'contacts',
389
- };
390
-
391
- const views = [
392
- { id: 'grid', label: 'Grid', type: 'grid' as const },
393
- ];
394
-
395
- render(
396
- <ObjectView schema={schema} dataSource={mockDataSource} views={views} />,
397
- );
398
-
399
- // Only one view, no switcher needed
400
- expect(screen.getByTestId('object-grid')).toBeDefined();
401
- });
402
- });
403
-
404
- // ============================
405
- // showViewSwitcher config
406
- // ============================
407
- describe('showViewSwitcher', () => {
408
- it('should hide view switcher when showViewSwitcher is false', () => {
409
- const schema: ObjectViewSchema = {
410
- type: 'object-view',
411
- objectName: 'contacts',
412
- showViewSwitcher: false,
413
- };
414
-
415
- const views = [
416
- { id: 'grid', label: 'Grid', type: 'grid' as const },
417
- { id: 'kanban', label: 'Kanban', type: 'kanban' as const },
418
- ];
419
-
420
- render(
421
- <ObjectView schema={schema} dataSource={mockDataSource} views={views} />,
422
- );
423
-
424
- // Switcher should be hidden
425
- expect(screen.queryByText('Kanban')).toBeNull();
426
- });
427
- });
428
-
429
- // ============================
430
- // Live Preview — viewConfig sync
431
- // ============================
432
- describe('Live Preview', () => {
433
- it('should re-render grid when views prop updates with new columns', async () => {
434
- const schema: ObjectViewSchema = {
435
- type: 'object-view',
436
- objectName: 'contacts',
437
- };
438
-
439
- const initialViews = [
440
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name', 'email'] },
441
- ];
442
-
443
- const { rerender } = render(
444
- <ObjectView schema={schema} dataSource={mockDataSource} views={initialViews} activeViewId="all" />,
445
- );
446
-
447
- expect(screen.getByTestId('object-grid')).toBeInTheDocument();
448
-
449
- // Simulate live preview: update views prop with new columns (as parent would after viewDraft change)
450
- const updatedViews = [
451
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name', 'email', 'status'] },
452
- ];
453
-
454
- rerender(
455
- <ObjectView schema={schema} dataSource={mockDataSource} views={updatedViews} activeViewId="all" />,
456
- );
457
-
458
- // Grid should still render (component did not crash on prop update)
459
- expect(screen.getByTestId('object-grid')).toBeInTheDocument();
460
- });
461
-
462
- it('should re-render when views prop updates with new sort config', async () => {
463
- const schema: ObjectViewSchema = {
464
- type: 'object-view',
465
- objectName: 'contacts',
466
- };
467
-
468
- const initialViews = [
469
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name'] },
470
- ];
471
-
472
- const { rerender } = render(
473
- <ObjectView schema={schema} dataSource={mockDataSource} views={initialViews} activeViewId="all" />,
474
- );
475
-
476
- // Update with sort config — simulates live preview of sort changes
477
- const updatedViews = [
478
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name'], sort: [{ field: 'name', direction: 'desc' as const }] },
479
- ];
480
-
481
- rerender(
482
- <ObjectView schema={schema} dataSource={mockDataSource} views={updatedViews} activeViewId="all" />,
483
- );
484
-
485
- expect(screen.getByTestId('object-grid')).toBeInTheDocument();
486
- });
487
-
488
- it('should re-render when views prop updates with new filter', async () => {
489
- const schema: ObjectViewSchema = {
490
- type: 'object-view',
491
- objectName: 'contacts',
492
- };
493
-
494
- const initialViews = [
495
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name'] },
496
- ];
497
-
498
- const { rerender } = render(
499
- <ObjectView schema={schema} dataSource={mockDataSource} views={initialViews} activeViewId="all" />,
500
- );
501
-
502
- // Update with filter — simulates live preview of filter changes
503
- const updatedViews = [
504
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name'], filter: [['status', '=', 'active']] },
505
- ];
506
-
507
- rerender(
508
- <ObjectView schema={schema} dataSource={mockDataSource} views={updatedViews} activeViewId="all" />,
509
- );
510
-
511
- expect(screen.getByTestId('object-grid')).toBeInTheDocument();
512
- });
513
-
514
- it('should re-render when views prop updates with appearance properties', async () => {
515
- const schema: ObjectViewSchema = {
516
- type: 'object-view',
517
- objectName: 'contacts',
518
- };
519
-
520
- const initialViews = [
521
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name'] },
522
- ];
523
-
524
- const { rerender } = render(
525
- <ObjectView schema={schema} dataSource={mockDataSource} views={initialViews} activeViewId="all" />,
526
- );
527
-
528
- // Update with appearance changes — simulates live preview of rowHeight/striped/bordered
529
- const updatedViews = [
530
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name'], striped: true, bordered: true },
531
- ];
532
-
533
- rerender(
534
- <ObjectView schema={schema} dataSource={mockDataSource} views={updatedViews} activeViewId="all" />,
535
- );
536
-
537
- expect(screen.getByTestId('object-grid')).toBeInTheDocument();
538
- });
539
-
540
- it('should pass renderListView with updated schema when views change', async () => {
541
- const schema: ObjectViewSchema = {
542
- type: 'object-view',
543
- objectName: 'contacts',
544
- };
545
-
546
- const renderListViewSpy = vi.fn(({ schema: listSchema }: any) => (
547
- <div data-testid="custom-list" data-fields={JSON.stringify(listSchema.fields)}>
548
- Custom ListView
549
- </div>
550
- ));
551
-
552
- const initialViews = [
553
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name'] },
554
- ];
555
-
556
- const { rerender } = render(
557
- <ObjectView
558
- schema={schema}
559
- dataSource={mockDataSource}
560
- views={initialViews}
561
- activeViewId="all"
562
- renderListView={renderListViewSpy}
563
- />,
564
- );
565
-
566
- expect(screen.getByTestId('custom-list')).toBeInTheDocument();
567
- const firstCallSchema = renderListViewSpy.mock.calls[0]?.[0]?.schema;
568
- expect(firstCallSchema?.fields).toEqual(['name']);
569
-
570
- // Update views — simulate live preview change
571
- const updatedViews = [
572
- { id: 'all', label: 'All', type: 'grid' as const, columns: ['name', 'email', 'status'] },
573
- ];
574
-
575
- rerender(
576
- <ObjectView
577
- schema={schema}
578
- dataSource={mockDataSource}
579
- views={updatedViews}
580
- activeViewId="all"
581
- renderListView={renderListViewSpy}
582
- />,
583
- );
584
-
585
- // renderListView should have been called again with the updated columns
586
- const lastCallIndex = renderListViewSpy.mock.calls.length - 1;
587
- const lastCallSchema = renderListViewSpy.mock.calls[lastCallIndex]?.[0]?.schema;
588
- expect(lastCallSchema?.fields).toEqual(['name', 'email', 'status']);
589
- });
590
-
591
- it('should pass showSort=false through schema to suppress sort UI', async () => {
592
- const schema: ObjectViewSchema = {
593
- type: 'object-view',
594
- objectName: 'contacts',
595
- showSort: false,
596
- };
597
-
598
- render(
599
- <ObjectView schema={schema} dataSource={mockDataSource} />,
600
- );
601
-
602
- // Component renders without crash — showSort is respected
603
- expect(screen.getByTestId('object-grid')).toBeInTheDocument();
604
- });
605
-
606
- it('should include showSearch/showFilters/showSort in renderListView schema', async () => {
607
- const schema: ObjectViewSchema = {
608
- type: 'object-view',
609
- objectName: 'contacts',
610
- showSearch: false,
611
- showFilters: false,
612
- showSort: false,
613
- };
614
-
615
- const renderListViewSpy = vi.fn(({ schema: listSchema }: any) => (
616
- <div data-testid="custom-list">Custom ListView</div>
617
- ));
618
-
619
- render(
620
- <ObjectView
621
- schema={schema}
622
- dataSource={mockDataSource}
623
- renderListView={renderListViewSpy}
624
- />,
625
- );
626
-
627
- expect(renderListViewSpy).toHaveBeenCalled();
628
- const callSchema = renderListViewSpy.mock.calls[0]?.[0]?.schema;
629
- expect(callSchema?.showSearch).toBe(false);
630
- expect(callSchema?.showFilters).toBe(false);
631
- expect(callSchema?.showSort).toBe(false);
632
- });
633
-
634
- it('should propagate showSearch/showFilters/showSort from activeView in renderListView', async () => {
635
- const schema: ObjectViewSchema = {
636
- type: 'object-view',
637
- objectName: 'contacts',
638
- };
639
-
640
- const renderListViewSpy = vi.fn(({ schema: listSchema }: any) => (
641
- <div data-testid="custom-list">Custom ListView</div>
642
- ));
643
-
644
- const views = [
645
- { id: 'v1', label: 'View 1', type: 'grid' as const, showSearch: false, showFilters: false, showSort: false },
646
- ];
647
-
648
- render(
649
- <ObjectView
650
- schema={schema}
651
- dataSource={mockDataSource}
652
- views={views}
653
- activeViewId="v1"
654
- renderListView={renderListViewSpy}
655
- />,
656
- );
657
-
658
- expect(renderListViewSpy).toHaveBeenCalled();
659
- const callSchema = renderListViewSpy.mock.calls[0]?.[0]?.schema;
660
- expect(callSchema?.showSearch).toBe(false);
661
- expect(callSchema?.showFilters).toBe(false);
662
- expect(callSchema?.showSort).toBe(false);
663
- });
664
-
665
- it('should propagate userFilters from activeView in renderListView', async () => {
666
- const schema: ObjectViewSchema = {
667
- type: 'object-view',
668
- objectName: 'contacts',
669
- };
670
-
671
- const renderListViewSpy = vi.fn(({ schema: listSchema }: any) => (
672
- <div data-testid="custom-list">Custom ListView</div>
673
- ));
674
-
675
- const views = [
676
- {
677
- id: 'v1',
678
- label: 'View 1',
679
- type: 'grid' as const,
680
- userFilters: {
681
- element: 'dropdown' as const,
682
- fields: [{ field: 'status' }],
683
- },
684
- },
685
- ];
686
-
687
- render(
688
- <ObjectView
689
- schema={schema}
690
- dataSource={mockDataSource}
691
- views={views}
692
- activeViewId="v1"
693
- renderListView={renderListViewSpy}
694
- />,
695
- );
696
-
697
- expect(renderListViewSpy).toHaveBeenCalled();
698
- const callSchema = renderListViewSpy.mock.calls[0]?.[0]?.schema;
699
- expect(callSchema?.userFilters).toEqual({
700
- element: 'dropdown',
701
- fields: [{ field: 'status' }],
702
- });
703
- });
704
- });
705
- });