1import Vue from 'vue'2import { supportsPassive } from 'core/util/env'3import { SpyInstanceFn } from 'vitest'45describe('Directive v-on', () => {6 let vm, spy: SpyInstanceFn, el: HTMLElement78 beforeEach(() => {9 vm = null10 spy = vi.fn()11 el = document.createElement('div')12 document.body.appendChild(el)13 })1415 afterEach(() => {16 if (vm) {17 document.body.removeChild(vm.$el)18 }19 })2021 it('should bind event to a method', () => {22 vm = new Vue({23 el,24 template: '<div v-on:click="foo"></div>',25 methods: { foo: spy }26 })27 triggerEvent(vm.$el, 'click')28 expect(spy.mock.calls.length).toBe(1)2930 const args = spy.mock.calls31 const event = (args[0] && args[0][0]) || {}32 expect(event.type).toBe('click')33 })3435 it('should bind event to an inline statement', () => {36 vm = new Vue({37 el,38 template: '<div v-on:click="foo(1,2,3,$event)"></div>',39 methods: { foo: spy }40 })41 triggerEvent(vm.$el, 'click')42 expect(spy.mock.calls.length).toBe(1)4344 const args = spy.mock.calls45 const firstArgs = args[0]46 expect(firstArgs.length).toBe(4)47 expect(firstArgs[0]).toBe(1)48 expect(firstArgs[1]).toBe(2)49 expect(firstArgs[2]).toBe(3)50 expect(firstArgs[3].type).toBe('click')51 })5253 it('should support inline function expression', () => {54 const spy = vi.fn()55 vm = new Vue({56 el,57 template: `<div class="test" @click="function (e) { log(e.target.className) }"></div>`,58 methods: {59 log: spy60 }61 }).$mount()62 triggerEvent(vm.$el, 'click')63 expect(spy).toHaveBeenCalledWith('test')64 })6566 it('should support shorthand', () => {67 vm = new Vue({68 el,69 template: '<a href="#test" @click.prevent="foo"></a>',70 methods: { foo: spy }71 })72 triggerEvent(vm.$el, 'click')73 expect(spy.mock.calls.length).toBe(1)74 })7576 it('should support stop propagation', () => {77 vm = new Vue({78 el,79 template: `80 <div @click.stop="foo"></div>81 `,82 methods: { foo: spy }83 })84 const hash = window.location.hash85 triggerEvent(vm.$el, 'click')86 expect(window.location.hash).toBe(hash)87 })8889 it('should support prevent default', () => {90 vm = new Vue({91 el,92 template: `93 <input type="checkbox" ref="input" @click.prevent="foo">94 `,95 methods: {96 foo($event) {97 spy($event.defaultPrevented)98 }99 }100 })101 vm.$refs.input.checked = false102 triggerEvent(vm.$refs.input, 'click')103 expect(spy).toHaveBeenCalledWith(true)104 })105106 it('should support capture', () => {107 const callOrder: any[] = []108 vm = new Vue({109 el,110 template: `111 <div @click.capture="foo">112 <div @click="bar"></div>113 </div>114 `,115 methods: {116 foo() {117 callOrder.push(1)118 },119 bar() {120 callOrder.push(2)121 }122 }123 })124 triggerEvent(vm.$el.firstChild, 'click')125 expect(callOrder.toString()).toBe('1,2')126 })127128 it('should support once', () => {129 vm = new Vue({130 el,131 template: `132 <div @click.once="foo">133 </div>134 `,135 methods: { foo: spy }136 })137 triggerEvent(vm.$el, 'click')138 expect(spy.mock.calls.length).toBe(1)139 triggerEvent(vm.$el, 'click')140 expect(spy.mock.calls.length).toBe(1) // should no longer trigger141 })142143 // #4655144 it('should handle .once on multiple elements properly', () => {145 vm = new Vue({146 el,147 template: `148 <div>149 <button ref="one" @click.once="foo">one</button>150 <button ref="two" @click.once="foo">two</button>151 </div>152 `,153 methods: { foo: spy }154 })155 triggerEvent(vm.$refs.one, 'click')156 expect(spy.mock.calls.length).toBe(1)157 triggerEvent(vm.$refs.one, 'click')158 expect(spy.mock.calls.length).toBe(1)159 triggerEvent(vm.$refs.two, 'click')160 expect(spy.mock.calls.length).toBe(2)161 triggerEvent(vm.$refs.one, 'click')162 triggerEvent(vm.$refs.two, 'click')163 expect(spy.mock.calls.length).toBe(2)164 })165166 it('should support capture and once', () => {167 const callOrder: any[] = []168 vm = new Vue({169 el,170 template: `171 <div @click.capture.once="foo">172 <div @click="bar"></div>173 </div>174 `,175 methods: {176 foo() {177 callOrder.push(1)178 },179 bar() {180 callOrder.push(2)181 }182 }183 })184 triggerEvent(vm.$el.firstChild, 'click')185 expect(callOrder.toString()).toBe('1,2')186 triggerEvent(vm.$el.firstChild, 'click')187 expect(callOrder.toString()).toBe('1,2,2')188 })189190 // #4846191 it('should support once and other modifiers', () => {192 vm = new Vue({193 el,194 template: `<div @click.once.self="foo"><span/></div>`,195 methods: { foo: spy }196 })197 triggerEvent(vm.$el.firstChild, 'click')198 expect(spy).not.toHaveBeenCalled()199 triggerEvent(vm.$el, 'click')200 expect(spy).toHaveBeenCalled()201 triggerEvent(vm.$el, 'click')202 expect(spy.mock.calls.length).toBe(1)203 })204205 it('should support keyCode', () => {206 vm = new Vue({207 el,208 template: `<input @keyup.enter="foo">`,209 methods: { foo: spy }210 })211 triggerEvent(vm.$el, 'keyup', e => {212 e.keyCode = 13213 })214 expect(spy).toHaveBeenCalled()215 })216217 it('should support automatic key name inference', () => {218 vm = new Vue({219 el,220 template: `<input @keyup.arrow-right="foo">`,221 methods: { foo: spy }222 })223 triggerEvent(vm.$el, 'keyup', e => {224 e.key = 'ArrowRight'225 })226 expect(spy).toHaveBeenCalled()227 })228229 // ctrl, shift, alt, meta230 it('should support system modifiers', () => {231 vm = new Vue({232 el,233 template: `234 <div>235 <input ref="ctrl" @keyup.ctrl="foo">236 <input ref="shift" @keyup.shift="foo">237 <input ref="alt" @keyup.alt="foo">238 <input ref="meta" @keyup.meta="foo">239 </div>240 `,241 methods: { foo: spy }242 })243244 triggerEvent(vm.$refs.ctrl, 'keyup')245 expect(spy.mock.calls.length).toBe(0)246 triggerEvent(vm.$refs.ctrl, 'keyup', e => {247 e.ctrlKey = true248 })249 expect(spy.mock.calls.length).toBe(1)250251 triggerEvent(vm.$refs.shift, 'keyup')252 expect(spy.mock.calls.length).toBe(1)253 triggerEvent(vm.$refs.shift, 'keyup', e => {254 e.shiftKey = true255 })256 expect(spy.mock.calls.length).toBe(2)257258 triggerEvent(vm.$refs.alt, 'keyup')259 expect(spy.mock.calls.length).toBe(2)260 triggerEvent(vm.$refs.alt, 'keyup', e => {261 e.altKey = true262 })263 expect(spy.mock.calls.length).toBe(3)264265 triggerEvent(vm.$refs.meta, 'keyup')266 expect(spy.mock.calls.length).toBe(3)267 triggerEvent(vm.$refs.meta, 'keyup', e => {268 e.metaKey = true269 })270 expect(spy.mock.calls.length).toBe(4)271 })272273 it('should support exact modifier', () => {274 vm = new Vue({275 el,276 template: `277 <div>278 <input ref="ctrl" @keyup.exact="foo">279 </div>280 `,281 methods: { foo: spy }282 })283284 triggerEvent(vm.$refs.ctrl, 'keyup')285 expect(spy.mock.calls.length).toBe(1)286287 triggerEvent(vm.$refs.ctrl, 'keyup', e => {288 e.ctrlKey = true289 })290 expect(spy.mock.calls.length).toBe(1)291292 // should not trigger if has other system modifiers293 triggerEvent(vm.$refs.ctrl, 'keyup', e => {294 e.ctrlKey = true295 e.altKey = true296 })297 expect(spy.mock.calls.length).toBe(1)298 })299300 it('should support system modifiers with exact', () => {301 vm = new Vue({302 el,303 template: `304 <div>305 <input ref="ctrl" @keyup.ctrl.exact="foo">306 </div>307 `,308 methods: { foo: spy }309 })310311 triggerEvent(vm.$refs.ctrl, 'keyup')312 expect(spy.mock.calls.length).toBe(0)313314 triggerEvent(vm.$refs.ctrl, 'keyup', e => {315 e.ctrlKey = true316 })317 expect(spy.mock.calls.length).toBe(1)318319 // should not trigger if has other system modifiers320 triggerEvent(vm.$refs.ctrl, 'keyup', e => {321 e.ctrlKey = true322 e.altKey = true323 })324 expect(spy.mock.calls.length).toBe(1)325 })326327 it('should support number keyCode', () => {328 vm = new Vue({329 el,330 template: `<input @keyup.13="foo">`,331 methods: { foo: spy }332 })333 triggerEvent(vm.$el, 'keyup', e => {334 e.keyCode = 13335 })336 expect(spy).toHaveBeenCalled()337 })338339 it('should support mouse modifier', () => {340 const left = 0341 const middle = 1342 const right = 2343 const spyLeft = vi.fn()344 const spyMiddle = vi.fn()345 const spyRight = vi.fn()346347 vm = new Vue({348 el,349 template: `350 <div>351 <div ref="left" @mousedown.left="foo">left</div>352 <div ref="right" @mousedown.right="foo1">right</div>353 <div ref="middle" @mousedown.middle="foo2">right</div>354 </div>355 `,356 methods: {357 foo: spyLeft,358 foo1: spyRight,359 foo2: spyMiddle360 }361 })362363 triggerEvent(vm.$refs.left, 'mousedown', e => {364 e.button = right365 })366 triggerEvent(vm.$refs.left, 'mousedown', e => {367 e.button = middle368 })369 expect(spyLeft).not.toHaveBeenCalled()370 triggerEvent(vm.$refs.left, 'mousedown', e => {371 e.button = left372 })373 expect(spyLeft).toHaveBeenCalled()374375 triggerEvent(vm.$refs.right, 'mousedown', e => {376 e.button = left377 })378 triggerEvent(vm.$refs.right, 'mousedown', e => {379 e.button = middle380 })381 expect(spyRight).not.toHaveBeenCalled()382 triggerEvent(vm.$refs.right, 'mousedown', e => {383 e.button = right384 })385 expect(spyRight).toHaveBeenCalled()386387 triggerEvent(vm.$refs.middle, 'mousedown', e => {388 e.button = left389 })390 triggerEvent(vm.$refs.middle, 'mousedown', e => {391 e.button = right392 })393 expect(spyMiddle).not.toHaveBeenCalled()394 triggerEvent(vm.$refs.middle, 'mousedown', e => {395 e.button = middle396 })397 expect(spyMiddle).toHaveBeenCalled()398 })399400 it('should support KeyboardEvent.key for built in aliases', () => {401 vm = new Vue({402 el,403 template: `404 <div>405 <input ref="enter" @keyup.enter="foo">406 <input ref="space" @keyup.space="foo">407 <input ref="esc" @keyup.esc="foo">408 <input ref="left" @keyup.left="foo">409 <input ref="delete" @keyup.delete="foo">410 </div>411 `,412 methods: { foo: spy }413 })414415 triggerEvent(vm.$refs.enter, 'keyup', e => {416 e.key = 'Enter'417 })418 expect(spy.mock.calls.length).toBe(1)419 triggerEvent(vm.$refs.space, 'keyup', e => {420 e.key = ' '421 })422 expect(spy.mock.calls.length).toBe(2)423 triggerEvent(vm.$refs.esc, 'keyup', e => {424 e.key = 'Escape'425 })426 expect(spy.mock.calls.length).toBe(3)427 triggerEvent(vm.$refs.left, 'keyup', e => {428 e.key = 'ArrowLeft'429 })430 expect(spy.mock.calls.length).toBe(4)431 triggerEvent(vm.$refs.delete, 'keyup', e => {432 e.key = 'Backspace'433 })434 expect(spy.mock.calls.length).toBe(5)435 triggerEvent(vm.$refs.delete, 'keyup', e => {436 e.key = 'Delete'437 })438 expect(spy.mock.calls.length).toBe(6)439 })440441 it('should support custom keyCode', () => {442 Vue.config.keyCodes.test = 1443 vm = new Vue({444 el,445 template: `<input @keyup.test="foo">`,446 methods: { foo: spy }447 })448 triggerEvent(vm.$el, 'keyup', e => {449 e.keyCode = 1450 })451 expect(spy).toHaveBeenCalled()452 Vue.config.keyCodes = Object.create(null)453 })454455 it('should override built-in keyCode', () => {456 Vue.config.keyCodes.up = [1, 87]457 vm = new Vue({458 el,459 template: `<input @keyup.up="foo" @keyup.down="foo">`,460 methods: { foo: spy }461 })462 triggerEvent(vm.$el, 'keyup', e => {463 e.keyCode = 87464 })465 expect(spy).toHaveBeenCalled()466 triggerEvent(vm.$el, 'keyup', e => {467 e.keyCode = 1468 })469 expect(spy).toHaveBeenCalledTimes(2)470 // should not affect built-in down keycode471 triggerEvent(vm.$el, 'keyup', e => {472 e.keyCode = 40473 })474 expect(spy).toHaveBeenCalledTimes(3)475 Vue.config.keyCodes = Object.create(null)476 })477478 it('should bind to a child component', () => {479 vm = new Vue({480 el,481 template: '<bar @custom="foo"></bar>',482 methods: { foo: spy },483 components: {484 bar: {485 template: '<span>Hello</span>'486 }487 }488 })489 vm.$children[0].$emit('custom', 'foo', 'bar')490 expect(spy).toHaveBeenCalledWith('foo', 'bar')491 })492493 it('should be able to bind native events for a child component', () => {494 vm = new Vue({495 el,496 template: '<bar @click.native="foo"></bar>',497 methods: { foo: spy },498 components: {499 bar: {500 template: '<span>Hello</span>'501 }502 }503 })504 vm.$children[0].$emit('click')505 expect(spy).not.toHaveBeenCalled()506 triggerEvent(vm.$children[0].$el, 'click')507 expect(spy).toHaveBeenCalled()508 })509510 it('should throw a warning if native modifier is used on native HTML element', () => {511 vm = new Vue({512 el,513 template: `514 <button @click.native="foo"></button>515 `,516 methods: { foo: spy }517 })518519 triggerEvent(vm.$el, 'click')520 expect(521 `The .native modifier for v-on is only valid on components but it was used on <button>.`522 ).toHaveBeenWarned()523 expect(spy.mock.calls.length).toBe(0)524 })525526 it('should not throw a warning if native modifier is used on a dynamic component', () => {527 vm = new Vue({528 el,529 template: `530 <component is="div" @click.native="foo('native')" @click="foo('regular')"/>531 `,532 methods: { foo: spy }533 })534535 triggerEvent(vm.$el, 'click')536 expect(537 `The .native modifier for v-on is only valid on components but it was used on <div>.`538 ).not.toHaveBeenWarned()539 expect(spy.mock.calls).toEqual([['regular']]) // Regular @click should work for dynamic components resolved to native HTML elements.540 })541542 it('.once modifier should work with child components', () => {543 vm = new Vue({544 el,545 template: '<bar @custom.once="foo"></bar>',546 methods: { foo: spy },547 components: {548 bar: {549 template: '<span>Hello</span>'550 }551 }552 })553 vm.$children[0].$emit('custom')554 expect(spy.mock.calls.length).toBe(1)555 vm.$children[0].$emit('custom')556 expect(spy.mock.calls.length).toBe(1) // should not be called again557 })558559 it('remove listener', done => {560 const spy2 = vi.fn()561 vm = new Vue({562 el,563 methods: { foo: spy, bar: spy2 },564 data: {565 ok: true566 },567 render(h) {568 return this.ok569 ? h('input', { on: { click: this.foo } })570 : h('input', { on: { input: this.bar } })571 }572 })573 triggerEvent(vm.$el, 'click')574 expect(spy.mock.calls.length).toBe(1)575 expect(spy2.mock.calls.length).toBe(0)576 vm.ok = false577 waitForUpdate(() => {578 triggerEvent(vm.$el, 'click')579 expect(spy.mock.calls.length).toBe(1) // should no longer trigger580 triggerEvent(vm.$el, 'input')581 expect(spy2.mock.calls.length).toBe(1)582 }).then(done)583 })584585 it('remove capturing listener', done => {586 const spy2 = vi.fn()587 vm = new Vue({588 el,589 methods: {590 foo: spy,591 bar: spy2,592 stopped(ev) {593 ev.stopPropagation()594 }595 },596 data: {597 ok: true598 },599 render(h) {600 return this.ok601 ? h('div', { on: { '!click': this.foo } }, [602 h('div', { on: { click: this.stopped } })603 ])604 : h('div', { on: { mouseOver: this.bar } }, [h('div')])605 }606 })607 triggerEvent(vm.$el.firstChild, 'click')608 expect(spy.mock.calls.length).toBe(1)609 expect(spy2.mock.calls.length).toBe(0)610 vm.ok = false611 waitForUpdate(() => {612 triggerEvent(vm.$el.firstChild, 'click')613 expect(spy.mock.calls.length).toBe(1) // should no longer trigger614 triggerEvent(vm.$el, 'mouseOver')615 expect(spy2.mock.calls.length).toBe(1)616 }).then(done)617 })618619 it('remove once listener', done => {620 const spy2 = vi.fn()621 vm = new Vue({622 el,623 methods: { foo: spy, bar: spy2 },624 data: {625 ok: true626 },627 render(h) {628 return this.ok629 ? h('input', { on: { '~click': this.foo } })630 : h('input', { on: { input: this.bar } })631 }632 })633 triggerEvent(vm.$el, 'click')634 expect(spy.mock.calls.length).toBe(1)635 triggerEvent(vm.$el, 'click')636 expect(spy.mock.calls.length).toBe(1) // should no longer trigger637 expect(spy2.mock.calls.length).toBe(0)638 vm.ok = false639 waitForUpdate(() => {640 triggerEvent(vm.$el, 'click')641 expect(spy.mock.calls.length).toBe(1) // should no longer trigger642 triggerEvent(vm.$el, 'input')643 expect(spy2.mock.calls.length).toBe(1)644 }).then(done)645 })646647 it('remove capturing and once listener', done => {648 const spy2 = vi.fn()649 vm = new Vue({650 el,651 methods: {652 foo: spy,653 bar: spy2,654 stopped(ev) {655 ev.stopPropagation()656 }657 },658 data: {659 ok: true660 },661 render(h) {662 return this.ok663 ? h('div', { on: { '~!click': this.foo } }, [664 h('div', { on: { click: this.stopped } })665 ])666 : h('div', { on: { mouseOver: this.bar } }, [h('div')])667 }668 })669 triggerEvent(vm.$el.firstChild, 'click')670 expect(spy.mock.calls.length).toBe(1)671 triggerEvent(vm.$el.firstChild, 'click')672 expect(spy.mock.calls.length).toBe(1) // should no longer trigger673 expect(spy2.mock.calls.length).toBe(0)674 vm.ok = false675 waitForUpdate(() => {676 triggerEvent(vm.$el.firstChild, 'click')677 expect(spy.mock.calls.length).toBe(1) // should no longer trigger678 triggerEvent(vm.$el, 'mouseOver')679 expect(spy2.mock.calls.length).toBe(1)680 }).then(done)681 })682683 it('remove listener on child component', done => {684 const spy2 = vi.fn()685 vm = new Vue({686 el,687 methods: { foo: spy, bar: spy2 },688 data: {689 ok: true690 },691 components: {692 test: {693 template: '<div></div>'694 }695 },696 render(h) {697 return this.ok698 ? h('test', { on: { foo: this.foo } })699 : h('test', { on: { bar: this.bar } })700 }701 })702 vm.$children[0].$emit('foo')703 expect(spy.mock.calls.length).toBe(1)704 expect(spy2.mock.calls.length).toBe(0)705 vm.ok = false706 waitForUpdate(() => {707 vm.$children[0].$emit('foo')708 expect(spy.mock.calls.length).toBe(1) // should no longer trigger709 vm.$children[0].$emit('bar')710 expect(spy2.mock.calls.length).toBe(1)711 }).then(done)712 })713714 it('warn missing handlers', () => {715 vm = new Vue({716 el,717 data: { none: null },718 template: `<div @click="none"></div>`719 })720 expect(`Invalid handler for event "click": got null`).toHaveBeenWarned()721 expect(() => {722 triggerEvent(vm.$el, 'click')723 }).not.toThrow()724 })725726 // Github Issue #5046727 it('should support keyboard modifier for direction keys', () => {728 const spyLeft = vi.fn()729 const spyRight = vi.fn()730 const spyUp = vi.fn()731 const spyDown = vi.fn()732 vm = new Vue({733 el,734 template: `735 <div>736 <input ref="left" @keydown.left="foo"></input>737 <input ref="right" @keydown.right="foo1"></input>738 <input ref="up" @keydown.up="foo2"></input>739 <input ref="down" @keydown.down="foo3"></input>740 </div>741 `,742 methods: {743 foo: spyLeft,744 foo1: spyRight,745 foo2: spyUp,746 foo3: spyDown747 }748 })749 triggerEvent(vm.$refs.left, 'keydown', e => {750 e.keyCode = 37751 })752 triggerEvent(vm.$refs.left, 'keydown', e => {753 e.keyCode = 39754 })755756 triggerEvent(vm.$refs.right, 'keydown', e => {757 e.keyCode = 39758 })759 triggerEvent(vm.$refs.right, 'keydown', e => {760 e.keyCode = 38761 })762763 triggerEvent(vm.$refs.up, 'keydown', e => {764 e.keyCode = 38765 })766 triggerEvent(vm.$refs.up, 'keydown', e => {767 e.keyCode = 37768 })769770 triggerEvent(vm.$refs.down, 'keydown', e => {771 e.keyCode = 40772 })773 triggerEvent(vm.$refs.down, 'keydown', e => {774 e.keyCode = 39775 })776777 expect(spyLeft.mock.calls.length).toBe(1)778 expect(spyRight.mock.calls.length).toBe(1)779 expect(spyUp.mock.calls.length).toBe(1)780 expect(spyDown.mock.calls.length).toBe(1)781 })782783 // This test case should only run when the test browser supports passive.784 if (supportsPassive) {785 it('should support passive', () => {786 vm = new Vue({787 el,788 template: `789 <div>790 <input type="checkbox" ref="normal" @click="foo"/>791 <input type="checkbox" ref="passive" @click.passive="foo"/>792 <input type="checkbox" ref="exclusive" @click.prevent.passive/>793 </div>794 `,795 methods: {796 foo(e) {797 e.preventDefault()798 }799 }800 })801802 vm.$refs.normal.checked = false803 vm.$refs.passive.checked = false804 vm.$refs.exclusive.checked = false805 vm.$refs.normal.click()806 vm.$refs.passive.click()807 vm.$refs.exclusive.click()808 expect(vm.$refs.normal.checked).toBe(false)809 expect(vm.$refs.passive.checked).toBe(true)810 expect(vm.$refs.exclusive.checked).toBe(true)811 expect(812 "passive and prevent can't be used together. Passive handler can't prevent default event."813 ).toHaveBeenWarned()814 })815 }816817 // GitHub Issues #5146818 it('should only prevent when match keycode', () => {819 let prevented = false820 vm = new Vue({821 el,822 template: `823 <input ref="input" @keydown.enter.prevent="foo">824 `,825 methods: {826 foo($event) {827 prevented = $event.defaultPrevented828 }829 }830 })831832 triggerEvent(vm.$refs.input, 'keydown', e => {833 e.keyCode = 32834 })835 expect(prevented).toBe(false)836 triggerEvent(vm.$refs.input, 'keydown', e => {837 e.keyCode = 13838 })839 expect(prevented).toBe(true)840 })841842 it('should transform click.right to contextmenu', () => {843 const spy = vi.fn()844 const vm = new Vue({845 template: `<div @click.right="foo"></div>`,846 methods: { foo: spy }847 }).$mount()848849 triggerEvent(vm.$el, 'contextmenu')850 expect(spy).toHaveBeenCalled()851 })852853 it('should transform click.middle to mouseup', () => {854 const spy = vi.fn()855 vm = new Vue({856 el,857 template: `<div @click.middle="foo"></div>`,858 methods: { foo: spy }859 })860 triggerEvent(vm.$el, 'mouseup', e => {861 e.button = 0862 })863 expect(spy).not.toHaveBeenCalled()864 triggerEvent(vm.$el, 'mouseup', e => {865 e.button = 1866 })867 expect(spy).toHaveBeenCalled()868 })869870 it('object syntax (no argument)', () => {871 const click = vi.fn()872 const mouseup = vi.fn()873 vm = new Vue({874 el,875 template: `<button v-on="listeners">foo</button>`,876 created() {877 this.listeners = {878 click,879 mouseup880 }881 }882 })883884 triggerEvent(vm.$el, 'click')885 expect(click.mock.calls.length).toBe(1)886 expect(mouseup.mock.calls.length).toBe(0)887888 triggerEvent(vm.$el, 'mouseup')889 expect(click.mock.calls.length).toBe(1)890 expect(mouseup.mock.calls.length).toBe(1)891 })892893 it('object syntax (no argument, mixed with normal listeners)', () => {894 const click1 = vi.fn()895 const click2 = vi.fn()896 const mouseup = vi.fn()897 vm = new Vue({898 el,899 template: `<button v-on="listeners" @click="click2">foo</button>`,900 created() {901 this.listeners = {902 click: click1,903 mouseup904 }905 },906 methods: {907 click2908 }909 })910911 triggerEvent(vm.$el, 'click')912 expect(click1.mock.calls.length).toBe(1)913 expect(click2.mock.calls.length).toBe(1)914 expect(mouseup.mock.calls.length).toBe(0)915916 triggerEvent(vm.$el, 'mouseup')917 expect(click1.mock.calls.length).toBe(1)918 expect(click2.mock.calls.length).toBe(1)919 expect(mouseup.mock.calls.length).toBe(1)920 })921922 it('object syntax (usage in HOC, mixed with native listeners)', () => {923 const click = vi.fn()924 const mouseup = vi.fn()925 const mousedown = vi.fn()926927 vm = new Vue({928 el,929 template: `930 <foo-button931 @click="click"932 @mousedown="mousedown"933 @mouseup.native="mouseup">934 </foo-button>935 `,936 methods: {937 click,938 mouseup,939 mousedown940 },941 components: {942 fooButton: {943 template: `944 <button v-on="$listeners"></button>945 `946 }947 }948 })949950 triggerEvent(vm.$el, 'click')951 expect(click.mock.calls.length).toBe(1)952 expect(mouseup.mock.calls.length).toBe(0)953 expect(mousedown.mock.calls.length).toBe(0)954955 triggerEvent(vm.$el, 'mouseup')956 expect(click.mock.calls.length).toBe(1)957 expect(mouseup.mock.calls.length).toBe(1)958 expect(mousedown.mock.calls.length).toBe(0)959960 triggerEvent(vm.$el, 'mousedown')961 expect(click.mock.calls.length).toBe(1)962 expect(mouseup.mock.calls.length).toBe(1)963 expect(mousedown.mock.calls.length).toBe(1)964 })965966 // #6805 (v-on="object" bind order problem)967 it('object syntax (no argument): should fire after high-priority listeners', done => {968 const MyCheckbox = {969 template: '<input type="checkbox" v-model="model" v-on="$listeners">',970 props: {971 value: false972 },973 computed: {974 model: {975 get() {976 return this.value977 },978 set(val) {979 this.$emit('input', val)980 }981 }982 }983 }984985 vm = new Vue({986 el,987 template: `988 <div>989 <my-checkbox v-model="check" @change="change"></my-checkbox>990 </div>991 `,992 components: { MyCheckbox },993 data: {994 check: false995 },996 methods: {997 change() {998 expect(this.check).toBe(true)999 done()1000 }1001 }1002 })10031004 vm.$el.querySelector('input').click()1005 })10061007 it('warn object syntax with modifier', () => {1008 new Vue({1009 template: `<button v-on.self="{}"></button>`1010 }).$mount()1011 expect(1012 `v-on without argument does not support modifiers`1013 ).toHaveBeenWarned()1014 })10151016 it('warn object syntax with non-object value', () => {1017 new Vue({1018 template: `<button v-on="123"></button>`1019 }).$mount()1020 expect(`v-on without argument expects an Object value`).toHaveBeenWarned()1021 })10221023 it('should correctly remove once listener', done => {1024 const vm = new Vue({1025 template: `1026 <div>1027 <span v-if="ok" @click.once="foo">1028 a1029 </span>1030 <span v-else a="a">1031 b1032 </span>1033 </div>1034 `,1035 data: {1036 ok: true1037 },1038 methods: {1039 foo: spy1040 }1041 }).$mount()10421043 vm.ok = false1044 waitForUpdate(() => {1045 triggerEvent(vm.$el.childNodes[0], 'click')1046 expect(spy.mock.calls.length).toBe(0)1047 }).then(done)1048 })10491050 // #76281051 it('handler should return the return value of inline function invocation', () => {1052 let value1053 new Vue({1054 template: `<test @foo="bar()"></test>`,1055 methods: {1056 bar() {1057 return 11058 }1059 },1060 components: {1061 test: {1062 created() {1063 value = this.$listeners.foo()1064 },1065 render(h) {1066 return h('div')1067 }1068 }1069 }1070 }).$mount()1071 expect(value).toBe(1)1072 })10731074 it('should not execute callback if modifiers are present', () => {1075 vm = new Vue({1076 el,1077 template: '<input @keyup.?="foo">',1078 methods: { foo: spy }1079 })1080 // simulating autocomplete event (Event object with type keyup but without keyCode)1081 triggerEvent(vm.$el, 'keyup')1082 expect(spy.mock.calls.length).toBe(0)1083 })10841085 describe('dynamic arguments', () => {1086 it('basic', done => {1087 const spy = vi.fn()1088 const vm = new Vue({1089 template: `<div v-on:[key]="spy"></div>`,1090 data: {1091 key: 'click'1092 },1093 methods: {1094 spy1095 }1096 }).$mount()1097 triggerEvent(vm.$el, 'click')1098 expect(spy.mock.calls.length).toBe(1)1099 vm.key = 'mouseup'1100 waitForUpdate(() => {1101 triggerEvent(vm.$el, 'click')1102 expect(spy.mock.calls.length).toBe(1)1103 triggerEvent(vm.$el, 'mouseup')1104 expect(spy.mock.calls.length).toBe(2)1105 // explicit null value1106 vm.key = null1107 })1108 .then(() => {1109 triggerEvent(vm.$el, 'click')1110 expect(spy.mock.calls.length).toBe(2)1111 triggerEvent(vm.$el, 'mouseup')1112 expect(spy.mock.calls.length).toBe(2)1113 })1114 .then(done)1115 })11161117 it('shorthand', done => {1118 const spy = vi.fn()1119 const vm = new Vue({1120 template: `<div @[key]="spy"></div>`,1121 data: {1122 key: 'click'1123 },1124 methods: {1125 spy1126 }1127 }).$mount()1128 triggerEvent(vm.$el, 'click')1129 expect(spy.mock.calls.length).toBe(1)1130 vm.key = 'mouseup'1131 waitForUpdate(() => {1132 triggerEvent(vm.$el, 'click')1133 expect(spy.mock.calls.length).toBe(1)1134 triggerEvent(vm.$el, 'mouseup')1135 expect(spy.mock.calls.length).toBe(2)1136 }).then(done)1137 })11381139 it('with .middle modifier', () => {1140 const spy = vi.fn()1141 const vm = new Vue({1142 template: `<div @[key].middle="spy"></div>`,1143 data: {1144 key: 'click'1145 },1146 methods: {1147 spy1148 }1149 }).$mount()1150 triggerEvent(vm.$el, 'mouseup', e => {1151 e.button = 01152 })1153 expect(spy).not.toHaveBeenCalled()1154 triggerEvent(vm.$el, 'mouseup', e => {1155 e.button = 11156 })1157 expect(spy).toHaveBeenCalled()1158 })11591160 it('with .right modifier', () => {1161 const spy = vi.fn()1162 const vm = new Vue({1163 template: `<div @[key].right="spy"></div>`,1164 data: {1165 key: 'click'1166 },1167 methods: {1168 spy1169 }1170 }).$mount()1171 triggerEvent(vm.$el, 'contextmenu')1172 expect(spy).toHaveBeenCalled()1173 })11741175 it('with .capture modifier', () => {1176 const callOrder: any[] = []1177 const vm = new Vue({1178 template: `1179 <div @[key].capture="foo">1180 <div @[key]="bar"></div>1181 </div>1182 `,1183 data: {1184 key: 'click'1185 },1186 methods: {1187 foo() {1188 callOrder.push(1)1189 },1190 bar() {1191 callOrder.push(2)1192 }1193 }1194 }).$mount()1195 triggerEvent(vm.$el.firstChild, 'click')1196 expect(callOrder.toString()).toBe('1,2')1197 })11981199 it('with .once modifier', () => {1200 const vm = new Vue({1201 template: `<div @[key].once="foo"></div>`,1202 data: { key: 'click' },1203 methods: { foo: spy }1204 }).$mount()1205 triggerEvent(vm.$el, 'click')1206 expect(spy.mock.calls.length).toBe(1)1207 triggerEvent(vm.$el, 'click')1208 expect(spy.mock.calls.length).toBe(1) // should no longer trigger1209 })1210 })1211})
Findings
✓ No findings reported for this file.