Skip to content

Commit

Permalink
test: add test for input-checkbox, add hasError in element-input-chec…
Browse files Browse the repository at this point in the history
…kbox
  • Loading branch information
Jenesius committed Aug 26, 2023
1 parent 5232582 commit ee270b6
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 25 deletions.
Empty file.
33 changes: 33 additions & 0 deletions examples/input-checkbox/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<div>
<form-field name = "checkbox" type = "checkbox" :options = "optionsCheckbox"/>
<form-field name = "checkbox" type = "checkbox" label = "With label" :options = "optionsCheckbox"/>
<form-field name = "checkbox" type = "checkbox" label = "Disabled" disabled :options = "optionsCheckbox"/>
<form-field name = "checkbox" type = "checkbox" label = "With Error" :errors = "['Some mistake']" :options = "optionsCheckbox"/>

</div>
</template>

<script setup>
import {Form, FormField} from "../../src";
const form = new Form();
const optionsCheckbox = [
{
label: "Red",
value: 'r'
},
{
label: "Green",
value: 'g'
},
{
label: "Yellow",
value: 'y'
}
]
</script>

<style scoped>
</style>
3 changes: 3 additions & 0 deletions examples/input-checkbox/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createApp } from 'vue'
import App from './App.vue';
createApp(App).mount('#app')
9 changes: 7 additions & 2 deletions src/widgets/inputs/input-checkbox/element-input-checkbox.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<template>
<div class = "element-input-checkbox" :tabindex="disabled? 'none' : 0">
<div class = "element-input-checkbox" >
<div
class = "element-input-checkbox-button"
:class = "{
'element-input-checkbox-button_active': modelValue,
'element-input-checkbox-button_disabled': disabled,
'element-input-checkbox-button_error': hasError,
}"
>
<i class = "element-input-checkbox-button__check"/>
Expand All @@ -18,7 +19,8 @@
defineProps<{
modelValue: boolean,
label?: string,
disabled: boolean
disabled: boolean,
hasError: boolean
}>()
</script>

Expand Down Expand Up @@ -56,6 +58,9 @@ defineProps<{
.element-input-checkbox-button_disabled{
cursor: default;
}
.element-input-checkbox-button_error {
border: var(--vf-input-border-error);
}
.element-input-checkbox-label{
margin: 0;
}
Expand Down
37 changes: 22 additions & 15 deletions src/widgets/inputs/input-checkbox/widget-input-checkbox.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
<template>
<field-wrap :label="label">
<field-wrap :label="label" :errors = "errors">
<div class="container-input-checkbox">
<element-input-checkbox
v-for="item in options"
:key="item.value"
:model-value="isActive(item.value)"
:disabled="disabled"
:label="item.label || item.title"
:tabindex="disabled? 'none' : 0"
:has-error = "errors.length !== 0"

@click="onInput(item.value)"
@keyup.enter="onInput(item.value)"
@click="handleInput(item.value)"
@keyup.enter="handleInput(item.value)"
@keydown.space.prevent
@keyup.space.prevent="handleInput(item.value)"
/>
</div>
</field-wrap>
Expand All @@ -24,31 +28,34 @@ const props = defineProps<{
label?: string,
options: OptionRow[],
modelValue: any,
disabled: boolean
disabled: boolean,
errors: string[],
}>()
const emit = defineEmits<{
(e: 'update:modelValue', v: any): void
}>()
function isActive(v: unknown) {
return props.modelValue?.includes?.(v);
return props.modelValue?.includes?.(v) || false;
}
function toggle(v: unknown) {
/**
* @description Функция либо добавляет значение в input, если его ещё нет в modelValue, либо убирает его, если оно так
* уже есть
* */
function modifyValue(v: unknown) {
const arr: any[] = Array.isArray(props.modelValue) ? props.modelValue : [];
const index = arr.indexOf(v);
if (index === -1) {
arr.push(v);
} else arr.splice(index, 1);
if (index === -1) arr.push(v);
else arr.splice(index, 1);
return arr;
}
const emit = defineEmits<{
(e: 'update:modelValue', v: any): void
}>()
function onInput(v: unknown) {
function handleInput(v: unknown) {
if (props.disabled) return;
emit('update:modelValue', toggle(v))
emit('update:modelValue', modifyValue(v))
}
</script>
Expand Down
4 changes: 0 additions & 4 deletions src/widgets/inputs/input-radio/widget-input-radio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
@input="onInput(item.value)"
@next = "handleMove(1)"
@prev = "handleMove(-1)"


/>

</div>

</field-wrap>
</template>

Expand Down
119 changes: 119 additions & 0 deletions tests/integrations/input-checkbox.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import {defineComponent} from "vue";
import {FormField, Form, STORE} from "../../src/index";
import {mount, VueWrapper} from "@vue/test-utils";
import EmptyApp from "./components/EmptyApp.vue";

const defaultOptions = [
{
label: "Red",
value: 'r'
},
{
label: "Green",
value: 'g'
},
{
label: "Yellow",
value: 'y'
}
]
const name = 'color';
function defineCheckboxComponent(options: any = defaultOptions) {
return defineComponent({
data: () => ({
options
}),
template: `<div><form-field type = "checkbox" name = "${name}" :options = "options" required /></div>`,
components: {FormField}
})
}
function defaultMount(component = defineCheckboxComponent()) {
return mount(EmptyApp, {
slots: {
default: component
},
attachTo: document.body
})
}

describe("Input checkbox", () => {
let app: VueWrapper<any>
let form: Form

beforeEach(() => {
app = defaultMount();
form = (app.vm as any).form
})

test("Должен отображать все Labels", () => {
expect(app.text()).toBe(defaultOptions.map(item => item.label).join(''))
})
test("Если есть активный элемент, должен отображать его", async () => {
form.setValues({
[name]: ['y']
})
await app.vm.$nextTick()
expect(app.find('.element-input-checkbox-button_active').exists()).toBe(true)
})
test("Click should change value", async () => {
await app.find('.element-input-checkbox-button').trigger('click');
expect(form.getValueByName(name)).toEqual(['r'])
})
test("Если disabled ввод не должен работать", async () => {

await app.find('.element-input-checkbox-button').trigger('click');

form.disable();
await app.vm.$nextTick()

const items = app.findAll('.element-input-checkbox-button');

await items[0].trigger('click');
await items[1].trigger('click');
await items[2].trigger('click');

expect(app.find('.element-input-checkbox-button_disabled').exists()).toBe(true)
expect(form.getValueByName(name)).toEqual(['r'])
})
test("Если disabled то элемент должен быть заблокирован", async () => {
form.disable();
await app.vm.$nextTick()
expect(app.find('.element-input-checkbox-button_disabled').exists()).toBe(true)
})
test("Значение должно быть установлено по Enter", async () => {
await app.find('.element-input-checkbox:nth-child(2)').trigger('keyup.space')
expect(form.getValueByName(name)).toEqual(['g'])
})
test("Значение должно быть установлено по Space", async () => {
await app.find('.element-input-checkbox:nth-child(2)').trigger('keyup.enter')
await app.find('.element-input-checkbox:nth-child(3)').trigger('keyup.enter')
expect(form.getValueByName(name)).toEqual(['g', 'y'])
})
test("Error should change the view of checkbox", async () => {
form.validate();
await app.vm.$nextTick();
expect(app.findAll('.element-input-checkbox-button_error').length).toBe(3);
expect(app.text()).toBe(
defaultOptions.map(el => el.label).join('') + STORE.requiredMessage
)
})

test("Tabindex should be added for all items", () => {
const items = app.findAll('.element-input-checkbox')

expect(items[0].element.getAttribute('tabindex')).toBe('0')
expect(items[1].element.getAttribute('tabindex')).toBe('0')
expect(items[2].element.getAttribute('tabindex')).toBe('0')
})
test("If checkbox is disabled status tabindex should be ignored", async () => {
form.disable();
await app.vm.$nextTick()
const items = app.findAll('.element-input-checkbox')


expect(items[0].element.getAttribute('tabindex')).toBe('none')
expect(items[1].element.getAttribute('tabindex')).toBe('none')
expect(items[2].element.getAttribute('tabindex')).toBe('none')
})

})
62 changes: 58 additions & 4 deletions tests/integrations/input-radio.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,63 @@ describe("Testing radio button", () => {
await checkClickChange(radioItems, 2)
await checkClickChange(radioItems, 0)
})
test("Значение меняется по нажатию на стрелки. Вверх/Вниз/ Переход",async () => {
const app = defaultMount();
const form = (app.vm as any).form as Form;

function triggerKey(this: {items: DOMWrapper<HTMLElement>[]}, index: number, dir: 'up' | 'down') {
return this.items[index].trigger('keydown.' + dir) ;
}

const obj = {
items: app.findAll<HTMLElement>('.element-input-radio')
}

await triggerKey.call(obj, 0, 'down');
expect(form.getValueByName(name)).toBe('g')

await triggerKey.call(obj, 1, 'down');
expect(form.getValueByName(name)).toBe('y')

await triggerKey.call(obj, 2, 'down');
expect(form.getValueByName(name)).toBe('r')
})
test("Элемент должен быть активным для Tab процессе", async () => {
const app = defaultMount();
const form = (app.vm as any).form as Form;

const firstItem = app.find<HTMLElement>('.element-input-radio');

expect(firstItem.element.tabIndex).toBe(0)
})
test("Если значение имеется, то tabindex должен быть активный элемент", async () => {
const app = defaultMount();
const form = (app.vm as any).form as Form;
form.setValues({
color: defaultOptions[1].value
})
await app.vm.$nextTick()

test("Значение меняется по нажатию на стрелки",() => {})
test("Контейнер должен реагировать на focus", () => {})
test("Элемент должен реагировать на disabled", () => {})
test("Элемент должен реагировать на errors", () => {})
const items = app.findAll<HTMLElement>('.element-input-radio');

expect(items[0].element.getAttribute('tabindex')).toBe('none')
expect(items[1].element.getAttribute('tabindex')).toBe('0')
expect(items[2].element.getAttribute('tabindex')).toBe('none')
})
test("Элемент должен реагировать на disabled", async () => {
const app = defaultMount();
const form = (app.vm as any).form as Form;
form.disable()
await app.vm.$nextTick()
})
test("Элемент должен реагировать на errors", async () => {
const app = defaultMount();
const form = (app.vm as any).form as Form;
form.validate()
await app.vm.$nextTick()

expect(app.findAll('.element-input-radio_error').length).toBe(3)


})
})
3 changes: 3 additions & 0 deletions vue.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ module.exports = defineConfig({
"input-select": {
entry: "./examples/input-select/main.ts"
},
"input-checkbox": {
entry: "./examples/input-checkbox/main.ts"
},
"all-inputs": {
entry: "./examples/all-inputs/main.ts"
}
Expand Down

0 comments on commit ee270b6

Please sign in to comment.