diff options
author | Sebastian <sebasjm@gmail.com> | 2021-08-23 16:46:06 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-08-23 16:48:30 -0300 |
commit | 38acabfa6089ab8ac469c12b5f55022fb96935e5 (patch) | |
tree | 453dbf70000cc5e338b06201af1eaca8343f8f73 /preact/test/browser/events.test.js | |
parent | f26125e039143b92dc0d84e7775f508ab0cdcaa8 (diff) | |
download | node-vendor-38acabfa6089ab8ac469c12b5f55022fb96935e5.tar.gz node-vendor-38acabfa6089ab8ac469c12b5f55022fb96935e5.tar.bz2 node-vendor-38acabfa6089ab8ac469c12b5f55022fb96935e5.zip |
Diffstat (limited to 'preact/test/browser/events.test.js')
-rw-r--r-- | preact/test/browser/events.test.js | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/preact/test/browser/events.test.js b/preact/test/browser/events.test.js new file mode 100644 index 0000000..2e43cba --- /dev/null +++ b/preact/test/browser/events.test.js @@ -0,0 +1,202 @@ +import { createElement, render } from 'preact'; +import { + setupScratch, + teardown, + supportsPassiveEvents +} from '../_util/helpers'; + +/** @jsx createElement */ + +describe('event handling', () => { + let scratch, proto; + + function fireEvent(on, type) { + let e = document.createEvent('Event'); + e.initEvent(type, true, true); + on.dispatchEvent(e); + } + + beforeEach(() => { + scratch = setupScratch(); + + proto = document.createElement('div').constructor.prototype; + + sinon.spy(proto, 'addEventListener'); + sinon.spy(proto, 'removeEventListener'); + }); + + afterEach(() => { + teardown(scratch); + + proto.addEventListener.restore(); + proto.removeEventListener.restore(); + }); + + it('should only register on* functions as handlers', () => { + let click = () => {}, + onclick = () => {}; + + render(<div click={click} onClick={onclick} />, scratch); + + expect(scratch.childNodes[0].attributes.length).to.equal(0); + + expect( + proto.addEventListener + ).to.have.been.calledOnce.and.to.have.been.calledWithExactly( + 'click', + sinon.match.func, + false + ); + }); + + it('should only register truthy values as handlers', () => { + function fooHandler() {} + const falsyHandler = false; + + render(<div onClick={falsyHandler} onOtherClick={fooHandler} />, scratch); + + expect( + proto.addEventListener + ).to.have.been.calledOnce.and.to.have.been.calledWithExactly( + 'OtherClick', + sinon.match.func, + false + ); + + expect(proto.addEventListener).not.to.have.been.calledWith('Click'); + expect(proto.addEventListener).not.to.have.been.calledWith('click'); + }); + + it('should support native event names', () => { + let click = sinon.spy(), + mousedown = sinon.spy(); + + render(<div onclick={() => click(1)} onmousedown={mousedown} />, scratch); + + expect(proto.addEventListener) + .to.have.been.calledTwice.and.to.have.been.calledWith('click') + .and.calledWith('mousedown'); + + fireEvent(scratch.childNodes[0], 'click'); + expect(click).to.have.been.calledOnce.and.calledWith(1); + }); + + it('should support camel-case event names', () => { + let click = sinon.spy(), + mousedown = sinon.spy(); + + render(<div onClick={() => click(1)} onMouseDown={mousedown} />, scratch); + + expect(proto.addEventListener) + .to.have.been.calledTwice.and.to.have.been.calledWith('click') + .and.calledWith('mousedown'); + + fireEvent(scratch.childNodes[0], 'click'); + expect(click).to.have.been.calledOnce.and.calledWith(1); + }); + + it('should update event handlers', () => { + let click1 = sinon.spy(); + let click2 = sinon.spy(); + + render(<div onClick={click1} />, scratch); + + fireEvent(scratch.childNodes[0], 'click'); + expect(click1).to.have.been.calledOnce; + expect(click2).to.not.have.been.called; + + click1.resetHistory(); + click2.resetHistory(); + + render(<div onClick={click2} />, scratch); + + fireEvent(scratch.childNodes[0], 'click'); + expect(click1).to.not.have.been.called; + expect(click2).to.have.been.called; + }); + + it('should remove event handlers', () => { + let click = sinon.spy(), + mousedown = sinon.spy(); + + render(<div onClick={() => click(1)} onMouseDown={mousedown} />, scratch); + render(<div onClick={() => click(2)} />, scratch); + + expect(proto.removeEventListener).to.have.been.calledWith('mousedown'); + + fireEvent(scratch.childNodes[0], 'mousedown'); + expect(mousedown).not.to.have.been.called; + + proto.removeEventListener.resetHistory(); + click.resetHistory(); + mousedown.resetHistory(); + + render(<div />, scratch); + + expect(proto.removeEventListener).to.have.been.calledWith('click'); + + fireEvent(scratch.childNodes[0], 'click'); + expect(click).not.to.have.been.called; + }); + + it('should register events not appearing on dom nodes', () => { + let onAnimationEnd = () => {}; + + render(<div onanimationend={onAnimationEnd} />, scratch); + expect( + proto.addEventListener + ).to.have.been.calledOnce.and.to.have.been.calledWithExactly( + 'animationend', + sinon.match.func, + false + ); + }); + + // Skip test if browser doesn't support passive events + if (supportsPassiveEvents()) { + it('should use capturing for event props ending with *Capture', () => { + let click = sinon.spy(), + focus = sinon.spy(); + + render( + <div onClickCapture={click} onFocusCapture={focus}> + <button /> + </div>, + scratch + ); + + let root = scratch.firstChild; + root.firstElementChild.click(); + root.firstElementChild.focus(); + + expect(click, 'click').to.have.been.calledOnce; + + // Focus delegation requires a 50b hack I'm not sure we want to incur + expect(focus, 'focus').to.have.been.calledOnce; + + // IE doesn't set it + if (!/Edge/.test(navigator.userAgent)) { + expect(click).to.have.been.calledWithMatch({ eventPhase: 0 }); // capturing + expect(focus).to.have.been.calledWithMatch({ eventPhase: 0 }); // capturing + } + }); + + it('should support both capturing and non-capturing events on the same element', () => { + let click = sinon.spy(), + clickCapture = sinon.spy(); + + render( + <div onClick={click} onClickCapture={clickCapture}> + <button /> + </div>, + scratch + ); + + let root = scratch.firstChild; + root.firstElementChild.click(); + + expect(clickCapture, 'click').to.have.been.calledOnce; + expect(click, 'click').to.have.been.calledOnce; + }); + } +}); |