component.spec.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import {
  2. h,
  3. ref,
  4. render,
  5. nodeOps,
  6. nextTick,
  7. defineComponent
  8. } from '@vue/runtime-test'
  9. import { mockWarn } from '@vue/shared'
  10. describe('renderer: component', () => {
  11. mockWarn()
  12. test.todo('should work')
  13. test.todo('shouldUpdateComponent')
  14. test.todo('componentProxy')
  15. describe('componentProps', () => {
  16. test.todo('should work')
  17. test('should convert empty booleans to true', () => {
  18. let b1: any, b2: any, b3: any
  19. const Comp = defineComponent({
  20. props: {
  21. b1: Boolean,
  22. b2: [Boolean, String],
  23. b3: [String, Boolean]
  24. },
  25. setup(props) {
  26. ;({ b1, b2, b3 } = props)
  27. return () => ''
  28. }
  29. })
  30. render(
  31. h(Comp, <any>{ b1: '', b2: '', b3: '' }),
  32. nodeOps.createElement('div')
  33. )
  34. expect(b1).toBe(true)
  35. expect(b2).toBe(true)
  36. expect(b3).toBe('')
  37. expect('type check failed for prop "b1"').toHaveBeenWarned()
  38. })
  39. })
  40. describe('slots', () => {
  41. test('should respect $stable flag', async () => {
  42. const flag1 = ref(1)
  43. const flag2 = ref(2)
  44. const spy = jest.fn()
  45. const Child = () => {
  46. spy()
  47. return 'child'
  48. }
  49. const App = {
  50. setup() {
  51. return () => [
  52. flag1.value,
  53. h(
  54. Child,
  55. { n: flag2.value },
  56. {
  57. foo: () => 'foo',
  58. $stable: true
  59. }
  60. )
  61. ]
  62. }
  63. }
  64. render(h(App), nodeOps.createElement('div'))
  65. expect(spy).toHaveBeenCalledTimes(1)
  66. // parent re-render, props didn't change, slots are stable
  67. // -> child should not update
  68. flag1.value++
  69. await nextTick()
  70. expect(spy).toHaveBeenCalledTimes(1)
  71. // parent re-render, props changed
  72. // -> child should update
  73. flag2.value++
  74. await nextTick()
  75. expect(spy).toHaveBeenCalledTimes(2)
  76. })
  77. })
  78. test('emit', async () => {
  79. let noMatchEmitResult: any
  80. let singleEmitResult: any
  81. let multiEmitResult: any
  82. const Child = defineComponent({
  83. setup(_, { emit }) {
  84. noMatchEmitResult = emit('foo')
  85. singleEmitResult = emit('bar')
  86. multiEmitResult = emit('baz')
  87. return () => h('div')
  88. }
  89. })
  90. const App = {
  91. setup() {
  92. return () =>
  93. h(Child, {
  94. // emit triggering single handler
  95. onBar: () => 1,
  96. // emit triggering multiple handlers
  97. onBaz: [() => Promise.resolve(2), () => Promise.resolve(3)]
  98. })
  99. }
  100. }
  101. render(h(App), nodeOps.createElement('div'))
  102. // assert return values from emit
  103. expect(noMatchEmitResult).toMatchObject([])
  104. expect(singleEmitResult).toMatchObject([1])
  105. expect(await Promise.all(multiEmitResult)).toMatchObject([2, 3])
  106. })
  107. // for v-model:foo-bar usage in DOM templates
  108. test('emit update:xxx events should trigger kebab-case equivalent', () => {
  109. const Child = defineComponent({
  110. setup(_, { emit }) {
  111. emit('update:fooBar', 1)
  112. return () => h('div')
  113. }
  114. })
  115. const handler = jest.fn()
  116. const App = {
  117. setup() {
  118. return () =>
  119. h(Child, {
  120. 'onUpdate:foo-bar': handler
  121. })
  122. }
  123. }
  124. render(h(App), nodeOps.createElement('div'))
  125. expect(handler).toHaveBeenCalled()
  126. })
  127. })