123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- import EventHandler from '../../../src/dom/event-handler'
- /** Test helpers */
- import { getFixture, clearFixture } from '../../helpers/fixture'
- describe('EventHandler', () => {
- let fixtureEl
- beforeAll(() => {
- fixtureEl = getFixture()
- })
- afterEach(() => {
- clearFixture()
- })
- describe('on', () => {
- it('should not add event listener if the event is not a string', () => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- EventHandler.on(div, null, () => {})
- EventHandler.on(null, 'click', () => {})
- expect().nothing()
- })
- it('should add event listener', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- EventHandler.on(div, 'click', () => {
- expect().nothing()
- done()
- })
- div.click()
- })
- it('should add namespaced event listener', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- EventHandler.on(div, 'bs.namespace', () => {
- expect().nothing()
- done()
- })
- EventHandler.trigger(div, 'bs.namespace')
- })
- it('should add native namespaced event listener', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- EventHandler.on(div, 'click.namespace', () => {
- expect().nothing()
- done()
- })
- EventHandler.trigger(div, 'click')
- })
- it('should handle event delegation', done => {
- EventHandler.on(document, 'click', '.test', () => {
- expect().nothing()
- done()
- })
- fixtureEl.innerHTML = '<div class="test"></div>'
- const div = fixtureEl.querySelector('div')
- div.click()
- })
- it('should handle mouseenter/mouseleave like the native counterpart', done => {
- fixtureEl.innerHTML = [
- '<div class="outer">',
- '<div class="inner">',
- '<div class="nested">',
- '<div class="deep"></div>',
- '</div>',
- '</div>',
- '<div class="sibling"></div>',
- '</div>'
- ]
- const outer = fixtureEl.querySelector('.outer')
- const inner = fixtureEl.querySelector('.inner')
- const nested = fixtureEl.querySelector('.nested')
- const deep = fixtureEl.querySelector('.deep')
- const sibling = fixtureEl.querySelector('.sibling')
- const enterSpy = jasmine.createSpy('mouseenter')
- const leaveSpy = jasmine.createSpy('mouseleave')
- const delegateEnterSpy = jasmine.createSpy('mouseenter')
- const delegateLeaveSpy = jasmine.createSpy('mouseleave')
- EventHandler.on(inner, 'mouseenter', enterSpy)
- EventHandler.on(inner, 'mouseleave', leaveSpy)
- EventHandler.on(outer, 'mouseenter', '.inner', delegateEnterSpy)
- EventHandler.on(outer, 'mouseleave', '.inner', delegateLeaveSpy)
- EventHandler.on(sibling, 'mouseenter', () => {
- expect(enterSpy.calls.count()).toBe(2)
- expect(leaveSpy.calls.count()).toBe(2)
- expect(delegateEnterSpy.calls.count()).toBe(2)
- expect(delegateLeaveSpy.calls.count()).toBe(2)
- done()
- })
- const moveMouse = (from, to) => {
- from.dispatchEvent(new MouseEvent('mouseout', {
- bubbles: true,
- relatedTarget: to
- }))
- to.dispatchEvent(new MouseEvent('mouseover', {
- bubbles: true,
- relatedTarget: from
- }))
- }
- // from outer to deep and back to outer (nested)
- moveMouse(outer, inner)
- moveMouse(inner, nested)
- moveMouse(nested, deep)
- moveMouse(deep, nested)
- moveMouse(nested, inner)
- moveMouse(inner, outer)
- setTimeout(() => {
- expect(enterSpy.calls.count()).toBe(1)
- expect(leaveSpy.calls.count()).toBe(1)
- expect(delegateEnterSpy.calls.count()).toBe(1)
- expect(delegateLeaveSpy.calls.count()).toBe(1)
- // from outer to inner to sibling (adjacent)
- moveMouse(outer, inner)
- moveMouse(inner, sibling)
- }, 20)
- })
- })
- describe('one', () => {
- it('should call listener just once', done => {
- fixtureEl.innerHTML = '<div></div>'
- let called = 0
- const div = fixtureEl.querySelector('div')
- const obj = {
- oneListener() {
- called++
- }
- }
- EventHandler.one(div, 'bootstrap', obj.oneListener)
- EventHandler.trigger(div, 'bootstrap')
- EventHandler.trigger(div, 'bootstrap')
- setTimeout(() => {
- expect(called).toEqual(1)
- done()
- }, 20)
- })
- it('should call delegated listener just once', done => {
- fixtureEl.innerHTML = '<div></div>'
- let called = 0
- const div = fixtureEl.querySelector('div')
- const obj = {
- oneListener() {
- called++
- }
- }
- EventHandler.one(fixtureEl, 'bootstrap', 'div', obj.oneListener)
- EventHandler.trigger(div, 'bootstrap')
- EventHandler.trigger(div, 'bootstrap')
- setTimeout(() => {
- expect(called).toEqual(1)
- done()
- }, 20)
- })
- })
- describe('off', () => {
- it('should not remove a listener', () => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- EventHandler.off(div, null, () => {})
- EventHandler.off(null, 'click', () => {})
- expect().nothing()
- })
- it('should remove a listener', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- let called = 0
- const handler = () => {
- called++
- }
- EventHandler.on(div, 'foobar', handler)
- EventHandler.trigger(div, 'foobar')
- EventHandler.off(div, 'foobar', handler)
- EventHandler.trigger(div, 'foobar')
- setTimeout(() => {
- expect(called).toEqual(1)
- done()
- }, 20)
- })
- it('should remove all the events', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- let called = 0
- EventHandler.on(div, 'foobar', () => {
- called++
- })
- EventHandler.on(div, 'foobar', () => {
- called++
- })
- EventHandler.trigger(div, 'foobar')
- EventHandler.off(div, 'foobar')
- EventHandler.trigger(div, 'foobar')
- setTimeout(() => {
- expect(called).toEqual(2)
- done()
- }, 20)
- })
- it('should remove all the namespaced listeners if namespace is passed', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- let called = 0
- EventHandler.on(div, 'foobar.namespace', () => {
- called++
- })
- EventHandler.on(div, 'foofoo.namespace', () => {
- called++
- })
- EventHandler.trigger(div, 'foobar.namespace')
- EventHandler.trigger(div, 'foofoo.namespace')
- EventHandler.off(div, '.namespace')
- EventHandler.trigger(div, 'foobar.namespace')
- EventHandler.trigger(div, 'foofoo.namespace')
- setTimeout(() => {
- expect(called).toEqual(2)
- done()
- }, 20)
- })
- it('should remove the namespaced listeners', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- let calledCallback1 = 0
- let calledCallback2 = 0
- EventHandler.on(div, 'foobar.namespace', () => {
- calledCallback1++
- })
- EventHandler.on(div, 'foofoo.namespace', () => {
- calledCallback2++
- })
- EventHandler.trigger(div, 'foobar.namespace')
- EventHandler.off(div, 'foobar.namespace')
- EventHandler.trigger(div, 'foobar.namespace')
- EventHandler.trigger(div, 'foofoo.namespace')
- setTimeout(() => {
- expect(calledCallback1).toEqual(1)
- expect(calledCallback2).toEqual(1)
- done()
- }, 20)
- })
- it('should remove the all the namespaced listeners for native events', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- let called = 0
- EventHandler.on(div, 'click.namespace', () => {
- called++
- })
- EventHandler.on(div, 'click.namespace2', () => {
- called++
- })
- EventHandler.trigger(div, 'click')
- EventHandler.off(div, 'click')
- EventHandler.trigger(div, 'click')
- setTimeout(() => {
- expect(called).toEqual(2)
- done()
- }, 20)
- })
- it('should remove the specified namespaced listeners for native events', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- let called1 = 0
- let called2 = 0
- EventHandler.on(div, 'click.namespace', () => {
- called1++
- })
- EventHandler.on(div, 'click.namespace2', () => {
- called2++
- })
- EventHandler.trigger(div, 'click')
- EventHandler.off(div, 'click.namespace')
- EventHandler.trigger(div, 'click')
- setTimeout(() => {
- expect(called1).toEqual(1)
- expect(called2).toEqual(2)
- done()
- }, 20)
- })
- it('should remove a listener registered by .one', done => {
- fixtureEl.innerHTML = '<div></div>'
- const div = fixtureEl.querySelector('div')
- const handler = () => {
- throw new Error('called')
- }
- EventHandler.one(div, 'foobar', handler)
- EventHandler.off(div, 'foobar', handler)
- EventHandler.trigger(div, 'foobar')
- setTimeout(() => {
- expect().nothing()
- done()
- }, 20)
- })
- it('should remove the correct delegated event listener', () => {
- const element = document.createElement('div')
- const subelement = document.createElement('span')
- element.appendChild(subelement)
- const anchor = document.createElement('a')
- element.appendChild(anchor)
- let i = 0
- const handler = () => {
- i++
- }
- EventHandler.on(element, 'click', 'a', handler)
- EventHandler.on(element, 'click', 'span', handler)
- fixtureEl.appendChild(element)
- EventHandler.trigger(anchor, 'click')
- EventHandler.trigger(subelement, 'click')
- // first listeners called
- expect(i).toEqual(2)
- EventHandler.off(element, 'click', 'span', handler)
- EventHandler.trigger(subelement, 'click')
- // removed listener not called
- expect(i).toEqual(2)
- EventHandler.trigger(anchor, 'click')
- // not removed listener called
- expect(i).toEqual(3)
- EventHandler.on(element, 'click', 'span', handler)
- EventHandler.trigger(anchor, 'click')
- EventHandler.trigger(subelement, 'click')
- // listener re-registered
- expect(i).toEqual(5)
- EventHandler.off(element, 'click', 'span')
- EventHandler.trigger(subelement, 'click')
- // listener removed again
- expect(i).toEqual(5)
- })
- })
- })
|