misc.spec.ts 5.4 KB

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