@object-ui/fields 4.0.1 → 4.0.4
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 +41 -0
- package/dist/index.cjs +3 -3
- package/dist/index.js +574 -574
- package/package.json +7 -7
- package/dist/dist-BoLAKgtw.cjs +0 -1
- package/dist/dist-qtNk7SzD.js +0 -32
- package/dist/packages/fields/src/__tests__/boolean-checkbox.test.d.ts +0 -0
- package/dist/packages/fields/src/__tests__/cell-renderers.test.d.ts +0 -0
- package/dist/packages/fields/src/__tests__/datetime-cell.test.d.ts +0 -0
- package/dist/packages/fields/src/__tests__/datetime-timezone.test.d.ts +0 -0
- package/dist/packages/fields/src/__tests__/extreme-inputs.test.d.ts +0 -0
- package/dist/packages/fields/src/__tests__/form-variants.test.d.ts +0 -0
- package/dist/packages/fields/src/lookup-depends-on.test.d.ts +0 -1
- package/dist/packages/fields/src/new-widgets.test.d.ts +0 -8
- package/dist/packages/fields/src/record-picker.test.d.ts +0 -1
- package/dist/packages/fields/src/remaining-widgets.test.d.ts +0 -1
- package/dist/packages/fields/src/text-rich-widgets.test.d.ts +0 -1
- package/dist/packages/fields/src/visual-widgets.test.d.ts +0 -1
- package/src/__tests__/boolean-checkbox.test.tsx +0 -74
- package/src/__tests__/cell-renderers.test.tsx +0 -1193
- package/src/__tests__/datetime-cell.test.tsx +0 -46
- package/src/__tests__/datetime-timezone.test.tsx +0 -770
- package/src/__tests__/extreme-inputs.test.tsx +0 -567
- package/src/__tests__/form-variants.test.tsx +0 -306
- package/src/lookup-depends-on.test.tsx +0 -130
- package/src/new-widgets.test.tsx +0 -302
- package/src/record-picker.test.tsx +0 -1703
- package/src/remaining-widgets.test.tsx +0 -211
- package/src/text-rich-widgets.test.tsx +0 -104
- package/src/visual-widgets.test.tsx +0 -97
- /package/dist/{ImageCropperDialog-DXLQcwWZ.cjs → ImageCropperDialog-CK1apFXU.cjs} +0 -0
- /package/dist/{ImageCropperDialog-BYRMqcYm.js → ImageCropperDialog-DNvktnyM.js} +0 -0
|
@@ -1,306 +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
|
-
/**
|
|
10
|
-
* P3.2 Field Widget Polish - Form Variants
|
|
11
|
-
*
|
|
12
|
-
* Tests that field widgets work correctly in different form contexts:
|
|
13
|
-
* standalone, multiple fields together, value changes, and controlled mode.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
17
|
-
import React, { useState } from 'react';
|
|
18
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
19
|
-
import '@testing-library/jest-dom';
|
|
20
|
-
|
|
21
|
-
import { TextField } from '../widgets/TextField';
|
|
22
|
-
import { NumberField } from '../widgets/NumberField';
|
|
23
|
-
import { EmailField } from '../widgets/EmailField';
|
|
24
|
-
import { BooleanField } from '../widgets/BooleanField';
|
|
25
|
-
import { TextAreaField } from '../widgets/TextAreaField';
|
|
26
|
-
import { CurrencyField } from '../widgets/CurrencyField';
|
|
27
|
-
import { UrlField } from '../widgets/UrlField';
|
|
28
|
-
|
|
29
|
-
const noop = vi.fn();
|
|
30
|
-
|
|
31
|
-
describe('P3.2 Form Variants', () => {
|
|
32
|
-
// ---------------------------------------------------------------
|
|
33
|
-
// Multiple fields rendered together
|
|
34
|
-
// ---------------------------------------------------------------
|
|
35
|
-
describe('multiple fields in a form', () => {
|
|
36
|
-
it('renders multiple different field types side by side', () => {
|
|
37
|
-
const { container } = render(
|
|
38
|
-
<div>
|
|
39
|
-
<TextField value="John" onChange={noop} field={{ type: 'text' } as any} />
|
|
40
|
-
<EmailField value="john@test.com" onChange={noop} field={{ type: 'email' } as any} />
|
|
41
|
-
<NumberField value={42} onChange={noop} field={{ type: 'number' } as any} />
|
|
42
|
-
<BooleanField value={true} onChange={noop} field={{ type: 'boolean' } as any} />
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
expect(screen.getAllByRole('textbox')).toHaveLength(2); // text + email
|
|
46
|
-
expect(screen.getByRole('spinbutton')).toHaveValue(42);
|
|
47
|
-
expect(screen.getByRole('switch')).toBeChecked();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('each field maintains independent state via onChange', () => {
|
|
51
|
-
const textChange = vi.fn();
|
|
52
|
-
const numberChange = vi.fn();
|
|
53
|
-
|
|
54
|
-
render(
|
|
55
|
-
<div>
|
|
56
|
-
<TextField value="" onChange={textChange} field={{ type: 'text' } as any} />
|
|
57
|
-
<NumberField value={0} onChange={numberChange} field={{ type: 'number' } as any} />
|
|
58
|
-
</div>
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const inputs = screen.getAllByRole('textbox');
|
|
62
|
-
fireEvent.change(inputs[0], { target: { value: 'hello' } });
|
|
63
|
-
expect(textChange).toHaveBeenCalledWith('hello');
|
|
64
|
-
expect(numberChange).not.toHaveBeenCalled();
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// ---------------------------------------------------------------
|
|
69
|
-
// Controlled component behavior
|
|
70
|
-
// ---------------------------------------------------------------
|
|
71
|
-
describe('controlled component behavior', () => {
|
|
72
|
-
function ControlledTextField() {
|
|
73
|
-
const [val, setVal] = useState('initial');
|
|
74
|
-
return (
|
|
75
|
-
<div>
|
|
76
|
-
<TextField value={val} onChange={setVal} field={{ type: 'text' } as any} />
|
|
77
|
-
<span data-testid="output">{val}</span>
|
|
78
|
-
</div>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
it('TextField works as controlled component', () => {
|
|
83
|
-
render(<ControlledTextField />);
|
|
84
|
-
const input = screen.getByRole('textbox');
|
|
85
|
-
expect(input).toHaveValue('initial');
|
|
86
|
-
|
|
87
|
-
fireEvent.change(input, { target: { value: 'updated' } });
|
|
88
|
-
expect(screen.getByTestId('output').textContent).toBe('updated');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
function ControlledNumberField() {
|
|
92
|
-
const [val, setVal] = useState(10);
|
|
93
|
-
return (
|
|
94
|
-
<div>
|
|
95
|
-
<NumberField value={val} onChange={setVal} field={{ type: 'number' } as any} />
|
|
96
|
-
<span data-testid="output">{String(val)}</span>
|
|
97
|
-
</div>
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
it('NumberField works as controlled component', () => {
|
|
102
|
-
render(<ControlledNumberField />);
|
|
103
|
-
const input = screen.getByRole('spinbutton');
|
|
104
|
-
expect(input).toHaveValue(10);
|
|
105
|
-
|
|
106
|
-
fireEvent.change(input, { target: { value: '25' } });
|
|
107
|
-
expect(screen.getByTestId('output').textContent).toBe('25');
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
function ControlledBooleanField() {
|
|
111
|
-
const [val, setVal] = useState(false);
|
|
112
|
-
return (
|
|
113
|
-
<div>
|
|
114
|
-
<BooleanField value={val} onChange={setVal} field={{ type: 'boolean' } as any} />
|
|
115
|
-
<span data-testid="output">{String(val)}</span>
|
|
116
|
-
</div>
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
it('BooleanField works as controlled component', () => {
|
|
121
|
-
render(<ControlledBooleanField />);
|
|
122
|
-
const toggle = screen.getByRole('switch');
|
|
123
|
-
expect(toggle).not.toBeChecked();
|
|
124
|
-
|
|
125
|
-
fireEvent.click(toggle);
|
|
126
|
-
expect(screen.getByTestId('output').textContent).toBe('true');
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// ---------------------------------------------------------------
|
|
131
|
-
// Switching between readonly and edit mode
|
|
132
|
-
// ---------------------------------------------------------------
|
|
133
|
-
describe('readonly/edit mode switching', () => {
|
|
134
|
-
function ModeToggle() {
|
|
135
|
-
const [ro, setRo] = useState(false);
|
|
136
|
-
return (
|
|
137
|
-
<div>
|
|
138
|
-
<button data-testid="toggle" onClick={() => setRo(!ro)}>Toggle</button>
|
|
139
|
-
<TextField value="hello" onChange={noop} field={{ type: 'text' } as any} readonly={ro} />
|
|
140
|
-
</div>
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
it('TextField switches from edit to readonly', () => {
|
|
145
|
-
render(<ModeToggle />);
|
|
146
|
-
// Start in edit mode
|
|
147
|
-
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
|
148
|
-
|
|
149
|
-
// Toggle to readonly
|
|
150
|
-
fireEvent.click(screen.getByTestId('toggle'));
|
|
151
|
-
expect(screen.queryByRole('textbox')).toBeNull();
|
|
152
|
-
expect(screen.getByText('hello')).toBeInTheDocument();
|
|
153
|
-
|
|
154
|
-
// Toggle back to edit
|
|
155
|
-
fireEvent.click(screen.getByTestId('toggle'));
|
|
156
|
-
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// ---------------------------------------------------------------
|
|
161
|
-
// TextField with rows (textarea variant)
|
|
162
|
-
// ---------------------------------------------------------------
|
|
163
|
-
describe('TextField textarea variant', () => {
|
|
164
|
-
it('renders as textarea when rows > 1', () => {
|
|
165
|
-
render(
|
|
166
|
-
<TextField
|
|
167
|
-
value="multi-line"
|
|
168
|
-
onChange={noop}
|
|
169
|
-
field={{ type: 'text', rows: 5 } as any}
|
|
170
|
-
/>
|
|
171
|
-
);
|
|
172
|
-
const el = screen.getByRole('textbox');
|
|
173
|
-
expect(el.tagName).toBe('TEXTAREA');
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('renders as input when rows is not set', () => {
|
|
177
|
-
render(
|
|
178
|
-
<TextField
|
|
179
|
-
value="single-line"
|
|
180
|
-
onChange={noop}
|
|
181
|
-
field={{ type: 'text' } as any}
|
|
182
|
-
/>
|
|
183
|
-
);
|
|
184
|
-
const el = screen.getByRole('textbox');
|
|
185
|
-
expect(el.tagName).toBe('INPUT');
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
// ---------------------------------------------------------------
|
|
190
|
-
// TextAreaField with custom rows
|
|
191
|
-
// ---------------------------------------------------------------
|
|
192
|
-
describe('TextAreaField with custom rows', () => {
|
|
193
|
-
it('uses custom rows from field metadata', () => {
|
|
194
|
-
render(
|
|
195
|
-
<TextAreaField
|
|
196
|
-
value=""
|
|
197
|
-
onChange={noop}
|
|
198
|
-
field={{ type: 'textarea', rows: 10 } as any}
|
|
199
|
-
/>
|
|
200
|
-
);
|
|
201
|
-
const textarea = screen.getByRole('textbox');
|
|
202
|
-
expect(textarea).toHaveAttribute('rows', '10');
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('defaults to 4 rows', () => {
|
|
206
|
-
render(
|
|
207
|
-
<TextAreaField
|
|
208
|
-
value=""
|
|
209
|
-
onChange={noop}
|
|
210
|
-
field={{ type: 'textarea' } as any}
|
|
211
|
-
/>
|
|
212
|
-
);
|
|
213
|
-
const textarea = screen.getByRole('textbox');
|
|
214
|
-
expect(textarea).toHaveAttribute('rows', '4');
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// ---------------------------------------------------------------
|
|
219
|
-
// CurrencyField interaction
|
|
220
|
-
// ---------------------------------------------------------------
|
|
221
|
-
describe('CurrencyField interaction', () => {
|
|
222
|
-
it('calls onChange with parsed number on input', () => {
|
|
223
|
-
const onChange = vi.fn();
|
|
224
|
-
render(
|
|
225
|
-
<CurrencyField
|
|
226
|
-
value={100}
|
|
227
|
-
onChange={onChange}
|
|
228
|
-
field={{ type: 'currency', currency: 'USD' } as any}
|
|
229
|
-
/>
|
|
230
|
-
);
|
|
231
|
-
fireEvent.change(screen.getByRole('spinbutton'), { target: { value: '250.50' } });
|
|
232
|
-
expect(onChange).toHaveBeenCalledWith(250.50);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('calls onChange with null on empty input', () => {
|
|
236
|
-
const onChange = vi.fn();
|
|
237
|
-
render(
|
|
238
|
-
<CurrencyField
|
|
239
|
-
value={100}
|
|
240
|
-
onChange={onChange}
|
|
241
|
-
field={{ type: 'currency', currency: 'USD' } as any}
|
|
242
|
-
/>
|
|
243
|
-
);
|
|
244
|
-
fireEvent.change(screen.getByRole('spinbutton'), { target: { value: '' } });
|
|
245
|
-
expect(onChange).toHaveBeenCalledWith(null);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it('readonly mode formats currency value', () => {
|
|
249
|
-
const { container } = render(
|
|
250
|
-
<CurrencyField
|
|
251
|
-
value={1234.56}
|
|
252
|
-
onChange={noop}
|
|
253
|
-
field={{ type: 'currency', currency: 'USD' } as any}
|
|
254
|
-
readonly={true}
|
|
255
|
-
/>
|
|
256
|
-
);
|
|
257
|
-
expect(container.textContent).toMatch(/\$1,234\.56/);
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
// ---------------------------------------------------------------
|
|
262
|
-
// Email and URL readonly links
|
|
263
|
-
// ---------------------------------------------------------------
|
|
264
|
-
describe('readonly link generation', () => {
|
|
265
|
-
it('EmailField generates mailto link in readonly', () => {
|
|
266
|
-
render(
|
|
267
|
-
<EmailField
|
|
268
|
-
value="user@example.com"
|
|
269
|
-
onChange={noop}
|
|
270
|
-
field={{ type: 'email' } as any}
|
|
271
|
-
readonly={true}
|
|
272
|
-
/>
|
|
273
|
-
);
|
|
274
|
-
const link = screen.getByRole('link');
|
|
275
|
-
expect(link).toHaveAttribute('href', 'mailto:user@example.com');
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it('UrlField generates external link in readonly', () => {
|
|
279
|
-
render(
|
|
280
|
-
<UrlField
|
|
281
|
-
value="https://example.com"
|
|
282
|
-
onChange={noop}
|
|
283
|
-
field={{ type: 'url' } as any}
|
|
284
|
-
readonly={true}
|
|
285
|
-
/>
|
|
286
|
-
);
|
|
287
|
-
const link = screen.getByRole('link');
|
|
288
|
-
expect(link).toHaveAttribute('href', 'https://example.com');
|
|
289
|
-
expect(link).toHaveAttribute('target', '_blank');
|
|
290
|
-
expect(link).toHaveAttribute('rel', 'noopener noreferrer');
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('UrlField does not generate link for non-http URLs', () => {
|
|
294
|
-
const { container } = render(
|
|
295
|
-
<UrlField
|
|
296
|
-
value="javascript:alert(1)"
|
|
297
|
-
onChange={noop}
|
|
298
|
-
field={{ type: 'url' } as any}
|
|
299
|
-
readonly={true}
|
|
300
|
-
/>
|
|
301
|
-
);
|
|
302
|
-
expect(screen.queryByRole('link')).toBeNull();
|
|
303
|
-
expect(container.textContent).toBe('javascript:alert(1)');
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
});
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the dependent-lookups feature: `field.depends_on` should add
|
|
3
|
-
* an `$filter` chain when querying, gate the trigger when dependencies are
|
|
4
|
-
* empty, and re-fetch when the dependency value changes.
|
|
5
|
-
*/
|
|
6
|
-
import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
|
|
7
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
8
|
-
import React, { useState } from 'react';
|
|
9
|
-
import { LookupField } from './widgets/LookupField';
|
|
10
|
-
|
|
11
|
-
const mockDataSource = {
|
|
12
|
-
find: vi.fn(),
|
|
13
|
-
findOne: vi.fn(),
|
|
14
|
-
create: vi.fn(),
|
|
15
|
-
update: vi.fn(),
|
|
16
|
-
delete: vi.fn(),
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
vi.clearAllMocks();
|
|
21
|
-
mockDataSource.find.mockResolvedValue({ data: [], total: 0 });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe('LookupField — depends_on', () => {
|
|
25
|
-
const baseField: any = {
|
|
26
|
-
name: 'city',
|
|
27
|
-
type: 'lookup',
|
|
28
|
-
reference: 'cities',
|
|
29
|
-
display_field: 'name',
|
|
30
|
-
id_field: 'id',
|
|
31
|
-
depends_on: ['country'],
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
it('disables the trigger when a dependency value is missing', () => {
|
|
35
|
-
render(
|
|
36
|
-
<LookupField
|
|
37
|
-
field={baseField}
|
|
38
|
-
value={null}
|
|
39
|
-
onChange={vi.fn()}
|
|
40
|
-
readonly={false}
|
|
41
|
-
dataSource={mockDataSource as any}
|
|
42
|
-
dependentValues={{}}
|
|
43
|
-
/>,
|
|
44
|
-
);
|
|
45
|
-
const trigger = screen.getByTestId('lookup-trigger-gated');
|
|
46
|
-
expect(trigger).toBeDisabled();
|
|
47
|
-
expect(trigger).toHaveTextContent(/Select country first/i);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('enables the trigger and includes a filter chain once the dependency is set', async () => {
|
|
51
|
-
render(
|
|
52
|
-
<LookupField
|
|
53
|
-
field={baseField}
|
|
54
|
-
value={null}
|
|
55
|
-
onChange={vi.fn()}
|
|
56
|
-
readonly={false}
|
|
57
|
-
dataSource={mockDataSource as any}
|
|
58
|
-
dependentValues={{ country: 'US' }}
|
|
59
|
-
/>,
|
|
60
|
-
);
|
|
61
|
-
// Trigger is enabled (no gated test id).
|
|
62
|
-
expect(screen.queryByTestId('lookup-trigger-gated')).not.toBeInTheDocument();
|
|
63
|
-
|
|
64
|
-
// Open the popover to fire fetch.
|
|
65
|
-
await act(async () => {
|
|
66
|
-
fireEvent.click(screen.getByRole('button', { name: /select|search/i }));
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
await waitFor(() => expect(mockDataSource.find).toHaveBeenCalled());
|
|
70
|
-
const [, params] = mockDataSource.find.mock.calls[0];
|
|
71
|
-
expect(params.$filter).toEqual({ country: 'US' });
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('supports the explicit { field, param } shape', async () => {
|
|
75
|
-
const explicitField: any = {
|
|
76
|
-
...baseField,
|
|
77
|
-
depends_on: [{ field: 'country', param: 'country_id' }],
|
|
78
|
-
};
|
|
79
|
-
render(
|
|
80
|
-
<LookupField
|
|
81
|
-
field={explicitField}
|
|
82
|
-
value={null}
|
|
83
|
-
onChange={vi.fn()}
|
|
84
|
-
readonly={false}
|
|
85
|
-
dataSource={mockDataSource as any}
|
|
86
|
-
dependentValues={{ country: 42 }}
|
|
87
|
-
/>,
|
|
88
|
-
);
|
|
89
|
-
await act(async () => {
|
|
90
|
-
fireEvent.click(screen.getByRole('button', { name: /select|search/i }));
|
|
91
|
-
});
|
|
92
|
-
await waitFor(() => expect(mockDataSource.find).toHaveBeenCalled());
|
|
93
|
-
const [, params] = mockDataSource.find.mock.calls[0];
|
|
94
|
-
// numeric value, no quoting
|
|
95
|
-
expect(params.$filter).toEqual({ country_id: 42 });
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('re-fetches when the dependency value changes while the picker is open', async () => {
|
|
99
|
-
function Harness() {
|
|
100
|
-
const [country, setCountry] = useState('US');
|
|
101
|
-
return (
|
|
102
|
-
<div>
|
|
103
|
-
<button data-testid="set-uk" onClick={() => setCountry('UK')}>UK</button>
|
|
104
|
-
<LookupField
|
|
105
|
-
field={baseField}
|
|
106
|
-
value={null}
|
|
107
|
-
onChange={vi.fn()}
|
|
108
|
-
readonly={false}
|
|
109
|
-
dataSource={mockDataSource as any}
|
|
110
|
-
dependentValues={{ country }}
|
|
111
|
-
/>
|
|
112
|
-
</div>
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
render(<Harness />);
|
|
116
|
-
// Open the popover.
|
|
117
|
-
await act(async () => {
|
|
118
|
-
fireEvent.click(screen.getByRole('button', { name: /select|search/i }));
|
|
119
|
-
});
|
|
120
|
-
await waitFor(() => expect(mockDataSource.find).toHaveBeenCalledTimes(1));
|
|
121
|
-
|
|
122
|
-
// Change the dependency — should re-fetch.
|
|
123
|
-
await act(async () => {
|
|
124
|
-
fireEvent.click(screen.getByTestId('set-uk'));
|
|
125
|
-
});
|
|
126
|
-
await waitFor(() => expect(mockDataSource.find).toHaveBeenCalledTimes(2));
|
|
127
|
-
const [, paramsAfter] = mockDataSource.find.mock.calls[1];
|
|
128
|
-
expect(paramsAfter.$filter).toEqual({ country: 'UK' });
|
|
129
|
-
});
|
|
130
|
-
});
|