diff --git a/src/Formulario.ts b/src/Formulario.ts index a9954da..08b912f 100644 --- a/src/Formulario.ts +++ b/src/Formulario.ts @@ -8,6 +8,7 @@ import FileUpload from '@/FileUpload' import RuleValidationMessages from '@/RuleValidationMessages' import { arrayify, has } from '@/libs/utils' import fauxUploader from '@/libs/faux-uploader' +import merge from '@/utils/merge' import FormularioForm from '@/FormularioForm.vue' import FormularioInput from '@/FormularioInput.vue' @@ -113,46 +114,12 @@ export default class Formulario { */ extend (extendWith: FormularioOptions) { if (typeof extendWith === 'object') { - this.options = this.merge(this.options as FormularioOptions, extendWith) + this.options = merge(this.options as FormularioOptions, extendWith) return this } throw new Error(`VueFormulario extend() should be passed an object (was ${typeof extendWith})`) } - /** - * Create a new object by copying properties of base and mergeWith. - * Note: arrays don't overwrite - they push - * - * @param {Object} base - * @param {Object} mergeWith - * @param {boolean} concatArrays - */ - merge (base: ObjectType, mergeWith: ObjectType, concatArrays: boolean = true) { - const merged: ObjectType = {} - - for (const key in base) { - if (has(mergeWith, key)) { - if (isPlainObject(mergeWith[key]) && isPlainObject(base[key])) { - merged[key] = this.merge(base[key], mergeWith[key], concatArrays) - } else if (concatArrays && Array.isArray(base[key]) && Array.isArray(mergeWith[key])) { - merged[key] = base[key].concat(mergeWith[key]) - } else { - merged[key] = mergeWith[key] - } - } else { - merged[key] = base[key] - } - } - - for (const prop in mergeWith) { - if (!has(merged, prop)) { - merged[prop] = mergeWith[prop] - } - } - - return merged - } - /** * Determine what "class" of input this element is given the "type". */ diff --git a/src/FormularioForm.vue b/src/FormularioForm.vue index d21defd..2a41913 100644 --- a/src/FormularioForm.vue +++ b/src/FormularioForm.vue @@ -20,7 +20,7 @@ import { arrayify, getNested, has, setNested, shallowEqualObjects } from '@/libs import { ObjectType } from '@/common.types' import Registry from '@/libs/registry' import FormSubmission from '@/FormSubmission' -import FormularioInput from '@/FormularioInput' +import FormularioInput from '@/FormularioInput.vue' @Component export default class FormularioForm extends Vue { diff --git a/src/utils/merge.ts b/src/utils/merge.ts new file mode 100644 index 0000000..27edc78 --- /dev/null +++ b/src/utils/merge.ts @@ -0,0 +1,37 @@ +import isPlainObject from 'is-plain-object' +import { ObjectType } from '@/common.types.ts' +import { has } from '@/libs/utils.ts' + +/** + * Create a new object by copying properties of base and mergeWith. + * Note: arrays don't overwrite - they push + * + * @param {Object} base + * @param {Object} mergeWith + * @param {boolean} concatArrays + */ +export default function merge (base: ObjectType, mergeWith: ObjectType, concatArrays: boolean = true) { + const merged: ObjectType = {} + + for (const key in base) { + if (has(mergeWith, key)) { + if (isPlainObject(mergeWith[key]) && isPlainObject(base[key])) { + merged[key] = merge(base[key], mergeWith[key], concatArrays) + } else if (concatArrays && Array.isArray(base[key]) && Array.isArray(mergeWith[key])) { + merged[key] = base[key].concat(mergeWith[key]) + } else { + merged[key] = mergeWith[key] + } + } else { + merged[key] = base[key] + } + } + + for (const prop in mergeWith) { + if (!has(merged, prop)) { + merged[prop] = mergeWith[prop] + } + } + + return merged +} diff --git a/test/unit/Formulario.test.js b/test/unit/Formulario.test.js index 05cd922..a82fded 100644 --- a/test/unit/Formulario.test.js +++ b/test/unit/Formulario.test.js @@ -1,65 +1,6 @@ import Formulario from '@/index.ts' describe('Formulario', () => { - it('can merge simple object', () => { - let a = { - optionA: true, - optionB: '1234' - } - let b = { - optionA: false - } - expect(Formulario.merge(a, b)).toEqual({ - optionA: false, - optionB: '1234' - }) - }) - - it('can add to simple array', () => { - let a = { - optionA: true, - optionB: ['first', 'second'] - } - let b = { - optionB: ['third'] - } - expect(Formulario.merge(a, b, true)).toEqual({ - optionA: true, - optionB: ['first', 'second', 'third'] - }) - }) - - it('can merge recursively', () => { - let a = { - optionA: true, - optionC: { - first: '123', - third: { - a: 'b' - } - }, - optionB: '1234' - } - let b = { - optionB: '567', - optionC: { - first: '1234', - second: '789', - } - } - expect(Formulario.merge(a, b)).toEqual({ - optionA: true, - optionC: { - first: '1234', - third: { - a: 'b' - }, - second: '789' - }, - optionB: '567' - }) - }) - it('installs on vue instance', () => { const components = [ 'FormularioForm', diff --git a/test/unit/FormularioGrouping.test.js b/test/unit/FormularioGrouping.test.js index 9033787..083c2a7 100644 --- a/test/unit/FormularioGrouping.test.js +++ b/test/unit/FormularioGrouping.test.js @@ -8,12 +8,12 @@ import FormularioGrouping from '@/FormularioGrouping.vue' Vue.use(Formulario) describe('FormularioGrouping', () => { - it('grouped fields to be setted', async () => { + it('Grouped fields to be set', async () => { const wrapper = mount(FormularioForm, { - propsData: { name: 'form', }, + propsData: { name: 'form' }, slots: { default: ` - + @@ -25,38 +25,40 @@ describe('FormularioGrouping', () => { wrapper.find('input[type="text"]').setValue('test') const submission = await wrapper.vm.formSubmitted() - expect(submission).toEqual({sub: {text: 'test'}}) + expect(submission).toEqual({ group: { text: 'test' } }) }) - it('grouped fields to be getted', async () => { + it('Grouped fields to be got', async () => { const wrapper = mount(FormularioForm, { - propsData: { name: 'form', formularioValue: { sub: {text: 'initial value'}, text: 'simple text' } }, + propsData: { + name: 'form', + formularioValue: { + group: { text: 'Group text' }, + text: 'Text', + } + }, slots: { default: ` - - - + + + ` } }) - expect(wrapper.find('input[type="text"]').element.value).toBe('initial value') + expect(wrapper.find('input[type="text"]').element.value).toBe('Group text') }) - it('data reactive with grouped fields', async () => { + it('Data reactive with grouped fields', async () => { const wrapper = mount({ - data () { - return { - formValues: {} - } - }, + data: () => ({ values: {} }), template: ` - - - - - {{ formValues.sub.text }} + + + + + {{ values.group.text }} @@ -68,18 +70,20 @@ describe('FormularioGrouping', () => { expect(wrapper.find('span').text()).toBe('test') }) - it('errors are setted for grouped fields', async () => { + it('Errors are set for grouped fields', async () => { const wrapper = mount({ - data () { - return { - formValues: {} - } - }, + data: () => ({ values: {} }), template: ` - - - - {{ error }} + + + + + {{ error }} + diff --git a/test/unit/merge.test.js b/test/unit/merge.test.js new file mode 100644 index 0000000..b29dfb8 --- /dev/null +++ b/test/unit/merge.test.js @@ -0,0 +1,56 @@ +import merge from '@/utils/merge.ts' + +describe('merge', () => { + it('Can merge simple object', () => { + expect(merge({ + optionA: true, + optionB: '1234', + }, { + optionA: false, + })).toEqual({ + optionA: false, + optionB: '1234', + }) + }) + + it('Can add to simple array', () => { + expect(merge({ + optionA: true, + optionB: ['first', 'second'] + }, { + optionB: ['third'] + }, true)).toEqual({ + optionA: true, + optionB: ['first', 'second', 'third'] + }) + }) + + it('Can merge recursively', () => { + expect(merge({ + optionA: true, + optionC: { + first: '123', + third: { + a: 'b', + }, + }, + optionB: '1234', + }, { + optionB: '567', + optionC: { + first: '1234', + second: '789', + } + })).toEqual({ + optionA: true, + optionC: { + first: '1234', + third: { + a: 'b', + }, + second: '789', + }, + optionB: '567', + }) + }) +})