on.spec.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. import Vue from 'vue'
  2. import { supportsPassive } from 'core/util/env'
  3. describe('Directive v-on', () => {
  4. let vm, spy, el
  5. beforeEach(() => {
  6. vm = null
  7. spy = jasmine.createSpy()
  8. el = document.createElement('div')
  9. document.body.appendChild(el)
  10. })
  11. afterEach(() => {
  12. if (vm) {
  13. document.body.removeChild(vm.$el)
  14. }
  15. })
  16. it('should bind event to a method', () => {
  17. vm = new Vue({
  18. el,
  19. template: '<div v-on:click="foo"></div>',
  20. methods: { foo: spy }
  21. })
  22. triggerEvent(vm.$el, 'click')
  23. expect(spy.calls.count()).toBe(1)
  24. const args = spy.calls.allArgs()
  25. const event = args[0] && args[0][0] || {}
  26. expect(event.type).toBe('click')
  27. })
  28. it('should bind event to a inline statement', () => {
  29. vm = new Vue({
  30. el,
  31. template: '<div v-on:click="foo(1,2,3,$event)"></div>',
  32. methods: { foo: spy }
  33. })
  34. triggerEvent(vm.$el, 'click')
  35. expect(spy.calls.count()).toBe(1)
  36. const args = spy.calls.allArgs()
  37. const firstArgs = args[0]
  38. expect(firstArgs.length).toBe(4)
  39. expect(firstArgs[0]).toBe(1)
  40. expect(firstArgs[1]).toBe(2)
  41. expect(firstArgs[2]).toBe(3)
  42. expect(firstArgs[3].type).toBe('click')
  43. })
  44. it('should support inline function expression', () => {
  45. const spy = jasmine.createSpy()
  46. vm = new Vue({
  47. el,
  48. template: `<div class="test" @click="function (e) { log(e.target.className) }"></div>`,
  49. methods: {
  50. log: spy
  51. }
  52. }).$mount()
  53. triggerEvent(vm.$el, 'click')
  54. expect(spy).toHaveBeenCalledWith('test')
  55. })
  56. it('should support shorthand', () => {
  57. vm = new Vue({
  58. el,
  59. template: '<a href="#test" @click.prevent="foo"></a>',
  60. methods: { foo: spy }
  61. })
  62. triggerEvent(vm.$el, 'click')
  63. expect(spy.calls.count()).toBe(1)
  64. })
  65. it('should support stop propagation', () => {
  66. vm = new Vue({
  67. el,
  68. template: `
  69. <div @click.stop="foo"></div>
  70. `,
  71. methods: { foo: spy }
  72. })
  73. const hash = window.location.hash
  74. triggerEvent(vm.$el, 'click')
  75. expect(window.location.hash).toBe(hash)
  76. })
  77. it('should support prevent default', () => {
  78. vm = new Vue({
  79. el,
  80. template: `
  81. <input type="checkbox" ref="input" @click.prevent="foo">
  82. `,
  83. methods: {
  84. foo ($event) {
  85. spy($event.defaultPrevented)
  86. }
  87. }
  88. })
  89. vm.$refs.input.checked = false
  90. triggerEvent(vm.$refs.input, 'click')
  91. expect(spy).toHaveBeenCalledWith(true)
  92. })
  93. it('should support capture', () => {
  94. const callOrder = []
  95. vm = new Vue({
  96. el,
  97. template: `
  98. <div @click.capture="foo">
  99. <div @click="bar"></div>
  100. </div>
  101. `,
  102. methods: {
  103. foo () { callOrder.push(1) },
  104. bar () { callOrder.push(2) }
  105. }
  106. })
  107. triggerEvent(vm.$el.firstChild, 'click')
  108. expect(callOrder.toString()).toBe('1,2')
  109. })
  110. it('should support once', () => {
  111. vm = new Vue({
  112. el,
  113. template: `
  114. <div @click.once="foo">
  115. </div>
  116. `,
  117. methods: { foo: spy }
  118. })
  119. triggerEvent(vm.$el, 'click')
  120. expect(spy.calls.count()).toBe(1)
  121. triggerEvent(vm.$el, 'click')
  122. expect(spy.calls.count()).toBe(1) // should no longer trigger
  123. })
  124. // #4655
  125. it('should handle .once on multiple elements properly', () => {
  126. vm = new Vue({
  127. el,
  128. template: `
  129. <div>
  130. <button ref="one" @click.once="foo">one</button>
  131. <button ref="two" @click.once="foo">two</button>
  132. </div>
  133. `,
  134. methods: { foo: spy }
  135. })
  136. triggerEvent(vm.$refs.one, 'click')
  137. expect(spy.calls.count()).toBe(1)
  138. triggerEvent(vm.$refs.one, 'click')
  139. expect(spy.calls.count()).toBe(1)
  140. triggerEvent(vm.$refs.two, 'click')
  141. expect(spy.calls.count()).toBe(2)
  142. triggerEvent(vm.$refs.one, 'click')
  143. triggerEvent(vm.$refs.two, 'click')
  144. expect(spy.calls.count()).toBe(2)
  145. })
  146. it('should support capture and once', () => {
  147. const callOrder = []
  148. vm = new Vue({
  149. el,
  150. template: `
  151. <div @click.capture.once="foo">
  152. <div @click="bar"></div>
  153. </div>
  154. `,
  155. methods: {
  156. foo () { callOrder.push(1) },
  157. bar () { callOrder.push(2) }
  158. }
  159. })
  160. triggerEvent(vm.$el.firstChild, 'click')
  161. expect(callOrder.toString()).toBe('1,2')
  162. triggerEvent(vm.$el.firstChild, 'click')
  163. expect(callOrder.toString()).toBe('1,2,2')
  164. })
  165. // #4846
  166. it('should support once and other modifiers', () => {
  167. vm = new Vue({
  168. el,
  169. template: `<div @click.once.self="foo"><span/></div>`,
  170. methods: { foo: spy }
  171. })
  172. triggerEvent(vm.$el.firstChild, 'click')
  173. expect(spy).not.toHaveBeenCalled()
  174. triggerEvent(vm.$el, 'click')
  175. expect(spy).toHaveBeenCalled()
  176. triggerEvent(vm.$el, 'click')
  177. expect(spy.calls.count()).toBe(1)
  178. })
  179. it('should support keyCode', () => {
  180. vm = new Vue({
  181. el,
  182. template: `<input @keyup.enter="foo">`,
  183. methods: { foo: spy }
  184. })
  185. triggerEvent(vm.$el, 'keyup', e => {
  186. e.keyCode = 13
  187. })
  188. expect(spy).toHaveBeenCalled()
  189. })
  190. it('should support automatic key name inference', () => {
  191. vm = new Vue({
  192. el,
  193. template: `<input @keyup.arrow-right="foo">`,
  194. methods: { foo: spy }
  195. })
  196. triggerEvent(vm.$el, 'keyup', e => {
  197. e.key = 'ArrowRight'
  198. })
  199. expect(spy).toHaveBeenCalled()
  200. })
  201. // ctrl, shift, alt, meta
  202. it('should support system modifers', () => {
  203. vm = new Vue({
  204. el,
  205. template: `
  206. <div>
  207. <input ref="ctrl" @keyup.ctrl="foo">
  208. <input ref="shift" @keyup.shift="foo">
  209. <input ref="alt" @keyup.alt="foo">
  210. <input ref="meta" @keyup.meta="foo">
  211. </div>
  212. `,
  213. methods: { foo: spy }
  214. })
  215. triggerEvent(vm.$refs.ctrl, 'keyup')
  216. expect(spy.calls.count()).toBe(0)
  217. triggerEvent(vm.$refs.ctrl, 'keyup', e => { e.ctrlKey = true })
  218. expect(spy.calls.count()).toBe(1)
  219. triggerEvent(vm.$refs.shift, 'keyup')
  220. expect(spy.calls.count()).toBe(1)
  221. triggerEvent(vm.$refs.shift, 'keyup', e => { e.shiftKey = true })
  222. expect(spy.calls.count()).toBe(2)
  223. triggerEvent(vm.$refs.alt, 'keyup')
  224. expect(spy.calls.count()).toBe(2)
  225. triggerEvent(vm.$refs.alt, 'keyup', e => { e.altKey = true })
  226. expect(spy.calls.count()).toBe(3)
  227. triggerEvent(vm.$refs.meta, 'keyup')
  228. expect(spy.calls.count()).toBe(3)
  229. triggerEvent(vm.$refs.meta, 'keyup', e => { e.metaKey = true })
  230. expect(spy.calls.count()).toBe(4)
  231. })
  232. it('should support exact modifier', () => {
  233. vm = new Vue({
  234. el,
  235. template: `
  236. <div>
  237. <input ref="ctrl" @keyup.exact="foo">
  238. </div>
  239. `,
  240. methods: { foo: spy }
  241. })
  242. triggerEvent(vm.$refs.ctrl, 'keyup')
  243. expect(spy.calls.count()).toBe(1)
  244. triggerEvent(vm.$refs.ctrl, 'keyup', e => {
  245. e.ctrlKey = true
  246. })
  247. expect(spy.calls.count()).toBe(1)
  248. // should not trigger if has other system modifiers
  249. triggerEvent(vm.$refs.ctrl, 'keyup', e => {
  250. e.ctrlKey = true
  251. e.altKey = true
  252. })
  253. expect(spy.calls.count()).toBe(1)
  254. })
  255. it('should support system modifers with exact', () => {
  256. vm = new Vue({
  257. el,
  258. template: `
  259. <div>
  260. <input ref="ctrl" @keyup.ctrl.exact="foo">
  261. </div>
  262. `,
  263. methods: { foo: spy }
  264. })
  265. triggerEvent(vm.$refs.ctrl, 'keyup')
  266. expect(spy.calls.count()).toBe(0)
  267. triggerEvent(vm.$refs.ctrl, 'keyup', e => {
  268. e.ctrlKey = true
  269. })
  270. expect(spy.calls.count()).toBe(1)
  271. // should not trigger if has other system modifiers
  272. triggerEvent(vm.$refs.ctrl, 'keyup', e => {
  273. e.ctrlKey = true
  274. e.altKey = true
  275. })
  276. expect(spy.calls.count()).toBe(1)
  277. })
  278. it('should support number keyCode', () => {
  279. vm = new Vue({
  280. el,
  281. template: `<input @keyup.13="foo">`,
  282. methods: { foo: spy }
  283. })
  284. triggerEvent(vm.$el, 'keyup', e => {
  285. e.keyCode = 13
  286. })
  287. expect(spy).toHaveBeenCalled()
  288. })
  289. it('should support mouse modifier', () => {
  290. const left = 0
  291. const middle = 1
  292. const right = 2
  293. const spyLeft = jasmine.createSpy()
  294. const spyMiddle = jasmine.createSpy()
  295. const spyRight = jasmine.createSpy()
  296. vm = new Vue({
  297. el,
  298. template: `
  299. <div>
  300. <div ref="left" @mousedown.left="foo">left</div>
  301. <div ref="right" @mousedown.right="foo1">right</div>
  302. <div ref="middle" @mousedown.middle="foo2">right</div>
  303. </div>
  304. `,
  305. methods: {
  306. foo: spyLeft,
  307. foo1: spyRight,
  308. foo2: spyMiddle
  309. }
  310. })
  311. triggerEvent(vm.$refs.left, 'mousedown', e => { e.button = right })
  312. triggerEvent(vm.$refs.left, 'mousedown', e => { e.button = middle })
  313. expect(spyLeft).not.toHaveBeenCalled()
  314. triggerEvent(vm.$refs.left, 'mousedown', e => { e.button = left })
  315. expect(spyLeft).toHaveBeenCalled()
  316. triggerEvent(vm.$refs.right, 'mousedown', e => { e.button = left })
  317. triggerEvent(vm.$refs.right, 'mousedown', e => { e.button = middle })
  318. expect(spyRight).not.toHaveBeenCalled()
  319. triggerEvent(vm.$refs.right, 'mousedown', e => { e.button = right })
  320. expect(spyRight).toHaveBeenCalled()
  321. triggerEvent(vm.$refs.middle, 'mousedown', e => { e.button = left })
  322. triggerEvent(vm.$refs.middle, 'mousedown', e => { e.button = right })
  323. expect(spyMiddle).not.toHaveBeenCalled()
  324. triggerEvent(vm.$refs.middle, 'mousedown', e => { e.button = middle })
  325. expect(spyMiddle).toHaveBeenCalled()
  326. })
  327. it('should support custom keyCode', () => {
  328. Vue.config.keyCodes.test = 1
  329. vm = new Vue({
  330. el,
  331. template: `<input @keyup.test="foo">`,
  332. methods: { foo: spy }
  333. })
  334. triggerEvent(vm.$el, 'keyup', e => {
  335. e.keyCode = 1
  336. })
  337. expect(spy).toHaveBeenCalled()
  338. Vue.config.keyCodes = Object.create(null)
  339. })
  340. it('should override build-in keyCode', () => {
  341. Vue.config.keyCodes.up = [1, 87]
  342. vm = new Vue({
  343. el,
  344. template: `<input @keyup.up="foo" @keyup.down="foo">`,
  345. methods: { foo: spy }
  346. })
  347. triggerEvent(vm.$el, 'keyup', e => {
  348. e.keyCode = 87
  349. })
  350. expect(spy).toHaveBeenCalled()
  351. triggerEvent(vm.$el, 'keyup', e => {
  352. e.keyCode = 1
  353. })
  354. expect(spy).toHaveBeenCalledTimes(2)
  355. // should not affect build-in down keycode
  356. triggerEvent(vm.$el, 'keyup', e => {
  357. e.keyCode = 40
  358. })
  359. expect(spy).toHaveBeenCalledTimes(3)
  360. Vue.config.keyCodes = Object.create(null)
  361. })
  362. it('should bind to a child component', () => {
  363. vm = new Vue({
  364. el,
  365. template: '<bar @custom="foo"></bar>',
  366. methods: { foo: spy },
  367. components: {
  368. bar: {
  369. template: '<span>Hello</span>'
  370. }
  371. }
  372. })
  373. vm.$children[0].$emit('custom', 'foo', 'bar')
  374. expect(spy).toHaveBeenCalledWith('foo', 'bar')
  375. })
  376. it('should be able to bind native events for a child component', () => {
  377. vm = new Vue({
  378. el,
  379. template: '<bar @click.native="foo"></bar>',
  380. methods: { foo: spy },
  381. components: {
  382. bar: {
  383. template: '<span>Hello</span>'
  384. }
  385. }
  386. })
  387. vm.$children[0].$emit('click')
  388. expect(spy).not.toHaveBeenCalled()
  389. triggerEvent(vm.$children[0].$el, 'click')
  390. expect(spy).toHaveBeenCalled()
  391. })
  392. it('.once modifier should work with child components', () => {
  393. vm = new Vue({
  394. el,
  395. template: '<bar @custom.once="foo"></bar>',
  396. methods: { foo: spy },
  397. components: {
  398. bar: {
  399. template: '<span>Hello</span>'
  400. }
  401. }
  402. })
  403. vm.$children[0].$emit('custom')
  404. expect(spy.calls.count()).toBe(1)
  405. vm.$children[0].$emit('custom')
  406. expect(spy.calls.count()).toBe(1) // should not be called again
  407. })
  408. it('remove listener', done => {
  409. const spy2 = jasmine.createSpy('remove listener')
  410. vm = new Vue({
  411. el,
  412. methods: { foo: spy, bar: spy2 },
  413. data: {
  414. ok: true
  415. },
  416. render (h) {
  417. return this.ok
  418. ? h('input', { on: { click: this.foo }})
  419. : h('input', { on: { input: this.bar }})
  420. }
  421. })
  422. triggerEvent(vm.$el, 'click')
  423. expect(spy.calls.count()).toBe(1)
  424. expect(spy2.calls.count()).toBe(0)
  425. vm.ok = false
  426. waitForUpdate(() => {
  427. triggerEvent(vm.$el, 'click')
  428. expect(spy.calls.count()).toBe(1) // should no longer trigger
  429. triggerEvent(vm.$el, 'input')
  430. expect(spy2.calls.count()).toBe(1)
  431. }).then(done)
  432. })
  433. it('remove capturing listener', done => {
  434. const spy2 = jasmine.createSpy('remove listener')
  435. vm = new Vue({
  436. el,
  437. methods: { foo: spy, bar: spy2, stopped (ev) { ev.stopPropagation() } },
  438. data: {
  439. ok: true
  440. },
  441. render (h) {
  442. return this.ok
  443. ? h('div', { on: { '!click': this.foo }}, [h('div', { on: { click: this.stopped }})])
  444. : h('div', { on: { mouseOver: this.bar }}, [h('div')])
  445. }
  446. })
  447. triggerEvent(vm.$el.firstChild, 'click')
  448. expect(spy.calls.count()).toBe(1)
  449. expect(spy2.calls.count()).toBe(0)
  450. vm.ok = false
  451. waitForUpdate(() => {
  452. triggerEvent(vm.$el.firstChild, 'click')
  453. expect(spy.calls.count()).toBe(1) // should no longer trigger
  454. triggerEvent(vm.$el, 'mouseOver')
  455. expect(spy2.calls.count()).toBe(1)
  456. }).then(done)
  457. })
  458. it('remove once listener', done => {
  459. const spy2 = jasmine.createSpy('remove listener')
  460. vm = new Vue({
  461. el,
  462. methods: { foo: spy, bar: spy2 },
  463. data: {
  464. ok: true
  465. },
  466. render (h) {
  467. return this.ok
  468. ? h('input', { on: { '~click': this.foo }})
  469. : h('input', { on: { input: this.bar }})
  470. }
  471. })
  472. triggerEvent(vm.$el, 'click')
  473. expect(spy.calls.count()).toBe(1)
  474. triggerEvent(vm.$el, 'click')
  475. expect(spy.calls.count()).toBe(1) // should no longer trigger
  476. expect(spy2.calls.count()).toBe(0)
  477. vm.ok = false
  478. waitForUpdate(() => {
  479. triggerEvent(vm.$el, 'click')
  480. expect(spy.calls.count()).toBe(1) // should no longer trigger
  481. triggerEvent(vm.$el, 'input')
  482. expect(spy2.calls.count()).toBe(1)
  483. }).then(done)
  484. })
  485. it('remove capturing and once listener', done => {
  486. const spy2 = jasmine.createSpy('remove listener')
  487. vm = new Vue({
  488. el,
  489. methods: { foo: spy, bar: spy2, stopped (ev) { ev.stopPropagation() } },
  490. data: {
  491. ok: true
  492. },
  493. render (h) {
  494. return this.ok
  495. ? h('div', { on: { '~!click': this.foo }}, [h('div', { on: { click: this.stopped }})])
  496. : h('div', { on: { mouseOver: this.bar }}, [h('div')])
  497. }
  498. })
  499. triggerEvent(vm.$el.firstChild, 'click')
  500. expect(spy.calls.count()).toBe(1)
  501. triggerEvent(vm.$el.firstChild, 'click')
  502. expect(spy.calls.count()).toBe(1) // should no longer trigger
  503. expect(spy2.calls.count()).toBe(0)
  504. vm.ok = false
  505. waitForUpdate(() => {
  506. triggerEvent(vm.$el.firstChild, 'click')
  507. expect(spy.calls.count()).toBe(1) // should no longer trigger
  508. triggerEvent(vm.$el, 'mouseOver')
  509. expect(spy2.calls.count()).toBe(1)
  510. }).then(done)
  511. })
  512. it('remove listener on child component', done => {
  513. const spy2 = jasmine.createSpy('remove listener')
  514. vm = new Vue({
  515. el,
  516. methods: { foo: spy, bar: spy2 },
  517. data: {
  518. ok: true
  519. },
  520. components: {
  521. test: {
  522. template: '<div></div>'
  523. }
  524. },
  525. render (h) {
  526. return this.ok
  527. ? h('test', { on: { foo: this.foo }})
  528. : h('test', { on: { bar: this.bar }})
  529. }
  530. })
  531. vm.$children[0].$emit('foo')
  532. expect(spy.calls.count()).toBe(1)
  533. expect(spy2.calls.count()).toBe(0)
  534. vm.ok = false
  535. waitForUpdate(() => {
  536. vm.$children[0].$emit('foo')
  537. expect(spy.calls.count()).toBe(1) // should no longer trigger
  538. vm.$children[0].$emit('bar')
  539. expect(spy2.calls.count()).toBe(1)
  540. }).then(done)
  541. })
  542. it('warn missing handlers', () => {
  543. vm = new Vue({
  544. el,
  545. data: { none: null },
  546. template: `<div @click="none"></div>`
  547. })
  548. expect(`Invalid handler for event "click": got null`).toHaveBeenWarned()
  549. expect(() => {
  550. triggerEvent(vm.$el, 'click')
  551. }).not.toThrow()
  552. })
  553. // Github Issue #5046
  554. it('should support keyboard modifier for direction keys', () => {
  555. const spyLeft = jasmine.createSpy()
  556. const spyRight = jasmine.createSpy()
  557. const spyUp = jasmine.createSpy()
  558. const spyDown = jasmine.createSpy()
  559. vm = new Vue({
  560. el,
  561. template: `
  562. <div>
  563. <input ref="left" @keydown.left="foo"></input>
  564. <input ref="right" @keydown.right="foo1"></input>
  565. <input ref="up" @keydown.up="foo2"></input>
  566. <input ref="down" @keydown.down="foo3"></input>
  567. </div>
  568. `,
  569. methods: {
  570. foo: spyLeft,
  571. foo1: spyRight,
  572. foo2: spyUp,
  573. foo3: spyDown
  574. }
  575. })
  576. triggerEvent(vm.$refs.left, 'keydown', e => { e.keyCode = 37 })
  577. triggerEvent(vm.$refs.left, 'keydown', e => { e.keyCode = 39 })
  578. triggerEvent(vm.$refs.right, 'keydown', e => { e.keyCode = 39 })
  579. triggerEvent(vm.$refs.right, 'keydown', e => { e.keyCode = 38 })
  580. triggerEvent(vm.$refs.up, 'keydown', e => { e.keyCode = 38 })
  581. triggerEvent(vm.$refs.up, 'keydown', e => { e.keyCode = 37 })
  582. triggerEvent(vm.$refs.down, 'keydown', e => { e.keyCode = 40 })
  583. triggerEvent(vm.$refs.down, 'keydown', e => { e.keyCode = 39 })
  584. expect(spyLeft.calls.count()).toBe(1)
  585. expect(spyRight.calls.count()).toBe(1)
  586. expect(spyUp.calls.count()).toBe(1)
  587. expect(spyDown.calls.count()).toBe(1)
  588. })
  589. // This test case should only run when the test browser supports passive.
  590. if (supportsPassive) {
  591. it('should support passive', () => {
  592. vm = new Vue({
  593. el,
  594. template: `
  595. <div>
  596. <input type="checkbox" ref="normal" @click="foo"/>
  597. <input type="checkbox" ref="passive" @click.passive="foo"/>
  598. <input type="checkbox" ref="exclusive" @click.prevent.passive/>
  599. </div>
  600. `,
  601. methods: {
  602. foo (e) {
  603. e.preventDefault()
  604. }
  605. }
  606. })
  607. vm.$refs.normal.checked = false
  608. vm.$refs.passive.checked = false
  609. vm.$refs.exclusive.checked = false
  610. vm.$refs.normal.click()
  611. vm.$refs.passive.click()
  612. vm.$refs.exclusive.click()
  613. expect(vm.$refs.normal.checked).toBe(false)
  614. expect(vm.$refs.passive.checked).toBe(true)
  615. expect(vm.$refs.exclusive.checked).toBe(true)
  616. expect('passive and prevent can\'t be used together. Passive handler can\'t prevent default event.').toHaveBeenWarned()
  617. })
  618. }
  619. // GitHub Issues #5146
  620. it('should only prevent when match keycode', () => {
  621. let prevented = false
  622. vm = new Vue({
  623. el,
  624. template: `
  625. <input ref="input" @keydown.enter.prevent="foo">
  626. `,
  627. methods: {
  628. foo ($event) {
  629. prevented = $event.defaultPrevented
  630. }
  631. }
  632. })
  633. triggerEvent(vm.$refs.input, 'keydown', e => { e.keyCode = 32 })
  634. expect(prevented).toBe(false)
  635. triggerEvent(vm.$refs.input, 'keydown', e => { e.keyCode = 13 })
  636. expect(prevented).toBe(true)
  637. })
  638. it('should warn click.right', () => {
  639. new Vue({
  640. template: `<div @click.right="foo"></div>`,
  641. methods: { foo () {} }
  642. }).$mount()
  643. expect(`Use "contextmenu" instead`).toHaveBeenWarned()
  644. })
  645. it('object syntax (no argument)', () => {
  646. const click = jasmine.createSpy('click')
  647. const mouseup = jasmine.createSpy('mouseup')
  648. vm = new Vue({
  649. el,
  650. template: `<button v-on="listeners">foo</button>`,
  651. created () {
  652. this.listeners = {
  653. click,
  654. mouseup
  655. }
  656. }
  657. })
  658. triggerEvent(vm.$el, 'click')
  659. expect(click.calls.count()).toBe(1)
  660. expect(mouseup.calls.count()).toBe(0)
  661. triggerEvent(vm.$el, 'mouseup')
  662. expect(click.calls.count()).toBe(1)
  663. expect(mouseup.calls.count()).toBe(1)
  664. })
  665. it('object syntax (no argument, mixed with normal listeners)', () => {
  666. const click1 = jasmine.createSpy('click1')
  667. const click2 = jasmine.createSpy('click2')
  668. const mouseup = jasmine.createSpy('mouseup')
  669. vm = new Vue({
  670. el,
  671. template: `<button v-on="listeners" @click="click2">foo</button>`,
  672. created () {
  673. this.listeners = {
  674. click: click1,
  675. mouseup
  676. }
  677. },
  678. methods: {
  679. click2
  680. }
  681. })
  682. triggerEvent(vm.$el, 'click')
  683. expect(click1.calls.count()).toBe(1)
  684. expect(click2.calls.count()).toBe(1)
  685. expect(mouseup.calls.count()).toBe(0)
  686. triggerEvent(vm.$el, 'mouseup')
  687. expect(click1.calls.count()).toBe(1)
  688. expect(click2.calls.count()).toBe(1)
  689. expect(mouseup.calls.count()).toBe(1)
  690. })
  691. it('object syntax (usage in HOC, mixed with native listeners)', () => {
  692. const click = jasmine.createSpy('click')
  693. const mouseup = jasmine.createSpy('mouseup')
  694. const mousedown = jasmine.createSpy('mousedown')
  695. var vm = new Vue({
  696. el,
  697. template: `
  698. <foo-button
  699. @click="click"
  700. @mousedown="mousedown"
  701. @mouseup.native="mouseup">
  702. </foo-button>
  703. `,
  704. methods: {
  705. click,
  706. mouseup,
  707. mousedown
  708. },
  709. components: {
  710. fooButton: {
  711. template: `
  712. <button v-on="$listeners"></button>
  713. `
  714. }
  715. }
  716. })
  717. triggerEvent(vm.$el, 'click')
  718. expect(click.calls.count()).toBe(1)
  719. expect(mouseup.calls.count()).toBe(0)
  720. expect(mousedown.calls.count()).toBe(0)
  721. triggerEvent(vm.$el, 'mouseup')
  722. expect(click.calls.count()).toBe(1)
  723. expect(mouseup.calls.count()).toBe(1)
  724. expect(mousedown.calls.count()).toBe(0)
  725. triggerEvent(vm.$el, 'mousedown')
  726. expect(click.calls.count()).toBe(1)
  727. expect(mouseup.calls.count()).toBe(1)
  728. expect(mousedown.calls.count()).toBe(1)
  729. })
  730. it('warn object syntax with modifier', () => {
  731. new Vue({
  732. template: `<button v-on.self="{}"></button>`
  733. }).$mount()
  734. expect(`v-on without argument does not support modifiers`).toHaveBeenWarned()
  735. })
  736. it('warn object syntax with non-object value', () => {
  737. new Vue({
  738. template: `<button v-on="123"></button>`
  739. }).$mount()
  740. expect(`v-on without argument expects an Object value`).toHaveBeenWarned()
  741. })
  742. })