model_spec.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. var _ = require('src/util')
  2. var Vue = require('src')
  3. // unset jQuery to bypass jQuery check for normal test cases
  4. jQuery = null
  5. /**
  6. * Mock event helper
  7. */
  8. function trigger (target, event, process) {
  9. var e = document.createEvent('HTMLEvents')
  10. e.initEvent(event, true, true)
  11. if (process) process(e)
  12. target.dispatchEvent(e)
  13. }
  14. /**
  15. * setting <select>'s value in IE9 doesn't work
  16. * we have to manually loop through the options
  17. */
  18. function updateSelect (el, value) {
  19. var options = el.options
  20. var i = options.length
  21. while (i--) {
  22. /* eslint-disable eqeqeq */
  23. if (options[i].value == value) {
  24. /* eslint-enable eqeqeq */
  25. options[i].selected = true
  26. break
  27. }
  28. }
  29. }
  30. describe('v-model', function () {
  31. var el
  32. beforeEach(function () {
  33. el = document.createElement('div')
  34. el.style.display = 'none'
  35. document.body.appendChild(el)
  36. spyWarns()
  37. })
  38. it('radio buttons', function (done) {
  39. var vm = new Vue({
  40. el: el,
  41. data: {
  42. test: '1'
  43. },
  44. template:
  45. '<input type="radio" value="1" v-model="test" name="test" number>' +
  46. '<input type="radio" value="2" v-model="test" name="test">'
  47. })
  48. expect(el.childNodes[0].checked).toBe(true)
  49. expect(el.childNodes[1].checked).toBe(false)
  50. vm.test = '2'
  51. _.nextTick(function () {
  52. expect(el.childNodes[0].checked).toBe(false)
  53. expect(el.childNodes[1].checked).toBe(true)
  54. el.childNodes[0].click()
  55. expect(el.childNodes[0].checked).toBe(true)
  56. expect(el.childNodes[1].checked).toBe(false)
  57. expect(vm.test).toBe(1)
  58. vm._directives[1]._teardown()
  59. el.childNodes[1].click()
  60. expect(vm.test).toBe(1)
  61. done()
  62. })
  63. })
  64. it('radio default value', function () {
  65. var vm = new Vue({
  66. el: el,
  67. data: {},
  68. template: '<input type="radio" checked value="a" v-model="test">'
  69. })
  70. expect(vm.test).toBe('a')
  71. })
  72. it('radio expression', function (done) {
  73. var vm = new Vue({
  74. el: el,
  75. data: {
  76. test: false,
  77. test2: 'string1',
  78. expression1: 'string1',
  79. expression2: 'string2'
  80. },
  81. template:
  82. '<input type="radio" value="1" v-model="test" name="test" :value="true">' +
  83. '<input type="radio" value="0" v-model="test" name="test" :value="false">' +
  84. '<input type="radio" value="1" v-model="test2" name="test2" :value="expression1">' +
  85. '<input type="radio" value="0" v-model="test2" name="test2" :value="expression2">'
  86. })
  87. expect(el.childNodes[0].checked).toBe(false)
  88. expect(el.childNodes[1].checked).toBe(true)
  89. expect(el.childNodes[2].checked).toBe(true)
  90. expect(el.childNodes[3].checked).toBe(false)
  91. _.nextTick(function () {
  92. el.childNodes[0].click()
  93. expect(vm.test).toBe(true)
  94. el.childNodes[3].click()
  95. expect(vm.test2).toBe('string2')
  96. done()
  97. })
  98. })
  99. it('checkbox', function (done) {
  100. var vm = new Vue({
  101. el: el,
  102. data: {
  103. test: true
  104. },
  105. template: '<input type="checkbox" v-model="test">'
  106. })
  107. expect(el.firstChild.checked).toBe(true)
  108. vm.test = false
  109. _.nextTick(function () {
  110. expect(el.firstChild.checked).toBe(false)
  111. expect(vm.test).toBe(false)
  112. el.firstChild.click()
  113. expect(el.firstChild.checked).toBe(true)
  114. expect(vm.test).toBe(true)
  115. vm._directives[0]._teardown()
  116. el.firstChild.click()
  117. expect(el.firstChild.checked).toBe(false)
  118. expect(vm.test).toBe(true)
  119. done()
  120. })
  121. })
  122. it('checkbox default value', function () {
  123. var vm = new Vue({
  124. el: el,
  125. data: {},
  126. template: '<input type="checkbox" checked v-model="test">'
  127. })
  128. expect(vm.test).toBe(true)
  129. })
  130. it('checkbox expression', function (done) {
  131. var vm = new Vue({
  132. el: el,
  133. data: {
  134. test: '',
  135. expression1: 'aTrueValue',
  136. expression2: 'aFalseValue'
  137. },
  138. template: '<input type="checkbox" v-model="test" :true-value="expression1" :false-value="expression2">'
  139. })
  140. expect(vm.test).toBe('')
  141. el.firstChild.click()
  142. expect(vm.test).toBe('aTrueValue')
  143. expect(el.firstChild.checked).toBe(true)
  144. el.firstChild.click()
  145. expect(vm.test).toBe('aFalseValue')
  146. expect(el.firstChild.checked).toBe(false)
  147. _.nextTick(function () {
  148. vm.test = 'aTrueValue'
  149. _.nextTick(function () {
  150. expect(el.firstChild.checked).toBe(true)
  151. done()
  152. })
  153. })
  154. })
  155. it('checkbox + array model', function (done) {
  156. var vm = new Vue({
  157. el: el,
  158. data: {
  159. list: [1],
  160. a: {}
  161. },
  162. template:
  163. '<input type="checkbox" v-model="list" number value="1">' +
  164. '<input type="checkbox" v-model="list" :value="a">'
  165. })
  166. expect(el.firstChild.checked).toBe(true)
  167. expect(el.lastChild.checked).toBe(false)
  168. el.firstChild.click()
  169. expect(vm.list.length).toBe(0)
  170. el.lastChild.click()
  171. expect(vm.list.length).toBe(1)
  172. expect(vm.list[0]).toBe(vm.a)
  173. el.firstChild.click()
  174. expect(vm.list.length).toBe(2)
  175. expect(vm.list[1]).toBe(1)
  176. vm.list = [vm.a]
  177. _.nextTick(function () {
  178. expect(el.firstChild.checked).toBe(false)
  179. expect(el.lastChild.checked).toBe(true)
  180. done()
  181. })
  182. })
  183. it('checkbox + array model default value', function () {
  184. var vm = new Vue({
  185. el: el,
  186. data: {
  187. list: [],
  188. a: {}
  189. },
  190. template:
  191. '<input type="checkbox" v-model="list" number value="1">' +
  192. '<input type="checkbox" checked v-model="list" :value="a">'
  193. })
  194. expect(vm.list.length).toBe(1)
  195. expect(vm.list[0]).toBe(vm.a)
  196. })
  197. it('select', function (done) {
  198. var vm = new Vue({
  199. el: el,
  200. data: {
  201. test: 'b'
  202. },
  203. template:
  204. '<select v-model="test">' +
  205. '<option>a</option>' +
  206. '<option>b</option>' +
  207. '<option>c</option>' +
  208. '</select>'
  209. })
  210. expect(vm.test).toBe('b')
  211. expect(el.firstChild.value).toBe('b')
  212. expect(el.firstChild.childNodes[1].selected).toBe(true)
  213. vm.test = 'c'
  214. _.nextTick(function () {
  215. expect(el.firstChild.value).toBe('c')
  216. expect(el.firstChild.childNodes[2].selected).toBe(true)
  217. updateSelect(el.firstChild, 'a')
  218. trigger(el.firstChild, 'change')
  219. expect(vm.test).toBe('a')
  220. done()
  221. })
  222. })
  223. it('select persist non-selected on append', function () {
  224. var vm = new Vue({
  225. el: el,
  226. data: {
  227. test: null
  228. },
  229. replace: true,
  230. template:
  231. '<select v-model="test">' +
  232. '<option>a</option>' +
  233. '<option>b</option>' +
  234. '<option>c</option>' +
  235. '</select>'
  236. })
  237. expect(vm.$el.value).toBe('')
  238. expect(vm.$el.selectedIndex).toBe(-1)
  239. vm.$remove()
  240. vm.$appendTo(document.body)
  241. expect(vm.$el.value).toBe('')
  242. expect(vm.$el.selectedIndex).toBe(-1)
  243. })
  244. it('select template default value', function () {
  245. var vm = new Vue({
  246. el: el,
  247. data: {
  248. test: 'a'
  249. },
  250. template:
  251. '<select v-model="test">' +
  252. '<option>a</option>' +
  253. '<option selected>b</option>' +
  254. '</select>'
  255. })
  256. expect(vm.test).toBe('b')
  257. expect(el.firstChild.value).toBe('b')
  258. expect(el.firstChild.childNodes[1].selected).toBe(true)
  259. })
  260. it('select + empty default value', function () {
  261. var vm = new Vue({
  262. el: el,
  263. template: '<select v-model="test"><option value="" selected>null</option><<option value="1">1</option></select>'
  264. })
  265. expect(vm.test).toBe('')
  266. trigger(vm.$el.firstChild, 'change')
  267. expect(vm.test).toBe('')
  268. })
  269. it('select + multiple', function (done) {
  270. var vm = new Vue({
  271. el: el,
  272. data: {
  273. test: [2] // test number soft equal
  274. },
  275. template:
  276. '<select v-model="test" multiple>' +
  277. '<option>1</option>' +
  278. '<option>2</option>' +
  279. '<option>3</option>' +
  280. '</select>'
  281. })
  282. var opts = el.firstChild.options
  283. expect(opts[0].selected).toBe(false)
  284. expect(opts[1].selected).toBe(true)
  285. expect(opts[2].selected).toBe(false)
  286. vm.test = [1, '3'] // mix of number/string
  287. _.nextTick(function () {
  288. expect(opts[0].selected).toBe(true)
  289. expect(opts[1].selected).toBe(false)
  290. expect(opts[2].selected).toBe(true)
  291. opts[0].selected = false
  292. opts[1].selected = true
  293. trigger(el.firstChild, 'change')
  294. expect(vm.test[0]).toBe('2')
  295. expect(vm.test[1]).toBe('3')
  296. done()
  297. })
  298. })
  299. it('select + multiple default value', function () {
  300. var vm = new Vue({
  301. el: el,
  302. data: {},
  303. template:
  304. '<select v-model="test" multiple>' +
  305. '<option>a</option>' +
  306. '<option selected>b</option>' +
  307. '<option selected>c</option>' +
  308. '</select>'
  309. })
  310. expect(vm.test[0]).toBe('b')
  311. expect(vm.test[1]).toBe('c')
  312. })
  313. it('select + number', function () {
  314. var vm = new Vue({
  315. el: el,
  316. data: {
  317. test: '1'
  318. },
  319. template: '<select v-model="test" number><option value="1">1</option></select>'
  320. })
  321. expect(vm.test).toBe('1')
  322. trigger(vm.$el.firstChild, 'change')
  323. expect(vm.test).toBe(1)
  324. })
  325. it('select + number + multiple', function () {
  326. var vm = new Vue({
  327. el: el,
  328. data: {
  329. test: []
  330. },
  331. template: '<select v-model="test" multiple number><option>1</option><option>2</option></select>'
  332. })
  333. ;[].forEach.call(el.querySelectorAll('option'), function (o) {
  334. o.selected = true
  335. })
  336. trigger(el.firstChild, 'change')
  337. expect(vm.test[0]).toBe(1)
  338. expect(vm.test[1]).toBe(2)
  339. })
  340. it('select + number initial value', function () {
  341. var vm = new Vue({
  342. el: el,
  343. data: {
  344. test: '1'
  345. },
  346. template: '<select v-model="test" number><option value="1" selected>1</option></select>'
  347. })
  348. expect(vm.test).toBe(1)
  349. })
  350. it('select + v-for', function (done) {
  351. var vm = new Vue({
  352. el: el,
  353. data: {
  354. test: { msg: 'A' },
  355. opts: [
  356. { text: 'a', value: { msg: 'A' }},
  357. { text: 'b', value: { msg: 'B' }}
  358. ]
  359. },
  360. template:
  361. '<select v-model="test">' +
  362. '<option v-for="op in opts" :value="op.value">{{op.text}}</option>' +
  363. '</select>'
  364. })
  365. var select = el.firstChild
  366. var opts = select.options
  367. expect(opts[0].selected).toBe(true)
  368. expect(opts[1].selected).toBe(false)
  369. expect(vm.test.msg).toBe('A')
  370. opts[1].selected = true
  371. trigger(select, 'change')
  372. _.nextTick(function () {
  373. expect(opts[0].selected).toBe(false)
  374. expect(opts[1].selected).toBe(true)
  375. expect(vm.test.msg).toBe('B')
  376. vm.test = { msg: 'A' }
  377. _.nextTick(function () {
  378. expect(opts[0].selected).toBe(true)
  379. expect(opts[1].selected).toBe(false)
  380. vm.test = { msg: 'C' }
  381. vm.opts.push({text: 'c', value: vm.test})
  382. _.nextTick(function () {
  383. // updating the opts array should force the
  384. // v-model to update
  385. expect(opts[0].selected).toBe(false)
  386. expect(opts[1].selected).toBe(false)
  387. expect(opts[2].selected).toBe(true)
  388. done()
  389. })
  390. })
  391. })
  392. })
  393. it('text', function (done) {
  394. var vm = new Vue({
  395. el: el,
  396. data: {
  397. test: 'b'
  398. },
  399. template: '<input v-model="test">'
  400. })
  401. expect(el.firstChild.value).toBe('b')
  402. vm.test = 'a'
  403. _.nextTick(function () {
  404. expect(el.firstChild.value).toBe('a')
  405. el.firstChild.value = 'c'
  406. trigger(el.firstChild, 'input')
  407. expect(vm.test).toBe('c')
  408. vm._directives[0]._teardown()
  409. el.firstChild.value = 'd'
  410. trigger(el.firstChild, 'input')
  411. expect(vm.test).toBe('c')
  412. done()
  413. })
  414. })
  415. it('text default value', function () {
  416. var vm = new Vue({
  417. el: el,
  418. data: {
  419. test: 'b'
  420. },
  421. template: '<input v-model="test | test" value="a">',
  422. filters: {
  423. test: {
  424. read: function (v) {
  425. return v.slice(0, -1)
  426. },
  427. write: function (v) {
  428. return v + 'c'
  429. }
  430. }
  431. }
  432. })
  433. expect(vm.test).toBe('ac')
  434. expect(el.firstChild.value).toBe('a')
  435. })
  436. it('text lazy', function () {
  437. var vm = new Vue({
  438. el: el,
  439. data: {
  440. test: 'b'
  441. },
  442. template: '<input v-model="test" lazy>'
  443. })
  444. expect(el.firstChild.value).toBe('b')
  445. expect(vm.test).toBe('b')
  446. el.firstChild.value = 'c'
  447. trigger(el.firstChild, 'input')
  448. expect(vm.test).toBe('b')
  449. trigger(el.firstChild, 'change')
  450. expect(vm.test).toBe('c')
  451. })
  452. it('text with filters', function (done) {
  453. var vm = new Vue({
  454. el: el,
  455. data: {
  456. test: 'b'
  457. },
  458. filters: {
  459. test: {
  460. write: function (val) {
  461. return val.toLowerCase()
  462. }
  463. }
  464. },
  465. template: '<input v-model="test | uppercase | test">'
  466. })
  467. expect(el.firstChild.value).toBe('B')
  468. trigger(el.firstChild, 'focus')
  469. el.firstChild.value = 'cc'
  470. trigger(el.firstChild, 'input')
  471. _.nextTick(function () {
  472. expect(el.firstChild.value).toBe('cc')
  473. expect(vm.test).toBe('cc')
  474. trigger(el.firstChild, 'blur')
  475. _.nextTick(function () {
  476. expect(el.firstChild.value).toBe('CC')
  477. expect(vm.test).toBe('cc')
  478. done()
  479. })
  480. })
  481. })
  482. it('text with only write filter', function (done) {
  483. var vm = new Vue({
  484. el: el,
  485. data: {
  486. test: 'b'
  487. },
  488. filters: {
  489. test: {
  490. write: function (val) {
  491. return val.toUpperCase()
  492. }
  493. }
  494. },
  495. template: '<input v-model="test | test">'
  496. })
  497. trigger(el.firstChild, 'focus')
  498. el.firstChild.value = 'cc'
  499. trigger(el.firstChild, 'input')
  500. _.nextTick(function () {
  501. expect(el.firstChild.value).toBe('cc')
  502. expect(vm.test).toBe('CC')
  503. trigger(el.firstChild, 'blur')
  504. _.nextTick(function () {
  505. expect(el.firstChild.value).toBe('CC')
  506. expect(vm.test).toBe('CC')
  507. done()
  508. })
  509. })
  510. })
  511. it('number', function () {
  512. var vm = new Vue({
  513. el: el,
  514. data: {
  515. test: 1
  516. },
  517. template: '<input v-model="test" value="2" number>'
  518. })
  519. expect(vm.test).toBe(2)
  520. el.firstChild.value = 3
  521. trigger(el.firstChild, 'input')
  522. expect(vm.test).toBe(3)
  523. })
  524. it('IE9 cut and delete', function (done) {
  525. var ie9 = _.isIE9
  526. _.isIE9 = true
  527. var vm = new Vue({
  528. el: el,
  529. data: {
  530. test: 'aaa'
  531. },
  532. template: '<input v-model="test">'
  533. })
  534. var input = el.firstChild
  535. input.value = 'aa'
  536. trigger(input, 'cut')
  537. _.nextTick(function () {
  538. expect(vm.test).toBe('aa')
  539. input.value = 'a'
  540. trigger(input, 'keyup', function (e) {
  541. e.keyCode = 8
  542. })
  543. expect(vm.test).toBe('a')
  544. // teardown
  545. vm._directives[0]._teardown()
  546. input.value = 'bbb'
  547. trigger(input, 'keyup', function (e) {
  548. e.keyCode = 8
  549. })
  550. expect(vm.test).toBe('a')
  551. _.isIE9 = ie9
  552. done()
  553. })
  554. })
  555. if (!_.isAndroid) {
  556. it('text + compositionevents', function (done) {
  557. var vm = new Vue({
  558. el: el,
  559. data: {
  560. test: 'aaa',
  561. test2: 'bbb'
  562. },
  563. template: '<input v-model="test"><input v-model="test2 | uppercase">'
  564. })
  565. var input = el.firstChild
  566. var input2 = el.childNodes[1]
  567. trigger(input, 'compositionstart')
  568. trigger(input2, 'compositionstart')
  569. input.value = input2.value = 'ccc'
  570. // input before composition unlock should not call set
  571. trigger(input, 'input')
  572. trigger(input2, 'input')
  573. expect(vm.test).toBe('aaa')
  574. expect(vm.test2).toBe('bbb')
  575. // after composition unlock it should work
  576. trigger(input, 'compositionend')
  577. trigger(input2, 'compositionend')
  578. trigger(input, 'input')
  579. trigger(input2, 'input')
  580. expect(vm.test).toBe('ccc')
  581. expect(vm.test2).toBe('ccc')
  582. // IE complains about "unspecified error" when calling
  583. // setSelectionRange() on an input element that's been
  584. // removed from the DOM, so we wait until the
  585. // selection range callback has fired to end this test.
  586. _.nextTick(done)
  587. })
  588. }
  589. it('textarea', function () {
  590. var vm = new Vue({
  591. el: el,
  592. data: {
  593. test: 'b',
  594. b: 'BB'
  595. },
  596. template: '<textarea v-model="test">a {{b}} c</textarea>'
  597. })
  598. expect(vm.test).toBe('a BB c')
  599. expect(el.firstChild.value).toBe('a BB c')
  600. })
  601. it('warn invalid tag', function () {
  602. new Vue({
  603. el: el,
  604. template: '<div v-model="test"></div>'
  605. })
  606. expect(hasWarned('does not support element type')).toBe(true)
  607. })
  608. it('warn read-only filters', function () {
  609. new Vue({
  610. el: el,
  611. template: '<input v-model="abc | test">',
  612. filters: {
  613. test: function (v) {
  614. return v
  615. }
  616. }
  617. })
  618. expect(hasWarned('read-only filter')).toBe(true)
  619. })
  620. it('support jQuery change event', function (done) {
  621. // restore jQuery
  622. jQuery = $
  623. var vm = new Vue({
  624. el: el,
  625. data: {
  626. test: 'b'
  627. },
  628. template: '<input v-model="test">'
  629. })
  630. expect(el.firstChild.value).toBe('b')
  631. vm.test = 'a'
  632. _.nextTick(function () {
  633. expect(el.firstChild.value).toBe('a')
  634. el.firstChild.value = 'c'
  635. jQuery(el.firstChild).trigger('change')
  636. expect(vm.test).toBe('c')
  637. vm._directives[0]._teardown()
  638. el.firstChild.value = 'd'
  639. jQuery(el.firstChild).trigger('change')
  640. expect(vm.test).toBe('c')
  641. // unset jQuery
  642. jQuery = null
  643. done()
  644. })
  645. })
  646. it('support debounce', function (done) {
  647. var spy = jasmine.createSpy()
  648. var vm = new Vue({
  649. el: el,
  650. data: {
  651. test: 'a'
  652. },
  653. watch: {
  654. test: spy
  655. },
  656. template: '<input v-model="test" debounce="100">'
  657. })
  658. el.firstChild.value = 'b'
  659. trigger(el.firstChild, 'input')
  660. setTimeout(function () {
  661. el.firstChild.value = 'c'
  662. trigger(el.firstChild, 'input')
  663. }, 10)
  664. setTimeout(function () {
  665. el.firstChild.value = 'd'
  666. trigger(el.firstChild, 'input')
  667. }, 20)
  668. setTimeout(function () {
  669. expect(spy.calls.count()).toBe(0)
  670. expect(vm.test).toBe('a')
  671. }, 30)
  672. setTimeout(function () {
  673. expect(spy.calls.count()).toBe(1)
  674. expect(spy).toHaveBeenCalledWith('d', 'a')
  675. expect(vm.test).toBe('d')
  676. setTimeout(function () {
  677. el.firstChild.value = 'e'
  678. // blur should trigger change instantly without debounce
  679. trigger(el.firstChild, 'blur')
  680. _.nextTick(function () {
  681. expect(spy.calls.count()).toBe(2)
  682. expect(spy).toHaveBeenCalledWith('e', 'd')
  683. expect(vm.test).toBe('e')
  684. done()
  685. })
  686. }, 10)
  687. }, 200)
  688. })
  689. it('update on bind value change', function (done) {
  690. var vm = new Vue({
  691. el: el,
  692. template:
  693. '<input type="radio" v-model="a" checked :value="b">' +
  694. '<input type="radio" v-model="a" :value="c">',
  695. data: {
  696. a: 0,
  697. b: 1,
  698. c: 2
  699. }
  700. })
  701. // should sync inline-checked value to a
  702. expect(vm.a).toBe(1)
  703. vm.b = 3
  704. _.nextTick(function () {
  705. expect(vm.a).toBe(3)
  706. expect(el.firstChild.checked).toBe(true)
  707. expect(el.lastChild.checked).toBe(false)
  708. vm.a = 2
  709. _.nextTick(function () {
  710. expect(el.firstChild.checked).toBe(false)
  711. expect(el.lastChild.checked).toBe(true)
  712. done()
  713. })
  714. })
  715. })
  716. it('should not sync value on blur when parent fragment is removed', function (done) {
  717. el.style.display = ''
  718. var vm = new Vue({
  719. el: el,
  720. replace: false,
  721. template:
  722. '<form v-if="ok" @submit.prevent="save">' +
  723. '<input v-model="msg">' +
  724. '</form>',
  725. data: {
  726. ok: true,
  727. msg: 'hi'
  728. },
  729. methods: {
  730. save: function () {
  731. this.ok = false
  732. this.msg = ''
  733. }
  734. }
  735. })
  736. el.querySelector('input').focus()
  737. trigger(el.querySelector('form'), 'submit')
  738. _.nextTick(function () {
  739. expect(vm.msg).toBe('')
  740. done()
  741. })
  742. })
  743. })