1
0
mirror of synced 2024-11-25 14:56:03 +03:00
vue-formulario/test/unit/FormularioForm.test.js

405 lines
14 KiB
JavaScript
Raw Normal View History

2020-05-22 14:22:16 +03:00
import Vue from 'vue'
import { mount } from '@vue/test-utils'
2020-05-22 14:22:16 +03:00
import flushPromises from 'flush-promises'
import Formulario from '@/index.ts'
2020-05-22 14:22:16 +03:00
import FormularioForm from '@/FormularioForm.vue'
Vue.use(Formulario, {
messages: {
required: () => 'required',
'in': () => 'in',
min: () => 'min',
}
})
2020-05-22 14:22:16 +03:00
describe('FormularioForm', () => {
it('render a form DOM element', () => {
const wrapper = mount(FormularioForm)
expect(wrapper.find('form').exists()).toBe(true)
})
it('accepts a default slot', () => {
const wrapper = mount(FormularioForm, {
slots: {
default: '<div class="default-slot-item" />'
}
})
expect(wrapper.find('form div.default-slot-item').exists()).toBe(true)
})
it('Intercepts submit event', () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
slots: {
default: '<button type="submit" />'
2020-05-22 14:22:16 +03:00
}
})
const spy = jest.spyOn(wrapper.vm, 'onFormSubmit')
2020-05-22 14:22:16 +03:00
wrapper.find('form').trigger('submit')
expect(spy).toHaveBeenCalled()
})
it('Adds subcomponents to the registry', () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
propsData: { formularioValue: {} },
slots: {
default: `
2020-10-22 17:16:49 +03:00
<FormularioInput name="sub1" />
<FormularioInput name="sub2" />
`
}
2020-05-22 14:22:16 +03:00
})
expect(wrapper.vm.registry.keys()).toEqual(['sub1', 'sub2'])
2020-05-22 14:22:16 +03:00
})
it('Removes subcomponents from the registry', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount({
data: () => ({ active: true }),
2020-05-22 14:22:16 +03:00
template: `
<FormularioForm>
2020-10-22 17:16:49 +03:00
<FormularioInput v-if="active" name="sub1" />
<FormularioInput name="sub2" />
2020-05-22 14:22:16 +03:00
</FormularioForm>
`
})
await flushPromises()
expect(wrapper.findComponent(FormularioForm).vm.registry.keys()).toEqual(['sub1', 'sub2'])
2020-05-22 14:22:16 +03:00
wrapper.setData({ active: false })
await flushPromises()
expect(wrapper.findComponent(FormularioForm).vm.registry.keys()).toEqual(['sub2'])
2020-05-22 14:22:16 +03:00
})
it('Can set a fields initial value', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
propsData: { formularioValue: { test: 'Has initial value' } },
slots: {
default: `
<FormularioInput v-slot="{ context }" validation="required|in:bar" name="test" >
<input v-model="context.model" type="text">
</FormularioInput>
`
}
2020-05-22 14:22:16 +03:00
})
await flushPromises()
expect(wrapper.find('input').element['value']).toBe('Has initial value')
2020-05-22 14:22:16 +03:00
})
it('Lets individual fields override form initial value', () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
propsData: { formularioValue: { test: 'has initial value' } },
slots: {
default: `
<FormularioInput v-slot="{ context }" name="test" value="123">
<input v-model="context.model" type="text">
</FormularioInput>
`
}
2020-05-22 14:22:16 +03:00
})
expect(wrapper.find('input').element['value']).toBe('123')
2020-05-22 14:22:16 +03:00
})
it('Lets fields set form initial value with value prop', () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount({
data: () => ({ values: {} }),
template: `
<FormularioForm v-model="values">
<FormularioInput name="test" value="123" />
</FormularioForm>
`
2020-05-22 14:22:16 +03:00
})
expect(wrapper.vm['values']).toEqual({ test: '123' })
2020-05-22 14:22:16 +03:00
})
it('Receives updates to form model when individual fields are edited', () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount({
data: () => ({ values: { test: '' } }),
2020-05-22 14:22:16 +03:00
template: `
<FormularioForm v-model="values">
<FormularioInput v-slot="{ context }" name="test" >
<input v-model="context.model" type="text">
2020-05-22 14:22:16 +03:00
</FormularioInput>
</FormularioForm>
`
})
wrapper.find('input').setValue('Edited value')
expect(wrapper.vm['values']).toEqual({ test: 'Edited value' })
2020-05-22 14:22:16 +03:00
})
it('Field data updates when it is type of date', async () => {
2020-10-16 10:52:40 +03:00
const wrapper = mount({
data: () => ({ formValues: { date: new Date(123) } }),
2020-10-16 10:52:40 +03:00
template: `
<FormularioForm v-model="formValues" ref="form">
<FormularioInput v-slot="{ context }" name="date" >
<span v-if="context.model">{{ context.model.getTime() }}</span>
2020-10-16 10:52:40 +03:00
</FormularioInput>
</FormularioForm>
`
})
2020-10-16 10:52:40 +03:00
expect(wrapper.find('span').text()).toBe('123')
wrapper.setData({ formValues: { date: new Date(234) } })
2020-10-16 10:52:40 +03:00
await flushPromises()
expect(wrapper.find('span').text()).toBe('234')
})
it('Updates initial form values when input contains a populated v-model', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount({
data: () => ({
formValues: { test: '' },
fieldValue: '123',
}),
2020-05-22 14:22:16 +03:00
template: `
<FormularioForm v-model="formValues">
2020-10-22 17:16:49 +03:00
<FormularioInput name="test" v-model="fieldValue" />
2020-05-22 14:22:16 +03:00
</FormularioForm>
`
})
await flushPromises()
expect(wrapper.vm['formValues']).toEqual({ test: '123' })
2020-05-22 14:22:16 +03:00
})
// Replacement test for the above test - not quite as good of a test.
2020-10-22 17:23:45 +03:00
it('Updates calls setFieldValue on form when a field contains a populated v-model on registration', () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
propsData: {
formularioValue: { test: 'Initial' }
2020-05-22 14:22:16 +03:00
},
slots: {
default: '<FormularioInput name="test" value="Overrides" />'
},
2020-05-22 14:22:16 +03:00
})
const emitted = wrapper.emitted('input')
expect(emitted).toBeTruthy()
expect(emitted[emitted.length - 1]).toEqual([{ test: 'Overrides' }])
2020-05-22 14:22:16 +03:00
})
it('updates an inputs value when the form v-model is modified', async () => {
const wrapper = mount({
data: () => ({ values: { test: 'abcd' } }),
2020-05-22 14:22:16 +03:00
template: `
<FormularioForm v-model="values">
<FormularioInput v-slot="{ context }" name="test" >
<input v-model="context.model" type="text">
2020-05-22 14:22:16 +03:00
</FormularioInput>
</FormularioForm>
`
})
wrapper.vm.values = { test: '1234' }
2020-05-22 14:22:16 +03:00
await flushPromises()
const input = wrapper.find('input[type="text"]')
expect(input).toBeTruthy()
expect(input.element['value']).toBe('1234')
2020-05-22 14:22:16 +03:00
})
2020-10-22 17:16:49 +03:00
it('Resolves hasValidationErrors to true', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
2020-10-22 17:16:49 +03:00
slots: { default: '<FormularioInput name="fieldName" validation="required" />' }
2020-05-22 14:22:16 +03:00
})
wrapper.find('form').trigger('submit')
await flushPromises()
const emitted = wrapper.emitted()
expect(emitted['error']).toBeTruthy()
expect(emitted['error'].length).toBe(1)
2020-05-22 14:22:16 +03:00
})
it('Resolves submitted form values to an object', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
2020-10-22 17:16:49 +03:00
slots: { default: '<FormularioInput name="fieldName" validation="required" value="Justin" />' }
2020-05-22 14:22:16 +03:00
})
wrapper.find('form').trigger('submit')
await flushPromises()
const emitted = wrapper.emitted()
expect(emitted['submit']).toBeTruthy()
expect(emitted['submit'].length).toBe(1)
expect(emitted['submit'][0]).toEqual([{ fieldName: 'Justin' }])
2020-05-22 14:22:16 +03:00
})
it('Receives a form-errors prop and displays it', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
propsData: { formErrors: ['first', 'second'] },
2020-05-22 14:22:16 +03:00
})
await flushPromises()
expect(wrapper.vm.mergedFormErrors.length).toBe(2)
2020-05-22 14:22:16 +03:00
})
it('Aggregates form-errors prop with form-named errors', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
propsData: { formErrors: ['first', 'second'] }
2020-05-22 14:22:16 +03:00
})
wrapper.vm.setErrors({ formErrors: ['third'] })
2020-05-22 14:22:16 +03:00
await flushPromises()
expect(Object.keys(wrapper.vm.mergedFormErrors).length).toBe(3)
2020-05-22 14:22:16 +03:00
})
it('displays field errors on inputs with errors prop', async () => {
const wrapper = mount(FormularioForm, {
propsData: { errors: { fieldWithErrors: ['This field has an error'] }},
2020-05-22 14:22:16 +03:00
slots: {
default: `
<FormularioInput v-slot="{ context }" name="fieldWithErrors">
<span v-for="error in context.errors">{{ error }}</span>
2020-05-22 14:22:16 +03:00
</FormularioInput>
`
}
})
await wrapper.vm.$nextTick()
expect(wrapper.find('span').exists()).toBe(true)
expect(wrapper.find('span').text()).toEqual('This field has an error')
2020-05-22 14:22:16 +03:00
})
it('Is able to display multiple errors on multiple elements', async () => {
2020-10-22 17:23:45 +03:00
const errors = { inputA: ['first'], inputB: ['first', 'second']}
const wrapper = mount(FormularioForm, { propsData: { errors } })
2020-05-22 14:22:16 +03:00
await wrapper.vm.$nextTick()
expect(Object.keys(wrapper.vm.mergedFieldErrors).length).toBe(2)
expect(wrapper.vm.mergedFieldErrors.inputA.length).toBe(1)
expect(wrapper.vm.mergedFieldErrors.inputB.length).toBe(2)
2020-05-22 14:22:16 +03:00
})
it('Can set multiple field errors with setErrors()', async () => {
2020-10-22 17:23:45 +03:00
const wrapper = mount(FormularioForm)
2020-05-22 14:22:16 +03:00
expect(Object.keys(wrapper.vm.mergedFieldErrors).length).toBe(0)
wrapper.vm.setErrors({
inputErrors: {
inputA: ['first'],
inputB: ['first', 'second'],
}
})
2020-05-22 14:22:16 +03:00
await wrapper.vm.$nextTick()
await flushPromises()
expect(Object.keys(wrapper.vm.mergedFieldErrors).length).toBe(2)
expect(wrapper.vm.mergedFieldErrors.inputA.length).toBe(1)
expect(wrapper.vm.mergedFieldErrors.inputB.length).toBe(2)
2020-05-22 14:22:16 +03:00
})
2020-10-22 17:16:49 +03:00
it('Emits correct validation event when no errors', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
2020-10-22 17:16:49 +03:00
slots: {
default: `
<FormularioInput v-slot="{ context }" name="foo" validation="required|in:foo">
<input v-model="context.model" type="text" @blur="context.runValidation()">
2020-10-22 17:16:49 +03:00
</FormularioInput>
<FormularioInput name="bar" validation="required" />
`,
}
2020-05-22 14:22:16 +03:00
})
2020-10-22 17:16:49 +03:00
wrapper.find('input[type="text"]').setValue('foo')
wrapper.find('input[type="text"]').trigger('blur')
2020-05-22 14:22:16 +03:00
await flushPromises()
2020-10-22 17:16:49 +03:00
expect(wrapper.emitted('validation')).toBeTruthy()
expect(wrapper.emitted('validation').length).toBe(1)
expect(wrapper.emitted('validation')[0][0]).toEqual({
name: 'foo',
violations: [],
2020-05-22 14:22:16 +03:00
})
})
2020-10-22 17:16:49 +03:00
it('Emits correct validation event on entry', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount(FormularioForm, {
slots: { default: `
2020-10-22 17:16:49 +03:00
<FormularioInput v-slot="{ context }" name="foo" validation="required|in:foo">
<input v-model="context.model" type="text" @blur="context.runValidation()">
2020-10-22 17:16:49 +03:00
</FormularioInput>
<FormularioInput name="bar" validation="required" />
2020-05-22 14:22:16 +03:00
` }
})
wrapper.find('input[type="text"]').setValue('bar')
2020-10-22 17:16:49 +03:00
wrapper.find('input[type="text"]').trigger('blur')
2020-05-22 14:22:16 +03:00
await flushPromises()
2020-10-22 17:16:49 +03:00
expect(wrapper.emitted('validation')).toBeTruthy()
expect(wrapper.emitted('validation').length).toBe(1)
expect(wrapper.emitted('validation')[0][0]).toEqual({
name: 'foo',
violations: [ expect.any(Object) ], // @TODO: Check object structure
2020-05-22 14:22:16 +03:00
})
})
2020-10-22 17:16:49 +03:00
return
it('Removes field data when that field is de-registered', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount({
2020-10-22 17:16:49 +03:00
data: () => ({ values: {} }),
2020-05-22 14:22:16 +03:00
template: `
2020-10-22 17:16:49 +03:00
<FormularioForm v-model="values">
<FormularioInput v-slot="{ context }" name="foo">
<input v-model="context.model" type="text" value="abc123">
2020-05-22 14:22:16 +03:00
</FormularioInput>
2020-10-22 17:16:49 +03:00
<FormularioInput v-if="values.foo !== 'bar'" name="bar" value="1" />
2020-05-22 14:22:16 +03:00
</FormularioForm>
`,
})
2020-10-22 17:16:49 +03:00
2020-05-22 14:22:16 +03:00
await flushPromises()
2020-10-22 17:16:49 +03:00
2020-05-22 14:22:16 +03:00
wrapper.find('input[type="text"]').setValue('bar')
2020-10-22 17:16:49 +03:00
2020-05-22 14:22:16 +03:00
await flushPromises()
2020-10-22 17:16:49 +03:00
2020-05-22 14:22:16 +03:00
expect(wrapper.findComponent(FormularioForm).vm.proxy).toEqual({ foo: 'bar' })
2020-10-22 17:16:49 +03:00
expect(wrapper.vm['values']).toEqual({ foo: 'bar' })
2020-05-22 14:22:16 +03:00
})
it('Allows resetting a form, hiding validation and clearing inputs.', async () => {
2020-05-22 14:22:16 +03:00
const wrapper = mount({
data: () => ({ values: {} }),
2020-05-22 14:22:16 +03:00
template: `
<FormularioForm
v-model="values"
2020-05-22 14:22:16 +03:00
name="login"
ref="form"
>
<FormularioInput v-slot="{ context }" name="username" validation="required">
<input v-model="context.model" type="text">
2020-05-22 14:22:16 +03:00
</FormularioInput>
<FormularioInput v-slot="{ context }" name="password" validation="required|min:4,length">
<input v-model="context.model" type="password">
2020-05-22 14:22:16 +03:00
</FormularioInput>
</FormularioForm>
`,
})
2020-05-22 14:22:16 +03:00
const password = wrapper.find('input[type="password"]')
password.setValue('foo')
password.trigger('blur')
2020-05-22 14:22:16 +03:00
wrapper.find('form').trigger('submit')
wrapper.vm.$refs.form.setErrors({ inputErrors: { username: ['Failed'] } })
2020-05-22 14:22:16 +03:00
await flushPromises()
// First make sure we caught the errors
2020-05-22 14:22:16 +03:00
expect(Object.keys(wrapper.vm.$refs.form.mergedFieldErrors).length).toBe(1)
wrapper.vm.$refs.form.resetValidation()
wrapper.vm.$refs.form.setValues({ })
2020-05-22 14:22:16 +03:00
await flushPromises()
expect(Object.keys(wrapper.vm.$refs.form.mergedFieldErrors).length).toBe(0)
expect(wrapper.vm['values']).toEqual({})
2020-05-22 14:22:16 +03:00
})
})