vnode.spec.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import { createVNode } from '@vue/runtime-test'
  2. import { ShapeFlags } from '@vue/runtime-core'
  3. import { mergeProps } from '../src/vnode'
  4. import { Data } from '../src/component'
  5. describe('vnode', () => {
  6. test('create with just tag', () => {
  7. const vnode = createVNode('p')
  8. expect(vnode.type).toBe('p')
  9. expect(vnode.props).toBe(null)
  10. })
  11. test('create with tag and props', () => {
  12. const vnode = createVNode('p', {})
  13. expect(vnode.type).toBe('p')
  14. expect(vnode.props).toMatchObject({})
  15. })
  16. test('create with tag, props and children', () => {
  17. const vnode = createVNode('p', {}, ['foo'])
  18. expect(vnode.type).toBe('p')
  19. expect(vnode.props).toMatchObject({})
  20. expect(vnode.children).toMatchObject(['foo'])
  21. })
  22. test('create with 0 as props', () => {
  23. const vnode = createVNode('p', null)
  24. expect(vnode.type).toBe('p')
  25. expect(vnode.props).toBe(null)
  26. })
  27. describe('class normalization', () => {
  28. test('string', () => {
  29. const vnode = createVNode('p', { class: 'foo baz' })
  30. expect(vnode.props).toMatchObject({ class: 'foo baz' })
  31. })
  32. test('array<string>', () => {
  33. const vnode = createVNode('p', { class: ['foo', 'baz'] })
  34. expect(vnode.props).toMatchObject({ class: 'foo baz' })
  35. })
  36. test('array<object>', () => {
  37. const vnode = createVNode('p', {
  38. class: [{ foo: 'foo' }, { baz: 'baz' }]
  39. })
  40. expect(vnode.props).toMatchObject({ class: 'foo baz' })
  41. })
  42. test('object', () => {
  43. const vnode = createVNode('p', { class: { foo: 'foo', baz: 'baz' } })
  44. expect(vnode.props).toMatchObject({ class: 'foo baz' })
  45. })
  46. })
  47. describe('style normalization', () => {
  48. test('array', () => {
  49. const vnode = createVNode('p', {
  50. style: [{ foo: 'foo' }, { baz: 'baz' }]
  51. })
  52. expect(vnode.props).toMatchObject({ style: { foo: 'foo', baz: 'baz' } })
  53. })
  54. test('object', () => {
  55. const vnode = createVNode('p', { style: { foo: 'foo', baz: 'baz' } })
  56. expect(vnode.props).toMatchObject({ style: { foo: 'foo', baz: 'baz' } })
  57. })
  58. })
  59. describe('children normalization', () => {
  60. const nop = jest.fn
  61. test('null', () => {
  62. const vnode = createVNode('p', null, null)
  63. expect(vnode.children).toBe(null)
  64. expect(vnode.shapeFlag).toBe(ShapeFlags.ELEMENT)
  65. })
  66. test('array', () => {
  67. const vnode = createVNode('p', null, ['foo'])
  68. expect(vnode.children).toMatchObject(['foo'])
  69. expect(vnode.shapeFlag).toBe(
  70. ShapeFlags.ELEMENT + ShapeFlags.ARRAY_CHILDREN
  71. )
  72. })
  73. test('object', () => {
  74. const vnode = createVNode('p', null, { foo: 'foo' })
  75. expect(vnode.children).toMatchObject({ foo: 'foo' })
  76. expect(vnode.shapeFlag).toBe(
  77. ShapeFlags.ELEMENT + ShapeFlags.SLOTS_CHILDREN
  78. )
  79. })
  80. test('function', () => {
  81. const vnode = createVNode('p', null, nop)
  82. expect(vnode.children).toMatchObject({ default: nop })
  83. expect(vnode.shapeFlag).toBe(
  84. ShapeFlags.ELEMENT + ShapeFlags.SLOTS_CHILDREN
  85. )
  86. })
  87. test('string', () => {
  88. const vnode = createVNode('p', null, 'foo')
  89. expect(vnode.children).toBe('foo')
  90. expect(vnode.shapeFlag).toBe(
  91. ShapeFlags.ELEMENT + ShapeFlags.TEXT_CHILDREN
  92. )
  93. })
  94. })
  95. test.todo('normalizeVNode')
  96. test.todo('node type/shapeFlag inference')
  97. test.todo('cloneVNode')
  98. describe('mergeProps', () => {
  99. test('class', () => {
  100. let props1: Data = { class: 'c' }
  101. let props2: Data = { class: ['cc'] }
  102. let props3: Data = { class: [{ ccc: true }] }
  103. let props4: Data = { class: { cccc: true } }
  104. expect(mergeProps(props1, props2, props3, props4)).toMatchObject({
  105. class: 'c cc ccc cccc'
  106. })
  107. })
  108. test('style', () => {
  109. let props1: Data = {
  110. style: {
  111. color: 'red',
  112. fontSize: 10
  113. }
  114. }
  115. let props2: Data = {
  116. style: [
  117. {
  118. color: 'blue',
  119. with: '200px'
  120. },
  121. {
  122. with: '300px',
  123. height: '300px',
  124. fontSize: 30
  125. }
  126. ]
  127. }
  128. expect(mergeProps(props1, props2)).toMatchObject({
  129. style: {
  130. color: 'blue',
  131. with: '300px',
  132. height: '300px',
  133. fontSize: 30
  134. }
  135. })
  136. })
  137. test('handlers', () => {
  138. let clickHander1 = function() {}
  139. let clickHander2 = function() {}
  140. let focusHander2 = function() {}
  141. let props1: Data = { onClick: clickHander1 }
  142. let props2: Data = { onClick: clickHander2, onFocus: focusHander2 }
  143. expect(mergeProps(props1, props2)).toMatchObject({
  144. onClick: [clickHander1, clickHander2],
  145. onFocus: focusHander2
  146. })
  147. })
  148. test('default', () => {
  149. let props1: Data = { foo: 'c' }
  150. let props2: Data = { foo: {}, bar: ['cc'] }
  151. let props3: Data = { baz: { ccc: true } }
  152. expect(mergeProps(props1, props2, props3)).toMatchObject({
  153. foo: {},
  154. bar: ['cc'],
  155. baz: { ccc: true }
  156. })
  157. })
  158. })
  159. })