import Vue from 'vue' import flushPromises from 'flush-promises' import { mount } from '@vue/test-utils' import Formulario from '@/index.ts' import FormularioField from '@/FormularioField.vue' import FormularioForm from '@/FormularioForm.vue' const globalRule = jest.fn(() => false) Vue.use(Formulario, { validationRules: { globalRule }, validationMessages: { required: () => 'required', 'in': () => 'in', min: () => 'min', globalRule: () => 'globalRule', }, }) describe('FormularioField', () => { const createWrapper = (props = {}) => mount(FormularioField, { propsData: { name: 'field', value: 'initial', validation: 'required|in:abcdef', validationMessages: { in: 'the value was different than expected' }, ...props, }, scopedSlots: { default: `
{{ violation.message }}
`, }, }) test('allows custom field-rule level validation strings', async () => { const wrapper = createWrapper({ validationBehavior: 'live', }) await flushPromises() expect(wrapper.find('[data-violation]').text()).toBe( 'the value was different than expected' ) }) test.each([ ['demand'], ['submit'], ])('no validation when validationBehavior is not "live"', async validationBehavior => { const wrapper = createWrapper({ validationBehavior }) await flushPromises() expect(wrapper.find('[data-violation]').exists()).toBe(false) wrapper.find('input').element['value'] = 'updated' wrapper.find('input').trigger('change') await flushPromises() expect(wrapper.find('input').element['value']).toBe('updated') expect(wrapper.find('[data-violation]').exists()).toBe(false) }) test('allows custom validation rule message', async () => { const wrapper = createWrapper({ value: 'other value', validationMessages: { in: ({ value }) => `the string "${value}" is not correct` }, validationBehavior: 'live', }) await flushPromises() expect(wrapper.find('[data-violation]').text()).toBe( 'the string "other value" is not correct' ) }) test.each([ ['bar', ({ value }) => value === 'foo'], ['bar', ({ value }) => Promise.resolve(value === 'foo')], ])('uses local custom validation rules', async (value, rule) => { const wrapper = createWrapper({ value, validation: 'required|custom', validationRules: { custom: rule }, validationMessages: { custom: 'failed the custom rule check' }, validationBehavior: 'live', }) await flushPromises() expect(wrapper.find('[data-violation]').text()).toBe('failed the custom rule check') }) test('uses global custom validation rules', async () => { mount(FormularioField, { propsData: { name: 'test', value: 'bar', validation: 'required|globalRule', validationBehavior: 'live', }, }) await flushPromises() expect(globalRule.mock.calls.length).toBe(1) }) test('emits correct validation event', async () => { const wrapper = mount(FormularioField, { propsData: { name: 'field', value: '', validation: 'required', validationBehavior: 'live', }, }) await flushPromises() expect(wrapper.emitted('validation')).toEqual([[{ path: 'field', violations: [{ rule: 'required', args: expect.any(Array), context: { name: 'field', value: '', formValues: {}, }, message: expect.any(String), }], }]]) }) test.each([ ['bail|required|in:xyz', 1], ['^required|in:xyz|min:10,length', 1], ['required|^in:xyz|min:10,length', 2], ['required|in:xyz|bail', 2], ])('prevents further validation if not passed a rule with bail modifier', async ( validation, expectedViolationsCount ) => { const wrapper = createWrapper({ value: '', validation, validationBehavior: 'live', }) await flushPromises() expect(wrapper.findAll('[data-violation]').length).toBe(expectedViolationsCount) }) test('proceeds validation if passed a rule with bail modifier', async () => { const wrapper = createWrapper({ value: '123', validation: '^required|in:xyz|min:10,length', validationBehavior: 'live', }) await flushPromises() expect(wrapper.findAll('[data-violation]').length).toBe(2) }) test('displays errors when validation-behavior is submit and form is submitted', async () => { const wrapper = mount(FormularioForm, { slots: { default: ` {{ violation.message }} ` } }) await flushPromises() expect(wrapper.find('[data-violation]').exists()).toBe(false) wrapper.trigger('submit') await flushPromises() expect(wrapper.find('[data-violation]').exists()).toBe(true) }) test('model getter for input', async () => { const wrapper = mount({ data: () => ({ state: { date: 'not a date' } }), template: ` {{ context.model }} `, methods: { onGet (source) { return source instanceof Date ? source.getDate() : 'invalid date' }, } }) await flushPromises() expect(wrapper.find('[data-output]').text()).toBe('invalid date') wrapper.vm.state = { date: new Date('1995-12-17') } await flushPromises() expect(wrapper.find('[data-output]').text()).toBe('17') }) test('model setter for input', async () => { const wrapper = mount({ data: () => ({ state: { date: 'not a date' } }), template: ` `, methods: { onGet (source) { return source instanceof Date ? source.getDate() : source }, onSet (source) { if (source instanceof Date) { return source } if (isNaN(source)) { return undefined } const result = new Date('2001-05-01') result.setDate(source) return result }, } }) await flushPromises() wrapper.find('input').setValue('12') wrapper.find('input').trigger('input') await flushPromises() const form = wrapper.findComponent(FormularioForm) expect(form.emitted('input')).toEqual([ [{ date: new Date('2001-05-12') }], ]) }) test('unregister behavior', async () => { const wrapper = mount({ props: { formExists: { type: Boolean, default: true, } }, data: () => ({ state: { fieldA: '', fieldB: '' } }), watch: { state () { this.$emit('updated', this.state) }, }, template: `
`, }) await wrapper.vm.$nextTick() wrapper.setProps({ formExists: false }) await wrapper.vm.$nextTick() expect(wrapper.emitted('updated')).toEqual([[{ fieldA: '' }]]) }) })