component.spec.ts 3.2 KB

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