componentEmits.spec.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Note: emits and listener fallthrough is tested in
  2. // ./rendererAttrsFallthrough.spec.ts.
  3. import { mockWarn } from '@vue/shared'
  4. import { render, defineComponent, h, nodeOps } from '@vue/runtime-test'
  5. import { isEmitListener } from '../src/componentEmits'
  6. describe('component: emit', () => {
  7. mockWarn()
  8. test('trigger handlers', () => {
  9. const Foo = defineComponent({
  10. render() {},
  11. created() {
  12. // the `emit` function is bound on component instances
  13. this.$emit('foo')
  14. this.$emit('bar')
  15. this.$emit('!baz')
  16. }
  17. })
  18. const onfoo = jest.fn()
  19. const onBar = jest.fn()
  20. const onBaz = jest.fn()
  21. const Comp = () => h(Foo, { onfoo, onBar, ['on!baz']: onBaz })
  22. render(h(Comp), nodeOps.createElement('div'))
  23. expect(onfoo).not.toHaveBeenCalled()
  24. // only capitalized or special chars are considerd event listeners
  25. expect(onBar).toHaveBeenCalled()
  26. expect(onBaz).toHaveBeenCalled()
  27. })
  28. // for v-model:foo-bar usage in DOM templates
  29. test('trigger hyphendated events for update:xxx events', () => {
  30. const Foo = defineComponent({
  31. render() {},
  32. created() {
  33. this.$emit('update:fooProp')
  34. this.$emit('update:barProp')
  35. }
  36. })
  37. const fooSpy = jest.fn()
  38. const barSpy = jest.fn()
  39. const Comp = () =>
  40. h(Foo, {
  41. 'onUpdate:fooProp': fooSpy,
  42. 'onUpdate:bar-prop': barSpy
  43. })
  44. render(h(Comp), nodeOps.createElement('div'))
  45. expect(fooSpy).toHaveBeenCalled()
  46. expect(barSpy).toHaveBeenCalled()
  47. })
  48. test('should trigger array of listeners', async () => {
  49. const Child = defineComponent({
  50. setup(_, { emit }) {
  51. emit('foo', 1)
  52. return () => h('div')
  53. }
  54. })
  55. const fn1 = jest.fn()
  56. const fn2 = jest.fn()
  57. const App = {
  58. setup() {
  59. return () =>
  60. h(Child, {
  61. onFoo: [fn1, fn2]
  62. })
  63. }
  64. }
  65. render(h(App), nodeOps.createElement('div'))
  66. expect(fn1).toHaveBeenCalledTimes(1)
  67. expect(fn1).toHaveBeenCalledWith(1)
  68. expect(fn2).toHaveBeenCalledTimes(1)
  69. expect(fn1).toHaveBeenCalledWith(1)
  70. })
  71. test('warning for undeclared event (array)', () => {
  72. const Foo = defineComponent({
  73. emits: ['foo'],
  74. render() {},
  75. created() {
  76. // @ts-ignore
  77. this.$emit('bar')
  78. }
  79. })
  80. render(h(Foo), nodeOps.createElement('div'))
  81. expect(
  82. `Component emitted event "bar" but it is neither declared`
  83. ).toHaveBeenWarned()
  84. })
  85. test('warning for undeclared event (object)', () => {
  86. const Foo = defineComponent({
  87. emits: {
  88. foo: null
  89. },
  90. render() {},
  91. created() {
  92. // @ts-ignore
  93. this.$emit('bar')
  94. }
  95. })
  96. render(h(Foo), nodeOps.createElement('div'))
  97. expect(
  98. `Component emitted event "bar" but it is neither declared`
  99. ).toHaveBeenWarned()
  100. })
  101. test('should not warn if has equivalent onXXX prop', () => {
  102. const Foo = defineComponent({
  103. props: ['onFoo'],
  104. emits: [],
  105. render() {},
  106. created() {
  107. // @ts-ignore
  108. this.$emit('foo')
  109. }
  110. })
  111. render(h(Foo), nodeOps.createElement('div'))
  112. expect(
  113. `Component emitted event "bar" but it is neither declared`
  114. ).not.toHaveBeenWarned()
  115. })
  116. test('validator warning', () => {
  117. const Foo = defineComponent({
  118. emits: {
  119. foo: (arg: number) => arg > 0
  120. },
  121. render() {},
  122. created() {
  123. this.$emit('foo', -1)
  124. }
  125. })
  126. render(h(Foo), nodeOps.createElement('div'))
  127. expect(`event validation failed for event "foo"`).toHaveBeenWarned()
  128. })
  129. test('isEmitListener', () => {
  130. expect(isEmitListener(['click'], 'onClick')).toBe(true)
  131. expect(isEmitListener(['click'], 'onclick')).toBe(false)
  132. expect(isEmitListener({ click: null }, 'onClick')).toBe(true)
  133. expect(isEmitListener({ click: null }, 'onclick')).toBe(false)
  134. expect(isEmitListener(['click'], 'onBlick')).toBe(false)
  135. expect(isEmitListener({ click: null }, 'onBlick')).toBe(false)
  136. })
  137. })