componentVModel.spec.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import Vue from '@vue/compat'
  2. import type { ComponentOptions } from '../../runtime-core/src/component'
  3. import { nextTick } from '../../runtime-core/src/scheduler'
  4. import {
  5. DeprecationTypes,
  6. deprecationData,
  7. toggleDeprecationWarning,
  8. } from '../../runtime-core/src/compat/compatConfig'
  9. import { triggerEvent } from './utils'
  10. beforeEach(() => {
  11. toggleDeprecationWarning(true)
  12. Vue.configureCompat({
  13. MODE: 2,
  14. GLOBAL_MOUNT: 'suppress-warning',
  15. })
  16. })
  17. afterEach(() => {
  18. toggleDeprecationWarning(false)
  19. Vue.configureCompat({ MODE: 3 })
  20. })
  21. describe('COMPONENT_V_MODEL', () => {
  22. async function runTest(CustomInput: ComponentOptions) {
  23. const vm = new Vue({
  24. data() {
  25. return {
  26. text: 'foo',
  27. }
  28. },
  29. components: { CustomInput },
  30. template: `
  31. <div>
  32. <span>{{ text }}</span>
  33. <custom-input v-model="text"></custom-input>
  34. </div>
  35. `,
  36. }).$mount() as any
  37. const input = vm.$el.querySelector('input')
  38. const span = vm.$el.querySelector('span')
  39. expect(input.value).toBe('foo')
  40. expect(span.textContent).toBe('foo')
  41. expect(
  42. (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(
  43. CustomInput,
  44. ),
  45. ).toHaveBeenWarned()
  46. input.value = 'bar'
  47. triggerEvent(input, 'input')
  48. await nextTick()
  49. expect(input.value).toBe('bar')
  50. expect(span.textContent).toBe('bar')
  51. vm.text = 'baz'
  52. await nextTick()
  53. expect(input.value).toBe('baz')
  54. expect(span.textContent).toBe('baz')
  55. }
  56. test('basic usage', async () => {
  57. await runTest({
  58. name: 'CustomInput',
  59. props: ['value'],
  60. template: `<input :value="value" @input="$emit('input', $event.target.value)">`,
  61. })
  62. })
  63. test('with model option', async () => {
  64. await runTest({
  65. name: 'CustomInput',
  66. props: ['input'],
  67. model: {
  68. prop: 'input',
  69. event: 'update',
  70. },
  71. template: `<input :value="input" @input="$emit('update', $event.target.value)">`,
  72. })
  73. })
  74. async function runTestWithModifier(CustomInput: ComponentOptions) {
  75. const vm = new Vue({
  76. data() {
  77. return {
  78. text: ' foo ',
  79. }
  80. },
  81. components: {
  82. CustomInput,
  83. },
  84. template: `
  85. <div>
  86. <span>{{ text }}</span>
  87. <custom-input v-model.trim="text"></custom-input>
  88. </div>
  89. `,
  90. }).$mount() as any
  91. const input = vm.$el.querySelector('input')
  92. const span = vm.$el.querySelector('span')
  93. expect(input.value).toBe(' foo ')
  94. expect(span.textContent).toBe(' foo ')
  95. expect(
  96. (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(
  97. CustomInput,
  98. ),
  99. ).toHaveBeenWarned()
  100. input.value = ' bar '
  101. triggerEvent(input, 'input')
  102. await nextTick()
  103. expect(input.value).toBe('bar')
  104. expect(span.textContent).toBe('bar')
  105. }
  106. test('with model modifiers', async () => {
  107. await runTestWithModifier({
  108. name: 'CustomInput',
  109. props: ['value'],
  110. template: `<input :value="value" @input="$emit('input', $event.target.value)">`,
  111. })
  112. })
  113. test('with model modifiers and model option', async () => {
  114. await runTestWithModifier({
  115. name: 'CustomInput',
  116. props: ['foo'],
  117. model: {
  118. prop: 'foo',
  119. event: 'bar',
  120. },
  121. template: `<input :value="foo" @input="$emit('bar', $event.target.value)">`,
  122. })
  123. })
  124. })