From 8e3ca76685d878a8193de56f63ed4926033e45ec Mon Sep 17 00:00:00 2001 From: Justin Schroeder Date: Wed, 6 May 2020 23:33:58 -0400 Subject: [PATCH] Adds initial grouping tests and first functional, repeatable, modelable grouped fields --- examples/specimens/SpecimenGroup.vue | 17 ++- src/FormSubmission.js | 6 +- src/FormulateForm.vue | 85 ++----------- src/FormulateGrouping.vue | 7 +- src/FormulateInput.vue | 10 +- src/libs/context.js | 4 +- src/libs/registry.js | 139 +++++++++++++++++++++- src/slots/FormulateRepeatableProvider.vue | 17 ++- test/unit/FormulateForm.test.js | 21 +++- test/unit/FormulateInputFile.test.js | 4 +- test/unit/FormulateInputGroup.test.js | 101 ++++++++++++++++ 11 files changed, 309 insertions(+), 102 deletions(-) create mode 100644 test/unit/FormulateInputGroup.test.js diff --git a/examples/specimens/SpecimenGroup.vue b/examples/specimens/SpecimenGroup.vue index 388db80..4438263 100644 --- a/examples/specimens/SpecimenGroup.vue +++ b/examples/specimens/SpecimenGroup.vue @@ -1,15 +1,17 @@ @@ -40,7 +45,13 @@ export default { data () { return { - formResult: null, + formData: { + }, + users: [ + { name: 'Justin' }, + { name: 'Bob' } + ], + email: 'justin@wearebraid.com', saveValues: null } }, diff --git a/src/FormSubmission.js b/src/FormSubmission.js index 7b625b1..30b33f0 100644 --- a/src/FormSubmission.js +++ b/src/FormSubmission.js @@ -26,11 +26,11 @@ export default class FormSubmission { values () { return new Promise((resolve, reject) => { const pending = [] - const values = cloneDeep(this.form.internalFormModelProxy) + const values = cloneDeep(this.form.proxy) for (const key in values) { - if (typeof this.form.internalFormModelProxy[key] === 'object' && this.form.internalFormModelProxy[key] instanceof FileUpload) { + if (typeof this.form.proxy[key] === 'object' && this.form.proxy[key] instanceof FileUpload) { pending.push( - this.form.internalFormModelProxy[key].upload().then(data => Object.assign(values, { [key]: data })) + this.form.proxy[key].upload().then(data => Object.assign(values, { [key]: data })) ) } } diff --git a/src/FormulateForm.vue b/src/FormulateForm.vue index 5b73c4c..98efa50 100644 --- a/src/FormulateForm.vue +++ b/src/FormulateForm.vue @@ -13,15 +13,13 @@ diff --git a/test/unit/FormulateForm.test.js b/test/unit/FormulateForm.test.js index 0712ece..02bd6f8 100644 --- a/test/unit/FormulateForm.test.js +++ b/test/unit/FormulateForm.test.js @@ -171,6 +171,26 @@ describe('FormulateForm', () => { expect(wrapper.emitted().input[wrapper.emitted().input.length - 1]).toEqual([{ testinput: 'override-data' }]) }) + it('updates an inputs value when the form v-model is modified', async () => { + const wrapper = mount({ + data () { + return { + formValues: { + testinput: 'abcd', + } + } + }, + template: ` + + + + ` + }) + await flushPromises() + wrapper.vm.formValues = { testinput: '1234' } + await flushPromises() + expect(wrapper.find('input[type="text"]').element.value).toBe('1234') + }) it('emits an instance of FormSubmission', async () => { const wrapper = mount(FormulateForm, { @@ -205,7 +225,6 @@ describe('FormulateForm', () => { slots: { default: `` } }) await flushPromises() - // expect(wrapper.vm.internalFormModelProxy).toEqual({ name: 'Dave Barnett', candy: true }) expect(wrapper.find('input[type="text"]').element.value).toBe('Dave Barnett') expect(wrapper.find('input[type="checkbox"]').element.checked).toBe(true) }) diff --git a/test/unit/FormulateInputFile.test.js b/test/unit/FormulateInputFile.test.js index 89a6a8f..60dc60d 100644 --- a/test/unit/FormulateInputFile.test.js +++ b/test/unit/FormulateInputFile.test.js @@ -1,8 +1,8 @@ import Vue from 'vue' import { mount } from '@vue/test-utils' import flushPromises from 'flush-promises' -import Formulate from '../../src/Formulate.js' -import FileUpload from '../../src/FileUpload.js' +import Formulate from '@/Formulate.js' +import FileUpload from '@/FileUpload.js' import FormulateInput from '@/FormulateInput.vue' import FormulateInputFile from '@/inputs/FormulateInputFile.vue' diff --git a/test/unit/FormulateInputGroup.test.js b/test/unit/FormulateInputGroup.test.js new file mode 100644 index 0000000..fe693b0 --- /dev/null +++ b/test/unit/FormulateInputGroup.test.js @@ -0,0 +1,101 @@ +import Vue from 'vue' +import { mount } from '@vue/test-utils' +import flushPromises from 'flush-promises' +import Formulate from '@/Formulate.js' +import FileUpload from '@/FileUpload.js' +import FormulateInput from '@/FormulateInput.vue' + +Vue.use(Formulate) + +describe('FormulateInputGroup', () => { + it('allows nested fields to be sub-rendered', async () => { + const wrapper = mount(FormulateInput, { + propsData: { type: 'group' }, + slots: { + default: '' + } + }) + expect(wrapper.findAll('.formulate-input-grouping input[type="text"]').length).toBe(1) + }) + + it('registers sub-fields with grouping', async () => { + const wrapper = mount(FormulateInput, { + propsData: { type: 'group' }, + slots: { + default: '' + } + }) + expect(wrapper.findAll('.formulate-input-grouping input[type="text"]').length).toBe(1) + }) + + it('is not repeatable by default', async () => { + const wrapper = mount(FormulateInput, { + propsData: { type: 'group' }, + slots: { + default: '' + } + }) + expect(wrapper.findAll('.formulate-input-group-add-more').length).toBe(0) + }) + + it('adds an add more button when repeatable', async () => { + const wrapper = mount(FormulateInput, { + propsData: { type: 'group', repeatable: true }, + slots: { + default: '' + } + }) + expect(wrapper.findAll('.formulate-input-group-add-more').length).toBe(1) + }) + + it('repeats the default slot when adding more', async () => { + const wrapper = mount(FormulateInput, { + propsData: { type: 'group', repeatable: true }, + slots: { + default: '
' + } + }) + wrapper.find('.formulate-input-group-add-more button').trigger('click') + await flushPromises(); + expect(wrapper.findAll('.wrap').length).toBe(2) + }) + + it('re-hydrates a repeatable field', async () => { + const wrapper = mount(FormulateInput, { + propsData: { type: 'group', repeatable: true, value: [{email: 'jon@example.com'}, {email:'jane@example.com'}] }, + slots: { + default: '
' + } + }) + await flushPromises() + const fields = wrapper.findAll('input[type="text"]') + expect(fields.length).toBe(2) + expect(fields.at(0).element.value).toBe('jon@example.com') + expect(fields.at(1).element.value).toBe('jane@example.com') + }) + + it('v-modeling a subfield changes all values', async () => { + const wrapper = mount({ + template: ` + + + + + `, + data () { + return { + users: [{email: 'jon@example.com'}, {email:'jane@example.com'}], + email: 'jim@example.com' + } + } + }) + await flushPromises() + const fields = wrapper.findAll('input[type="text"]') + expect(fields.length).toBe(4) + expect(fields.at(0).element.value).toBe('jim@example.com') + expect(fields.at(2).element.value).toBe('jim@example.com') + }) +})