feat!: formularioValue prop removed, prop value now used as model
This commit is contained in:
parent
357d493899
commit
3d31c461e6
@ -1,10 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="formulario-input">
|
<div class="formulario-input">
|
||||||
<slot
|
<slot :context="context" />
|
||||||
:id="id"
|
|
||||||
:context="context"
|
|
||||||
:violations="validationErrors"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -33,6 +29,7 @@ import {
|
|||||||
const ERROR_BEHAVIOR = {
|
const ERROR_BEHAVIOR = {
|
||||||
BLUR: 'blur',
|
BLUR: 'blur',
|
||||||
LIVE: 'live',
|
LIVE: 'live',
|
||||||
|
NONE: 'none',
|
||||||
SUBMIT: 'submit',
|
SUBMIT: 'submit',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,50 +44,81 @@ export default class FormularioInput extends Vue {
|
|||||||
@Inject({ default: undefined }) removeErrorObserver!: Function|undefined
|
@Inject({ default: undefined }) removeErrorObserver!: Function|undefined
|
||||||
@Inject({ default: '' }) path!: string
|
@Inject({ default: '' }) path!: string
|
||||||
|
|
||||||
@Model('input', { default: '' }) formularioValue: any
|
@Model('input', { default: '' }) value!: any
|
||||||
|
|
||||||
|
@Prop({
|
||||||
|
required: true,
|
||||||
|
validator: (name: any): boolean => typeof name === 'string' && name.length > 0,
|
||||||
|
}) name!: string
|
||||||
|
|
||||||
@Prop({ default: null }) id!: string|number|null
|
|
||||||
@Prop({ required: true }) name!: string
|
|
||||||
@Prop({ default: false }) value!: any
|
|
||||||
@Prop({ default: '' }) validation!: string|any[]
|
@Prop({ default: '' }) validation!: string|any[]
|
||||||
@Prop({ default: () => ({}) }) validationRules!: Record<string, ValidationRule>
|
@Prop({ default: () => ({}) }) validationRules!: Record<string, ValidationRule>
|
||||||
@Prop({ default: () => ({}) }) validationMessages!: Record<string, any>
|
@Prop({ default: () => ({}) }) validationMessages!: Record<string, any>
|
||||||
@Prop({ default: () => [] }) errors!: string[]
|
@Prop({ default: () => [] }) errors!: string[]
|
||||||
@Prop({
|
@Prop({
|
||||||
default: ERROR_BEHAVIOR.BLUR,
|
default: ERROR_BEHAVIOR.BLUR,
|
||||||
validator: behavior => [ERROR_BEHAVIOR.BLUR, ERROR_BEHAVIOR.LIVE, ERROR_BEHAVIOR.SUBMIT].includes(behavior)
|
validator: behavior => [
|
||||||
|
ERROR_BEHAVIOR.BLUR,
|
||||||
|
ERROR_BEHAVIOR.LIVE,
|
||||||
|
ERROR_BEHAVIOR.NONE,
|
||||||
|
ERROR_BEHAVIOR.SUBMIT,
|
||||||
|
].includes(behavior)
|
||||||
}) errorBehavior!: string
|
}) errorBehavior!: string
|
||||||
|
|
||||||
@Prop({ default: false }) disableErrors!: boolean
|
@Prop({ default: false }) errorsDisabled!: boolean
|
||||||
|
|
||||||
defaultId: string = this.$formulario.nextId(this)
|
proxy: any = this.getInitialValue()
|
||||||
proxy: Record<string, any> = this.getInitialValue()
|
|
||||||
localErrors: string[] = []
|
localErrors: string[] = []
|
||||||
validationErrors: ValidationError[] = []
|
violations: ValidationError[] = []
|
||||||
pendingValidation: Promise<any> = Promise.resolve()
|
pendingValidation: Promise<any> = Promise.resolve()
|
||||||
|
|
||||||
|
get model (): any {
|
||||||
|
const model = this.hasModel ? 'value' : 'proxy'
|
||||||
|
if (this[model] === undefined) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return this[model]
|
||||||
|
}
|
||||||
|
|
||||||
|
set model (value: any) {
|
||||||
|
if (!shallowEqualObjects(value, this.proxy)) {
|
||||||
|
this.proxy = value
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('input', value)
|
||||||
|
|
||||||
|
if (typeof this.formularioSetter === 'function') {
|
||||||
|
this.formularioSetter(this.context.name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get context (): Record<string, any> {
|
get context (): Record<string, any> {
|
||||||
return Object.defineProperty({
|
return Object.defineProperty({
|
||||||
id: this.id || this.defaultId,
|
name: this.fullQualifiedName,
|
||||||
name: this.nameOrFallback,
|
validate: this.performValidation.bind(this),
|
||||||
|
violations: this.violations,
|
||||||
|
errors: this.mergedErrors,
|
||||||
|
// @TODO: Deprecated
|
||||||
|
allErrors: [
|
||||||
|
...this.mergedErrors.map(message => ({ message })),
|
||||||
|
...arrayify(this.violations)
|
||||||
|
],
|
||||||
blurHandler: this.blurHandler.bind(this),
|
blurHandler: this.blurHandler.bind(this),
|
||||||
errors: this.explicitErrors,
|
|
||||||
allErrors: this.allErrors,
|
|
||||||
performValidation: this.performValidation.bind(this),
|
performValidation: this.performValidation.bind(this),
|
||||||
validationErrors: this.validationErrors,
|
|
||||||
value: this.value,
|
|
||||||
}, 'model', {
|
}, 'model', {
|
||||||
get: this.modelGetter.bind(this),
|
get: () => this.model,
|
||||||
set: this.modelSetter.bind(this),
|
set: (value: any) => {
|
||||||
|
this.model = value
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get parsedValidationRules (): Record<string, ValidationRule> {
|
get parsedValidationRules (): Record<string, ValidationRule> {
|
||||||
const parsedValidationRules: Record<string, ValidationRule> = {}
|
const rules: Record<string, ValidationRule> = {}
|
||||||
Object.keys(this.validationRules).forEach(key => {
|
Object.keys(this.validationRules).forEach(key => {
|
||||||
parsedValidationRules[snakeToCamel(key)] = this.validationRules[key]
|
rules[snakeToCamel(key)] = this.validationRules[key]
|
||||||
})
|
})
|
||||||
return parsedValidationRules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
get messages (): Record<string, any> {
|
get messages (): Record<string, any> {
|
||||||
@ -104,32 +132,14 @@ export default class FormularioInput extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Return the element’s name, or select a fallback.
|
* Return the element’s name, or select a fallback.
|
||||||
*/
|
*/
|
||||||
get nameOrFallback (): string {
|
get fullQualifiedName (): string {
|
||||||
return this.path !== '' ? `${this.path}.${this.name}` : this.name
|
return this.path !== '' ? `${this.path}.${this.name}` : this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this computed property have errors
|
|
||||||
*/
|
|
||||||
get hasErrors (): boolean {
|
|
||||||
return this.allErrors.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The merged errors computed property.
|
|
||||||
* Each error is an object with fields message (translated message), rule (rule name) and context
|
|
||||||
*/
|
|
||||||
get allErrors (): ValidationError[] {
|
|
||||||
return [
|
|
||||||
...this.explicitErrors.map(message => ({ message })),
|
|
||||||
...arrayify(this.validationErrors)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These are errors we that have been explicitly passed to us.
|
* These are errors we that have been explicitly passed to us.
|
||||||
*/
|
*/
|
||||||
get explicitErrors (): string[] {
|
get mergedErrors (): string[] {
|
||||||
return [...arrayify(this.errors), ...this.localErrors]
|
return [...arrayify(this.errors), ...this.localErrors]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,35 +147,35 @@ export default class FormularioInput extends Vue {
|
|||||||
* Determines if this formulario element is v-modeled or not.
|
* Determines if this formulario element is v-modeled or not.
|
||||||
*/
|
*/
|
||||||
get hasModel (): boolean {
|
get hasModel (): boolean {
|
||||||
return has(this.$options.propsData || {}, 'formularioValue')
|
return has(this.$options.propsData || {}, 'value')
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('proxy')
|
@Watch('proxy')
|
||||||
onProxyChanged (newValue: Record<string, any>, oldValue: Record<string, any>): void {
|
onProxyChanged (newValue: any, oldValue: any): void {
|
||||||
if (this.errorBehavior === ERROR_BEHAVIOR.LIVE) {
|
|
||||||
this.performValidation()
|
|
||||||
} else {
|
|
||||||
this.validationErrors = []
|
|
||||||
}
|
|
||||||
if (!this.hasModel && !shallowEqualObjects(newValue, oldValue)) {
|
if (!this.hasModel && !shallowEqualObjects(newValue, oldValue)) {
|
||||||
this.context.model = newValue
|
this.context.model = newValue
|
||||||
}
|
}
|
||||||
|
if (this.errorBehavior === ERROR_BEHAVIOR.LIVE) {
|
||||||
|
this.performValidation()
|
||||||
|
} else {
|
||||||
|
this.violations = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('formularioValue')
|
@Watch('value')
|
||||||
onFormularioValueChanged (newValue: Record<string, any>, oldValue: Record<string, any>): void {
|
onValueChanged (newValue: any, oldValue: any): void {
|
||||||
if (this.hasModel && !shallowEqualObjects(newValue, oldValue)) {
|
if (this.hasModel && !shallowEqualObjects(newValue, oldValue)) {
|
||||||
this.context.model = newValue
|
this.context.model = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
created (): void {
|
created (): void {
|
||||||
this.applyInitialValue()
|
this.initProxy()
|
||||||
if (this.formularioRegister && typeof this.formularioRegister === 'function') {
|
if (typeof this.formularioRegister === 'function') {
|
||||||
this.formularioRegister(this.nameOrFallback, this)
|
this.formularioRegister(this.fullQualifiedName, this)
|
||||||
}
|
}
|
||||||
if (!this.disableErrors && typeof this.addErrorObserver === 'function') {
|
if (typeof this.addErrorObserver === 'function' && !this.errorsDisabled) {
|
||||||
this.addErrorObserver({ callback: this.setErrors, type: 'input', field: this.nameOrFallback })
|
this.addErrorObserver({ callback: this.setErrors, type: 'input', field: this.fullQualifiedName })
|
||||||
}
|
}
|
||||||
if (this.errorBehavior === ERROR_BEHAVIOR.LIVE) {
|
if (this.errorBehavior === ERROR_BEHAVIOR.LIVE) {
|
||||||
this.performValidation()
|
this.performValidation()
|
||||||
@ -174,35 +184,11 @@ export default class FormularioInput extends Vue {
|
|||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
beforeDestroy (): void {
|
beforeDestroy (): void {
|
||||||
if (!this.disableErrors && typeof this.removeErrorObserver === 'function') {
|
if (!this.errorsDisabled && typeof this.removeErrorObserver === 'function') {
|
||||||
this.removeErrorObserver(this.setErrors)
|
this.removeErrorObserver(this.setErrors)
|
||||||
}
|
}
|
||||||
if (typeof this.formularioDeregister === 'function') {
|
if (typeof this.formularioDeregister === 'function') {
|
||||||
this.formularioDeregister(this.nameOrFallback)
|
this.formularioDeregister(this.fullQualifiedName)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value from a model.
|
|
||||||
*/
|
|
||||||
modelGetter (): any {
|
|
||||||
const model = this.hasModel ? 'formularioValue' : 'proxy'
|
|
||||||
if (this[model] === undefined) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
return this[model]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value from a model.
|
|
||||||
*/
|
|
||||||
modelSetter (value: any): void {
|
|
||||||
if (!shallowEqualObjects(value, this.proxy)) {
|
|
||||||
this.proxy = value
|
|
||||||
}
|
|
||||||
this.$emit('input', value)
|
|
||||||
if (this.context.name && typeof this.formularioSetter === 'function') {
|
|
||||||
this.formularioSetter(this.context.name, value)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,15 +203,10 @@ export default class FormularioInput extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getInitialValue (): any {
|
getInitialValue (): any {
|
||||||
if (has(this.$options.propsData as Record<string, any>, 'value')) {
|
return has(this.$options.propsData || {}, 'value') ? this.value : ''
|
||||||
return this.value
|
|
||||||
} else if (has(this.$options.propsData as Record<string, any>, 'formularioValue')) {
|
|
||||||
return this.formularioValue
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyInitialValue (): void {
|
initProxy (): void {
|
||||||
// This should only be run immediately on created and ensures that the
|
// This should only be run immediately on created and ensures that the
|
||||||
// proxy and the model are both the same before any additional registration.
|
// proxy and the model are both the same before any additional registration.
|
||||||
if (!shallowEqualObjects(this.context.model, this.proxy)) {
|
if (!shallowEqualObjects(this.context.model, this.proxy)) {
|
||||||
@ -277,12 +258,12 @@ export default class FormularioInput extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
didValidate (violations: ValidationError[]): void {
|
didValidate (violations: ValidationError[]): void {
|
||||||
const validationChanged = !shallowEqualObjects(violations, this.validationErrors)
|
const validationChanged = !shallowEqualObjects(violations, this.violations)
|
||||||
this.validationErrors = violations
|
this.violations = violations
|
||||||
if (validationChanged) {
|
if (validationChanged) {
|
||||||
const errorBag = {
|
const errorBag = {
|
||||||
name: this.context.name,
|
name: this.context.name,
|
||||||
errors: this.validationErrors,
|
errors: this.violations,
|
||||||
}
|
}
|
||||||
this.$emit('validation', errorBag)
|
this.$emit('validation', errorBag)
|
||||||
if (this.onFormularioFieldValidation && typeof this.onFormularioFieldValidation === 'function') {
|
if (this.onFormularioFieldValidation && typeof this.onFormularioFieldValidation === 'function') {
|
||||||
@ -324,7 +305,7 @@ export default class FormularioInput extends Vue {
|
|||||||
hasValidationErrors (): Promise<boolean> {
|
hasValidationErrors (): Promise<boolean> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.pendingValidation.then(() => resolve(!!this.validationErrors.length))
|
this.pendingValidation.then(() => resolve(this.violations.length > 0))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -335,7 +316,7 @@ export default class FormularioInput extends Vue {
|
|||||||
|
|
||||||
resetValidation (): void {
|
resetValidation (): void {
|
||||||
this.localErrors = []
|
this.localErrors = []
|
||||||
this.validationErrors = []
|
this.violations = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -115,8 +115,7 @@ export default class Registry {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.registry.set(field, component)
|
this.registry.set(field, component)
|
||||||
const hasModel = has(component.$options.propsData || {}, 'formularioValue')
|
const hasModel = has(component.$options.propsData || {}, 'value')
|
||||||
const hasValue = has(component.$options.propsData || {}, 'value')
|
|
||||||
if (
|
if (
|
||||||
!hasModel &&
|
!hasModel &&
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -129,7 +128,7 @@ export default class Registry {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
component.context.model = getNested(this.ctx.initialValues, field)
|
component.context.model = getNested(this.ctx.initialValues, field)
|
||||||
} else if (
|
} else if (
|
||||||
(hasModel || hasValue) &&
|
hasModel &&
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
!shallowEqualObjects(component.proxy, getNested(this.ctx.initialValues, field))
|
!shallowEqualObjects(component.proxy, getNested(this.ctx.initialValues, field))
|
||||||
) {
|
) {
|
||||||
|
@ -88,7 +88,7 @@ describe('FormularioForm', () => {
|
|||||||
propsData: { formularioValue: { test: 'has initial value' } },
|
propsData: { formularioValue: { test: 'has initial value' } },
|
||||||
slots: {
|
slots: {
|
||||||
default: `
|
default: `
|
||||||
<FormularioInput v-slot="{ context }" formulario-value="123" name="test" >
|
<FormularioInput v-slot="{ context }" name="test" value="123">
|
||||||
<input v-model="context.model" type="text">
|
<input v-model="context.model" type="text">
|
||||||
</FormularioInput>
|
</FormularioInput>
|
||||||
`
|
`
|
||||||
@ -164,30 +164,39 @@ describe('FormularioForm', () => {
|
|||||||
it('Updates calls setFieldValue on form when a field contains a populated v-model on registration', () => {
|
it('Updates calls setFieldValue on form when a field contains a populated v-model on registration', () => {
|
||||||
const wrapper = mount(FormularioForm, {
|
const wrapper = mount(FormularioForm, {
|
||||||
propsData: {
|
propsData: {
|
||||||
formularioValue: { test: '123' }
|
formularioValue: { test: 'Initial' }
|
||||||
},
|
},
|
||||||
slots: {
|
slots: {
|
||||||
default: '<FormularioInput name="test" formulario-value="override-data" />'
|
default: '<FormularioInput name="test" value="Overrides" />'
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(wrapper.emitted().input[wrapper.emitted().input.length - 1]).toEqual([{ test: 'override-data' }])
|
|
||||||
|
const emitted = wrapper.emitted('input')
|
||||||
|
|
||||||
|
expect(emitted).toBeTruthy()
|
||||||
|
expect(emitted[emitted.length - 1]).toEqual([{ test: 'Overrides' }])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('updates an inputs value when the form v-model is modified', async () => {
|
it('updates an inputs value when the form v-model is modified', async () => {
|
||||||
const wrapper = mount({
|
const wrapper = mount({
|
||||||
data: () => ({ formValues: { test: 'abcd' } }),
|
data: () => ({ values: { test: 'abcd' } }),
|
||||||
template: `
|
template: `
|
||||||
<FormularioForm v-model="formValues">
|
<FormularioForm v-model="values">
|
||||||
<FormularioInput v-slot="{ context }" name="test" >
|
<FormularioInput v-slot="{ context }" name="test" >
|
||||||
<input v-model="context.model" type="text">
|
<input v-model="context.model" type="text">
|
||||||
</FormularioInput>
|
</FormularioInput>
|
||||||
</FormularioForm>
|
</FormularioForm>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
wrapper.vm.values = { test: '1234' }
|
||||||
|
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
wrapper.vm.formValues = { test: '1234' }
|
|
||||||
await flushPromises()
|
const input = wrapper.find('input[type="text"]')
|
||||||
expect(wrapper.find('input[type="text"]').element['value']).toBe('1234')
|
|
||||||
|
expect(input).toBeTruthy()
|
||||||
|
expect(input.element['value']).toBe('1234')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Resolves hasValidationErrors to true', async () => {
|
it('Resolves hasValidationErrors to true', async () => {
|
||||||
|
@ -53,7 +53,7 @@ describe('FormularioGrouping', () => {
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
expect(wrapper.find('input[type="text"]').element.value).toBe('Group text')
|
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 () => {
|
||||||
|
@ -19,17 +19,17 @@ Vue.use(Formulario, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('FormularioInput', () => {
|
describe('FormularioInput', () => {
|
||||||
it('allows custom field-rule level validation strings', async () => {
|
it('Allows custom field-rule level validation strings', async () => {
|
||||||
const wrapper = mount(FormularioInput, {
|
const wrapper = mount(FormularioInput, {
|
||||||
propsData: {
|
propsData: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
validation: 'required|in:abcdef',
|
validation: 'required|in:abcdef',
|
||||||
validationMessages: {in: 'the value was different than expected'},
|
validationMessages: { in: 'the value was different than expected' },
|
||||||
errorBehavior: 'live',
|
errorBehavior: 'live',
|
||||||
value: 'other value'
|
value: 'other value',
|
||||||
},
|
},
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
default: `<div><span v-for="error in props.context.allErrors">{{ error.message }}</span></div>`
|
default: `<div><span v-for="violation in props.context.violations">{{ violation.message }}</span></div>`
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
@ -52,30 +52,33 @@ describe('FormularioInput', () => {
|
|||||||
expect(wrapper.find('span').exists()).toBe(false)
|
expect(wrapper.find('span').exists()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('no validation on value change when errorBehavior is not live', async () => {
|
it('No validation on value change when errorBehavior is not live', async () => {
|
||||||
const wrapper = mount(FormularioInput, {
|
const wrapper = mount(FormularioInput, {
|
||||||
propsData: {
|
propsData: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
validation: 'required|in:abcdef',
|
validation: 'required|in:abcdef',
|
||||||
validationMessages: {in: 'the value was different than expected'},
|
validationMessages: {in: 'the value was different than expected'},
|
||||||
errorBehavior: 'submit',
|
errorBehavior: 'submit',
|
||||||
value: 'other value'
|
value: 'Initial'
|
||||||
},
|
},
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
default: `<div>
|
default: `<div>
|
||||||
<input type="text" v-model="props.context.model">
|
<input type="text" v-model="props.context.model">
|
||||||
<span v-for="error in props.context.allErrors">{{ error.message }}</span>
|
<span v-for="error in props.context.violations">{{ error.message }}</span>
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
|
|
||||||
expect(wrapper.find('span').exists()).toBe(false)
|
expect(wrapper.find('span').exists()).toBe(false)
|
||||||
|
|
||||||
const input = wrapper.find('input[type="text"]')
|
wrapper.find('input[type="text"]').element['value'] = 'Test'
|
||||||
input.element.value = 'test'
|
wrapper.find('input[type="text"]').trigger('change')
|
||||||
input.trigger('input')
|
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
expect(wrapper.find('input[type="text"]').element.value).toBe('test')
|
|
||||||
|
expect(wrapper.find('input[type="text"]').element['value']).toBe('Test')
|
||||||
expect(wrapper.find('span').exists()).toBe(false)
|
expect(wrapper.find('span').exists()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -156,7 +159,7 @@ describe('FormularioInput', () => {
|
|||||||
expect(wrapper.find('span').text()).toBe('failed the foobar check')
|
expect(wrapper.find('span').text()).toBe('failed the foobar check')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('uses global custom validation rules', async () => {
|
it('Uses global custom validation rules', async () => {
|
||||||
const wrapper = mount(FormularioInput, {
|
const wrapper = mount(FormularioInput, {
|
||||||
propsData: {
|
propsData: {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
@ -169,7 +172,7 @@ describe('FormularioInput', () => {
|
|||||||
expect(globalRule.mock.calls.length).toBe(1)
|
expect(globalRule.mock.calls.length).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('emits correct validation event', async () => {
|
it('Emits correct validation event', async () => {
|
||||||
const wrapper = mount(FormularioInput, {
|
const wrapper = mount(FormularioInput, {
|
||||||
propsData: {
|
propsData: {
|
||||||
validation: 'required',
|
validation: 'required',
|
||||||
@ -195,7 +198,7 @@ describe('FormularioInput', () => {
|
|||||||
propsData: { name: 'test', validation: 'bail|required|in:xyz', errorBehavior: 'live' }
|
propsData: { name: 'test', validation: 'bail|required|in:xyz', errorBehavior: 'live' }
|
||||||
})
|
})
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
expect(wrapper.vm.context.validationErrors.length).toBe(1);
|
expect(wrapper.vm.context.violations.length).toBe(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can show multiple validation errors if they occur before the bail rule', async () => {
|
it('can show multiple validation errors if they occur before the bail rule', async () => {
|
||||||
@ -203,7 +206,7 @@ describe('FormularioInput', () => {
|
|||||||
propsData: { name: 'test', validation: 'required|in:xyz|bail', errorBehavior: 'live' }
|
propsData: { name: 'test', validation: 'required|in:xyz|bail', errorBehavior: 'live' }
|
||||||
})
|
})
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
expect(wrapper.vm.context.validationErrors.length).toBe(2);
|
expect(wrapper.vm.context.violations.length).toBe(2);
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can avoid bail behavior by using modifier', async () => {
|
it('can avoid bail behavior by using modifier', async () => {
|
||||||
@ -211,7 +214,7 @@ describe('FormularioInput', () => {
|
|||||||
propsData: { name: 'test', validation: '^required|in:xyz|min:10,length', errorBehavior: 'live', value: '123' }
|
propsData: { name: 'test', validation: '^required|in:xyz|min:10,length', errorBehavior: 'live', value: '123' }
|
||||||
})
|
})
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
expect(wrapper.vm.context.validationErrors.length).toBe(2);
|
expect(wrapper.vm.context.violations.length).toBe(2);
|
||||||
})
|
})
|
||||||
|
|
||||||
it('prevents later error messages when modified rule fails', async () => {
|
it('prevents later error messages when modified rule fails', async () => {
|
||||||
@ -219,7 +222,7 @@ describe('FormularioInput', () => {
|
|||||||
propsData: { name: 'test', validation: '^required|in:xyz|min:10,length', errorBehavior: 'live' }
|
propsData: { name: 'test', validation: '^required|in:xyz|min:10,length', errorBehavior: 'live' }
|
||||||
})
|
})
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
expect(wrapper.vm.context.validationErrors.length).toBe(1);
|
expect(wrapper.vm.context.violations.length).toBe(1);
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can bail in the middle of the rule set with a modifier', async () => {
|
it('can bail in the middle of the rule set with a modifier', async () => {
|
||||||
@ -227,7 +230,7 @@ describe('FormularioInput', () => {
|
|||||||
propsData: { name: 'test', validation: 'required|^in:xyz|min:10,length', errorBehavior: 'live' }
|
propsData: { name: 'test', validation: 'required|^in:xyz|min:10,length', errorBehavior: 'live' }
|
||||||
})
|
})
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
expect(wrapper.vm.context.validationErrors.length).toBe(2);
|
expect(wrapper.vm.context.violations.length).toBe(2);
|
||||||
})
|
})
|
||||||
|
|
||||||
it('does not show errors on blur when set error-behavior is submit', async () => {
|
it('does not show errors on blur when set error-behavior is submit', async () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user