misc.spec.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import { vi } from 'vitest'
  2. import Vue from '@vue/compat'
  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. import { h } from '@vue/runtime-core'
  11. beforeEach(() => {
  12. toggleDeprecationWarning(true)
  13. Vue.configureCompat({
  14. MODE: 2,
  15. GLOBAL_MOUNT: 'suppress-warning'
  16. })
  17. })
  18. afterEach(() => {
  19. toggleDeprecationWarning(false)
  20. Vue.configureCompat({ MODE: 3 })
  21. })
  22. test('mode as function', () => {
  23. const Foo = {
  24. name: 'Foo',
  25. render: (h: any) => h('div', 'foo')
  26. }
  27. const Bar = {
  28. name: 'Bar',
  29. data: () => ({ msg: 'bar' }),
  30. render: (ctx: any) => h('div', ctx.msg)
  31. }
  32. toggleDeprecationWarning(false)
  33. Vue.configureCompat({
  34. MODE: comp => (comp && comp.name === 'Bar' ? 3 : 2)
  35. })
  36. const vm = new Vue({
  37. components: { Foo, Bar },
  38. template: `<div><foo/><bar/></div>`
  39. }).$mount()
  40. expect(vm.$el).toBeInstanceOf(HTMLDivElement)
  41. expect(vm.$el.innerHTML).toBe(`<div>foo</div><div>bar</div>`)
  42. })
  43. test('WATCH_ARRAY', async () => {
  44. const spy = vi.fn()
  45. const vm = new Vue({
  46. data() {
  47. return {
  48. foo: []
  49. }
  50. },
  51. watch: {
  52. foo: spy
  53. }
  54. }) as any
  55. expect(
  56. deprecationData[DeprecationTypes.WATCH_ARRAY].message
  57. ).toHaveBeenWarned()
  58. expect(spy).not.toHaveBeenCalled()
  59. vm.foo.push(1)
  60. await nextTick()
  61. expect(spy).toHaveBeenCalledTimes(1)
  62. })
  63. test('PROPS_DEFAULT_THIS', () => {
  64. let thisCtx: any
  65. const Child = {
  66. customOption: 1,
  67. inject: ['provided'],
  68. props: {
  69. foo: null,
  70. bar: {
  71. default(this: any) {
  72. // copy values since injection must be sync
  73. thisCtx = {
  74. foo: this.foo,
  75. $options: this.$options,
  76. provided: this.provided
  77. }
  78. return this.foo + 1
  79. }
  80. }
  81. },
  82. template: `{{ bar }}`
  83. }
  84. const vm = new Vue({
  85. components: { Child },
  86. provide: {
  87. provided: 2
  88. },
  89. template: `<child :foo="0" />`
  90. }).$mount()
  91. expect(vm.$el.textContent).toBe('1')
  92. // other props
  93. expect(thisCtx.foo).toBe(0)
  94. // $options
  95. expect(thisCtx.$options.customOption).toBe(1)
  96. // injections
  97. expect(thisCtx.provided).toBe(2)
  98. expect(
  99. (deprecationData[DeprecationTypes.PROPS_DEFAULT_THIS].message as Function)(
  100. 'bar'
  101. )
  102. ).toHaveBeenWarned()
  103. })
  104. test('V_ON_KEYCODE_MODIFIER', () => {
  105. const spy = vi.fn()
  106. const vm = new Vue({
  107. template: `<input @keyup.1="spy">`,
  108. methods: { spy }
  109. }).$mount()
  110. expect(vm.$el).toBeInstanceOf(HTMLInputElement)
  111. triggerEvent(vm.$el, 'keyup', e => {
  112. e.key = '_'
  113. e.keyCode = 1
  114. })
  115. expect(spy).toHaveBeenCalled()
  116. expect(
  117. deprecationData[DeprecationTypes.V_ON_KEYCODE_MODIFIER].message
  118. ).toHaveBeenWarned()
  119. })
  120. test('CUSTOM_DIR', async () => {
  121. const myDir = {
  122. bind: vi.fn(),
  123. inserted: vi.fn(),
  124. update: vi.fn(),
  125. componentUpdated: vi.fn(),
  126. unbind: vi.fn()
  127. } as any
  128. const getCalls = () =>
  129. Object.keys(myDir).map(key => myDir[key].mock.calls.length)
  130. const vm = new Vue({
  131. data() {
  132. return {
  133. ok: true,
  134. foo: 1
  135. }
  136. },
  137. template: `<div v-if="ok" v-my-dir="foo"/>`,
  138. directives: {
  139. myDir
  140. }
  141. }).$mount() as any
  142. expect(getCalls()).toMatchObject([1, 1, 0, 0, 0])
  143. expect(
  144. (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(
  145. 'bind',
  146. 'beforeMount'
  147. )
  148. ).toHaveBeenWarned()
  149. expect(
  150. (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(
  151. 'inserted',
  152. 'mounted'
  153. )
  154. ).toHaveBeenWarned()
  155. vm.foo++
  156. await nextTick()
  157. expect(getCalls()).toMatchObject([1, 1, 1, 1, 0])
  158. expect(
  159. (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(
  160. 'update',
  161. 'updated'
  162. )
  163. ).toHaveBeenWarned()
  164. expect(
  165. (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(
  166. 'componentUpdated',
  167. 'updated'
  168. )
  169. ).toHaveBeenWarned()
  170. })
  171. test('ATTR_FALSE_VALUE', () => {
  172. const vm = new Vue({
  173. template: `<div :id="false" :foo="false"/>`
  174. }).$mount()
  175. expect(vm.$el).toBeInstanceOf(HTMLDivElement)
  176. expect(vm.$el.hasAttribute('id')).toBe(false)
  177. expect(vm.$el.hasAttribute('foo')).toBe(false)
  178. expect(
  179. (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(
  180. 'id'
  181. )
  182. ).toHaveBeenWarned()
  183. expect(
  184. (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(
  185. 'foo'
  186. )
  187. ).toHaveBeenWarned()
  188. })
  189. test('ATTR_ENUMERATED_COERCION', () => {
  190. const vm = new Vue({
  191. template: `<div :draggable="null" :spellcheck="0" contenteditable="foo" />`
  192. }).$mount()
  193. expect(vm.$el).toBeInstanceOf(HTMLDivElement)
  194. expect(vm.$el.getAttribute('draggable')).toBe('false')
  195. expect(vm.$el.getAttribute('spellcheck')).toBe('true')
  196. expect(vm.$el.getAttribute('contenteditable')).toBe('true')
  197. expect(
  198. (
  199. deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]
  200. .message as Function
  201. )('draggable', null, 'false')
  202. ).toHaveBeenWarned()
  203. expect(
  204. (
  205. deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]
  206. .message as Function
  207. )('spellcheck', 0, 'true')
  208. ).toHaveBeenWarned()
  209. expect(
  210. (
  211. deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]
  212. .message as Function
  213. )('contenteditable', 'foo', 'true')
  214. ).toHaveBeenWarned()
  215. })