model-checkbox.spec.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. import Vue from 'vue'
  2. describe('Directive v-model checkbox', () => {
  3. it('should work', done => {
  4. const vm = new Vue({
  5. data: {
  6. test: true
  7. },
  8. template: '<input type="checkbox" v-model="test">'
  9. }).$mount()
  10. document.body.appendChild(vm.$el)
  11. expect(vm.$el.checked).toBe(true)
  12. vm.test = false
  13. waitForUpdate(function () {
  14. expect(vm.$el.checked).toBe(false)
  15. expect(vm.test).toBe(false)
  16. vm.$el.click()
  17. expect(vm.$el.checked).toBe(true)
  18. expect(vm.test).toBe(true)
  19. }).then(() => {
  20. document.body.removeChild(vm.$el)
  21. }).then(done)
  22. })
  23. it('should respect value bindings', done => {
  24. const vm = new Vue({
  25. data: {
  26. test: 1,
  27. a: 1,
  28. b: 2
  29. },
  30. template: '<input type="checkbox" v-model="test" :true-value="a" :false-value="b">'
  31. }).$mount()
  32. document.body.appendChild(vm.$el)
  33. expect(vm.$el.checked).toBe(true)
  34. vm.$el.click()
  35. expect(vm.$el.checked).toBe(false)
  36. expect(vm.test).toBe(2)
  37. vm.$el.click()
  38. expect(vm.$el.checked).toBe(true)
  39. expect(vm.test).toBe(1)
  40. vm.test = 2
  41. waitForUpdate(() => {
  42. expect(vm.$el.checked).toBe(false)
  43. vm.test = 1
  44. }).then(() => {
  45. expect(vm.$el.checked).toBe(true)
  46. document.body.removeChild(vm.$el)
  47. }).then(done)
  48. })
  49. it('bind to Array value', done => {
  50. const vm = new Vue({
  51. data: {
  52. test: ['1']
  53. },
  54. template: `
  55. <div>
  56. {{ test }}
  57. <input type="checkbox" v-model="test" value="1">
  58. <input type="checkbox" v-model="test" value="2">
  59. </div>
  60. `
  61. }).$mount()
  62. document.body.appendChild(vm.$el)
  63. expect(vm.$el.children[0].checked).toBe(true)
  64. expect(vm.$el.children[1].checked).toBe(false)
  65. vm.$el.children[0].click()
  66. waitForUpdate(() => {
  67. expect(vm.test.length).toBe(0)
  68. vm.$el.children[1].click()
  69. }).then(() => {
  70. expect(vm.test).toEqual(['2'])
  71. vm.$el.children[0].click()
  72. }).then(() => {
  73. expect(vm.test).toEqual(['2', '1'])
  74. vm.test = ['1']
  75. }).then(() => {
  76. expect(vm.$el.children[0].checked).toBe(true)
  77. expect(vm.$el.children[1].checked).toBe(false)
  78. }).then(done)
  79. })
  80. it('bind to Array value ignores false-value', done => {
  81. const vm = new Vue({
  82. data: {
  83. test: ['1']
  84. },
  85. template: `
  86. <div>
  87. <input type="checkbox" v-model="test" value="1" :false-value="true">
  88. <input type="checkbox" v-model="test" value="2" :false-value="true">
  89. </div>
  90. `
  91. }).$mount()
  92. document.body.appendChild(vm.$el)
  93. expect(vm.$el.children[0].checked).toBe(true)
  94. expect(vm.$el.children[1].checked).toBe(false)
  95. vm.$el.children[0].click()
  96. waitForUpdate(() => {
  97. expect(vm.test.length).toBe(0)
  98. vm.$el.children[1].click()
  99. }).then(() => {
  100. expect(vm.test).toEqual(['2'])
  101. vm.$el.children[0].click()
  102. }).then(() => {
  103. expect(vm.test).toEqual(['2', '1'])
  104. vm.test = ['1']
  105. }).then(() => {
  106. expect(vm.$el.children[0].checked).toBe(true)
  107. expect(vm.$el.children[1].checked).toBe(false)
  108. }).then(done)
  109. })
  110. it('bind to Array value with value bindings', done => {
  111. const vm = new Vue({
  112. data: {
  113. test: [1]
  114. },
  115. template: `
  116. <div>
  117. <input type="checkbox" v-model="test" :value="1">
  118. <input type="checkbox" v-model="test" :value="2">
  119. </div>
  120. `
  121. }).$mount()
  122. document.body.appendChild(vm.$el)
  123. expect(vm.$el.children[0].checked).toBe(true)
  124. expect(vm.$el.children[1].checked).toBe(false)
  125. vm.$el.children[0].click()
  126. waitForUpdate(() => {
  127. expect(vm.test.length).toBe(0)
  128. vm.$el.children[1].click()
  129. }).then(() => {
  130. expect(vm.test).toEqual([2])
  131. vm.$el.children[0].click()
  132. }).then(() => {
  133. expect(vm.test).toEqual([2, 1])
  134. vm.test = [1]
  135. }).then(() => {
  136. expect(vm.$el.children[0].checked).toBe(true)
  137. expect(vm.$el.children[1].checked).toBe(false)
  138. }).then(done)
  139. })
  140. it('bind to Array value with value bindings (object loose equal)', done => {
  141. const vm = new Vue({
  142. data: {
  143. test: [{ a: 1 }]
  144. },
  145. template: `
  146. <div>
  147. <input type="checkbox" v-model="test" :value="{ a: 1 }">
  148. <input type="checkbox" v-model="test" :value="{ a: 2 }">
  149. </div>
  150. `
  151. }).$mount()
  152. document.body.appendChild(vm.$el)
  153. expect(vm.$el.children[0].checked).toBe(true)
  154. expect(vm.$el.children[1].checked).toBe(false)
  155. vm.$el.children[0].click()
  156. waitForUpdate(() => {
  157. expect(vm.test.length).toBe(0)
  158. vm.$el.children[1].click()
  159. }).then(() => {
  160. expect(vm.test).toEqual([{ a: 2 }])
  161. vm.$el.children[0].click()
  162. }).then(() => {
  163. expect(vm.test).toEqual([{ a: 2 }, { a: 1 }])
  164. vm.test = [{ a: 1 }]
  165. }).then(() => {
  166. expect(vm.$el.children[0].checked).toBe(true)
  167. expect(vm.$el.children[1].checked).toBe(false)
  168. }).then(done)
  169. })
  170. it('bind to Array value with array value bindings (object loose equal)', done => {
  171. const vm = new Vue({
  172. data: {
  173. test: [{ a: 1 }]
  174. },
  175. template: `
  176. <div>
  177. <input type="checkbox" v-model="test" :value="{ a: 1 }">
  178. <input type="checkbox" v-model="test" :value="[2]">
  179. </div>
  180. `
  181. }).$mount()
  182. document.body.appendChild(vm.$el)
  183. expect(vm.$el.children[0].checked).toBe(true)
  184. expect(vm.$el.children[1].checked).toBe(false)
  185. vm.$el.children[0].click()
  186. waitForUpdate(() => {
  187. expect(vm.test.length).toBe(0)
  188. vm.$el.children[1].click()
  189. }).then(() => {
  190. expect(vm.test).toEqual([[2]])
  191. vm.$el.children[0].click()
  192. }).then(() => {
  193. expect(vm.test).toEqual([[2], { a: 1 }])
  194. vm.test = [{ a: 1 }]
  195. }).then(() => {
  196. expect(vm.$el.children[0].checked).toBe(true)
  197. expect(vm.$el.children[1].checked).toBe(false)
  198. }).then(done)
  199. })
  200. it('.number modifier', () => {
  201. const vm = new Vue({
  202. data: {
  203. test: [],
  204. check: true
  205. },
  206. template: `
  207. <div>
  208. <input type="checkbox" v-model.number="test" value="1">
  209. <input type="checkbox" v-model="test" value="2">
  210. <input type="checkbox" v-model.number="check">
  211. </div>
  212. `
  213. }).$mount()
  214. document.body.appendChild(vm.$el)
  215. const checkboxInputs = vm.$el.getElementsByTagName('input')
  216. expect(checkboxInputs[0].checked).toBe(false)
  217. expect(checkboxInputs[1].checked).toBe(false)
  218. expect(checkboxInputs[2].checked).toBe(true)
  219. checkboxInputs[0].click()
  220. checkboxInputs[1].click()
  221. checkboxInputs[2].click()
  222. expect(vm.test).toEqual([1, '2'])
  223. expect(vm.check).toEqual(false)
  224. })
  225. it('should respect different primitive type value', (done) => {
  226. const vm = new Vue({
  227. data: {
  228. test: [0]
  229. },
  230. template:
  231. '<div>' +
  232. '<input type="checkbox" value="" v-model="test">' +
  233. '<input type="checkbox" value="0" v-model="test">' +
  234. '<input type="checkbox" value="1" v-model="test">' +
  235. '<input type="checkbox" value="false" v-model="test">' +
  236. '<input type="checkbox" value="true" v-model="test">' +
  237. '</div>'
  238. }).$mount()
  239. const checkboxInput = vm.$el.children
  240. expect(checkboxInput[0].checked).toBe(false)
  241. expect(checkboxInput[1].checked).toBe(true)
  242. expect(checkboxInput[2].checked).toBe(false)
  243. expect(checkboxInput[3].checked).toBe(false)
  244. expect(checkboxInput[4].checked).toBe(false)
  245. vm.test = [1]
  246. waitForUpdate(() => {
  247. expect(checkboxInput[0].checked).toBe(false)
  248. expect(checkboxInput[1].checked).toBe(false)
  249. expect(checkboxInput[2].checked).toBe(true)
  250. expect(checkboxInput[3].checked).toBe(false)
  251. expect(checkboxInput[4].checked).toBe(false)
  252. vm.test = ['']
  253. }).then(() => {
  254. expect(checkboxInput[0].checked).toBe(true)
  255. expect(checkboxInput[1].checked).toBe(false)
  256. expect(checkboxInput[2].checked).toBe(false)
  257. expect(checkboxInput[3].checked).toBe(false)
  258. expect(checkboxInput[4].checked).toBe(false)
  259. vm.test = [false]
  260. }).then(() => {
  261. expect(checkboxInput[0].checked).toBe(false)
  262. expect(checkboxInput[1].checked).toBe(false)
  263. expect(checkboxInput[2].checked).toBe(false)
  264. expect(checkboxInput[3].checked).toBe(true)
  265. expect(checkboxInput[4].checked).toBe(false)
  266. vm.test = [true]
  267. }).then(() => {
  268. expect(checkboxInput[0].checked).toBe(false)
  269. expect(checkboxInput[1].checked).toBe(false)
  270. expect(checkboxInput[2].checked).toBe(false)
  271. expect(checkboxInput[3].checked).toBe(false)
  272. expect(checkboxInput[4].checked).toBe(true)
  273. vm.test = ['', 0, 1, false, true]
  274. }).then(() => {
  275. expect(checkboxInput[0].checked).toBe(true)
  276. expect(checkboxInput[1].checked).toBe(true)
  277. expect(checkboxInput[2].checked).toBe(true)
  278. expect(checkboxInput[3].checked).toBe(true)
  279. expect(checkboxInput[4].checked).toBe(true)
  280. }).then(done)
  281. })
  282. // #4521
  283. it('should work with click event', (done) => {
  284. const vm = new Vue({
  285. data: {
  286. num: 1,
  287. checked: false
  288. },
  289. template: '<div @click="add">click {{ num }}<input ref="checkbox" type="checkbox" v-model="checked"/></div>',
  290. methods: {
  291. add: function () {
  292. this.num++
  293. }
  294. }
  295. }).$mount()
  296. document.body.appendChild(vm.$el)
  297. const checkbox = vm.$refs.checkbox
  298. checkbox.click()
  299. waitForUpdate(() => {
  300. expect(checkbox.checked).toBe(true)
  301. expect(vm.num).toBe(2)
  302. }).then(done)
  303. })
  304. it('should get updated with model when in focus', (done) => {
  305. const vm = new Vue({
  306. data: {
  307. a: 2
  308. },
  309. template: '<input type="checkbox" v-model="a"/>'
  310. }).$mount()
  311. document.body.appendChild(vm.$el)
  312. vm.$el.click()
  313. waitForUpdate(() => {
  314. expect(vm.$el.checked).toBe(false)
  315. vm.a = 2
  316. }).then(() => {
  317. expect(vm.$el.checked).toBe(true)
  318. }).then(done)
  319. })
  320. it('triggers a watcher when binding to an array value in a checkbox', done => {
  321. const vm = new Vue({
  322. data: {
  323. test: {
  324. thing: false,
  325. arr: [true]
  326. }
  327. },
  328. template: `
  329. <div>
  330. <input type="checkbox" v-model="test.arr[0]">
  331. <span>{{ test.arr[0] }}</span>
  332. </div>
  333. `
  334. }).$mount()
  335. document.body.appendChild(vm.$el)
  336. expect(vm.$el.children[0].checked).toBe(true)
  337. expect(vm.$el.children[1].textContent).toBe('true')
  338. vm.$el.children[0].click()
  339. expect(vm.$el.children[0].checked).toBe(false)
  340. waitForUpdate(() => {
  341. expect(vm.$el.children[1].textContent).toBe('false')
  342. }).then(done)
  343. })
  344. // #7811
  345. it('type should not be overwritten by v-bind', () => {
  346. const vm = new Vue({
  347. data: {
  348. test: true
  349. },
  350. template: '<input type="checkbox" v-model="test" v-bind="$attrs">'
  351. }).$mount()
  352. expect(vm.$el.type).toBe('checkbox')
  353. })
  354. })