1
0

$model.spec.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import { beSelected, haveText, haveValue, html, notBeSelected, test } from '../../utils'
  2. test('$model allows you to interact with parent x-model bindings explicitly',
  3. html`
  4. <div x-data="{ foo: 'bar' }" x-model="foo">
  5. <button @click="$model.set('baz')">click me</button>
  6. <h1 x-text="$model.get()"></h1>
  7. <h2 x-text="foo"></h2>
  8. </div>
  9. `,
  10. ({ get }) => {
  11. get('h1').should(haveText('bar'))
  12. get('h2').should(haveText('bar'))
  13. get('button').click()
  14. get('h1').should(haveText('baz'))
  15. get('h2').should(haveText('baz'))
  16. }
  17. )
  18. test('$model accepts a callback when setting a value',
  19. html`
  20. <div x-data="{ foo: 'bar' }" x-model="foo">
  21. <button @click="$model.set(i => i + 'r')">click me</button>
  22. <h1 x-text="$model.get()"></h1>
  23. <h2 x-text="foo"></h2>
  24. </div>
  25. `,
  26. ({ get }) => {
  27. get('h1').should(haveText('bar'))
  28. get('h2').should(haveText('bar'))
  29. get('button').click()
  30. get('h1').should(haveText('barr'))
  31. get('h2').should(haveText('barr'))
  32. }
  33. )
  34. test('$model can be used with a getter and setter',
  35. html`
  36. <div x-data="{ foo: 'bar' }" x-model="foo">
  37. <div x-data="{
  38. get value() {
  39. return this.$model.get()
  40. },
  41. set value(value) {
  42. this.$model.set(value)
  43. }
  44. }">
  45. <button @click="value = 'baz'">click me</button>
  46. <h1 x-text="foo"></h1>
  47. <h2 x-text="value"></h2>
  48. <h3 x-text="$model.get()"></h3>
  49. </div>
  50. </div>
  51. `,
  52. ({ get }) => {
  53. get('h1').should(haveText('bar'))
  54. get('h2').should(haveText('bar'))
  55. get('h3').should(haveText('bar'))
  56. get('button').click()
  57. get('h1').should(haveText('baz'))
  58. get('h2').should(haveText('baz'))
  59. get('h3').should(haveText('baz'))
  60. }
  61. )
  62. // @todo: this is failing...
  63. test('$model can be used with another x-model',
  64. html`
  65. <div x-data="{ foo: 'bar' }" x-model="foo">
  66. <select x-model="$model">
  67. <option>bar</option>
  68. <option>baz</option>
  69. </select>
  70. <h1 x-text="foo"></h1>
  71. <h2 x-text="$model.get()"></h2>
  72. </div>
  73. `,
  74. ({ get }) => {
  75. get('h1').should(haveText('bar'))
  76. get('h2').should(haveText('bar'))
  77. get('option:first').should(beSelected())
  78. get('option:last').should(notBeSelected())
  79. get('select').
  80. get('select').select('baz')
  81. get('h1').should(haveText('baz'))
  82. get('h2').should(haveText('baz'))
  83. get('option:first').should(notBeSelected())
  84. get('option:last').should(beSelected())
  85. }
  86. )
  87. test('$model can be used on the same element as the corresponding x-model',
  88. html`
  89. <div x-data="{ foo: 'bar' }">
  90. <button @click="foo = 'baz'">click me</button>
  91. <div x-data="{ value: $model }" x-model="foo">
  92. <h1 x-text="value"></h1>
  93. </div>
  94. </div>
  95. `,
  96. ({ get }) => {
  97. get('h1').should(haveText('bar'))
  98. get('button').click()
  99. get('h1').should(haveText('baz'))
  100. }
  101. )
  102. test('$model destroys x-model event listeners on initialization',
  103. html`
  104. <div x-data="{ foo: 'bar' }">
  105. <div x-data="{ value: $model }" x-model="foo">
  106. <h1 x-text="value"></h1>
  107. <input type="text">
  108. </div>
  109. </div>
  110. `,
  111. ({ get }) => {
  112. get('h1').should(haveText('bar'))
  113. get('input').type('baz')
  114. get('h1').should(haveText('bar'))
  115. }
  116. )
  117. test('$model doesnt destroy x-model event listeners when on an input element',
  118. html`
  119. <div x-data="{ foo: 'bar' }">
  120. <div>
  121. <h1 x-text="foo"></h1>
  122. <input type="text" x-data="{ value: $model }" x-model="foo">
  123. </div>
  124. </div>
  125. `,
  126. ({ get }) => {
  127. get('h1').should(haveText('bar'))
  128. get('input').should(haveValue('bar'))
  129. get('input').type('baz')
  130. get('h1').should(haveText('barbaz'))
  131. }
  132. )
  133. test('$model can watch for changing values and watcher gets cleaned up on element removal',
  134. html`
  135. <div x-data="{ foo: 'bar' }" x-model="foo">
  136. <button @click="$model.set('baz')">click me</button>
  137. <h1 x-text="$model.get()"></h1>
  138. <h2 x-init="$model.watch(newValue => $el.textContent = newValue)" x-on:click="$el.remove()"></h2>
  139. <h3 x-on:click="$model.set('bob')">click me</h3>
  140. </div>
  141. `,
  142. ({ get }) => {
  143. get('h1').should(haveText('bar'))
  144. get('h2').should(haveText(''))
  145. get('button').click()
  146. get('h1').should(haveText('baz'))
  147. get('h2').should(haveText('baz'))
  148. get('h2').click()
  149. get('h3').click()
  150. get('h1').should(haveText('bob'))
  151. }
  152. )
  153. test('$model can be used as a getter/setter pair in x-data',
  154. html`
  155. <div x-data="{ foo: 'bar' }" x-model="foo">
  156. <div x-data="{ value: $model }">
  157. <button @click="value = 'baz'">click me</button>
  158. <h2 x-text="value"></h2>
  159. </div>
  160. </div>
  161. `,
  162. ({ get }) => {
  163. get('h2').should(haveText('bar'))
  164. get('button').click()
  165. get('h2').should(haveText('baz'))
  166. }
  167. )
  168. test('$model can be used as a getter/setter pair in x-data with an initial value that makes x-model optional',
  169. html`
  170. <div x-data="{ foo: 'bar' }">
  171. <div x-data="{ value: $model('bar') }">
  172. <button @click="value = 'baz'">click me</button>
  173. <h2 x-text="value"></h2>
  174. </div>
  175. </div>
  176. `,
  177. ({ get }) => {
  178. get('h2').should(haveText('bar'))
  179. get('button').click()
  180. get('h2').should(haveText('baz'))
  181. }
  182. )
  183. test('$model can be used as a getter/setter pair in x-data on the same element when defined within a custom directive binding',
  184. [html`
  185. <div x-data="{ foo: 'bar' }">
  186. <div x-test x-model="foo">
  187. <button @click="value = 'baz'">click me</button>
  188. <h2 x-text="value"></h2>
  189. </div>
  190. </div>
  191. `,
  192. `
  193. Alpine.directive('test', (el) => {
  194. Alpine.bind(el, {
  195. 'x-data'() {
  196. return {
  197. value: this.$model
  198. }
  199. }
  200. })
  201. })
  202. `],
  203. ({ get }) => {
  204. get('h2').should(haveText('bar'))
  205. get('button').click()
  206. get('h2').should(haveText('baz'))
  207. }
  208. )