constructor.spec.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import Alpine from 'alpinejs'
  2. import { fireEvent, wait } from '@testing-library/dom'
  3. test('auto-detect new components at the top level', async () => {
  4. var runObservers = []
  5. global.MutationObserver = class {
  6. constructor(callback) { runObservers.push(callback) }
  7. observe() {}
  8. }
  9. document.body.innerHTML = `
  10. <section></section>
  11. `
  12. Alpine.start()
  13. document.querySelector('section').innerHTML = `
  14. <div x-data="{ foo: '' }">
  15. <input x-model="foo">
  16. <span x-text="foo"></span>
  17. </div>
  18. `
  19. runObservers[0]([
  20. {
  21. target: document.querySelector('section'),
  22. type: 'childList',
  23. addedNodes: [ document.querySelector('div') ],
  24. }
  25. ])
  26. fireEvent.input(document.querySelector('input'), { target: { value: 'bar' }})
  27. await wait(() => { expect(document.querySelector('span').innerText).toEqual('bar') })
  28. })
  29. test('auto-detect newsted new components at the top level', async () => {
  30. var runObservers = []
  31. global.MutationObserver = class {
  32. constructor(callback) { runObservers.push(callback) }
  33. observe() {}
  34. }
  35. document.body.innerHTML = `
  36. <section></section>
  37. `
  38. Alpine.start()
  39. document.querySelector('section').innerHTML = `
  40. <article>
  41. <div x-data="{ foo: '' }">
  42. <input x-model="foo">
  43. <span x-text="foo"></span>
  44. </div>
  45. </article>
  46. `
  47. runObservers[0]([
  48. {
  49. target: document.querySelector('section'),
  50. type: 'childList',
  51. addedNodes: [ document.querySelector('article') ],
  52. }
  53. ])
  54. fireEvent.input(document.querySelector('input'), { target: { value: 'bar' }})
  55. await wait(() => { expect(document.querySelector('span').innerText).toEqual('bar') })
  56. })
  57. test('auto-detect new components and dont lose state of existing ones', async () => {
  58. var runObservers = []
  59. global.MutationObserver = class {
  60. constructor(callback) { runObservers.push(callback) }
  61. observe() {}
  62. }
  63. document.body.innerHTML = `
  64. <div id="A" x-data="{ foo: '' }">
  65. <input x-model="foo">
  66. <span x-text="foo"></span>
  67. <div id="B"></div>
  68. </div>
  69. `
  70. Alpine.start()
  71. fireEvent.input(document.querySelector('input'), { target: { value: 'bar' }})
  72. await wait(() => { expect(document.querySelector('#A span').innerText).toEqual('bar') })
  73. document.querySelector('#B').innerHTML = `
  74. <div x-data="{foo: 'baz'}">
  75. <input x-model="foo">
  76. <span x-text="foo"></span>
  77. </div>
  78. `
  79. runObservers[0]([
  80. {
  81. target: document.querySelector('#A'),
  82. type: 'childList',
  83. addedNodes: [ document.querySelector('#B div') ],
  84. }
  85. ])
  86. await wait(() => {
  87. expect(document.querySelector('#A span').innerText).toEqual('bar')
  88. expect(document.querySelector('#B span').innerText).toEqual('baz')
  89. })
  90. })
  91. test('auto-detect new components that are wrapped in non-new component tags', async () => {
  92. var runObservers = []
  93. global.MutationObserver = class {
  94. constructor(callback) { runObservers.push(callback) }
  95. observe() {}
  96. }
  97. document.body.innerHTML = `
  98. <div id="A" x-data="{ foo: '' }">
  99. <input x-model="foo">
  100. <span x-text="foo"></span>
  101. <div id="B"></div>
  102. </div>
  103. `
  104. Alpine.start()
  105. fireEvent.input(document.querySelector('input'), { target: { value: 'bar' }})
  106. await wait(() => { expect(document.querySelector('#A span').innerText).toEqual('bar') })
  107. document.querySelector('#B').innerHTML = `
  108. <section>
  109. <div x-data="{foo: 'baz'}">
  110. <input x-model="foo">
  111. <span x-text="foo"></span>
  112. </div>
  113. </section>
  114. `
  115. runObservers[0]([
  116. {
  117. target: document.querySelector('#A'),
  118. type: 'childList',
  119. addedNodes: [ document.querySelector('#B section') ],
  120. }
  121. ])
  122. await wait(() => {
  123. expect(document.querySelector('#A span').innerText).toEqual('bar')
  124. expect(document.querySelector('#B span').innerText).toEqual('baz')
  125. })
  126. })
  127. test('auto-initialize new elements added to a component', async () => {
  128. var runObservers = []
  129. global.MutationObserver = class {
  130. constructor(callback) { runObservers.push(callback) }
  131. observe() {}
  132. }
  133. document.body.innerHTML = `
  134. <div x-data="{ count: 0 }">
  135. <span x-text="count"></span>
  136. <div id="target">
  137. </div>
  138. </div>
  139. `
  140. Alpine.start()
  141. expect(document.querySelector('span').innerText).toEqual(0)
  142. document.querySelector('#target').innerHTML = `
  143. <span x-text="count"></span>
  144. <button x-on:click="count++"></button>
  145. `
  146. runObservers[0]([
  147. { target: document.querySelector('#target'), addedNodes: [
  148. document.querySelector('#target span'),
  149. document.querySelector('#target button'),
  150. ] }
  151. ])
  152. await wait(() => { expect(document.querySelector('#target span').innerText).toEqual(0) })
  153. document.querySelector('button').click()
  154. await wait(() => { expect(document.querySelector('span').innerText).toEqual(1) })
  155. await wait(() => { expect(document.querySelector('#target span').innerText).toEqual(1) })
  156. })
  157. test('auto-detect x-data property changes at run-time', async () => {
  158. var runObservers = []
  159. global.MutationObserver = class {
  160. constructor(callback) { runObservers.push(callback) }
  161. observe() {}
  162. }
  163. document.body.innerHTML = `
  164. <div x-data="{ count: 0 }">
  165. <span x-text="count"></span>
  166. </div>
  167. `
  168. Alpine.start()
  169. expect(document.querySelector('span').innerText).toEqual(0)
  170. document.querySelector('div').setAttribute('x-data', '{ count: 1 }')
  171. runObservers[0]([
  172. {
  173. addedNodes: [],
  174. type: 'attributes',
  175. attributeName: 'x-data',
  176. target: document.querySelector('div')
  177. }
  178. ])
  179. await wait(() => { expect(document.querySelector('span').innerText).toEqual(1) })
  180. })