Adding upstream version 5.2.3+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
b80f12a01d
commit
bc475d7d0d
617 changed files with 89471 additions and 0 deletions
480
js/tests/unit/dom/event-handler.spec.js
Normal file
480
js/tests/unit/dom/event-handler.spec.js
Normal file
|
@ -0,0 +1,480 @@
|
|||
import EventHandler from '../../../src/dom/event-handler'
|
||||
import { clearFixture, getFixture } from '../../helpers/fixture'
|
||||
import { noop } from '../../../src/util'
|
||||
|
||||
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, noop)
|
||||
EventHandler.on(null, 'click', noop)
|
||||
|
||||
expect().nothing()
|
||||
})
|
||||
|
||||
it('should add event listener', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.on(div, 'click', () => {
|
||||
expect().nothing()
|
||||
resolve()
|
||||
})
|
||||
|
||||
div.click()
|
||||
})
|
||||
})
|
||||
|
||||
it('should add namespaced event listener', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.on(div, 'bs.namespace', () => {
|
||||
expect().nothing()
|
||||
resolve()
|
||||
})
|
||||
|
||||
EventHandler.trigger(div, 'bs.namespace')
|
||||
})
|
||||
})
|
||||
|
||||
it('should add native namespaced event listener', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.on(div, 'click.namespace', () => {
|
||||
expect().nothing()
|
||||
resolve()
|
||||
})
|
||||
|
||||
EventHandler.trigger(div, 'click')
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle event delegation', () => {
|
||||
return new Promise(resolve => {
|
||||
EventHandler.on(document, 'click', '.test', () => {
|
||||
expect().nothing()
|
||||
resolve()
|
||||
})
|
||||
|
||||
fixtureEl.innerHTML = '<div class="test"></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
div.click()
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle mouseenter/mouseleave like the native counterpart', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div class="outer">',
|
||||
'<div class="inner">',
|
||||
'<div class="nested">',
|
||||
'<div class="deep"></div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="sibling"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
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()).toEqual(2)
|
||||
expect(leaveSpy.calls.count()).toEqual(2)
|
||||
expect(delegateEnterSpy.calls.count()).toEqual(2)
|
||||
expect(delegateLeaveSpy.calls.count()).toEqual(2)
|
||||
resolve()
|
||||
})
|
||||
|
||||
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()).toEqual(1)
|
||||
expect(leaveSpy.calls.count()).toEqual(1)
|
||||
expect(delegateEnterSpy.calls.count()).toEqual(1)
|
||||
expect(delegateLeaveSpy.calls.count()).toEqual(1)
|
||||
|
||||
// from outer to inner to sibling (adjacent)
|
||||
moveMouse(outer, inner)
|
||||
moveMouse(inner, sibling)
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('one', () => {
|
||||
it('should call listener just once', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should call delegated listener just once', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('off', () => {
|
||||
it('should not remove a listener', () => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
const div = fixtureEl.querySelector('div')
|
||||
|
||||
EventHandler.off(div, null, noop)
|
||||
EventHandler.off(null, 'click', noop)
|
||||
expect().nothing()
|
||||
})
|
||||
|
||||
it('should remove a listener', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove all the events', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove all the namespaced listeners if namespace is passed', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove the namespaced listeners', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove the all the namespaced listeners for native events', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove the specified namespaced listeners for native events', () => {
|
||||
return new Promise(resolve => {
|
||||
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)
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove a listener registered by .one', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fixtureEl.innerHTML = '<div></div>'
|
||||
|
||||
const div = fixtureEl.querySelector('div')
|
||||
const handler = () => {
|
||||
reject(new Error('called'))
|
||||
}
|
||||
|
||||
EventHandler.one(div, 'foobar', handler)
|
||||
EventHandler.off(div, 'foobar', handler)
|
||||
|
||||
EventHandler.trigger(div, 'foobar')
|
||||
setTimeout(() => {
|
||||
expect().nothing()
|
||||
resolve()
|
||||
}, 20)
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove the correct delegated event listener', () => {
|
||||
const element = document.createElement('div')
|
||||
const subelement = document.createElement('span')
|
||||
element.append(subelement)
|
||||
|
||||
const anchor = document.createElement('a')
|
||||
element.append(anchor)
|
||||
|
||||
let i = 0
|
||||
const handler = () => {
|
||||
i++
|
||||
}
|
||||
|
||||
EventHandler.on(element, 'click', 'a', handler)
|
||||
EventHandler.on(element, 'click', 'span', handler)
|
||||
|
||||
fixtureEl.append(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)
|
||||
})
|
||||
})
|
||||
|
||||
describe('general functionality', () => {
|
||||
it('should hydrate properties, and make them configurable', () => {
|
||||
return new Promise(resolve => {
|
||||
fixtureEl.innerHTML = [
|
||||
'<div id="div1">',
|
||||
' <div id="div2"></div>',
|
||||
' <div id="div3"></div>',
|
||||
'</div>'
|
||||
].join('')
|
||||
|
||||
const div1 = fixtureEl.querySelector('#div1')
|
||||
const div2 = fixtureEl.querySelector('#div2')
|
||||
|
||||
EventHandler.on(div1, 'click', event => {
|
||||
expect(event.currentTarget).toBe(div2)
|
||||
expect(event.delegateTarget).toBe(div1)
|
||||
expect(event.originalTarget).toBeNull()
|
||||
|
||||
Object.defineProperty(event, 'currentTarget', {
|
||||
configurable: true,
|
||||
get() {
|
||||
return div1
|
||||
}
|
||||
})
|
||||
|
||||
expect(event.currentTarget).toBe(div1)
|
||||
resolve()
|
||||
})
|
||||
|
||||
expect(() => {
|
||||
EventHandler.trigger(div1, 'click', { originalTarget: null, currentTarget: div2 })
|
||||
}).not.toThrowError(TypeError)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue