import Vue from 'vue' import flushPromises from 'flush-promises' import { mount } from '@vue/test-utils' import Formulario from '@/index.ts' import FormularioForm from '@/FormularioForm.vue' import FormularioInput from '@/FormularioInput.vue' const globalRule = jest.fn(() => { return false }) Vue.use(Formulario, { rules: { globalRule }, validationMessages: { required: () => 'required', 'in': () => 'in', min: () => 'min', globalRule: () => 'globalRule', } }) describe('FormularioInput', () => { it('Allows custom field-rule level validation strings', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|in:abcdef', validationMessages: { in: 'the value was different than expected' }, errorBehavior: 'live', value: 'other value', }, scopedSlots: { default: `
{{ violation.message }}
` }, }) await flushPromises() expect(wrapper.find('span').text()).toBe('the value was different than expected') }) it('no validation on created when errorBehavior is not live', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|in:abcdef', validationMessages: {in: 'the value was different than expected'}, value: 'other value' }, scopedSlots: { default: `
{{ error.message }}
` } }) await flushPromises() expect(wrapper.find('span').exists()).toBe(false) }) it('No validation on value change when errorBehavior is not live', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|in:abcdef', validationMessages: {in: 'the value was different than expected'}, errorBehavior: 'submit', value: 'Initial' }, scopedSlots: { default: `
{{ error.message }}
` } }) await flushPromises() expect(wrapper.find('span').exists()).toBe(false) wrapper.find('input[type="text"]').element['value'] = 'Test' wrapper.find('input[type="text"]').trigger('change') await flushPromises() expect(wrapper.find('input[type="text"]').element['value']).toBe('Test') expect(wrapper.find('span').exists()).toBe(false) }) it('allows custom field-rule level validation functions', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|in:abcdef', validationMessages: { in: ({ value }) => `The string ${value} is not correct.` }, errorBehavior: 'live', value: 'other value' }, scopedSlots: { default: `
{{ error.message }}
` } }) await flushPromises() expect(wrapper.find('span').text()).toBe('The string other value is not correct.') }) it('no validation on created when errorBehavior is not live', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|in:abcdef', validationMessages: {in: 'the value was different than expected'}, value: 'other value' }, scopedSlots: { default: `
{{ error.message }}
` } }) await flushPromises() expect(wrapper.find('span').exists()).toBe(false) }) it('uses custom async validation rules on defined on the field', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|foobar', validationMessages: { foobar: 'failed the foobar check' }, validationRules: { foobar: async ({ value }) => value === 'foo' }, errorBehavior: 'live', value: 'bar' }, scopedSlots: { default: `
{{ error.message }}
` } }) await flushPromises() expect(wrapper.find('span').text()).toBe('failed the foobar check') }) it('uses custom sync validation rules on defined on the field', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|foobar', validationMessages: { foobar: 'failed the foobar check' }, validationRules: { foobar: ({ value }) => value === 'foo' }, errorBehavior: 'live', value: 'bar' }, scopedSlots: { default: `
{{ error.message }}
` } }) await flushPromises() expect(wrapper.find('span').text()).toBe('failed the foobar check') }) it('Uses global custom validation rules', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|globalRule', errorBehavior: 'live', value: 'bar' } }) await flushPromises() expect(globalRule.mock.calls.length).toBe(1) }) it('Emits correct validation event', async () => { const wrapper = mount(FormularioInput, { propsData: { validation: 'required', errorBehavior: 'live', value: '', name: 'fieldName', } }) await flushPromises() expect(wrapper.emitted('validation')).toBeTruthy() expect(wrapper.emitted('validation')[0][0]).toEqual({ name: 'fieldName', violations: [{ rule: expect.stringContaining('required'), args: expect.any(Array), context: expect.any(Object), message: expect.any(String), }], }) }) it('Can bail on validation when encountering the bail rule', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'bail|required|in:xyz', errorBehavior: 'live' } }) await flushPromises(); expect(wrapper.vm.context.violations.length).toBe(1); }) it('can show multiple validation errors if they occur before the bail rule', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|in:xyz|bail', errorBehavior: 'live' } }) await flushPromises(); expect(wrapper.vm.context.violations.length).toBe(2); }) it('can avoid bail behavior by using modifier', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: '^required|in:xyz|min:10,length', errorBehavior: 'live', value: '123' } }) await flushPromises(); expect(wrapper.vm.context.violations.length).toBe(2); }) it('prevents later error messages when modified rule fails', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: '^required|in:xyz|min:10,length', errorBehavior: 'live' } }) await flushPromises(); expect(wrapper.vm.context.violations.length).toBe(1); }) it('can bail in the middle of the rule set with a modifier', async () => { const wrapper = mount(FormularioInput, { propsData: { name: 'test', validation: 'required|^in:xyz|min:10,length', errorBehavior: 'live' } }) await flushPromises(); expect(wrapper.vm.context.violations.length).toBe(2); }) it('does not show errors on blur when set error-behavior is submit', async () => { const wrapper = mount(FormularioInput, { propsData: { validation: 'required', errorBehavior: 'submit', name: 'test', }, scopedSlots: { default: `
{{ error.message }}
` } }) expect(wrapper.find('span').exists()).toBe(false) wrapper.find('input').trigger('input') wrapper.find('input').trigger('blur') await flushPromises() expect(wrapper.find('span').exists()).toBe(false) }) it('displays errors when error-behavior is submit and form is submitted', async () => { const wrapper = mount(FormularioForm, { propsData: { name: 'test' }, slots: { default: ` {{ error.message }} ` } }) await flushPromises() expect(wrapper.find('span').exists()).toBe(false) wrapper.trigger('submit') await flushPromises() expect(wrapper.find('span').exists()).toBe(true) }) })