Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 877022a

Browse files
committed
test(checkbox-input): unit test and e2e
1 parent f519ab9 commit 877022a

File tree

15 files changed

+499
-16
lines changed

15 files changed

+499
-16
lines changed

demos/vue-3/src/components/Console.vue

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
<li class="rounded w-2 h-2 bg-yellow-300 inline-block mr-1"></li>
66
<li class="rounded w-2 h-2 bg-green-500 inline-block"></li>
77
</ul>
8-
<pre data-cy="form-values" class="shadow-lg pt-4">{{ content }}</pre>
8+
<pre
9+
data-cy="form-values"
10+
class="shadow-lg pt-4"
11+
:data-formValues="jsonValues"
12+
>{{ content }}</pre
13+
>
914
</div>
1015
</template>
1116

1217
<script lang="ts">
13-
import { defineComponent } from 'vue';
18+
import { computed, defineComponent } from 'vue';
1419
1520
const props = {
1621
content: String,
@@ -19,6 +24,12 @@ const props = {
1924
export default defineComponent({
2025
name: 'console',
2126
props,
27+
setup(props) {
28+
const jsonValues = computed(() => JSON.stringify(props.content));
29+
return {
30+
jsonValues,
31+
};
32+
},
2233
});
2334
</script>
2435

demos/vue-3/src/router/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ const routes: Array<RouteRecordRaw> = [
6363
/* webpackChunkName: "text-fields" */ '../views/TextAreaFields.vue'
6464
),
6565
},
66+
{
67+
path: '/checkbox-fields',
68+
name: 'Checkbox Fields',
69+
meta: {
70+
title: 'Checkbox Fields',
71+
},
72+
component: () =>
73+
import(
74+
/* webpackChunkName: "checkbox-fields" */ '../views/CheckboxFields.vue'
75+
),
76+
},
6677
{
6778
path: '/login',
6879
name: 'Login',
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<template>
2+
<div class="page container">
3+
<div class="mx-auto w-full sm:w-1/2 relative mb-24">
4+
<div
5+
class="absolute inset-0 bg-gradient-to-r from-blue-400 to-green-200 shadow-xl transform -skew-y-3 sm:skew-y-0 sm:-rotate-3 sm:rounded-3xl"
6+
></div>
7+
<div class="relative card p-6 bg-white">
8+
<dynamic-form
9+
:form="form"
10+
@submitted="handleSubmit"
11+
@change="valueChanged"
12+
@error="handleError"
13+
/>
14+
<button
15+
data-cy="submit"
16+
class="btn bg-green-500 text-white hover:bg-green-700 mt-4"
17+
submit="true"
18+
:form="form?.id"
19+
>
20+
Sign In
21+
</button>
22+
</div>
23+
</div>
24+
<div class="mx-auto w-full sm:w-1/2"><Console :content="formValues" /></div>
25+
</div>
26+
</template>
27+
28+
<script lang="ts">
29+
import { CheckboxField, Validator, required } from '@/';
30+
import { computed, defineComponent, reactive } from 'vue';
31+
import Console from '../components/Console.vue';
32+
33+
const components = {
34+
Console,
35+
};
36+
/* } from '../../dist/as-dynamic-forms.esm'; */
37+
export default defineComponent({
38+
name: 'TextFieldsDemo',
39+
components,
40+
setup() {
41+
const formValues = reactive({});
42+
43+
const form = computed(() => ({
44+
id: 'text-fields-demo',
45+
fields: {
46+
awesomeness: CheckboxField({
47+
label: "Check if you're awesome",
48+
}),
49+
certified: CheckboxField({
50+
label: 'Last Name',
51+
customClass: 'w-1/2',
52+
value: true,
53+
}),
54+
required: CheckboxField({
55+
label: 'Required',
56+
customClass: 'w-1/2',
57+
validations: [
58+
Validator({ validator: required, text: 'This field is required' }),
59+
],
60+
}),
61+
disabled: CheckboxField({
62+
label: 'Disabled',
63+
customClass: 'w-1/2',
64+
disabled: true,
65+
}),
66+
},
67+
options: {
68+
customClass: 'flex flex-wrap',
69+
},
70+
}));
71+
72+
function handleSubmit(values) {
73+
console.log('Values Submitted', values);
74+
}
75+
76+
function valueChanged(values) {
77+
Object.assign(formValues, values);
78+
console.log('Values', values);
79+
}
80+
81+
function handleError(errors) {
82+
console.error('Errors', errors);
83+
}
84+
85+
return {
86+
form,
87+
formValues,
88+
handleSubmit,
89+
valueChanged,
90+
handleError,
91+
};
92+
},
93+
});
94+
</script>
95+
<style lang="scss"></style>

demos/vue-3/src/views/Home.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ export default defineComponent({
6666
route: '/textarea-fields',
6767
tags: ['textarea-field'],
6868
},
69+
{
70+
name: 'Checkbox Fields',
71+
route: '/checkbox-fields',
72+
tags: ['checkbox-field'],
73+
},
6974
{
7075
name: 'Login',
7176
route: '/login',
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { mount } from '@vue/test-utils';
2+
import CheckboxInput from './CheckboxInput.vue';
3+
import { FieldControl, CheckboxField, Validator, required } from '../../index';
4+
5+
describe('CheckboxInput', () => {
6+
let cmp;
7+
8+
beforeEach(() => {
9+
cmp = mount(CheckboxInput, {
10+
props: {
11+
control: FieldControl({
12+
name: 'test-checkbox',
13+
...CheckboxField({
14+
label: 'Test Checkbox',
15+
}),
16+
}),
17+
},
18+
});
19+
});
20+
21+
it('renders an input of type checkbox', () => {
22+
const input = cmp.find('.checkbox-control');
23+
expect(input.exists()).toBe(true);
24+
});
25+
26+
it(`renders an input with class 'checkbox-control'`, () => {
27+
const input = cmp.find('input');
28+
expect(input.classes()).toContain('checkbox-control');
29+
});
30+
31+
it(`renders an input with id equal to field name`, () => {
32+
const input = cmp.find('input');
33+
expect(input.attributes('id')).toBe('test-checkbox');
34+
});
35+
36+
// TODO: Open ticket with reproduction link on https://github.com/vuejs/vue-test-utils-next/issues
37+
/*
38+
it(`input gets checked when value is true`, async () => {
39+
await cmp.setProps({
40+
control: FieldControl({
41+
name: 'test-input',
42+
...CheckboxField({
43+
label: 'Test Checkbox',
44+
value: true,
45+
}),
46+
}),
47+
});
48+
const input = cmp.find('.checkbox-control');
49+
expect(input.attributes('checked')).toBe('');
50+
});
51+
52+
it(`input gets disabled when form control does it`, async () => {
53+
await cmp.setProps({
54+
control: FieldControl({
55+
name: 'test-input',
56+
...CheckboxField({
57+
label: 'Test Input',
58+
disabled: true,
59+
}),
60+
}),
61+
});
62+
const input = cmp.find('.checkbox-control');
63+
expect(input.attributes('disabled')).toBe('');
64+
});
65+
66+
it(`renders a required input`, async () => {
67+
await cmp.setProps({
68+
control: FieldControl({
69+
name: 'test-input',
70+
...CheckboxField({
71+
label: 'Test Input',
72+
validations: [
73+
Validator({ validator: required, text: 'This field is required' }),
74+
],
75+
}),
76+
}),
77+
});
78+
const input = cmp.find('.checkbox-control');
79+
expect(input.attributes('required')).toBe('');
80+
});
81+
82+
it(`sets ariaRequired when required`, async () => {
83+
await cmp.setProps({
84+
control: FieldControl({
85+
name: 'test-input',
86+
...CheckboxField({
87+
label: 'Test Input',
88+
validations: [
89+
Validator({ validator: required, text: 'This field is required' }),
90+
],
91+
}),
92+
}),
93+
});
94+
const input = cmp.find('.checkbox-control');
95+
expect(input.attributes('ariarequired')).toBe('true');
96+
});
97+
98+
it(`renders a readonly input`, async () => {
99+
await cmp.setProps({
100+
control: FieldControl({
101+
name: 'test-input',
102+
...CheckboxField({
103+
label: 'Test Input',
104+
readonly: true,
105+
}),
106+
}),
107+
});
108+
const input = cmp.find('.checkbox-control');
109+
expect(input.attributes('readonly')).toBe('');
110+
});
111+
112+
it(`renders an input with aria labels`, async () => {
113+
await cmp.setProps({
114+
control: FieldControl({
115+
name: 'test-input',
116+
...CheckboxField({
117+
label: 'Test Input',
118+
ariaLabel: 'Im a test input',
119+
}),
120+
}),
121+
});
122+
const input = cmp.find('.checkbox-control');
123+
expect(input.attributes('arialabel')).toBe('Im a test input');
124+
}); */
125+
126+
it('emits an event when value changed', async () => {
127+
const input = cmp.find('input');
128+
await input.setValue();
129+
130+
expect(cmp.emitted()).toHaveProperty('change');
131+
expect(cmp.emitted('change')[0][0].value).toBe(true);
132+
});
133+
134+
it('emits the control name when value change', async () => {
135+
const input = cmp.find('input');
136+
await input.setValue();
137+
138+
expect(cmp.emitted('change')[0][0].name).toBe('test-checkbox');
139+
});
140+
141+
it('emits an event when blur', async () => {
142+
const input = cmp.find('input');
143+
await input.trigger('blur');
144+
145+
expect(cmp.emitted()).toHaveProperty('blur');
146+
});
147+
148+
it('emits an event when focus', async () => {
149+
const input = cmp.find('input');
150+
await input.trigger('focus');
151+
152+
expect(cmp.emitted()).toHaveProperty('focus');
153+
});
154+
});

src/components/checkbox-input/CheckboxInput.vue

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,40 @@ export default defineComponent({
1717
inheritAttrs: false,
1818
props,
1919
setup(props, { emit }) {
20-
const { onCheck, onFocus, onBlur } = useInputEvents(props, emit);
21-
22-
const { errorMessages, isPendingValidation } = useInputValidation(
20+
const { onCheck, onFocus, onBlur, getCheckboxClasses } = useInputEvents(
2321
props,
2422
emit,
2523
);
2624
25+
const {
26+
errorMessages,
27+
isPendingValidation,
28+
isRequired,
29+
} = useInputValidation(props, emit);
30+
31+
const requiredStar = h(
32+
'span',
33+
{
34+
ariaHidden: true,
35+
class: 'form-required-star',
36+
},
37+
' *',
38+
);
39+
2740
const renderCheckbox = [
2841
h('input', {
2942
name: props.control.name || '',
3043
type: props.control.type,
3144
id: props.control.name,
3245
disabled: props.control.disabled,
33-
class: ['checkbox-control'],
46+
class: 'checkbox-control',
3447
value: props.control.value,
3548
checked: props.control.value,
49+
required: isRequired.value,
50+
readonly: props.control.readonly,
51+
ariaRequired: isRequired.value,
52+
ariaLabel: props.control.ariaLabel,
53+
ariaLabelledBy: props.control.ariaLabelledBy,
3654
onFocus,
3755
onBlur,
3856
onChange: onCheck,
@@ -43,15 +61,15 @@ export default defineComponent({
4361
class: ['checkbox-label'],
4462
for: props.control.name,
4563
},
46-
props.control.label,
64+
[props.control.label, isRequired.value ? requiredStar : ''],
4765
),
4866
];
4967
5068
return () => [
5169
h(
5270
'div',
5371
{
54-
class: 'checkbox-group',
72+
class: getCheckboxClasses.value,
5573
tabIndex: -1,
5674
role: 'group',
5775
},

src/components/dynamic-form/DynamicForm.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export default defineComponent({
175175
? FieldControl({
176176
...field,
177177
name: key,
178-
value: null,
178+
value: field.type === FieldTypes.CHECKBOX ? false : null,
179179
})
180180
: FieldControl({
181181
...field,

src/components/dynamic-input/DynamicInput.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import DynamicInput from './DynamicInput.vue';
44
import {
55
CheckboxField,
66
ColorField,
7-
CustomField,
87
EmailField,
98
FieldControl,
109
NumberField,

src/components/text-area-input/TextAreaInput.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,3 @@ export default defineComponent({
6262
},
6363
});
6464
</script>
65-
66-
<style></style>

0 commit comments

Comments
 (0)