nodeOps.spec.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { defineComponent, h, nextTick, ref } from 'vue'
  2. import { mathmlNS, nodeOps, svgNS } from '../src/nodeOps'
  3. import { render } from '@vue/runtime-dom'
  4. describe('runtime-dom: node-ops', () => {
  5. test("the <select>'s multiple attr should be set in createElement", () => {
  6. const el = nodeOps.createElement('select', undefined, undefined, {
  7. multiple: '',
  8. }) as HTMLSelectElement
  9. const option1 = nodeOps.createElement('option') as HTMLOptionElement
  10. const option2 = nodeOps.createElement('option') as HTMLOptionElement
  11. option1.selected = true
  12. option2.selected = true
  13. nodeOps.insert(option1, el)
  14. nodeOps.insert(option2, el)
  15. expect(el.multiple).toBe(true)
  16. expect(option1.selected).toBe(true)
  17. expect(option2.selected).toBe(true)
  18. })
  19. test('create custom elements', () => {
  20. const spyCreateElement = vi.spyOn(document, 'createElement')
  21. nodeOps.createElement('custom-element')
  22. expect(spyCreateElement).toHaveBeenLastCalledWith('custom-element')
  23. nodeOps.createElement('custom-element', undefined, 'li')
  24. expect(spyCreateElement).toHaveBeenLastCalledWith('custom-element', {
  25. is: 'li',
  26. })
  27. spyCreateElement.mockClear()
  28. })
  29. describe('insertStaticContent', () => {
  30. test('fresh insertion', () => {
  31. const content = `<div>one</div><div>two</div>three`
  32. const parent = document.createElement('div')
  33. const nodes = nodeOps.insertStaticContent!(
  34. content,
  35. parent,
  36. null,
  37. undefined,
  38. )
  39. expect(parent.innerHTML).toBe(content)
  40. expect(nodes[0]).toBe(parent.firstChild)
  41. expect(nodes[1]).toBe(parent.lastChild)
  42. })
  43. test('fresh insertion with anchor', () => {
  44. const content = `<div>one</div><div>two</div>three`
  45. const existing = `<div>existing</div>`
  46. const parent = document.createElement('div')
  47. parent.innerHTML = existing
  48. const anchor = parent.firstChild
  49. const nodes = nodeOps.insertStaticContent!(
  50. content,
  51. parent,
  52. anchor,
  53. undefined,
  54. )
  55. expect(parent.innerHTML).toBe(content + existing)
  56. expect(nodes[0]).toBe(parent.firstChild)
  57. expect(nodes[1]).toBe(parent.childNodes[parent.childNodes.length - 2])
  58. })
  59. test('fresh insertion as svg', () => {
  60. const content = `<text>hello</text><circle cx="100" cy="100" r="80"></circle>`
  61. const parent = document.createElementNS(svgNS, 'svg')
  62. const [first, last] = nodeOps.insertStaticContent!(
  63. content,
  64. parent,
  65. null,
  66. 'svg',
  67. )
  68. expect(parent.innerHTML).toBe(content)
  69. expect(first).toBe(parent.firstChild)
  70. expect(last).toBe(parent.lastChild)
  71. expect((first as Element).namespaceURI).toMatch('svg')
  72. expect((last as Element).namespaceURI).toMatch('svg')
  73. })
  74. test('fresh insertion as svg, with anchor', () => {
  75. const content = `<text>hello</text><circle cx="100" cy="100" r="80"></circle>`
  76. const existing = `<path></path>`
  77. const parent = document.createElementNS(svgNS, 'svg')
  78. parent.innerHTML = existing
  79. const anchor = parent.firstChild
  80. const [first, last] = nodeOps.insertStaticContent!(
  81. content,
  82. parent,
  83. anchor,
  84. 'svg',
  85. )
  86. expect(parent.innerHTML).toBe(content + existing)
  87. expect(first).toBe(parent.firstChild)
  88. expect(last).toBe(parent.childNodes[parent.childNodes.length - 2])
  89. expect((first as Element).namespaceURI).toMatch('svg')
  90. expect((last as Element).namespaceURI).toMatch('svg')
  91. })
  92. test('cached insertion', () => {
  93. const content = `<div>one</div><div>two</div>three`
  94. const existing = `<div>existing</div>`
  95. const parent = document.createElement('div')
  96. parent.innerHTML = existing
  97. const anchor = parent.firstChild
  98. const cached = document.createElement('div')
  99. cached.innerHTML = content
  100. const nodes = nodeOps.insertStaticContent!(
  101. content,
  102. parent,
  103. anchor,
  104. undefined,
  105. cached.firstChild,
  106. cached.lastChild,
  107. )
  108. expect(parent.innerHTML).toBe(content + existing)
  109. expect(nodes[0]).toBe(parent.firstChild)
  110. expect(nodes[1]).toBe(parent.childNodes[parent.childNodes.length - 2])
  111. })
  112. test('The math elements should keep their MathML namespace', async () => {
  113. let root = document.createElement('div') as any
  114. let countRef: any
  115. const component = defineComponent({
  116. data() {
  117. return { value: 0 }
  118. },
  119. setup() {
  120. const count = ref(0)
  121. countRef = count
  122. return {
  123. count,
  124. }
  125. },
  126. template: `
  127. <div>
  128. <math>
  129. <mrow class="bar" v-if="count % 2">Bar</mrow>
  130. <msup class="foo" v-else>Foo</msup>
  131. </math>
  132. </div>
  133. `,
  134. })
  135. render(h(component), root)
  136. const foo = root.querySelector('.foo')
  137. expect(foo.namespaceURI).toBe(mathmlNS)
  138. countRef.value++
  139. await nextTick()
  140. const bar = root.querySelector('.bar')
  141. expect(bar.namespaceURI).toBe(mathmlNS)
  142. })
  143. })
  144. })