@scality/core-ui 0.162.0 → 0.164.0
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/dist/components/barchartv2/Barchart.component.d.ts +9 -3
- package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
- package/dist/components/barchartv2/Barchart.component.js +22 -5
- package/dist/components/barchartv2/utils.d.ts +26 -3
- package/dist/components/barchartv2/utils.d.ts.map +1 -1
- package/dist/components/barchartv2/utils.js +76 -22
- package/dist/components/chartlegend/ChartLegend.d.ts +8 -0
- package/dist/components/chartlegend/ChartLegend.d.ts.map +1 -0
- package/dist/components/chartlegend/ChartLegend.js +65 -0
- package/dist/components/chartlegend/ChartLegendWrapper.d.ts +17 -0
- package/dist/components/chartlegend/ChartLegendWrapper.d.ts.map +1 -0
- package/dist/components/chartlegend/ChartLegendWrapper.js +50 -0
- package/dist/components/date/FormattedDateTime.d.ts +3 -1
- package/dist/components/date/FormattedDateTime.d.ts.map +1 -1
- package/dist/components/date/FormattedDateTime.js +19 -1
- package/dist/components/date/FormattedDateTime.spec.js +12 -0
- package/dist/components/icon/Icon.component.d.ts +5 -5
- package/dist/components/icon/Icon.component.d.ts.map +1 -1
- package/dist/components/icon/Icon.component.js +33 -31
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts +33 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.js +249 -0
- package/dist/components/selectv2/Selectv2.component.d.ts.map +1 -1
- package/dist/components/selectv2/Selectv2.component.js +11 -6
- package/dist/components/steppers/Stepper.component.d.ts.map +1 -1
- package/dist/components/steppers/Stepper.component.js +9 -8
- package/dist/components/toast/ToastProvider.d.ts.map +1 -1
- package/dist/components/toast/ToastProvider.js +4 -5
- package/dist/components/vegachartv2/SyncedCursorCharts.d.ts.map +1 -1
- package/dist/components/vegachartv2/SyncedCursorCharts.js +3 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/next.d.ts +2 -0
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +2 -0
- package/dist/style/theme.d.ts +1 -0
- package/dist/style/theme.d.ts.map +1 -1
- package/dist/style/theme.js +28 -0
- package/package.json +2 -2
- package/src/lib/components/accordion/Accordion.test.tsx +8 -16
- package/src/lib/components/barchartv2/Barchart.component.test.tsx +117 -111
- package/src/lib/components/barchartv2/Barchart.component.tsx +54 -7
- package/src/lib/components/barchartv2/utils.test.ts +127 -2
- package/src/lib/components/barchartv2/utils.ts +103 -19
- package/src/lib/components/chartlegend/ChartLegend.tsx +113 -0
- package/src/lib/components/chartlegend/ChartLegendWrapper.tsx +85 -0
- package/src/lib/components/date/FormattedDateTime.spec.tsx +24 -0
- package/src/lib/components/date/FormattedDateTime.tsx +36 -2
- package/src/lib/components/healthselectorv2/HealthSelector.component.test.tsx +10 -10
- package/src/lib/components/icon/Icon.component.tsx +48 -60
- package/src/lib/components/infomessage/InfoMessageUtils.test.tsx +0 -1
- package/src/lib/components/inlineinput/InlineInput.test.tsx +28 -22
- package/src/lib/components/inputlist/InputList.test.tsx +22 -21
- package/src/lib/components/linetemporalchart/ChartUtil.test.ts +5 -4
- package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +502 -0
- package/src/lib/components/searchinput/SearchInput.test.tsx +3 -7
- package/src/lib/components/selectv2/Selectv2.component.tsx +13 -5
- package/src/lib/components/selectv2/selectv2.test.tsx +70 -61
- package/src/lib/components/steppers/Stepper.component.tsx +10 -8
- package/src/lib/components/tablev2/TableSync.test.tsx +8 -12
- package/src/lib/components/tablev2/TableUtils.test.ts +6 -3
- package/src/lib/components/tablev2/Tablev2.test.tsx +38 -40
- package/src/lib/components/toast/ToastProvider.tsx +14 -6
- package/src/lib/components/toggle/Toggle.test.tsx +1 -1
- package/src/lib/components/vegachartv2/SyncedCursorCharts.tsx +5 -7
- package/src/lib/index.ts +1 -0
- package/src/lib/next.ts +2 -0
- package/src/lib/style/theme.ts +29 -0
- package/stories/BarChart/barchart.stories.tsx +387 -129
- package/stories/format.mdx +4 -2
- package/stories/linetimeseriechart.stories.tsx +485 -0
- package/tsconfig.json +0 -1
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import { screen, render as testingRender } from '@testing-library/react';
|
|
1
|
+
import { act, screen, render as testingRender, waitFor } from '@testing-library/react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import React, { useState, useRef } from 'react';
|
|
4
|
-
import { QueryClient, QueryClientProvider } from 'react-query';
|
|
5
4
|
import { Option, Select, SelectRef } from '../selectv2/Selectv2.component';
|
|
5
|
+
import { GroupTypeBase, OptionTypeBase } from 'react-select';
|
|
6
6
|
|
|
7
7
|
const render = (args) => {
|
|
8
|
-
return testingRender(
|
|
9
|
-
<QueryClientProvider client={new QueryClient()}>
|
|
10
|
-
{args}
|
|
11
|
-
</QueryClientProvider>,
|
|
12
|
-
);
|
|
8
|
+
return testingRender(args);
|
|
13
9
|
};
|
|
14
10
|
|
|
15
11
|
const generateOptionsData = (n: number) =>
|
|
@@ -71,30 +67,35 @@ describe('SelectV2', () => {
|
|
|
71
67
|
};
|
|
72
68
|
|
|
73
69
|
it('should throw error if <Option/> is outside <Select/>', () => {
|
|
70
|
+
// mock console.error as this is the only way to silent expected error thrown by the component
|
|
71
|
+
const consoleErrorFn = jest.spyOn(console, 'error').mockImplementation(() => jest.fn());
|
|
74
72
|
expect(() => render(<Option value="Option 1" />)).toThrowError();
|
|
73
|
+
consoleErrorFn.mockRestore();
|
|
75
74
|
});
|
|
76
75
|
|
|
77
|
-
it('should open/close on click', () => {
|
|
76
|
+
it('should open/close on click', async () => {
|
|
78
77
|
render(<SelectWrapper />);
|
|
78
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
79
79
|
const select = selectors.select();
|
|
80
80
|
expect(select).toBeInTheDocument();
|
|
81
81
|
let options = selectors.options();
|
|
82
82
|
expect(options).toHaveLength(0);
|
|
83
83
|
|
|
84
84
|
// should open on click
|
|
85
|
-
userEvent.click(select);
|
|
85
|
+
await act(() => userEvent.click(select));
|
|
86
86
|
simpleOptions.forEach((opt) => {
|
|
87
87
|
const option = selectors.option(opt.props.label);
|
|
88
88
|
expect(option).toBeInTheDocument();
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
-
userEvent.click(select);
|
|
91
|
+
await act(() => userEvent.click(select));
|
|
92
92
|
options = selectors.options();
|
|
93
93
|
expect(options).toHaveLength(0);
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
-
it('should open/close with keyboard', () => {
|
|
96
|
+
it('should open/close with keyboard', async () => {
|
|
97
97
|
render(<SelectWrapper />);
|
|
98
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
98
99
|
const select = selectors.select();
|
|
99
100
|
expect(select).toBeInTheDocument();
|
|
100
101
|
const options = selectors.options();
|
|
@@ -102,7 +103,7 @@ describe('SelectV2', () => {
|
|
|
102
103
|
|
|
103
104
|
// should open on Enter
|
|
104
105
|
userEvent.tab();
|
|
105
|
-
userEvent.keyboard('{Enter}');
|
|
106
|
+
await act(() => userEvent.keyboard('{Enter}'));
|
|
106
107
|
simpleOptions.forEach((opt) => {
|
|
107
108
|
const option = selectors.option(opt.props.label);
|
|
108
109
|
expect(option).toBeInTheDocument();
|
|
@@ -121,13 +122,14 @@ describe('SelectV2', () => {
|
|
|
121
122
|
});
|
|
122
123
|
});
|
|
123
124
|
|
|
124
|
-
it('should display custom placeholder', () => {
|
|
125
|
+
it('should display custom placeholder', async () => {
|
|
125
126
|
const placeholder = 'My placeholder...';
|
|
126
127
|
render(<SelectWrapper placeholder={placeholder} />);
|
|
128
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
127
129
|
expect(screen.getByText(placeholder)).toBeInTheDocument();
|
|
128
130
|
});
|
|
129
131
|
|
|
130
|
-
it('should be disabled', () => {
|
|
132
|
+
it('should be disabled', async () => {
|
|
131
133
|
render(
|
|
132
134
|
<SelectWrapper value="1" disabled={true}>
|
|
133
135
|
{simpleOptions}
|
|
@@ -139,27 +141,29 @@ describe('SelectV2', () => {
|
|
|
139
141
|
// use input instead of select because select will still trigger the open/close action
|
|
140
142
|
// despite select container not being clickable and input being disabled
|
|
141
143
|
const input = selectors.input();
|
|
142
|
-
userEvent.click(input);
|
|
144
|
+
await act(() => userEvent.click(input));
|
|
143
145
|
const options = selectors.options();
|
|
144
146
|
expect(options).toHaveLength(0);
|
|
145
147
|
});
|
|
146
148
|
|
|
147
|
-
it('should display no option', () => {
|
|
149
|
+
it('should display no option', async () => {
|
|
148
150
|
render(
|
|
149
151
|
<SelectWrapper>
|
|
150
152
|
<></>
|
|
151
153
|
</SelectWrapper>,
|
|
152
154
|
);
|
|
155
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
153
156
|
const select = selectors.select();
|
|
154
|
-
userEvent.click(select);
|
|
157
|
+
await act(() => userEvent.click(select));
|
|
155
158
|
const noOptions = selectors.noOptions();
|
|
156
159
|
expect(noOptions).toBeInTheDocument();
|
|
157
160
|
});
|
|
158
161
|
|
|
159
|
-
it('should filter and highlight on search', () => {
|
|
162
|
+
it('should filter and highlight on search', async () => {
|
|
160
163
|
render(<SelectWrapper>{optionsWithScrollSearchBar} </SelectWrapper>);
|
|
164
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
161
165
|
const select = selectors.select(true);
|
|
162
|
-
userEvent.click(select);
|
|
166
|
+
await act(() => userEvent.click(select));
|
|
163
167
|
const input = selectors.input();
|
|
164
168
|
|
|
165
169
|
userEvent.type(input, '2');
|
|
@@ -169,25 +173,26 @@ describe('SelectV2', () => {
|
|
|
169
173
|
expect(searchedText).toHaveTextContent('2');
|
|
170
174
|
});
|
|
171
175
|
|
|
172
|
-
it('should unfocus the search input when the select is closed', () => {
|
|
176
|
+
it('should unfocus the search input when the select is closed', async () => {
|
|
173
177
|
render(<SelectWrapper>{optionsWithScrollSearchBar} </SelectWrapper>);
|
|
178
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
174
179
|
const select = selectors.select(true);
|
|
175
|
-
userEvent.click(select);
|
|
180
|
+
await act(() => userEvent.click(select));
|
|
176
181
|
let input = selectors.input();
|
|
177
182
|
expect(input).toHaveFocus();
|
|
178
183
|
const option = selectors.option(/Item 1/);
|
|
179
|
-
userEvent.click(option);
|
|
184
|
+
await act(() => userEvent.click(option));
|
|
180
185
|
input = selectors.input();
|
|
181
186
|
expect(input).not.toHaveFocus();
|
|
182
187
|
});
|
|
183
188
|
|
|
184
|
-
it('should be possible to use searchbar when option is selected', () => {
|
|
189
|
+
it('should be possible to use searchbar when option is selected', async () => {
|
|
185
190
|
render(
|
|
186
191
|
<SelectWrapper value="1">{optionsWithScrollSearchBar}</SelectWrapper>,
|
|
187
192
|
);
|
|
188
193
|
expect(screen.getByText(/Item 1/)).toBeVisible();
|
|
189
194
|
const select = selectors.select(true);
|
|
190
|
-
userEvent.click(select);
|
|
195
|
+
await act(() => userEvent.click(select));
|
|
191
196
|
const input = selectors.input();
|
|
192
197
|
userEvent.type(input, '2');
|
|
193
198
|
expect(screen.queryByText(/Item 1/)).not.toBeInTheDocument();
|
|
@@ -195,47 +200,48 @@ describe('SelectV2', () => {
|
|
|
195
200
|
expect(options).toHaveLength(1);
|
|
196
201
|
});
|
|
197
202
|
|
|
198
|
-
it('should select/unselect option with keyboard', () => {
|
|
203
|
+
it('should select/unselect option with keyboard', async () => {
|
|
199
204
|
render(<SelectWrapper />);
|
|
205
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
200
206
|
const select = selectors.select();
|
|
201
207
|
userEvent.tab();
|
|
202
|
-
userEvent.keyboard('{ArrowDown}');
|
|
208
|
+
act(() => userEvent.keyboard('{ArrowDown}'));
|
|
203
209
|
|
|
204
210
|
// should select first option
|
|
205
|
-
userEvent.keyboard('{Enter}');
|
|
211
|
+
await act(() => userEvent.keyboard('{Enter}'));
|
|
206
212
|
expect(select).toHaveTextContent('Item 0');
|
|
207
213
|
|
|
208
214
|
// should select second option
|
|
209
215
|
userEvent.tab();
|
|
210
|
-
userEvent.keyboard('{ArrowDown}');
|
|
211
|
-
userEvent.keyboard('{ArrowDown}');
|
|
216
|
+
await act(() => userEvent.keyboard('{ArrowDown}'));
|
|
217
|
+
await act(() => userEvent.keyboard('{ArrowDown}'));
|
|
212
218
|
|
|
213
|
-
userEvent.keyboard('{Enter}');
|
|
219
|
+
await act(() => userEvent.keyboard('{Enter}'));
|
|
214
220
|
expect(select).toHaveTextContent('Item 1');
|
|
215
221
|
});
|
|
216
222
|
|
|
217
|
-
it('should scroll to selected value when opening select', () => {
|
|
223
|
+
it('should scroll to selected value when opening select', async () => {
|
|
218
224
|
render(
|
|
219
225
|
<SelectWrapper value={optionsWithScrollSearchBar[9].props.value}>
|
|
220
226
|
{optionsWithScrollSearchBar}
|
|
221
227
|
</SelectWrapper>,
|
|
222
228
|
);
|
|
223
229
|
const select = selectors.select(true);
|
|
224
|
-
userEvent.click(select);
|
|
230
|
+
await act(() => userEvent.click(select));
|
|
225
231
|
const option = selectors.option(/Item 9/);
|
|
226
232
|
expect(screen.queryByRole('option', { name: /Item 1/i })).toBeNull();
|
|
227
233
|
expect(option).toBeVisible();
|
|
228
234
|
});
|
|
229
235
|
|
|
230
|
-
it('should be able to reset the value', () => {
|
|
236
|
+
it('should be able to reset the value', async () => {
|
|
231
237
|
render(<SelectReset>{simpleOptions}</SelectReset>);
|
|
232
238
|
const button = screen.getByText(/reset/);
|
|
233
|
-
userEvent.click(button);
|
|
239
|
+
await act(() => userEvent.click(button));
|
|
234
240
|
const select = selectors.select();
|
|
235
241
|
expect(select).toHaveTextContent('Select...');
|
|
236
242
|
});
|
|
237
243
|
|
|
238
|
-
it('should not be possible to select an option if it is disabled', () => {
|
|
244
|
+
it('should not be possible to select an option if it is disabled', async () => {
|
|
239
245
|
render(
|
|
240
246
|
<SelectWrapper>
|
|
241
247
|
<Option value="1" disabled>
|
|
@@ -245,15 +251,15 @@ describe('SelectV2', () => {
|
|
|
245
251
|
</SelectWrapper>,
|
|
246
252
|
);
|
|
247
253
|
const select = selectors.select();
|
|
248
|
-
userEvent.click(select);
|
|
254
|
+
await act(() => userEvent.click(select));
|
|
249
255
|
const option = selectors.option(/Item 1/);
|
|
250
256
|
|
|
251
|
-
userEvent.click(option);
|
|
257
|
+
await act(() => userEvent.click(option));
|
|
252
258
|
const option2 = selectors.option(/Item 2/);
|
|
253
259
|
expect(option2).toBeVisible();
|
|
254
260
|
});
|
|
255
261
|
|
|
256
|
-
it('should display a tooltip if the option is disabled with a reason', () => {
|
|
262
|
+
it('should display a tooltip if the option is disabled with a reason', async () => {
|
|
257
263
|
render(
|
|
258
264
|
<SelectWrapper>
|
|
259
265
|
<Option value="1" disabled disabledReason="This option is disabled">
|
|
@@ -262,10 +268,10 @@ describe('SelectV2', () => {
|
|
|
262
268
|
</SelectWrapper>,
|
|
263
269
|
);
|
|
264
270
|
const select = selectors.select();
|
|
265
|
-
userEvent.click(select);
|
|
271
|
+
await act(() => userEvent.click(select));
|
|
266
272
|
const option = selectors.option(/Item 1/);
|
|
267
273
|
expect(option).toHaveAttribute('aria-disabled', 'true');
|
|
268
|
-
userEvent.hover(option);
|
|
274
|
+
await act(() => userEvent.hover(option));
|
|
269
275
|
const tooltip = screen.getByText(/This option is disabled/);
|
|
270
276
|
expect(tooltip).toBeInTheDocument();
|
|
271
277
|
});
|
|
@@ -309,9 +315,9 @@ describe('SelectV2', () => {
|
|
|
309
315
|
// It's not our case here, so it makes thing difficult to select the right select
|
|
310
316
|
// I workaround this by using setting the aria-label to the select container (cf: test below)
|
|
311
317
|
const singleSelect = screen.getByRole('listbox');
|
|
312
|
-
await userEvent.click(singleSelect);
|
|
318
|
+
await act(() => userEvent.click(singleSelect));
|
|
313
319
|
|
|
314
|
-
await userEvent.click(screen.getByRole('option', { name: /account 1/i }));
|
|
320
|
+
await act(() => userEvent.click(screen.getByRole('option', { name: /account 1/i })));
|
|
315
321
|
});
|
|
316
322
|
|
|
317
323
|
it('should be testable if we have several select', async () => {
|
|
@@ -372,13 +378,13 @@ describe('SelectV2', () => {
|
|
|
372
378
|
|
|
373
379
|
render(<MyWrapperWith2Select />);
|
|
374
380
|
|
|
375
|
-
await userEvent.click(screen.getByLabelText(/select account/i));
|
|
381
|
+
await act(() => userEvent.click(screen.getByLabelText(/select account/i)));
|
|
376
382
|
|
|
377
|
-
await userEvent.click(screen.getByRole('option', { name: /account 1/i }));
|
|
383
|
+
await act(() => userEvent.click(screen.getByRole('option', { name: /account 1/i })));
|
|
378
384
|
|
|
379
|
-
await userEvent.click(screen.getByLabelText(/select user/i));
|
|
385
|
+
await act(() => userEvent.click(screen.getByLabelText(/select user/i)));
|
|
380
386
|
|
|
381
|
-
await userEvent.click(screen.getByRole('option', { name: /user 1/i }));
|
|
387
|
+
await act(() => userEvent.click(screen.getByRole('option', { name: /user 1/i })));
|
|
382
388
|
});
|
|
383
389
|
|
|
384
390
|
it('should be testable even if we have several select with the same value, the placeholder should be different', async () => {
|
|
@@ -439,8 +445,8 @@ describe('SelectV2', () => {
|
|
|
439
445
|
|
|
440
446
|
render(<MyWrapperWith2Select />);
|
|
441
447
|
|
|
442
|
-
await userEvent.click(screen.getByLabelText(/select account/i));
|
|
443
|
-
await userEvent.click(screen.getByLabelText(/Select Second Account/i));
|
|
448
|
+
await act(() => userEvent.click(screen.getByLabelText(/select account/i)));
|
|
449
|
+
await act(() => userEvent.click(screen.getByLabelText(/Select Second Account/i)));
|
|
444
450
|
|
|
445
451
|
/**
|
|
446
452
|
* This is possible because only 1 select can be open at a time
|
|
@@ -450,13 +456,13 @@ describe('SelectV2', () => {
|
|
|
450
456
|
* const selectContainer = select?.parentElement?.parentElement;
|
|
451
457
|
* const option = within(selectContainer).getByRole('option', { name: /account 1/i });
|
|
452
458
|
*/
|
|
453
|
-
await userEvent.click(screen.getByRole('option', { name: /account 1/i }));
|
|
459
|
+
await act(() => userEvent.click(screen.getByRole('option', { name: /account 1/i })));
|
|
454
460
|
});
|
|
455
461
|
|
|
456
462
|
describe('Ref API', () => {
|
|
457
463
|
it('should expose focus method via ref', async () => {
|
|
458
464
|
const RefTestComponent = () => {
|
|
459
|
-
const selectRef = useRef<SelectRef
|
|
465
|
+
const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
|
|
460
466
|
const [value, setValue] = useState<string>('');
|
|
461
467
|
|
|
462
468
|
return (
|
|
@@ -478,13 +484,13 @@ describe('SelectV2', () => {
|
|
|
478
484
|
render(<RefTestComponent />);
|
|
479
485
|
expect(selectors.input()).not.toHaveFocus();
|
|
480
486
|
|
|
481
|
-
userEvent.click(screen.getByRole('button', { name: /Focus/i }));
|
|
487
|
+
await act(() => userEvent.click(screen.getByRole('button', { name: /Focus/i })));
|
|
482
488
|
expect(selectors.input()).toHaveFocus();
|
|
483
489
|
});
|
|
484
490
|
|
|
485
491
|
it('should expose openMenu and closeMenu methods via ref', async () => {
|
|
486
492
|
const RefTestComponent = () => {
|
|
487
|
-
const selectRef = useRef<SelectRef
|
|
493
|
+
const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
|
|
488
494
|
const [value, setValue] = useState<string>('');
|
|
489
495
|
|
|
490
496
|
return (
|
|
@@ -511,14 +517,14 @@ describe('SelectV2', () => {
|
|
|
511
517
|
render(<RefTestComponent />);
|
|
512
518
|
expect(selectors.options()).toHaveLength(0);
|
|
513
519
|
|
|
514
|
-
userEvent.click(screen.getByRole('button', { name: /Open Menu/i }));
|
|
520
|
+
await act(() => userEvent.click(screen.getByRole('button', { name: /Open Menu/i })));
|
|
515
521
|
expect(selectors.options().length).toBeGreaterThan(0);
|
|
516
522
|
simpleOptions.forEach((opt) => {
|
|
517
523
|
const option = selectors.option(opt.props.label);
|
|
518
524
|
expect(option).toBeInTheDocument();
|
|
519
525
|
});
|
|
520
526
|
|
|
521
|
-
userEvent.click(screen.getByRole('button', { name: /Close Menu/i }));
|
|
527
|
+
await act(() => userEvent.click(screen.getByRole('button', { name: /Close Menu/i })));
|
|
522
528
|
expect(selectors.options()).toHaveLength(0);
|
|
523
529
|
});
|
|
524
530
|
|
|
@@ -527,7 +533,7 @@ describe('SelectV2', () => {
|
|
|
527
533
|
|
|
528
534
|
const RefTestComponent = () => {
|
|
529
535
|
const [value, setValue] = useState('');
|
|
530
|
-
const selectRef = useRef<SelectRef
|
|
536
|
+
const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
|
|
531
537
|
|
|
532
538
|
return (
|
|
533
539
|
<div>
|
|
@@ -565,19 +571,22 @@ describe('SelectV2', () => {
|
|
|
565
571
|
|
|
566
572
|
render(<RefTestComponent />);
|
|
567
573
|
|
|
568
|
-
|
|
574
|
+
let select;
|
|
575
|
+
await act(() => {
|
|
576
|
+
select = selectors.select();
|
|
577
|
+
});
|
|
569
578
|
expect(select).toHaveTextContent('Select with ref');
|
|
570
579
|
|
|
571
|
-
userEvent.click(screen.getByRole('button', { name: /Set Value/i }));
|
|
580
|
+
await act(() => userEvent.click(screen.getByRole('button', { name: /Set Value/i })));
|
|
572
581
|
expect(select).toHaveTextContent('Item 0');
|
|
573
582
|
|
|
574
|
-
userEvent.click(screen.getByRole('button', { name: /Clear/i }));
|
|
583
|
+
await act(() => userEvent.click(screen.getByRole('button', { name: /Clear/i })));
|
|
575
584
|
expect(select).toHaveTextContent('Select with ref');
|
|
576
585
|
});
|
|
577
586
|
|
|
578
587
|
it('should expose blur method via ref', async () => {
|
|
579
588
|
const RefTestComponent = () => {
|
|
580
|
-
const selectRef = useRef<SelectRef
|
|
589
|
+
const selectRef = useRef<SelectRef<OptionTypeBase, boolean, GroupTypeBase<OptionTypeBase>>>(null);
|
|
581
590
|
const [value, setValue] = useState<string>('');
|
|
582
591
|
|
|
583
592
|
return (
|
|
@@ -599,10 +608,10 @@ describe('SelectV2', () => {
|
|
|
599
608
|
|
|
600
609
|
render(<RefTestComponent />);
|
|
601
610
|
|
|
602
|
-
userEvent.click(screen.getByRole('button', { name: /Focus/i }));
|
|
611
|
+
await act(() => userEvent.click(screen.getByRole('button', { name: /Focus/i })));
|
|
603
612
|
expect(selectors.input()).toHaveFocus();
|
|
604
613
|
|
|
605
|
-
userEvent.click(screen.getByRole('button', { name: /Blur/i }));
|
|
614
|
+
await act(() => userEvent.click(screen.getByRole('button', { name: /Blur/i })));
|
|
606
615
|
expect(selectors.input()).not.toHaveFocus();
|
|
607
616
|
});
|
|
608
617
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference path="./Stepper.component.d.ts" />
|
|
2
|
-
import { createContext, useContext, useState } from 'react';
|
|
2
|
+
import { createContext, useContext, useState, useCallback, useMemo } from 'react';
|
|
3
3
|
import { Steppers } from './Steppers.component';
|
|
4
4
|
import { Box } from '../box/Box';
|
|
5
5
|
export interface StepperContextType {
|
|
@@ -33,19 +33,21 @@ export const Stepper: Stepper = ({ steps }) => {
|
|
|
33
33
|
props: Record<string, unknown>;
|
|
34
34
|
}>({ step: 0, props: {} });
|
|
35
35
|
|
|
36
|
-
const next = (props: Record<string, unknown>) => {
|
|
37
|
-
setStepProps({ step:
|
|
38
|
-
};
|
|
36
|
+
const next = useCallback((props: Record<string, unknown>) => {
|
|
37
|
+
setStepProps(current => ({ step: current.step + 1, props }));
|
|
38
|
+
}, []);
|
|
39
39
|
|
|
40
|
-
const prev = (props: Record<string, unknown>) => {
|
|
41
|
-
setStepProps({ step:
|
|
42
|
-
};
|
|
40
|
+
const prev = useCallback((props: Record<string, unknown>) => {
|
|
41
|
+
setStepProps(current => ({ step: current.step - 1, props }));
|
|
42
|
+
}, []);
|
|
43
43
|
|
|
44
44
|
const { Component } = steps[stepProps.step];
|
|
45
45
|
const StepperContext = window.StepperContext;
|
|
46
46
|
|
|
47
|
+
const stepperValue = useMemo(() => ({ next, prev }), [next, prev]);
|
|
48
|
+
|
|
47
49
|
return (
|
|
48
|
-
<StepperContext.Provider value={
|
|
50
|
+
<StepperContext.Provider value={stepperValue}>
|
|
49
51
|
<Box display="flex" gap={32} flex={1} height="100%">
|
|
50
52
|
<Steppers
|
|
51
53
|
activeStep={stepProps.step}
|
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
import { fireEvent, render, screen } from '@testing-library/react';
|
|
2
|
-
import React from 'react';
|
|
1
|
+
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
3
2
|
import { TableSync } from './TableSync';
|
|
4
|
-
import { QueryClient, QueryClientProvider } from 'react-query';
|
|
5
3
|
|
|
6
4
|
describe('TableSync', () => {
|
|
7
|
-
it('should render correctly', () => {
|
|
5
|
+
it('should render correctly', async () => {
|
|
8
6
|
const onSync = jest.fn();
|
|
9
7
|
render(
|
|
10
|
-
<
|
|
11
|
-
<TableSync onSync={onSync} />
|
|
12
|
-
</QueryClientProvider>,
|
|
8
|
+
<TableSync onSync={onSync} tooltipOverlay='sync' />
|
|
13
9
|
);
|
|
10
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
14
11
|
|
|
15
12
|
const button = screen.getByRole('button');
|
|
16
13
|
expect(button).toBeInTheDocument();
|
|
17
14
|
});
|
|
18
15
|
|
|
19
|
-
it('should call onSync when clicked', () => {
|
|
16
|
+
it('should call onSync when clicked', async () => {
|
|
20
17
|
const onSync = jest.fn();
|
|
21
18
|
render(
|
|
22
|
-
<
|
|
23
|
-
<TableSync onSync={onSync} />
|
|
24
|
-
</QueryClientProvider>,
|
|
19
|
+
<TableSync onSync={onSync} tooltipOverlay='sync' />
|
|
25
20
|
);
|
|
21
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
26
22
|
|
|
27
23
|
const button = screen.getByRole('button');
|
|
28
|
-
fireEvent.click(button);
|
|
24
|
+
await act(() => fireEvent.click(button));
|
|
29
25
|
expect(onSync).toHaveBeenCalledTimes(1);
|
|
30
26
|
});
|
|
31
27
|
});
|
|
@@ -9,9 +9,12 @@ it('should return -1 or 1 to sort the status', () => {
|
|
|
9
9
|
expect(result).toEqual(1);
|
|
10
10
|
expect(result2).toEqual(-1);
|
|
11
11
|
});
|
|
12
|
-
it('should return
|
|
13
|
-
const
|
|
14
|
-
const
|
|
12
|
+
it('should return undefined for the unknown status', () => {
|
|
13
|
+
const consoleErrorMockHandle = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
14
|
+
const result = compareHealth('invalidStatus' as any, 'healthy');
|
|
15
|
+
const result2 = compareHealth('none', 'invalidStatus' as any);
|
|
16
|
+
expect(consoleErrorMockHandle).toHaveBeenCalled();
|
|
17
|
+
consoleErrorMockHandle.mockRestore();
|
|
15
18
|
expect(result).toEqual(undefined);
|
|
16
19
|
expect(result2).toEqual(undefined);
|
|
17
20
|
});
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { Table } from './Tablev2.component';
|
|
2
|
-
import
|
|
3
|
-
import { render } from '@testing-library/react';
|
|
4
|
-
import { QueryClient, QueryClientProvider } from 'react-query';
|
|
1
|
+
import { Table, TableProps } from './Tablev2.component';
|
|
2
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
5
3
|
|
|
6
4
|
jest.mock('./TableUtils', () => ({
|
|
7
5
|
...jest.requireActual('./TableUtils'),
|
|
@@ -43,7 +41,7 @@ const data = [
|
|
|
43
41
|
health: 'healthy',
|
|
44
42
|
},
|
|
45
43
|
];
|
|
46
|
-
const columns = [
|
|
44
|
+
const columns: TableProps['columns'] = [
|
|
47
45
|
{
|
|
48
46
|
Header: 'First Name',
|
|
49
47
|
accessor: 'firstName',
|
|
@@ -66,17 +64,17 @@ const columns = [
|
|
|
66
64
|
describe('TableV2', () => {
|
|
67
65
|
test('it should display all the data', async () => {
|
|
68
66
|
const { getAllByRole } = render(
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
<Table
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
</div>
|
|
78
|
-
</QueryClientProvider>,
|
|
67
|
+
<div>
|
|
68
|
+
<Table columns={columns} data={data} defaultSortingKey={'health'}>
|
|
69
|
+
<Table.SingleSelectableContent
|
|
70
|
+
rowHeight="h40"
|
|
71
|
+
separationLineVariant="backgroundLevel3"
|
|
72
|
+
/>
|
|
73
|
+
</Table>
|
|
74
|
+
</div>
|
|
79
75
|
);
|
|
76
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
77
|
+
|
|
80
78
|
// we check that the table is displaying all the data
|
|
81
79
|
const rows = getAllByRole('row');
|
|
82
80
|
expect(rows[4]).toHaveTextContent(/Ninette/i);
|
|
@@ -85,17 +83,17 @@ describe('TableV2', () => {
|
|
|
85
83
|
});
|
|
86
84
|
test('it should sort by defaultSortingKey', async () => {
|
|
87
85
|
const { getAllByRole } = render(
|
|
88
|
-
<
|
|
89
|
-
<
|
|
90
|
-
<Table
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
</div>
|
|
97
|
-
</QueryClientProvider>,
|
|
86
|
+
<div>
|
|
87
|
+
<Table columns={columns} data={data} defaultSortingKey={'firstName'}>
|
|
88
|
+
<Table.SingleSelectableContent
|
|
89
|
+
rowHeight="h40"
|
|
90
|
+
separationLineVariant="backgroundLevel3"
|
|
91
|
+
/>
|
|
92
|
+
</Table>
|
|
93
|
+
</div>
|
|
98
94
|
);
|
|
95
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
96
|
+
|
|
99
97
|
// we check that the table is displaying all the data
|
|
100
98
|
const rows = getAllByRole('row');
|
|
101
99
|
expect(rows[1]).toHaveTextContent(/ninette/i);
|
|
@@ -104,22 +102,22 @@ describe('TableV2', () => {
|
|
|
104
102
|
});
|
|
105
103
|
test('it should filterGlobally', async () => {
|
|
106
104
|
const { getAllByRole } = render(
|
|
107
|
-
<
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
</div>
|
|
121
|
-
</QueryClientProvider>,
|
|
105
|
+
<div>
|
|
106
|
+
<Table
|
|
107
|
+
columns={columns}
|
|
108
|
+
data={data}
|
|
109
|
+
defaultSortingKey={'firstName'}
|
|
110
|
+
globalFilter="an"
|
|
111
|
+
>
|
|
112
|
+
<Table.SingleSelectableContent
|
|
113
|
+
rowHeight="h40"
|
|
114
|
+
separationLineVariant="backgroundLevel3"
|
|
115
|
+
/>
|
|
116
|
+
</Table>
|
|
117
|
+
</div>
|
|
122
118
|
);
|
|
119
|
+
await waitFor(() => screen.queryAllByRole('img', { hidden: true }));
|
|
120
|
+
|
|
123
121
|
// we check that the table is displaying all the data
|
|
124
122
|
const rows = getAllByRole('row');
|
|
125
123
|
expect(rows[1]).toHaveTextContent(/an/i); //first name yoh-an-n
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode, createContext, useContext, useState } from 'react';
|
|
1
|
+
import { ReactNode, createContext, useCallback, useContext, useMemo, useState } from 'react';
|
|
2
2
|
import { Toast, ToastProps } from './Toast.component';
|
|
3
3
|
|
|
4
4
|
export type ToastContextState = Omit<ToastProps, 'onClose'>;
|
|
@@ -14,20 +14,27 @@ export const ToastContext = createContext<ToastContextType | undefined>(
|
|
|
14
14
|
interface ToastProviderProps {
|
|
15
15
|
children: ReactNode;
|
|
16
16
|
}
|
|
17
|
+
|
|
17
18
|
export const ToastProvider: React.FC<
|
|
18
19
|
React.PropsWithChildren<ToastProviderProps>
|
|
19
20
|
> = ({ children }) => {
|
|
20
21
|
const [toastProps, setToastProps] = useState<ToastContextState | null>(null);
|
|
21
22
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const toastCtxValue = useMemo(
|
|
24
|
+
() => ({ showToast: setToastProps }),
|
|
25
|
+
[],
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const closeToast = useCallback(
|
|
29
|
+
() => setToastProps(null),
|
|
30
|
+
[]
|
|
31
|
+
);
|
|
25
32
|
|
|
26
33
|
return (
|
|
27
|
-
<ToastContext.Provider value={
|
|
34
|
+
<ToastContext.Provider value={toastCtxValue}>
|
|
28
35
|
{children}
|
|
29
36
|
{toastProps && (
|
|
30
|
-
<Toast {...toastProps} onClose={
|
|
37
|
+
<Toast {...toastProps} onClose={closeToast} />
|
|
31
38
|
)}
|
|
32
39
|
</ToastContext.Provider>
|
|
33
40
|
);
|
|
@@ -38,5 +45,6 @@ export const useToast = () => {
|
|
|
38
45
|
if (!context) {
|
|
39
46
|
throw new Error('useToast must be used within a ToastProvider');
|
|
40
47
|
}
|
|
48
|
+
|
|
41
49
|
return context;
|
|
42
50
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, createContext, useContext } from 'react';
|
|
1
|
+
import { useState, createContext, useContext, useMemo, useCallback } from 'react';
|
|
2
2
|
export const SyncedCursorChartsContext = createContext<{
|
|
3
3
|
cursorX: number;
|
|
4
4
|
setCursorX: (cursorX: number) => void;
|
|
@@ -17,13 +17,11 @@ export const useCursorX = (): {
|
|
|
17
17
|
};
|
|
18
18
|
export function SyncedCursorCharts({ children }: { children: JSX.Element }) {
|
|
19
19
|
const [cursorX, setCursorX] = useState(0);
|
|
20
|
+
|
|
21
|
+
const contextValue = useMemo(() => ({cursorX, setCursorX}), [cursorX]);
|
|
22
|
+
|
|
20
23
|
return (
|
|
21
|
-
<SyncedCursorChartsContext.Provider
|
|
22
|
-
value={{
|
|
23
|
-
cursorX,
|
|
24
|
-
setCursorX,
|
|
25
|
-
}}
|
|
26
|
-
>
|
|
24
|
+
<SyncedCursorChartsContext.Provider value={contextValue}>
|
|
27
25
|
{children}
|
|
28
26
|
</SyncedCursorChartsContext.Provider>
|
|
29
27
|
);
|