refactor: Simplified logic of field components registry, moved value set logic from registry to form component
This commit is contained in:
parent
8144c27c69
commit
4c3274e621
@ -73,7 +73,7 @@ export default class FormularioField extends Vue {
|
|||||||
validator: behavior => Object.values(VALIDATION_BEHAVIOR).includes(behavior)
|
validator: behavior => Object.values(VALIDATION_BEHAVIOR).includes(behavior)
|
||||||
}) validationBehavior!: string
|
}) validationBehavior!: string
|
||||||
|
|
||||||
// Affects only observing & setting of local errors
|
// Affects only setting of local errors
|
||||||
@Prop({ default: false }) errorsDisabled!: boolean
|
@Prop({ default: false }) errorsDisabled!: boolean
|
||||||
|
|
||||||
@Prop({ default: () => <U, T>(value: U|Empty): U|T|Empty => value }) modelGetConverter!: ModelGetConverter
|
@Prop({ default: () => <U, T>(value: U|Empty): U|T|Empty => value }) modelGetConverter!: ModelGetConverter
|
||||||
@ -87,10 +87,17 @@ export default class FormularioField extends Vue {
|
|||||||
|
|
||||||
private validationRun: Promise<Violation[]> = Promise.resolve([])
|
private validationRun: Promise<Violation[]> = Promise.resolve([])
|
||||||
|
|
||||||
public get fullQualifiedName (): string {
|
public get fullPath (): string {
|
||||||
return this.__Formulario_path !== '' ? `${this.__Formulario_path}.${this.name}` : this.name
|
return this.__Formulario_path !== '' ? `${this.__Formulario_path}.${this.name}` : this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if this formulario element is v-modeled or not.
|
||||||
|
*/
|
||||||
|
get hasModel (): boolean {
|
||||||
|
return has(this.$options.propsData || {}, 'value')
|
||||||
|
}
|
||||||
|
|
||||||
private get model (): unknown {
|
private get model (): unknown {
|
||||||
const model = this.hasModel ? 'value' : 'proxy'
|
const model = this.hasModel ? 'value' : 'proxy'
|
||||||
return this.modelGetConverter(this[model])
|
return this.modelGetConverter(this[model])
|
||||||
@ -112,7 +119,7 @@ export default class FormularioField extends Vue {
|
|||||||
|
|
||||||
private get context (): FormularioFieldContext<unknown> {
|
private get context (): FormularioFieldContext<unknown> {
|
||||||
return Object.defineProperty({
|
return Object.defineProperty({
|
||||||
name: this.fullQualifiedName,
|
name: this.fullPath,
|
||||||
runValidation: this.runValidation.bind(this),
|
runValidation: this.runValidation.bind(this),
|
||||||
violations: this.violations,
|
violations: this.violations,
|
||||||
errors: this.localErrors,
|
errors: this.localErrors,
|
||||||
@ -141,13 +148,6 @@ export default class FormularioField extends Vue {
|
|||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if this formulario element is v-modeled or not.
|
|
||||||
*/
|
|
||||||
private get hasModel (): boolean {
|
|
||||||
return has(this.$options.propsData || {}, 'value')
|
|
||||||
}
|
|
||||||
|
|
||||||
@Watch('proxy')
|
@Watch('proxy')
|
||||||
private onProxyChange (newValue: unknown, oldValue: unknown): void {
|
private onProxyChange (newValue: unknown, oldValue: unknown): void {
|
||||||
if (!this.hasModel && !shallowEquals(newValue, oldValue)) {
|
if (!this.hasModel && !shallowEquals(newValue, oldValue)) {
|
||||||
@ -170,7 +170,7 @@ export default class FormularioField extends Vue {
|
|||||||
created (): void {
|
created (): void {
|
||||||
this.initProxy()
|
this.initProxy()
|
||||||
if (typeof this.__FormularioForm_register === 'function') {
|
if (typeof this.__FormularioForm_register === 'function') {
|
||||||
this.__FormularioForm_register(this.fullQualifiedName, this)
|
this.__FormularioForm_register(this.fullPath, this)
|
||||||
}
|
}
|
||||||
if (this.validationBehavior === VALIDATION_BEHAVIOR.LIVE) {
|
if (this.validationBehavior === VALIDATION_BEHAVIOR.LIVE) {
|
||||||
this.runValidation()
|
this.runValidation()
|
||||||
@ -179,7 +179,7 @@ export default class FormularioField extends Vue {
|
|||||||
|
|
||||||
beforeDestroy (): void {
|
beforeDestroy (): void {
|
||||||
if (typeof this.__FormularioForm_unregister === 'function') {
|
if (typeof this.__FormularioForm_unregister === 'function') {
|
||||||
this.__FormularioForm_unregister(this.fullQualifiedName)
|
this.__FormularioForm_unregister(this.fullPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export default class FormularioFieldGroup extends Vue {
|
|||||||
readonly isArrayItem!: boolean
|
readonly isArrayItem!: boolean
|
||||||
|
|
||||||
@Provide('__Formulario_path')
|
@Provide('__Formulario_path')
|
||||||
get groupPath (): string {
|
get fullPath (): string {
|
||||||
if (this.isArrayItem) {
|
if (this.isArrayItem) {
|
||||||
return `${this.__Formulario_path}[${this.name}]`
|
return `${this.__Formulario_path}[${this.name}]`
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ export default class FormularioFieldGroup extends Vue {
|
|||||||
return this.name
|
return this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${this.path}.${this.name}`
|
return `${this.__Formulario_path}.${this.name}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
shallowEquals,
|
shallowEquals,
|
||||||
} from '@/utils'
|
} from '@/utils'
|
||||||
|
|
||||||
import FormularioFormRegistry from '@/FormularioFormRegistry'
|
import PathRegistry from '@/PathRegistry'
|
||||||
|
|
||||||
import FormularioField from '@/FormularioField.vue'
|
import FormularioField from '@/FormularioField.vue'
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ export default class FormularioForm extends Vue {
|
|||||||
|
|
||||||
public proxy: Record<string, unknown> = {}
|
public proxy: Record<string, unknown> = {}
|
||||||
|
|
||||||
private registry: FormularioFormRegistry = new FormularioFormRegistry(this)
|
private registry: PathRegistry<FormularioField> = new PathRegistry()
|
||||||
|
|
||||||
// Local error messages are temporal, they wiped each resetValidation call
|
// Local error messages are temporal, they wiped each resetValidation call
|
||||||
private localFormErrors: string[] = []
|
private localFormErrors: string[] = []
|
||||||
@ -85,13 +85,13 @@ export default class FormularioForm extends Vue {
|
|||||||
|
|
||||||
@Watch('mergedFieldErrors', { deep: true, immediate: true })
|
@Watch('mergedFieldErrors', { deep: true, immediate: true })
|
||||||
onMergedFieldErrorsChange (errors: Record<string, string[]>): void {
|
onMergedFieldErrorsChange (errors: Record<string, string[]>): void {
|
||||||
this.registry.forEach((vm, path) => {
|
this.registry.forEach((field, path) => {
|
||||||
vm.setErrors(errors[path] || [])
|
field.setErrors(errors[path] || [])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
created (): void {
|
created (): void {
|
||||||
this.initProxy()
|
this.syncProxy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provide('__FormularioForm_getValue')
|
@Provide('__FormularioForm_getValue')
|
||||||
@ -112,58 +112,77 @@ export default class FormularioForm extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Provide('__FormularioForm_emitValidation')
|
@Provide('__FormularioForm_emitValidation')
|
||||||
onFormularioFieldValidation (payload: ValidationEventPayload): void {
|
private emitValidation (payload: ValidationEventPayload): void {
|
||||||
this.$emit('validation', payload)
|
this.$emit('validation', payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provide('__FormularioForm_register')
|
@Provide('__FormularioForm_register')
|
||||||
private register (field: string, vm: FormularioField): void {
|
private register (path: string, field: FormularioField): void {
|
||||||
this.registry.add(field, vm)
|
this.registry.add(path, field)
|
||||||
|
|
||||||
if (has(this.mergedFieldErrors, field)) {
|
const value = getNested(this.initialValues, path)
|
||||||
vm.setErrors(this.mergedFieldErrors[field] || [])
|
|
||||||
|
if (!field.hasModel && this.hasInitialValue && value !== undefined) {
|
||||||
|
// In the case that the form is carrying an initial value and the
|
||||||
|
// element is not, set it directly.
|
||||||
|
// @ts-ignore
|
||||||
|
field.context.model = value
|
||||||
|
} else if (field.hasModel && !shallowEquals(field.proxy, value)) {
|
||||||
|
// In this case, the field is v-modeled or has an initial value and the
|
||||||
|
// form has no value or a different value, so use the field value
|
||||||
|
this.setFieldValueAndEmit(path, field.proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has(this.mergedFieldErrors, path)) {
|
||||||
|
field.setErrors(this.mergedFieldErrors[path] || [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provide('__FormularioForm_unregister')
|
@Provide('__FormularioForm_unregister')
|
||||||
private unregister (field: string): void {
|
private unregister (path: string): void {
|
||||||
if (this.registry.has(field)) {
|
if (this.registry.has(path)) {
|
||||||
this.registry.remove(field)
|
this.registry.remove(path)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { [path]: _, ...newProxy } = this.proxy
|
||||||
|
this.proxy = newProxy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initProxy (): void {
|
syncProxy (): void {
|
||||||
if (this.hasInitialValue) {
|
if (this.hasInitialValue) {
|
||||||
this.proxy = this.initialValues
|
this.proxy = this.initialValues
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setValues (values: Record<string, unknown>): void {
|
setValues (state: Record<string, unknown>): void {
|
||||||
const keys = Array.from(new Set([...Object.keys(values), ...Object.keys(this.proxy)]))
|
const paths = Array.from(new Set([
|
||||||
|
...Object.keys(state),
|
||||||
|
...Object.keys(this.proxy),
|
||||||
|
]))
|
||||||
|
|
||||||
let proxyHasChanges = false
|
let proxyHasChanges = false
|
||||||
keys.forEach(field => {
|
|
||||||
if (!this.registry.hasNested(field)) {
|
paths.forEach(path => {
|
||||||
|
if (!this.registry.hasSubset(path)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.registry.getNested(field).forEach((_, fqn) => {
|
this.registry.getSubset(path).forEach((field, path) => {
|
||||||
const $field = this.registry.get(fqn) as FormularioField
|
const oldValue = getNested(this.proxy, path)
|
||||||
|
const newValue = getNested(state, path)
|
||||||
const oldValue = getNested(this.proxy, fqn)
|
|
||||||
const newValue = getNested(values, fqn)
|
|
||||||
|
|
||||||
if (!shallowEquals(newValue, oldValue)) {
|
if (!shallowEquals(newValue, oldValue)) {
|
||||||
this.setFieldValue(fqn, newValue)
|
this.setFieldValue(path, newValue)
|
||||||
proxyHasChanges = true
|
proxyHasChanges = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shallowEquals(newValue, $field.proxy)) {
|
if (!shallowEquals(newValue, field.proxy)) {
|
||||||
$field.context.model = newValue
|
field.context.model = newValue
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.initProxy()
|
this.syncProxy()
|
||||||
|
|
||||||
if (proxyHasChanges) {
|
if (proxyHasChanges) {
|
||||||
this.$emit('input', { ...this.proxy })
|
this.$emit('input', { ...this.proxy })
|
||||||
|
@ -1,142 +0,0 @@
|
|||||||
import { getNested, has, shallowEquals } from '@/utils'
|
|
||||||
|
|
||||||
import FormularioField from '@/FormularioField.vue'
|
|
||||||
import FormularioForm from '@/FormularioForm.vue'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Component registry with inherent depth to handle complex nesting. This is
|
|
||||||
* important for features such as grouped fields.
|
|
||||||
*/
|
|
||||||
export default class FormularioFormRegistry {
|
|
||||||
private ctx: FormularioForm
|
|
||||||
private registry: Map<string, FormularioField>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new registry of components.
|
|
||||||
* @param {FormularioForm} ctx The host vm context of the registry.
|
|
||||||
*/
|
|
||||||
constructor (ctx: FormularioForm) {
|
|
||||||
this.registry = new Map()
|
|
||||||
this.ctx = ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fully register a component.
|
|
||||||
* @param {string} field name of the field.
|
|
||||||
* @param {FormularioForm} component the actual component instance.
|
|
||||||
*/
|
|
||||||
add (field: string, component: FormularioField): void {
|
|
||||||
if (this.registry.has(field)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.registry.set(field, component)
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
const value = getNested(this.ctx.initialValues, field)
|
|
||||||
const hasModel = has(component.$options.propsData || {}, 'value')
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
if (!hasModel && this.ctx.hasInitialValue && value !== undefined) {
|
|
||||||
// In the case that the form is carrying an initial value and the
|
|
||||||
// element is not, set it directly.
|
|
||||||
// @ts-ignore
|
|
||||||
component.context.model = value
|
|
||||||
// @ts-ignore
|
|
||||||
} else if (hasModel && !shallowEquals(component.proxy, value)) {
|
|
||||||
// In this case, the field is v-modeled or has an initial value and the
|
|
||||||
// form has no value or a different value, so use the field value
|
|
||||||
// @ts-ignore
|
|
||||||
this.ctx.setFieldValueAndEmit(field, component.proxy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an item from the registry.
|
|
||||||
*/
|
|
||||||
remove (name: string): void {
|
|
||||||
this.registry.delete(name)
|
|
||||||
// @ts-ignore
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const { [name]: value, ...newProxy } = this.ctx.proxy
|
|
||||||
// @ts-ignore
|
|
||||||
this.ctx.proxy = newProxy
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the registry has the given key.
|
|
||||||
*/
|
|
||||||
has (key: string): boolean {
|
|
||||||
return this.registry.has(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the registry has elements, that equals or nested given key
|
|
||||||
*/
|
|
||||||
hasNested (key: string): boolean {
|
|
||||||
for (const i of this.registry.keys()) {
|
|
||||||
if (i === key || i.includes(key + '.')) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a particular registry value.
|
|
||||||
*/
|
|
||||||
get (key: string): FormularioField | undefined {
|
|
||||||
return this.registry.get(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get registry value for key or nested to given key
|
|
||||||
*/
|
|
||||||
getNested (key: string): Map<string, FormularioField> {
|
|
||||||
const result = new Map()
|
|
||||||
|
|
||||||
for (const i of this.registry.keys()) {
|
|
||||||
const objectKey = key + '.'
|
|
||||||
const arrayKey = key + '['
|
|
||||||
|
|
||||||
if (
|
|
||||||
i === key ||
|
|
||||||
i.substring(0, objectKey.length) === objectKey ||
|
|
||||||
i.substring(0, arrayKey.length) === arrayKey
|
|
||||||
) {
|
|
||||||
result.set(i, this.registry.get(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterate over the registry.
|
|
||||||
*/
|
|
||||||
forEach (callback: (component: FormularioField, field: string) => void): void {
|
|
||||||
this.registry.forEach((component, field) => {
|
|
||||||
callback(component, field)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the keys of the registry.
|
|
||||||
*/
|
|
||||||
keys (): string[] {
|
|
||||||
return Array.from(this.registry.keys())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reduce the registry.
|
|
||||||
* @param {function} callback
|
|
||||||
* @param accumulator
|
|
||||||
*/
|
|
||||||
reduce<U> (callback: Function, accumulator: U): U {
|
|
||||||
this.registry.forEach((component, field) => {
|
|
||||||
accumulator = callback(accumulator, component, field)
|
|
||||||
})
|
|
||||||
return accumulator
|
|
||||||
}
|
|
||||||
}
|
|
82
src/PathRegistry.ts
Normal file
82
src/PathRegistry.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export default class PathRegistry<T> {
|
||||||
|
private registry: Map<string, T>
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
this.registry = new Map()
|
||||||
|
}
|
||||||
|
|
||||||
|
has (path: string): boolean {
|
||||||
|
return this.registry.has(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
hasSubset (path: string): boolean {
|
||||||
|
for (const itemPath of this.registry.keys()) {
|
||||||
|
if (itemPath === path || itemPath.includes(path + '.')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
get (path: string): T | undefined {
|
||||||
|
return this.registry.get(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns registry subset by given path - field & descendants
|
||||||
|
*/
|
||||||
|
getSubset (path: string): PathRegistry<T> {
|
||||||
|
const subset: PathRegistry<T> = new PathRegistry()
|
||||||
|
|
||||||
|
for (const itemPath of this.registry.keys()) {
|
||||||
|
if (
|
||||||
|
itemPath === path ||
|
||||||
|
itemPath.startsWith(path + '.') ||
|
||||||
|
itemPath.startsWith(path + '[')
|
||||||
|
) {
|
||||||
|
subset.add(itemPath, this.registry.get(itemPath) as T)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return subset
|
||||||
|
}
|
||||||
|
|
||||||
|
add (path: string, item: T): void {
|
||||||
|
if (!this.registry.has(path)) {
|
||||||
|
this.registry.set(path, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove (path: string): void {
|
||||||
|
this.registry.delete(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
paths (): IterableIterator<string> {
|
||||||
|
return this.registry.keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over the registry.
|
||||||
|
*/
|
||||||
|
forEach (callback: (field: T, path: string) => void): void {
|
||||||
|
this.registry.forEach((field, path) => {
|
||||||
|
callback(field, path)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce the registry.
|
||||||
|
* @param {function} callback
|
||||||
|
* @param accumulator
|
||||||
|
*/
|
||||||
|
reduce<U> (callback: (accumulator: U, item: T, path: string) => U, accumulator: U): U {
|
||||||
|
this.registry.forEach((item, path) => {
|
||||||
|
accumulator = callback(accumulator, item, path)
|
||||||
|
})
|
||||||
|
return accumulator
|
||||||
|
}
|
||||||
|
}
|
@ -38,63 +38,6 @@ describe('FormularioForm', () => {
|
|||||||
expect(spy).toHaveBeenCalled()
|
expect(spy).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Adds subcomponents to the registry', () => {
|
|
||||||
const wrapper = mount(FormularioForm, {
|
|
||||||
propsData: { state: {} },
|
|
||||||
slots: {
|
|
||||||
default: `
|
|
||||||
<FormularioField name="sub1" />
|
|
||||||
<FormularioField name="sub2" />
|
|
||||||
`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
expect(wrapper.vm['registry'].keys()).toEqual(['sub1', 'sub2'])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Removes subcomponents from the registry', async () => {
|
|
||||||
const wrapper = mount({
|
|
||||||
data: () => ({ active: true }),
|
|
||||||
template: `
|
|
||||||
<FormularioForm>
|
|
||||||
<FormularioField v-if="active" name="sub1" />
|
|
||||||
<FormularioField name="sub2" />
|
|
||||||
</FormularioForm>
|
|
||||||
`
|
|
||||||
})
|
|
||||||
await flushPromises()
|
|
||||||
expect(wrapper.findComponent(FormularioForm).vm['registry'].keys()).toEqual(['sub1', 'sub2'])
|
|
||||||
wrapper.setData({ active: false })
|
|
||||||
await flushPromises()
|
|
||||||
expect(wrapper.findComponent(FormularioForm).vm['registry'].keys()).toEqual(['sub2'])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Getting nested fields from registry', async () => {
|
|
||||||
const wrapper = mount({
|
|
||||||
data: () => ({ active: true, nested: { groups: { value: 'value' } }, groups: [{ name: 'group1' }, { name: 'group2' }] }),
|
|
||||||
template: `
|
|
||||||
<FormularioForm>
|
|
||||||
<FormularioField name="sub1" />
|
|
||||||
<FormularioField name="sub2" />
|
|
||||||
<FormularioField name="nested.groups.value" />
|
|
||||||
<FormularioField name="groups">
|
|
||||||
<FormularioFieldGroup :name="'groups[' + index + ']'" v-for="(_, index) in groups" :key="index">
|
|
||||||
<FormularioField name="name" />
|
|
||||||
</FormularioFieldGroup>
|
|
||||||
</FormularioField>
|
|
||||||
</FormularioForm>
|
|
||||||
`
|
|
||||||
})
|
|
||||||
await flushPromises()
|
|
||||||
expect(Array.from(wrapper.findComponent(FormularioForm).vm.registry.getNested('sub1').keys())).toEqual(['sub1'])
|
|
||||||
expect(Array.from(wrapper.findComponent(FormularioForm).vm.registry.getNested('groups').keys()))
|
|
||||||
.toEqual(['groups', 'groups[0].name', 'groups[1].name'])
|
|
||||||
|
|
||||||
wrapper.setData({ active: true, groups: [{ name: 'group1' }] })
|
|
||||||
await flushPromises()
|
|
||||||
expect(Array.from(wrapper.findComponent(FormularioForm).vm.registry.getNested('groups').keys()))
|
|
||||||
.toEqual(['groups', 'groups[0].name'])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Can set a field’s initial value', async () => {
|
it('Can set a field’s initial value', async () => {
|
||||||
const wrapper = mount(FormularioForm, {
|
const wrapper = mount(FormularioForm, {
|
||||||
propsData: { state: { test: 'Has initial value' } },
|
propsData: { state: { test: 'Has initial value' } },
|
||||||
|
50
test/unit/PathRegistry.test.js
Normal file
50
test/unit/PathRegistry.test.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import PathRegistry from '@/PathRegistry'
|
||||||
|
|
||||||
|
describe('PathRegistry', () => {
|
||||||
|
test ('subset structure', () => {
|
||||||
|
const registry = new PathRegistry()
|
||||||
|
|
||||||
|
const paths = path => Array.from(registry.getSubset(path).paths())
|
||||||
|
|
||||||
|
registry.add('name', null)
|
||||||
|
registry.add('address', [])
|
||||||
|
registry.add('address[0]', {})
|
||||||
|
registry.add('address[0].street', 'Baker Street')
|
||||||
|
registry.add('address[0].building', '221b')
|
||||||
|
registry.add('address[1]', {})
|
||||||
|
registry.add('address[1].street', '')
|
||||||
|
registry.add('address[1].building', '')
|
||||||
|
|
||||||
|
expect(paths('name')).toEqual(['name'])
|
||||||
|
expect(paths('address')).toEqual([
|
||||||
|
'address',
|
||||||
|
'address[0]',
|
||||||
|
'address[0].street',
|
||||||
|
'address[0].building',
|
||||||
|
'address[1]',
|
||||||
|
'address[1].street',
|
||||||
|
'address[1].building',
|
||||||
|
])
|
||||||
|
expect(paths('address[1]')).toEqual([
|
||||||
|
'address[1]',
|
||||||
|
'address[1].street',
|
||||||
|
'address[1].building',
|
||||||
|
])
|
||||||
|
|
||||||
|
registry.remove('address[1]')
|
||||||
|
|
||||||
|
expect(paths('address')).toEqual([
|
||||||
|
'address',
|
||||||
|
'address[0]',
|
||||||
|
'address[0].street',
|
||||||
|
'address[0].building',
|
||||||
|
'address[1].street',
|
||||||
|
'address[1].building',
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(paths('address[1]')).toEqual([
|
||||||
|
'address[1].street',
|
||||||
|
'address[1].building',
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user