mirror of https://github.com/vuejs/core.git
test(compiler-vapor): v-model (#132)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
parent
ebc157c84c
commit
ba29b4c89a
|
@ -0,0 +1,236 @@
|
||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > modifiers > .lazy 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model, void 0, { lazy: true }]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > modifiers > .number 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model, void 0, { number: true }]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > modifiers > .trim 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model, void 0, { trim: true }]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support input (checkbox) 1`] = `
|
||||||
|
"import { children as _children, vModelCheckbox as _vModelCheckbox, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input type=\\"checkbox\\">")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelCheckbox, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support input (dynamic type) 1`] = `
|
||||||
|
"import { children as _children, vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelDynamic, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support input (radio) 1`] = `
|
||||||
|
"import { children as _children, vModelRadio as _vModelRadio, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input type=\\"radio\\">")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelRadio, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support input (text) 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input type=\\"text\\">")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support select 1`] = `
|
||||||
|
"import { children as _children, vModelSelect as _vModelSelect, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<select></select>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelSelect, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support simple expression 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support textarea 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<textarea></textarea>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support w/ dynamic v-bind 1`] = `
|
||||||
|
"import { children as _children, vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelDynamic, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
_renderEffect(() => _setDynamicProps(n1, _ctx.obj))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should support w/ dynamic v-bind 2`] = `
|
||||||
|
"import { children as _children, vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelDynamic, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should work with input (checkbox) 1`] = `
|
||||||
|
"import { children as _children, vModelCheckbox as _vModelCheckbox, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input type=\\"checkbox\\">")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelCheckbox, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should work with input (dynamic type) 1`] = `
|
||||||
|
"import { children as _children, vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelDynamic, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should work with input (radio) 1`] = `
|
||||||
|
"import { children as _children, vModelRadio as _vModelRadio, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input type=\\"radio\\">")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelRadio, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should work with input (text) 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input type=\\"text\\">")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should work with select 1`] = `
|
||||||
|
"import { children as _children, vModelSelect as _vModelSelect, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<select></select>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelSelect, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: vModel transform > should work with simple expression 1`] = `
|
||||||
|
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
|
||||||
|
const t0 = _template("<input>")
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n0 = t0()
|
||||||
|
const n1 = _children(n0, 0)
|
||||||
|
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
|
||||||
|
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
|
||||||
|
return n0
|
||||||
|
}"
|
||||||
|
`;
|
|
@ -1,4 +1,174 @@
|
||||||
// TODO: add tests for this transform
|
import { makeCompile } from './_utils'
|
||||||
describe('compiler: vModel transform', () => {
|
import { transformElement, transformVModel } from '../../src'
|
||||||
test.todo('basic')
|
import { DOMErrorCodes } from '@vue/compiler-dom'
|
||||||
|
|
||||||
|
const compileWithVModel = makeCompile({
|
||||||
|
nodeTransforms: [transformElement],
|
||||||
|
directiveTransforms: {
|
||||||
|
model: transformVModel,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('compiler: vModel transform', () => {
|
||||||
|
test('should support simple expression', () => {
|
||||||
|
const { code, vaporHelpers } = compileWithVModel(
|
||||||
|
'<input v-model="model" />',
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(vaporHelpers).toContain('vModelText')
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should support input (text)', () => {
|
||||||
|
const { code, vaporHelpers } = compileWithVModel(
|
||||||
|
'<input type="text" v-model="model" />',
|
||||||
|
)
|
||||||
|
expect(vaporHelpers).toContain('vModelText')
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should support input (radio)', () => {
|
||||||
|
const { code, vaporHelpers } = compileWithVModel(
|
||||||
|
'<input type="radio" v-model="model" />',
|
||||||
|
)
|
||||||
|
expect(vaporHelpers).toContain('vModelRadio')
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should support input (checkbox)', () => {
|
||||||
|
const { code, vaporHelpers } = compileWithVModel(
|
||||||
|
'<input type="checkbox" v-model="model" />',
|
||||||
|
)
|
||||||
|
expect(vaporHelpers).toContain('vModelCheckbox')
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should support select', () => {
|
||||||
|
const { code, vaporHelpers } = compileWithVModel(
|
||||||
|
'<select v-model="model" />',
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(vaporHelpers).toContain('vModelSelect')
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should support textarea', () => {
|
||||||
|
const { code, vaporHelpers } = compileWithVModel(
|
||||||
|
'<textarea v-model="model" />',
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(vaporHelpers).toContain('vModelText')
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should support input (dynamic type)', () => {
|
||||||
|
const { code, vaporHelpers } = compileWithVModel(
|
||||||
|
'<input :type="foo" v-model="model" />',
|
||||||
|
)
|
||||||
|
expect(vaporHelpers).toContain('vModelDynamic')
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should support w/ dynamic v-bind', () => {
|
||||||
|
const root1 = compileWithVModel('<input v-bind="obj" v-model="model" />')
|
||||||
|
expect(root1.vaporHelpers).toContain('vModelDynamic')
|
||||||
|
expect(root1.code).toMatchSnapshot()
|
||||||
|
|
||||||
|
const root2 = compileWithVModel(
|
||||||
|
'<input v-bind:[key]="val" v-model="model" />',
|
||||||
|
)
|
||||||
|
expect(root2.vaporHelpers).toContain('vModelDynamic')
|
||||||
|
expect(root2.code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('errors', () => {
|
||||||
|
test('invalid element', () => {
|
||||||
|
const onError = vi.fn()
|
||||||
|
compileWithVModel('<span v-model="model" />', { onError })
|
||||||
|
|
||||||
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
|
expect(onError).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
code: DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: component
|
||||||
|
test.fails('plain elements with argument', () => {
|
||||||
|
const onError = vi.fn()
|
||||||
|
compileWithVModel('<input v-model:value="model" />', { onError })
|
||||||
|
|
||||||
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
|
expect(onError).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
code: DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: component
|
||||||
|
test.fails('should allow usage on custom element', () => {
|
||||||
|
const onError = vi.fn()
|
||||||
|
const root = compileWithVModel('<my-input v-model="model" />', {
|
||||||
|
onError,
|
||||||
|
isCustomElement: tag => tag.startsWith('my-'),
|
||||||
|
})
|
||||||
|
expect(root.helpers).toContain('vModelText')
|
||||||
|
expect(onError).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should raise error if used file input element', () => {
|
||||||
|
const onError = vi.fn()
|
||||||
|
compileWithVModel(`<input type="file" v-model="test"/>`, {
|
||||||
|
onError,
|
||||||
|
})
|
||||||
|
expect(onError).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
code: DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should error on dynamic value binding alongside v-model', () => {
|
||||||
|
const onError = vi.fn()
|
||||||
|
compileWithVModel(`<input v-model="test" :value="test" />`, {
|
||||||
|
onError,
|
||||||
|
})
|
||||||
|
expect(onError).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
code: DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// #3596
|
||||||
|
test('should NOT error on static value binding alongside v-model', () => {
|
||||||
|
const onError = vi.fn()
|
||||||
|
compileWithVModel(`<input v-model="test" value="test" />`, {
|
||||||
|
onError,
|
||||||
|
})
|
||||||
|
expect(onError).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('modifiers', () => {
|
||||||
|
test('.number', () => {
|
||||||
|
const { code } = compileWithVModel('<input v-model.number="model" />')
|
||||||
|
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('.trim', () => {
|
||||||
|
const { code } = compileWithVModel('<input v-model.trim="model" />')
|
||||||
|
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('.lazy', () => {
|
||||||
|
const { code } = compileWithVModel('<input v-model.lazy="model" />')
|
||||||
|
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,3 +19,4 @@ export { transformVShow } from './transforms/vShow'
|
||||||
export { transformVText } from './transforms/vText'
|
export { transformVText } from './transforms/vText'
|
||||||
export { transformVIf } from './transforms/vIf'
|
export { transformVIf } from './transforms/vIf'
|
||||||
export { transformVFor } from './transforms/vFor'
|
export { transformVFor } from './transforms/vFor'
|
||||||
|
export { transformVModel } from './transforms/vModel'
|
||||||
|
|
Loading…
Reference in New Issue