model-select.spec.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import Vue from 'vue'
  2. /**
  3. * setting <select>'s value in IE9 doesn't work
  4. * we have to manually loop through the options
  5. */
  6. function updateSelect (el, value) {
  7. var options = el.options
  8. var i = options.length
  9. while (i--) {
  10. /* eslint-disable eqeqeq */
  11. if (options[i].value == value) {
  12. /* eslint-enable eqeqeq */
  13. options[i].selected = true
  14. break
  15. }
  16. }
  17. }
  18. describe('Directive v-model select', () => {
  19. it('should work', done => {
  20. const vm = new Vue({
  21. data: {
  22. test: 'b'
  23. },
  24. template:
  25. '<select v-model="test">' +
  26. '<option>a</option>' +
  27. '<option>b</option>' +
  28. '<option>c</option>' +
  29. '</select>'
  30. }).$mount()
  31. document.body.appendChild(vm.$el)
  32. expect(vm.test).toBe('b')
  33. expect(vm.$el.value).toBe('b')
  34. expect(vm.$el.childNodes[1].selected).toBe(true)
  35. vm.test = 'c'
  36. waitForUpdate(function () {
  37. expect(vm.$el.value).toBe('c')
  38. expect(vm.$el.childNodes[2].selected).toBe(true)
  39. updateSelect(vm.$el, 'a')
  40. triggerEvent(vm.$el, 'change')
  41. expect(vm.test).toBe('a')
  42. }).then(done)
  43. })
  44. it('should work with value bindings', done => {
  45. const vm = new Vue({
  46. data: {
  47. test: 2
  48. },
  49. template:
  50. '<select v-model="test">' +
  51. '<option value="1">a</option>' +
  52. '<option :value="2">b</option>' +
  53. '<option :value="3">c</option>' +
  54. '</select>'
  55. }).$mount()
  56. document.body.appendChild(vm.$el)
  57. expect(vm.$el.value).toBe('2')
  58. expect(vm.$el.childNodes[1].selected).toBe(true)
  59. vm.test = 3
  60. waitForUpdate(function () {
  61. expect(vm.$el.value).toBe('3')
  62. expect(vm.$el.childNodes[2].selected).toBe(true)
  63. updateSelect(vm.$el, '1')
  64. triggerEvent(vm.$el, 'change')
  65. expect(vm.test).toBe('1')
  66. }).then(done)
  67. })
  68. it('should work with v-for', done => {
  69. const vm = new Vue({
  70. data: {
  71. test: 'b',
  72. opts: ['a', 'b', 'c']
  73. },
  74. template:
  75. '<select v-model="test">' +
  76. '<option v-for="o in opts">{{ o }}</option>' +
  77. '</select>'
  78. }).$mount()
  79. document.body.appendChild(vm.$el)
  80. expect(vm.test).toBe('b')
  81. expect(vm.$el.value).toBe('b')
  82. expect(vm.$el.childNodes[1].selected).toBe(true)
  83. vm.test = 'c'
  84. waitForUpdate(function () {
  85. expect(vm.$el.value).toBe('c')
  86. expect(vm.$el.childNodes[2].selected).toBe(true)
  87. updateSelect(vm.$el, 'a')
  88. triggerEvent(vm.$el, 'change')
  89. expect(vm.test).toBe('a')
  90. // update v-for opts
  91. vm.opts = ['d', 'a']
  92. }).then(() => {
  93. expect(vm.$el.childNodes[0].selected).toBe(false)
  94. expect(vm.$el.childNodes[1].selected).toBe(true)
  95. }).then(done)
  96. })
  97. it('should work with v-for & value bindings', done => {
  98. const vm = new Vue({
  99. data: {
  100. test: 2,
  101. opts: [1, 2, 3]
  102. },
  103. template:
  104. '<select v-model="test">' +
  105. '<option v-for="o in opts" :value="o">optio {{ o }}</option>' +
  106. '</select>'
  107. }).$mount()
  108. document.body.appendChild(vm.$el)
  109. expect(vm.$el.value).toBe('2')
  110. expect(vm.$el.childNodes[1].selected).toBe(true)
  111. vm.test = 3
  112. waitForUpdate(function () {
  113. expect(vm.$el.value).toBe('3')
  114. expect(vm.$el.childNodes[2].selected).toBe(true)
  115. updateSelect(vm.$el, 1)
  116. triggerEvent(vm.$el, 'change')
  117. expect(vm.test).toBe(1)
  118. // update v-for opts
  119. vm.opts = [0, 1]
  120. }).then(() => {
  121. expect(vm.$el.childNodes[0].selected).toBe(false)
  122. expect(vm.$el.childNodes[1].selected).toBe(true)
  123. }).then(done)
  124. })
  125. it('multiple', done => {
  126. const vm = new Vue({
  127. data: {
  128. test: ['b']
  129. },
  130. template:
  131. '<select v-model="test" multiple>' +
  132. '<option>a</option>' +
  133. '<option>b</option>' +
  134. '<option>c</option>' +
  135. '</select>'
  136. }).$mount()
  137. var opts = vm.$el.options
  138. expect(opts[0].selected).toBe(false)
  139. expect(opts[1].selected).toBe(true)
  140. expect(opts[2].selected).toBe(false)
  141. vm.test = ['a', 'c']
  142. waitForUpdate(() => {
  143. expect(opts[0].selected).toBe(true)
  144. expect(opts[1].selected).toBe(false)
  145. expect(opts[2].selected).toBe(true)
  146. opts[0].selected = false
  147. opts[1].selected = true
  148. triggerEvent(vm.$el, 'change')
  149. expect(vm.test).toEqual(['b', 'c'])
  150. }).then(done)
  151. })
  152. it('multiple + v-for', done => {
  153. const vm = new Vue({
  154. data: {
  155. test: ['b'],
  156. opts: ['a', 'b', 'c']
  157. },
  158. template:
  159. '<select v-model="test" multiple>' +
  160. '<option v-for="o in opts">{{ o }}</option>' +
  161. '</select>'
  162. }).$mount()
  163. var opts = vm.$el.options
  164. expect(opts[0].selected).toBe(false)
  165. expect(opts[1].selected).toBe(true)
  166. expect(opts[2].selected).toBe(false)
  167. vm.test = ['a', 'c']
  168. waitForUpdate(() => {
  169. expect(opts[0].selected).toBe(true)
  170. expect(opts[1].selected).toBe(false)
  171. expect(opts[2].selected).toBe(true)
  172. opts[0].selected = false
  173. opts[1].selected = true
  174. triggerEvent(vm.$el, 'change')
  175. expect(vm.test).toEqual(['b', 'c'])
  176. // update v-for opts
  177. vm.opts = ['c', 'd']
  178. }).then(() => {
  179. expect(opts[0].selected).toBe(true)
  180. expect(opts[1].selected).toBe(false)
  181. expect(vm.test).toEqual(['c']) // should remove 'd' which no longer has a matching option
  182. }).then(done)
  183. })
  184. it('should warn inline selected', () => {
  185. const vm = new Vue({
  186. data: {
  187. test: null
  188. },
  189. template:
  190. '<select v-model="test">' +
  191. '<option selected>a</option>' +
  192. '</select>'
  193. }).$mount()
  194. expect(vm.$el.selectedIndex).toBe(-1)
  195. expect('inline selected attributes on <option> will be ignored when using v-model')
  196. .toHaveBeenWarned()
  197. })
  198. it('should warn multiple with non-Array value', () => {
  199. new Vue({
  200. data: {
  201. test: 'meh'
  202. },
  203. template:
  204. '<select v-model="test" multiple></select>'
  205. }).$mount()
  206. expect('<select multiple v-model="test"> expects an Array value for its binding, but got String')
  207. .toHaveBeenWarned()
  208. })
  209. })