@ouestfrance/sipa-bms-ui 8.6.0 → 8.7.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.
Files changed (54) hide show
  1. package/dist/components/form/BmsAutocomplete.vue.d.ts +2 -0
  2. package/dist/components/form/BmsInputBooleanCheckbox.vue.d.ts +1 -1
  3. package/dist/components/form/BmsInputCheckboxGroup.vue.d.ts +2 -2
  4. package/dist/components/form/BmsInputCode.vue.d.ts +2 -2
  5. package/dist/components/form/BmsInputNumber.vue.d.ts +2 -2
  6. package/dist/components/form/BmsInputRadio.vue.d.ts +2 -2
  7. package/dist/components/form/BmsInputText.vue.d.ts +24 -22
  8. package/dist/components/form/BmsMultiSelect.vue.d.ts +3 -1
  9. package/dist/components/form/BmsSearch.vue.d.ts +28 -24
  10. package/dist/components/form/BmsSelect.vue.d.ts +7 -17
  11. package/dist/components/form/RawAutocomplete.vue.d.ts +17 -21
  12. package/dist/components/form/RawInputText.vue.d.ts +9 -9
  13. package/dist/components/form/RawSelect.vue.d.ts +30 -0
  14. package/dist/components/navigation/UiTenantSwitcher.vue.d.ts +28 -24
  15. package/dist/components/table/BmsServerTable.vue.d.ts +18 -0
  16. package/dist/components/table/BmsTable.vue.d.ts +18 -1
  17. package/dist/components/table/BmsTableFilters.vue.d.ts +47 -25
  18. package/dist/composables/search.composable.d.ts +1 -0
  19. package/dist/plugins/field/FieldDatalist.vue.d.ts +2 -0
  20. package/dist/plugins/field/field-component.model.d.ts +2 -2
  21. package/dist/sipa-bms-ui.css +163 -116
  22. package/dist/sipa-bms-ui.es.js +725 -520
  23. package/dist/sipa-bms-ui.es.js.map +1 -1
  24. package/dist/sipa-bms-ui.umd.js +730 -525
  25. package/dist/sipa-bms-ui.umd.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/components/form/BmsAutocomplete.vue +3 -0
  28. package/src/components/form/BmsInputNumber.spec.ts +26 -0
  29. package/src/components/form/BmsInputNumber.stories.js +20 -3
  30. package/src/components/form/BmsInputNumber.vue +36 -4
  31. package/src/components/form/BmsInputRadio.vue +1 -1
  32. package/src/components/form/BmsInputText.spec.ts +25 -0
  33. package/src/components/form/BmsInputText.stories.js +28 -3
  34. package/src/components/form/BmsInputText.vue +73 -12
  35. package/src/components/form/BmsMultiSelect.vue +66 -28
  36. package/src/components/form/BmsSelect.vue +60 -57
  37. package/src/components/form/RawAutocomplete.spec.ts +0 -8
  38. package/src/components/form/RawAutocomplete.vue +42 -24
  39. package/src/components/form/RawInputText.vue +14 -21
  40. package/src/components/form/RawSelect.vue +111 -0
  41. package/src/components/table/BmsServerTable.vue +18 -3
  42. package/src/components/table/BmsTable.vue +15 -2
  43. package/src/components/table/BmsTableFilters.vue +19 -7
  44. package/src/composables/search.composable.spec.ts +75 -0
  45. package/src/composables/search.composable.ts +54 -11
  46. package/src/plugins/field/FieldComponent.vue +6 -4
  47. package/src/plugins/field/FieldDatalist.stories.js +0 -9
  48. package/src/plugins/field/FieldDatalist.vue +16 -13
  49. package/src/plugins/field/field-component.model.ts +2 -2
  50. package/src/showroom/pages/autocomplete.vue +22 -1
  51. package/src/showroom/pages/server-table.vue +53 -22
  52. package/src/showroom/pages/table.vue +42 -3
  53. package/dist/plugins/field/FieldDatalist.spec.d.ts +0 -1
  54. package/src/plugins/field/FieldDatalist.spec.ts +0 -35
@@ -6,6 +6,7 @@ import {
6
6
  } from './search.composable';
7
7
  import { defineComponent, nextTick } from 'vue';
8
8
  import { mount } from '@vue/test-utils';
9
+ import { Filter } from '@/models';
9
10
 
10
11
  vi.mock('vue-router', () => ({
11
12
  useRoute: vi.fn(),
@@ -1292,5 +1293,79 @@ describe('search and filter composable', () => {
1292
1293
  ]);
1293
1294
  });
1294
1295
  });
1296
+
1297
+ describe('updateFiltersFromProps', () => {
1298
+ test('should update select options', () => {
1299
+ const wrapper = factory();
1300
+ const filter: Filter = {
1301
+ key: 'filter0',
1302
+ label: 'Zéro',
1303
+ type: 'select',
1304
+ selectOptions: [{ label: 'option1', value: '1' }],
1305
+ value: 1,
1306
+ };
1307
+
1308
+ wrapper.vm.filters = [filter];
1309
+ wrapper.vm.updateFiltersFromProps([{ ...filter, selectOptions: [] }]);
1310
+ expect(wrapper.vm.filters).toStrictEqual([
1311
+ { ...filter, selectOptions: [], value: null },
1312
+ ]);
1313
+ });
1314
+
1315
+ test('should not change filter other than options', () => {
1316
+ const wrapper = factory();
1317
+ const filter: Filter = {
1318
+ key: 'filter0',
1319
+ label: 'Zéro',
1320
+ type: 'select',
1321
+ selectOptions: [{ label: 'option1', value: '1' }],
1322
+ };
1323
+
1324
+ wrapper.vm.filters = [filter];
1325
+ wrapper.vm.updateFiltersFromProps([
1326
+ {
1327
+ key: 'filter0',
1328
+ label: 'new label',
1329
+ type: 'input',
1330
+ selectOptions: [{ label: 'option1', value: '1' }],
1331
+ },
1332
+ ]);
1333
+ expect(wrapper.vm.filters).toStrictEqual([filter]);
1334
+ });
1335
+ test('should keep value if is in new options', () => {
1336
+ const wrapper = factory();
1337
+ const filter: Filter = {
1338
+ key: 'filter0',
1339
+ label: 'Zéro',
1340
+ type: 'select',
1341
+ selectOptions: [
1342
+ { label: 'option1', value: '1' },
1343
+ { label: 'option2', value: '2' },
1344
+ ],
1345
+ };
1346
+
1347
+ wrapper.vm.filters = [filter];
1348
+ wrapper.vm.updateFiltersFromProps([
1349
+ {
1350
+ key: 'filter0',
1351
+ label: 'Zéro',
1352
+ type: 'select',
1353
+ selectOptions: [
1354
+ { label: 'option1', value: '1' },
1355
+ { label: 'option3', value: '3' },
1356
+ ],
1357
+ },
1358
+ ]);
1359
+ expect(wrapper.vm.filters).toStrictEqual([
1360
+ {
1361
+ ...filter,
1362
+ selectOptions: [
1363
+ { label: 'option1', value: '1' },
1364
+ { label: 'option3', value: '3' },
1365
+ ],
1366
+ },
1367
+ ]);
1368
+ });
1369
+ });
1295
1370
  });
1296
1371
  });
@@ -183,6 +183,7 @@ export const useSearch = (
183
183
  reflectSearchToUserPref(search.value);
184
184
  }
185
185
  });
186
+
186
187
  watch(
187
188
  () => filters,
188
189
  () => {
@@ -233,19 +234,23 @@ export const useSearch = (
233
234
  });
234
235
  };
235
236
 
237
+ const resetFilterValue = (filter: Filter) => {
238
+ let resetFilter = { ...filter };
239
+ const valueKeys = ['value', 'valueFrom', 'valueTo'];
240
+ valueKeys.forEach((key) => {
241
+ if (
242
+ resetFilter[key as keyof Filter] !== null &&
243
+ resetFilter[key as keyof Filter] !== undefined
244
+ ) {
245
+ resetFilter[key as keyof Filter] = null;
246
+ }
247
+ });
248
+ return resetFilter;
249
+ };
250
+
236
251
  const resetFilters = () => {
237
252
  filters.value = filters.value.map((filter) => {
238
- let resetFilter = { ...filter };
239
- const valueKeys = ['value', 'valueFrom', 'valueTo'];
240
- valueKeys.forEach((key) => {
241
- if (
242
- resetFilter[key as keyof Filter] !== null &&
243
- resetFilter[key as keyof Filter] !== undefined
244
- ) {
245
- resetFilter[key as keyof Filter] = null;
246
- }
247
- });
248
- return resetFilter;
253
+ return resetFilterValue(filter);
249
254
  });
250
255
  };
251
256
 
@@ -264,6 +269,43 @@ export const useSearch = (
264
269
  }
265
270
  };
266
271
 
272
+ const updateFiltersFromProps = (updatedFilters: Filter[]) => {
273
+ filters.value = filters.value.map((filter) => {
274
+ const updatedFilter = updatedFilters.find((f) => f.key === filter.key);
275
+
276
+ if (updatedFilter) {
277
+ let mergedFilter = { ...filter };
278
+
279
+ if (updatedFilter.autocompleteOptions)
280
+ mergedFilter.autocompleteOptions = updatedFilter.autocompleteOptions;
281
+ if (updatedFilter.selectOptions)
282
+ mergedFilter.selectOptions = updatedFilter.selectOptions;
283
+
284
+ const value = filter.value || filter.valueFrom || filter.valueTo;
285
+
286
+ const isValueValidSelectOption =
287
+ updatedFilter.type === 'select' &&
288
+ updatedFilter.selectOptions?.find((option) => option.value === value);
289
+
290
+ const isValueValidAutocompleteOption =
291
+ updatedFilter.type === 'autocomplete' &&
292
+ updatedFilter.autocompleteOptions?.find((option) => option === value);
293
+
294
+ if (
295
+ value &&
296
+ !isValueValidSelectOption &&
297
+ !isValueValidAutocompleteOption
298
+ ) {
299
+ mergedFilter = resetFilterValue(mergedFilter);
300
+ }
301
+
302
+ return mergedFilter;
303
+ } else {
304
+ return filter;
305
+ }
306
+ });
307
+ };
308
+
267
309
  return {
268
310
  search,
269
311
  reflect,
@@ -277,6 +319,7 @@ export const useSearch = (
277
319
  resetFilters,
278
320
  selectSavedFilter,
279
321
  resetAllFilters,
322
+ updateFiltersFromProps,
280
323
  };
281
324
  };
282
325
 
@@ -24,17 +24,17 @@
24
24
  </span>
25
25
  </div>
26
26
 
27
- <div v-if="captions?.length" class="field__captions">
27
+ <div v-if="captions?.length || errors?.length" class="field__captions">
28
28
  <div
29
+ v-if="captions?.length"
29
30
  v-for="caption in captions"
30
31
  :key="getCaptionIdentifier(caption)"
31
32
  class="information field__caption"
32
33
  >
33
34
  <BmsCaption :caption="caption" />
34
35
  </div>
35
- </div>
36
- <div v-if="errors?.length" class="field__errors">
37
36
  <div
37
+ v-if="errors?.length"
38
38
  v-for="error in computedErrors"
39
39
  :key="error.label"
40
40
  class="field__error"
@@ -186,7 +186,9 @@ const getCaptionIdentifier = (caption: string | Caption): string => {
186
186
  --field-padding: 0.5em;
187
187
  --field-margin: 0;
188
188
  --field-label-font-weight: normal;
189
- // color: var(--bms-grey-75);
189
+ .field__captions {
190
+ margin-top: 0.5rem;
191
+ }
190
192
  }
191
193
 
192
194
  &.is-error {
@@ -27,15 +27,6 @@ Default.args = {
27
27
  })),
28
28
  };
29
29
 
30
- export const WithSelectedItem = Template.bind({});
31
- WithSelectedItem.args = {
32
- currentSelectedItemIndex: 1,
33
- options: ['toto', 'titi', 'tutu', 'tirlitititututatoooo'].map((i) => ({
34
- label: i,
35
- value: i,
36
- })),
37
- };
38
-
39
30
  export const CanAddNewOption = Template.bind({});
40
31
  CanAddNewOption.args = {
41
32
  options: ['toto', 'titi', 'tutu', 'tirlitititututatoooo'].map((i) => ({
@@ -1,29 +1,21 @@
1
1
  <template>
2
- <ul
3
- class="options-list"
4
- data-testid="select-options"
5
- @keydown.up="keyUp"
6
- @keydown.down="keyDown"
7
- @keydown.enter="keyEnter"
8
- >
2
+ <ul class="options-list" data-testid="select-options">
9
3
  <li
10
4
  v-for="(option, index) in options"
11
5
  :key="index"
12
6
  :data-testid="option.value"
13
7
  :class="{
8
+ 'datalist-option': true,
14
9
  selected: index === currentSelectedItemIndex,
15
10
  small,
16
11
  }"
17
- @click.prevent="onClick(option)"
12
+ @click.stop="onClick(option)"
18
13
  >
19
14
  <slot name="option" :option="option">
20
15
  {{ option.label === null ? 'N/A' : option.label }}
21
16
  </slot>
22
17
  </li>
23
- <li
24
- v-if="displayNewOption"
25
- @click.prevent="$emits('addNewOption', newOption)"
26
- >
18
+ <li v-if="displayNewOption" @click.stop="$emits('addNewOption', newOption)">
27
19
  <slot name="new-option"> {{ newOption }} (nouvelle option) </slot>
28
20
  </li>
29
21
  </ul>
@@ -31,7 +23,7 @@
31
23
 
32
24
  <script setup lang="ts">
33
25
  import { InputOption } from '@/models';
34
- import { computed, onMounted, ref } from 'vue';
26
+ import { computed, onMounted, onUnmounted, ref } from 'vue';
35
27
 
36
28
  export interface Props {
37
29
  options: InputOption[];
@@ -52,17 +44,24 @@ const currentSelectedItemIndex = ref<number>(-1);
52
44
  const $emits = defineEmits<{
53
45
  select: [option: any];
54
46
  addNewOption: [option: string];
47
+ blur: [];
55
48
  }>();
56
49
 
57
50
  const keyDownEventListener = (ev: KeyboardEvent) => {
58
51
  if (props.isInputFocused) {
59
52
  switch (ev.key) {
60
53
  case 'ArrowDown':
54
+ ev.preventDefault();
61
55
  return keyDown();
62
56
  case 'ArrowUp':
57
+ ev.preventDefault();
63
58
  return keyUp();
64
59
  case 'Enter':
60
+ ev.preventDefault();
65
61
  return keyEnter();
62
+ case 'Escape':
63
+ ev.preventDefault();
64
+ return keyEscape();
66
65
  default:
67
66
  return;
68
67
  }
@@ -96,6 +95,10 @@ const keyEnter = () => {
96
95
  }
97
96
  };
98
97
 
98
+ const keyEscape = () => {
99
+ $emits('blur');
100
+ };
101
+
99
102
  const onClick = (option: { label: string; value: any }) => {
100
103
  $emits('select', option);
101
104
  };
@@ -5,8 +5,8 @@ export interface FieldComponentProps {
5
5
  required?: boolean;
6
6
  optional?: boolean;
7
7
  helperText?: string;
8
- errors?: string[] | Caption[];
9
- captions?: string[] | Caption[];
8
+ errors?: (string | Caption)[];
9
+ captions?: (string | Caption)[];
10
10
  disabled?: boolean;
11
11
  small?: boolean;
12
12
  }
@@ -11,7 +11,6 @@
11
11
  :can-add-new-option="true"
12
12
  @add-new-option="onAddNewOption"
13
13
  />
14
-
15
14
  Valeur: {{ inputValueIcon }}
16
15
  <BmsAutocomplete
17
16
  label="Autocomplete avec icones"
@@ -26,6 +25,20 @@
26
25
  :options="optionsText"
27
26
  v-model="inputText"
28
27
  />
28
+
29
+ <BmsSelect
30
+ label="Select"
31
+ @blur="console.log('blur')"
32
+ v-model="select"
33
+ :options="optionsLabelValue"
34
+ />
35
+
36
+ <BmsMultiSelect
37
+ label="Multi-select"
38
+ v-model="multiSelect"
39
+ :options="optionsLabelValue"
40
+ />
41
+ <br />
29
42
  </template>
30
43
 
31
44
  <script setup lang="ts">
@@ -34,6 +47,14 @@ import { Heart, Cat } from 'lucide-vue-next';
34
47
  import { range } from 'lodash';
35
48
  import { ref } from 'vue';
36
49
  import BmsButton from '@/components/button/BmsButton.vue';
50
+ import BmsSelect from '@/components/form/BmsSelect.vue';
51
+ import BmsMultiSelect from '@/components/form/BmsMultiSelect.vue';
52
+ import FieldDatalist from '@/plugins/field/FieldDatalist.vue';
53
+ import RawAutocomplete from '@/components/form/RawAutocomplete.vue';
54
+ import BmsInputText from '@/components/form/BmsInputText.vue';
55
+
56
+ const select = ref('');
57
+ const multiSelect = ref([]);
37
58
 
38
59
  const optionsLabelValue = ref(
39
60
  range(0, 30).map((i) =>
@@ -1,4 +1,5 @@
1
1
  <template>
2
+ {{ filters }}
2
3
  <bms-server-table
3
4
  v-model:selectedItems="selectedItems"
4
5
  v-model:selectMode="selectMode"
@@ -13,6 +14,8 @@
13
14
  :total="totalItems"
14
15
  @saveFilter="onSaveFilter"
15
16
  @deleteSavedFilter="onDeleteSavedFilter"
17
+ @filterInput="onFilterInput"
18
+ @filterChange="onFilterChange"
16
19
  >
17
20
  <template #default="{ row }: { row: any }">
18
21
  <td>
@@ -40,7 +43,7 @@
40
43
  <script lang="ts" setup>
41
44
  import { Filter, SavedFilter, SelectMode } from '@/models';
42
45
  import axios from 'axios';
43
- import { Ref, ref } from 'vue';
46
+ import { computed, Ref, ref } from 'vue';
44
47
  import { isEmptyStringOrNotDefined } from '@/helpers';
45
48
 
46
49
  const serverHeaders = [
@@ -49,7 +52,27 @@ const serverHeaders = [
49
52
  { label: 'Type', key: 'type' },
50
53
  ];
51
54
 
52
- const filters = [
55
+ const typeOptions = ref([
56
+ 'Grass',
57
+ 'Poison',
58
+ 'Fire',
59
+ 'Flying',
60
+ 'Water',
61
+ 'Bug',
62
+ 'Normal',
63
+ 'Electric',
64
+ 'Ground',
65
+ 'Fairy',
66
+ 'Fighting',
67
+ 'Psychic',
68
+ 'Rock',
69
+ 'Steel',
70
+ 'Ice',
71
+ 'Ghost',
72
+ 'Dragon',
73
+ ]);
74
+
75
+ const filters = computed(() => [
53
76
  {
54
77
  label: 'Name',
55
78
  key: 'name',
@@ -65,27 +88,9 @@ const filters = [
65
88
  label: 'Type',
66
89
  key: 'type',
67
90
  type: 'autocomplete',
68
- autocompleteOptions: [
69
- 'Grass',
70
- 'Poison',
71
- 'Fire',
72
- 'Flying',
73
- 'Water',
74
- 'Bug',
75
- 'Normal',
76
- 'Electric',
77
- 'Ground',
78
- 'Fairy',
79
- 'Fighting',
80
- 'Psychic',
81
- 'Rock',
82
- 'Steel',
83
- 'Ice',
84
- 'Ghost',
85
- 'Dragon',
86
- ],
91
+ autocompleteOptions: typeOptions.value,
87
92
  },
88
- ];
93
+ ]);
89
94
 
90
95
  const savedFilters: Ref<SavedFilter[]> = ref<SavedFilter[]>([]);
91
96
  const selectedItems = ref<any[]>([]);
@@ -102,6 +107,32 @@ const onDeleteSavedFilter = (savedFilter: SavedFilter) => {
102
107
  );
103
108
  };
104
109
 
110
+ const onFilterInput = ({
111
+ filterKey,
112
+ e,
113
+ }: {
114
+ filterKey: string;
115
+ e: InputEvent;
116
+ }) => {
117
+ typeOptions.value = [];
118
+ console.log(
119
+ `user filtered key ${filterKey} with val ${(e.target as HTMLInputElement)?.value}`,
120
+ );
121
+ };
122
+
123
+ const onFilterChange = ({
124
+ filterKey,
125
+ e,
126
+ }: {
127
+ filterKey: string;
128
+ e: InputEvent;
129
+ }) => {
130
+ typeOptions.value = [];
131
+ console.log(
132
+ `user filtered key ${filterKey} changed with val ${(e.target as HTMLInputElement)?.value}`,
133
+ );
134
+ };
135
+
105
136
  const customFetchData = async (
106
137
  params: any,
107
138
  abortController: AbortController,
@@ -1,5 +1,7 @@
1
1
  <template>
2
2
  <BmsBackButton :fallback="{ path: '/' }" />
3
+ <br />
4
+ <BmsButton @click="changeChoice">Change choice</BmsButton>
3
5
  <bms-table
4
6
  :headers="headers"
5
7
  :filters="filters"
@@ -13,6 +15,8 @@
13
15
  v-model:selectedItems="selectedItems"
14
16
  @saveFilter="onSaveFilter"
15
17
  @deleteSavedFilter="onDeleteSavedFilter"
18
+ @filterInput="onFilterInput"
19
+ @filterChange="onFilterChange"
16
20
  >
17
21
  <template #choice2="{ row }">
18
22
  <BmsTooltip tooltipText="tooltip">
@@ -140,7 +144,6 @@ const items = Array(100)
140
144
 
141
145
  const savedFilters: Ref<SavedFilter[]> = ref<SavedFilter[]>([]);
142
146
  const selectedItems: Ref<any[]> = ref([]);
143
-
144
147
  const onSaveFilter = (savedFilter: SavedFilter) => {
145
148
  savedFilters.value.push(savedFilter);
146
149
  };
@@ -151,7 +154,28 @@ const onDeleteSavedFilter = (savedFilter: SavedFilter) => {
151
154
  );
152
155
  };
153
156
 
154
- const filters: Filter[] = [
157
+ const onFilterInput = ({
158
+ filterKey,
159
+ e,
160
+ value,
161
+ }: {
162
+ filterKey: string;
163
+ e: InputEvent;
164
+ value: any;
165
+ }) => {
166
+ console.log(`Input in filter ${filterKey} with val ${value}`);
167
+ };
168
+ const onFilterChange = ({
169
+ filterKey,
170
+ value,
171
+ }: {
172
+ filterKey: string;
173
+ value: any;
174
+ }) => {
175
+ console.log(`Change in filter ${filterKey} with val`, value);
176
+ };
177
+
178
+ const filters = ref<Filter[]>([
155
179
  {
156
180
  label: 'inputText Colonne 1',
157
181
  key: 'column1',
@@ -199,5 +223,20 @@ const filters: Filter[] = [
199
223
  customFilter: (item: any, value: any, target: string) =>
200
224
  item[target] > 0.5 === value,
201
225
  },
202
- ];
226
+ ]);
227
+ const changeChoice = () => {
228
+ filters.value = filters.value.map((f) =>
229
+ f.key === 'choice2'
230
+ ? {
231
+ ...f,
232
+ selectOptions: [
233
+ { label: 'huey', value: 'huey' },
234
+ { label: 'riri', value: 'riri' },
235
+ { label: 'fifi', value: 'fifi' },
236
+ { label: 'loulou', value: 'loulou' },
237
+ ],
238
+ }
239
+ : f,
240
+ );
241
+ };
203
242
  </script>
@@ -1 +0,0 @@
1
- export {};
@@ -1,35 +0,0 @@
1
- import FieldDatalist, { type Props } from '@/plugins/field/FieldDatalist.vue';
2
- import { mount } from '@vue/test-utils';
3
- import { field } from '@/plugins/field';
4
-
5
- const factory = (props?: Props) => {
6
- const wrapper = mount(FieldDatalist, {
7
- global: {
8
- plugins: [field],
9
- },
10
- props: {
11
- isInputFocused: false,
12
- options: [
13
- { label: 'titi', value: 'i' },
14
- { label: 'toto', value: 'o' },
15
- { label: 'tutu', value: 'u' },
16
- ],
17
- modelValue: '',
18
- ...props,
19
- },
20
- attachTo: document.body,
21
- });
22
-
23
- return { wrapper };
24
- };
25
-
26
- describe('FieldDatalist', () => {
27
- it('should be able to select with keyboard', async () => {
28
- const { wrapper } = factory();
29
- const titi = wrapper.get('[data-testid="i"]');
30
-
31
- expect(titi.classes()).toStrictEqual([]);
32
- await wrapper.trigger('keydown.down');
33
- expect(titi.classes()).toStrictEqual(['selected']);
34
- });
35
- });