Skip to content

Commit e6f3e9d

Browse files
committed
test: modify tests, add input-select effect for Shift
1 parent 3c4350b commit e6f3e9d

File tree

10 files changed

+160
-51
lines changed

10 files changed

+160
-51
lines changed

docs/inputs/input-select.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ according to the value in the `value` field of the passed `options`. Если у
8888
- Blocking fields cancels navigation using `Tab`. There is also a change in the style of `select`.
8989
- If the validation fails, the field should change the style of the `select`.
9090
- При использовании аттрибута `multiple` выборка не должна закрывать выпадающий список.
91-
- В режиме `miltiple:true` с зажатой `Shift` используется следующий порядок переходов (`_` означение состояние
92-
в котором ни один элемент не выбран, `->` - переход с одного элемента на другой, `0` - элемент не выбран, `1` - элемент
93-
уже был выбран):
91+
- In `miltiple:true` mode with `Shift` held down, the following transition order is used (`_` state value
92+
in which no element is selected, `->` - transition from one element to another, `0` - element not selected, `1` - element
93+
already selected):
9494
- _ -> 0 = _ , 1
95-
- 1 -> 0 = 1 , 1
96-
- 1 -> 1 = 0 , 1
97-
- 0 -> 0 = 1 , 1
98-
- 0 -> 1 = 0 , 0
95+
- 1 -> 0 = 1, 1
96+
- 1 -> 1 = 0, 1
97+
- 0 -> 0 = 1, 0
98+
- 0 -> 1 = 0, 0
9999

100100

101101
## Examples

docs/ru/inputs/input-select.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ ____
9696
- _ -> 0 = _ , 1
9797
- 1 -> 0 = 1 , 1
9898
- 1 -> 1 = 0 , 1
99-
- 0 -> 0 = 1 , 1
99+
- 0 -> 0 = 1 , 0
100100
- 0 -> 1 = 0 , 0
101101

102102
## Пример

examples/input-select/App.vue

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
<template>
22
<div class="container">
3-
<div>
4-
<h2>Values</h2>
5-
<pre class="container-values">{{ JSON.stringify(values, undefined, 4) }}</pre>
6-
</div>
3+
74

85
<div class="wrap-app ">
96
<select name="select">
107
<!--Supplement an id here instead of using 'name'-->
118
<option value="value1">Значение 1</option>
12-
<option value="value2" selected>Значение 2</option>
9+
<option value="value2" >Значение 2</option>
1310
<option value="value3">Значение 3</option>
1411
<option value="value3">Значение 4</option>
1512
<option value="value3">Значение 5</option>
@@ -39,6 +36,10 @@
3936

4037
<button class="button" @click="form.cleanValues()">Clean Form</button>
4138
</div>
39+
<div>
40+
<h2>Values</h2>
41+
<pre class="container-values">{{ JSON.stringify(values, undefined, 4) }}</pre>
42+
</div>
4243
</div>
4344
</template>
4445

src/debug/warn.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import debug from "./debug";
2-
31
export default function warn(subject: string, text: string, error?: any) {
42
console.log(`%c[${subject}] %c${text}`, 'color: #dac400', 'color: black',error);
53
}

src/widgets/form-field.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
:disabled = "input?.disabled || $attrs['disabled'] || false"
1111
:changed = "input?.changed"
1212
:errors="input?.errors || []"
13-
:options="parseOptions(options)"
13+
:options="parseOptions(options || [])"
1414
/>
1515
</template>
1616

src/widgets/inputs/input-radio/widget-input-radio.vue

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import FieldWrap from "../field-wrap.vue";
2525
import {OptionRow} from "../../../types";
2626
import ElementInputRadio from "./element-input-radio.vue";
2727
import {nextTick, ref} from "vue";
28-
import updateInputPosition from "../../../utils/update-input-position";
28+
import getOptionRowByDuration from "../../../utils/get-option-row-by-duration";
2929
3030
const props = defineProps<{
3131
label?: string,
@@ -53,8 +53,9 @@ function getTabindex(index: number) {
5353
}
5454
5555
function handleMove(duration: number) {
56-
57-
updateInputPosition({options: props.options, value: props.modelValue || props.options[0].value, onInput, duration});
56+
onInput(
57+
getOptionRowByDuration( props.options, props.modelValue || props.options[0].value, duration).value
58+
)
5859
focusActiveItem()
5960
}
6061

src/widgets/inputs/input-select/input-select.vue

+23-15
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,7 @@ const scrollToActiveItem = debounce(function (behavior: 'auto' | 'smooth' = 'aut
166166
})
167167
})
168168
169-
function handleSpace() {
170-
if (!props.multiple) return;
171-
input(toggleMultipleValue(props.modelValue,valueOfActiveItem.value))
172-
}
169+
173170
174171
/**
175172
* @description Карта переходов.
@@ -178,11 +175,11 @@ function handleSpace() {
178175
* 1, 0, 1, 1 - означает, что при переходе с активного на неактивный (1 -> 0), у нас должно получится активный и активный(1, 1)
179176
180177
const MAP_SHIFT_TRANSITION = [
181-
undefined, 0, undefined, 1, // 0
182-
1, 0, 1, 1, // 1
183-
1, 0, 0, 1, // 2
184-
0, 0, 1, 1, // 3
185-
0, 1, 0, 0, // 4
178+
undefined, 0................undefined, (1), // 0
179+
1, 0........................1, (1) // 1
180+
1, 1........................(0), 1 // 2
181+
0, 0........................(1), 0 // 3
182+
0, 1........................0, (0) // 4
186183
]
187184
* @description Функция для обработки перехода по списку, если пользователь нажимает клавиши вниз/вверх.
188185
* В режиме multi с зажатой Shift зависит от текущего положения пользователя.
@@ -203,12 +200,12 @@ function handleArrowKeyMove(event: KeyboardEvent) {
203200
*/
204201
let result: unknown[] = Array.isArray(props.modelValue) ? props.modelValue : [];
205202
if (event.shiftKey) {
206-
const movement = [result.length ? isActiveItem(savedPrevActiveItem) : undefined , isActiveItem(valueOfActiveItem.value)]
207-
// 1-> 1. Для более краткой записи используется
208-
const isPositiveMovement = (movement[0] && movement[1])
203+
const movement = [savedPrevActiveItem ? isActiveItem(savedPrevActiveItem) : undefined , isActiveItem(valueOfActiveItem.value)]
204+
// Закономерность
205+
result = (movement[0] === movement[1])
206+
? toggleMultipleValue(result, savedPrevActiveItem)
207+
: toggleMultipleValue(result, valueOfActiveItem.value)
209208
210-
if (!isPositiveMovement) result = toggleMultipleValue(result, valueOfActiveItem.value)
211-
if ((movement[0] === false && movement[1] === false) || isPositiveMovement) result = toggleMultipleValue(result, savedPrevActiveItem)
212209
input(result);
213210
}
214211
else if (!event.ctrlKey) input([valueOfActiveItem.value]);
@@ -220,7 +217,7 @@ function handleArrowKeyMove(event: KeyboardEvent) {
220217
* @description Wrapper over data input.
221218
*/
222219
function handleSelect(value: any) {
223-
if (!props.disabled) input(props.multiple ? toggleMultipleValue(props.modelValue, value) : value)
220+
input(props.multiple ? toggleMultipleValue(props.modelValue, value) : value)
224221
if (!props.multiple) setActive(false)
225222
}
226223
@@ -231,12 +228,23 @@ function handleSelect(value: any) {
231228
function toggleMultipleValue(array: unknown[], value: unknown) {
232229
return toggleValueFromArray(Array.isArray(array) ? array : [], value, parsedLimit.value)
233230
}
231+
function handleSpace() {
232+
if (!isActive.value) return setActive()
233+
if (!props.multiple) return;
234234
235+
/**
236+
* @description Если выделенный элемент отсутствует.
237+
*/
238+
if (!props.options.find(item => item.value === valueOfActiveItem.value)) return;
239+
240+
input(toggleMultipleValue(props.modelValue, valueOfActiveItem.value))
241+
}
235242
/**
236243
* @description Конечная точка ввода данных. Используется для проверки типа.
237244
* @param value
238245
*/
239246
function input(value: unknown) {
247+
if (props.disabled) return ;
240248
if (props.multiple && !(Array.isArray(value) || value === null || value === undefined))
241249
return console.warn('An attempt to set a value for input-select(multiple: true) failed. The data is not an array, null or undefined.', value);
242250
emit('update:modelValue', value)

tests/integrations/input-radio.spec.ts

-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ describe("Testing radio button", () => {
8585
const obj = {
8686
items: app.findAll<HTMLElement>('.element-input-radio')
8787
}
88-
8988
await triggerKey.call(obj, 0, 'down');
9089
expect(form.getValueByName(name)).toBe('g')
9190

tests/integrations/inputs/input-select.spec.ts

+111-9
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ describe("Input Select Testing", () => {
7575
})
7676
await app.vm.$nextTick()
7777
await wait(233)
78-
console.log(app.html())
7978
expect(app.text()).toBe(defaultOptions[0].label);
8079
})
8180
test("Открытие списка выборки по нажатию на иконку", async () => {
@@ -88,12 +87,12 @@ describe("Input Select Testing", () => {
8887
expect(app.text()).toBe(defaultOptions.map(a => a.label).join(''))
8988
})
9089
test("Открытие списка выборки по нажатию space при фокусе на поле", async () => {
91-
await app.get('.input-select').trigger('keyup.space');
90+
await app.get('.input-select').trigger('keydown.space');
9291
expect(app.text()).toBe(defaultOptions.map(a => a.label).join(''))
9392
})
9493
test("Переключение значений при нажатии клавиши вниз при фокусе на поле.", async () => {
9594
function triggerDown() {
96-
return app.get('.input-select').trigger('keydown.down');
95+
return app.get('.input-select').trigger('keydown', {key: "ArrowDown"});
9796
}
9897

9998
await triggerDown()
@@ -144,10 +143,9 @@ describe("Input Select Testing", () => {
144143
})
145144

146145
test("Disabled select", async () => {
147-
148146
form.disable()
149147
await app.vm.$nextTick()
150-
expect(app.find('.input-select_disabled').exists()).toBe(true)
148+
expect(app.find('.vf-input-select_disabled').exists()).toBe(true)
151149

152150
function triggerDown() {
153151
return app.get('.input-select').trigger('keydown.down');
@@ -160,7 +158,7 @@ describe("Input Select Testing", () => {
160158
test("Error Select", async () => {
161159
expect(form.validate()).toBe(false);
162160
await app.vm.$nextTick()
163-
expect(app.find('.input-select_error').exists()).toBe(true)
161+
expect(app.find('.vf-input-select_error').exists()).toBe(true)
164162
expect(app.text()).toBe(STORE.requiredMessage)
165163
})
166164

@@ -186,14 +184,14 @@ describe("Input Select Testing", () => {
186184
expect(input.element.getAttribute('tabindex')).toBe("0")
187185
})
188186
test("Press down should change value", async () => {
189-
await input.trigger('keydown.down');
187+
await input.trigger('keydown', {key: "ArrowDown"});
190188
expect(form.getValueByName(name)).toBe(defaultOptions[0].value)
191189

192-
await input.trigger('keydown.down');
190+
await input.trigger('keydown', {key: "ArrowDown"});
193191
expect(form.getValueByName(name)).toBe(defaultOptions[1].value)
194192
})
195193
test("Press up should change value", async () => {
196-
await input.trigger('keydown.up');
194+
await input.trigger('keydown', {key: "ArrowUp"});
197195
expect(form.getValueByName(name)).toBe(defaultOptions[2].value)
198196
})
199197
test("Press up and down not work in disabled status", async () => {
@@ -280,4 +278,108 @@ describe("Input Select Testing", () => {
280278

281279
expect(form.getValueByName(name)).toEqual(defaultOptions.map(item => item.value).slice(0, 2))
282280
})
281+
282+
test("Shift + ArrowDown: _ -> 0 = _, 1", async () => {
283+
const wrap = defaultMount(defineSelectComponent({
284+
multiple: true,
285+
options: defaultOptions,
286+
limit: 2
287+
}))
288+
const form = (wrap.vm as any).form as Form;
289+
currentItem = wrap.find('.container-input-select-current')
290+
await currentItem.trigger('keydown.shift.down');
291+
292+
expect(form.getValueByName(name)).toEqual([defaultOptions[0].value]);
293+
})
294+
test("Shift + ArrowDown: 1 -> 0 = 1, 1", async () => {
295+
const wrap = defaultMount(defineSelectComponent({
296+
multiple: true,
297+
options: defaultOptions,
298+
}))
299+
const form = (wrap.vm as any).form as Form;
300+
form.setValues({
301+
[name]: [defaultOptions[1].value]
302+
})
303+
await app.vm.$nextTick()
304+
await wrap.find('.container-input-select-current').trigger('click');
305+
currentItem = wrap.find('.container-input-select-current')
306+
await currentItem.trigger('keydown.shift', {
307+
key: "ArrowDown"
308+
});
309+
310+
expect(form.getValueByName(name)).toEqual([defaultOptions[1].value, defaultOptions[2].value]);
311+
})
312+
test("Shift + ArrowDown: 0 -> 1 = 0, 0", async () => {
313+
const wrap = defaultMount(defineSelectComponent({
314+
multiple: true,
315+
options: defaultOptions,
316+
}))
317+
const form = (wrap.vm as any).form as Form;
318+
form.setValues({
319+
[name]: [defaultOptions[1].value]
320+
})
321+
await app.vm.$nextTick()
322+
await wrap.find('.container-input-select-current').trigger('click');
323+
currentItem = wrap.find('.container-input-select-current')
324+
325+
await currentItem.trigger('keydown.ctrl', { key: "ArrowUp" })
326+
await currentItem.trigger('keydown.shift', {
327+
key: "ArrowDown"
328+
});
329+
330+
expect(form.getValueByName(name)).toEqual([]);
331+
})
332+
test("Shift + ArrowDown: 0 -> 0 = 1, 0", async () => {
333+
const wrap = defaultMount(defineSelectComponent({
334+
multiple: true,
335+
options: defaultOptions,
336+
}))
337+
const form = (wrap.vm as any).form as Form;
338+
await wrap.find('.container-input-select-current').trigger('click');
339+
currentItem = wrap.find('.container-input-select-current')
340+
341+
await currentItem.trigger('keydown.ctrl', { key: "ArrowDown" })
342+
await currentItem.trigger('keydown.shift', {
343+
key: "ArrowDown"
344+
});
345+
expect(form.getValueByName(name)).toEqual([defaultOptions[0].value]);
346+
await currentItem.trigger('keydown.shift', {
347+
key: "ArrowDown"
348+
});
349+
expect(form.getValueByName(name)).toEqual([defaultOptions[0].value, defaultOptions[1].value]);
350+
})
351+
test("Shift + ArrowDown: 1 -> 1 = 0, 1", async () => {
352+
const wrap = defaultMount(defineSelectComponent({
353+
multiple: true,
354+
options: defaultOptions,
355+
}))
356+
const form = (wrap.vm as any).form as Form;
357+
await wrap.find('.container-input-select-current').trigger('click');
358+
currentItem = wrap.find('.container-input-select-current')
359+
360+
await currentItem.trigger('keydown.shift', { key: "ArrowDown" });
361+
await currentItem.trigger('keydown.shift', { key: "ArrowDown" });
362+
363+
await currentItem.trigger('keydown.ctrl', { key: "ArrowUp" });
364+
365+
expect(form.getValueByName(name)).toEqual([defaultOptions[0].value, defaultOptions[1].value]);
366+
await currentItem.trigger('keydown.shift', { key: "ArrowDown" });
367+
expect(form.getValueByName(name)).toEqual([defaultOptions[1].value]);
368+
})
369+
370+
test("Double SPACE press should not make effect for multiple", async () => {
371+
const wrap = defaultMount(defineSelectComponent({
372+
multiple: true,
373+
options: defaultOptions,
374+
limit: 2
375+
}))
376+
const form = (wrap.vm as any).form as Form;
377+
form.setValues({
378+
[name]: []
379+
})
380+
currentItem = wrap.find('.container-input-select-current')
381+
await currentItem.trigger('keydown.space');
382+
await currentItem.trigger('keydown.space');
383+
expect(form.getValueByName(name).length).toBe(0)
384+
})
283385
})

tests/units/utils/get-option-row-by-duration.spec.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ describe("testing getOptionRowByDuration", () => {
1919
test("By default should return duration value if not value was provided", () => {
2020
const value = undefined;
2121
expect(getOptionRowByDuration(options, value, 0)).toBe(red)
22-
expect(getOptionRowByDuration(options, value, 1)).toBe(green)
23-
expect(getOptionRowByDuration(options, value, 2)).toBe(yellow)
24-
expect(getOptionRowByDuration(options, value, 3)).toBe(black)
22+
expect(getOptionRowByDuration(options, value, 1)).toBe(red)
23+
expect(getOptionRowByDuration(options, value, 2)).toBe(green)
24+
expect(getOptionRowByDuration(options, value, 3)).toBe(yellow)
2525
})
2626
test("If result duration less 0 should return the value from end", () => {
2727
expect(getOptionRowByDuration(options, undefined, -1)).toBe(black);
@@ -30,10 +30,10 @@ describe("testing getOptionRowByDuration", () => {
3030
expect(getOptionRowByDuration(options, undefined, -4)).toBe(red);
3131
})
3232
test("If result is more then length of options it should be div by options.length", () => {
33-
expect(getOptionRowByDuration(options, undefined, 4)).toBe(red);
34-
expect(getOptionRowByDuration(options, undefined, 5)).toBe(green);
35-
expect(getOptionRowByDuration(options, undefined, 6)).toBe(yellow);
36-
expect(getOptionRowByDuration(options, undefined, 7)).toBe(black);
33+
expect(getOptionRowByDuration(options, undefined, 5)).toBe(red);
34+
expect(getOptionRowByDuration(options, undefined, 5)).toBe(red);
35+
expect(getOptionRowByDuration(options, undefined, 6)).toBe(green);
36+
expect(getOptionRowByDuration(options, undefined, 7)).toBe(yellow);
3737
})
3838
test("If value was provided duration should be summed", () => {
3939
expect(getOptionRowByDuration(options, black.value, -1)).toBe(yellow);

0 commit comments

Comments
 (0)