model_spec.js 20 KB

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