2017-01-18 08:52:23 +02:00
/* eslint-env qunit */
import sinon from 'sinon' ;
import evented from '../../../src/js/mixins/evented' ;
2021-07-28 21:55:35 +02:00
import DomData from '../../../src/js/utils/dom-data' ;
2017-01-18 08:52:23 +02:00
import * as Dom from '../../../src/js/utils/dom' ;
import * as Obj from '../../../src/js/utils/obj' ;
2021-07-28 21:55:35 +02:00
import * as Events from '../../../src/js/utils/events.js' ;
2017-01-18 08:52:23 +02:00
// Common errors thrown by evented objects.
const errors = {
2021-01-22 00:00:12 +02:00
type : ( objName , fnName ) => new Error ( ` Invalid event type for ${ objName } # ${ fnName } ; must be a non-empty string or array. ` ) ,
listener : ( objName , fnName ) => new Error ( ` Invalid listener for ${ objName } # ${ fnName } ; must be a function. ` ) ,
target : ( objName , fnName ) => new Error ( ` Invalid target for ${ objName } # ${ fnName } ; must be a DOM node or evented object. ` ) ,
trigger : ( objName ) => new Error ( ` Invalid event type for ${ objName } #trigger; must be a non-empty string or object with a type key that has a non-empty value. ` )
2017-01-18 08:52:23 +02:00
} ;
const validateListenerCall = ( call , thisValue , eventExpectation ) => {
const eventActual = call . args [ 0 ] ;
QUnit . assert . strictEqual ( call . thisValue , thisValue , 'the listener had the expected "this" value' ) ;
QUnit . assert . strictEqual ( typeof eventActual , 'object' , 'the listener was passed an event object' ) ;
// We don't use `deepEqual` here because we only want to test a subset of
// properties (designated by the `eventExpectation`).
Object . keys ( eventExpectation ) . forEach ( key => {
QUnit . assert . strictEqual ( eventActual [ key ] , eventExpectation [ key ] , ` the event had the expected " ${ key } " ` ) ;
} ) ;
} ;
QUnit . module ( 'mixins: evented' , {
beforeEach ( ) {
this . targets = { } ;
} ,
afterEach ( ) {
2019-03-18 21:49:48 +02:00
Object . keys ( this . targets ) . forEach ( ( k ) => this . targets [ k ] . trigger ( 'dispose' ) ) ;
2017-01-18 08:52:23 +02:00
}
} ) ;
QUnit . test ( 'evented() mutates an object as expected' , function ( assert ) {
const target = this . targets . a = { } ;
assert . strictEqual ( typeof evented , 'function' , 'the mixin is a function' ) ;
assert . strictEqual ( evented ( target ) , target , 'returns the target object' ) ;
assert . ok ( Obj . isObject ( target ) , 'the target is still an object' ) ;
assert . ok ( Dom . isEl ( target . eventBusEl _ ) , 'the target has an event bus element' ) ;
assert . strictEqual ( typeof target . off , 'function' , 'the target has an off method' ) ;
assert . strictEqual ( typeof target . on , 'function' , 'the target has an on method' ) ;
assert . strictEqual ( typeof target . one , 'function' , 'the target has a one method' ) ;
assert . strictEqual ( typeof target . trigger , 'function' , 'the target has a trigger method' ) ;
} ) ;
QUnit . test ( 'evented() with custom element' , function ( assert ) {
const target = this . targets . a = evented ( { foo : Dom . createEl ( 'span' ) } , { eventBusKey : 'foo' } ) ;
assert . strictEqual ( target . eventBusEl _ , target . foo , 'the custom DOM element is re-used' ) ;
assert . throws (
( ) => evented ( { foo : { } } , { eventBusKey : 'foo' } ) ,
new Error ( 'The eventBusKey "foo" does not refer to an element.' ) ,
'throws if the target does not have an element at the supplied key'
) ;
} ) ;
2021-01-22 00:00:12 +02:00
QUnit . test ( 'trigger() errors' , function ( assert ) {
class Test { }
2022-05-16 23:27:23 +02:00
const targeta = evented ( { } ) ;
2021-01-22 00:00:12 +02:00
const targetb = evented ( new Test ( ) ) ;
const targetc = evented ( new Test ( ) ) ;
targetc . name _ = 'foo' ;
2022-05-16 23:27:23 +02:00
[ targeta , targetb , targetc ] . forEach ( ( target ) => {
2021-01-22 00:00:12 +02:00
const objName = target . name _ || target . constructor . name || typeof target ;
2022-05-16 23:27:23 +02:00
const triggerError = errors . trigger ( objName ) ;
2021-01-22 00:00:12 +02:00
2022-05-16 23:27:23 +02:00
assert . throws ( ( ) => target . trigger ( ) , triggerError , 'expected error' ) ;
assert . throws ( ( ) => target . trigger ( ' ' ) , triggerError , 'expected error' ) ;
assert . throws ( ( ) => target . trigger ( { } ) , triggerError , 'expected error' ) ;
assert . throws ( ( ) => target . trigger ( { type : '' } ) , triggerError , 'expected error' ) ;
assert . throws ( ( ) => target . trigger ( { type : ' ' } ) , triggerError , 'expected error' ) ;
2021-01-22 00:00:12 +02:00
delete target . eventBusEl _ ;
2022-05-16 23:27:23 +02:00
assert . throws ( ( ) => target . trigger ( { type : 'foo' } ) , errors . target ( objName , 'trigger' ) , 'expected error' ) ;
} ) ;
2021-01-22 00:00:12 +02:00
} ) ;
2019-06-17 20:04:25 +02:00
QUnit . test ( 'on(), one(), and any() errors' , function ( assert ) {
2021-01-22 00:00:12 +02:00
class Test { }
2019-03-18 21:49:48 +02:00
const targeta = this . targets . a = evented ( { } ) ;
const targetb = this . targets . b = evented ( { } ) ;
2021-01-22 00:00:12 +02:00
const targetc = this . targets . c = evented ( new Test ( ) ) ;
const targetd = this . targets . d = evented ( new Test ( ) ) ;
targetd . name _ = 'foo' ;
2017-01-18 08:52:23 +02:00
2019-06-17 20:04:25 +02:00
[ 'on' , 'one' , 'any' ] . forEach ( method => {
2021-01-22 00:00:12 +02:00
[ targeta , targetc , targetd ] . forEach ( ( target ) => {
const objName = target . name _ || target . constructor . name || typeof target ;
assert . throws ( ( ) => target [ method ] ( ) , errors . type ( objName , method ) , 'expected error' ) ;
assert . throws ( ( ) => target [ method ] ( ' ' ) , errors . type ( objName , method ) , 'expected error' ) ;
assert . throws ( ( ) => target [ method ] ( [ ] ) , errors . type ( objName , method ) , 'expected error' ) ;
assert . throws ( ( ) => target [ method ] ( 'x' ) , errors . listener ( objName , method ) , 'expected error' ) ;
assert . throws ( ( ) => target [ method ] ( { } , 'x' , ( ) => { } ) , errors . target ( objName , method ) , 'expected error' ) ;
assert . throws ( ( ) => target [ method ] ( targetb , 'x' , null ) , errors . listener ( objName , method ) , 'expected error' ) ;
} ) ;
2017-01-18 08:52:23 +02:00
} ) ;
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'off() errors' , function ( assert ) {
2021-01-22 00:00:12 +02:00
class Test { }
2019-03-18 21:49:48 +02:00
const targeta = this . targets . a = evented ( { } ) ;
const targetb = this . targets . b = evented ( { } ) ;
const targetc = this . targets . c = evented ( { } ) ;
const targetd = this . targets . d = evented ( { } ) ;
2021-01-22 00:00:12 +02:00
const targete = this . targets . e = evented ( new Test ( ) ) ;
const targetf = this . targets . f = evented ( new Test ( ) ) ;
targetf . name _ = 'foo' ;
2017-01-18 08:52:23 +02:00
// An invalid event actually causes an invalid target error because it
// gets passed into code that assumes the first argument is the target.
2021-01-22 00:00:12 +02:00
[ targeta , targete , targetf ] . forEach ( function ( target ) {
const objName = target . name _ || target . constructor . name || typeof target ;
assert . throws ( ( ) => target . off ( [ ] ) , errors . target ( objName , 'off' ) , 'expected error' ) ;
assert . throws ( ( ) => target . off ( { } , 'x' , ( ) => { } ) , errors . target ( objName , 'off' ) , 'expected error' ) ;
assert . throws ( ( ) => target . off ( targetb , '' , ( ) => { } ) , errors . type ( objName , 'off' ) , 'expected error' ) ;
assert . throws ( ( ) => target . off ( targetc , [ ] , ( ) => { } ) , errors . type ( objName , 'off' ) , 'expected error' ) ;
assert . throws ( ( ) => target . off ( targetd , 'x' , null ) , errors . listener ( objName , 'off' ) , 'expected error' ) ;
assert . throws ( ( ) => target . off ( targetd , 'x' , null ) , errors . listener ( objName , 'off' ) , 'expected error' ) ;
} ) ;
2017-01-18 08:52:23 +02:00
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'on() can add a listener to one event type on this object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . on ( 'x' , spy ) ;
a . trigger ( 'x' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'on() can add a listener to an array of event types on this object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . on ( [ 'x' , 'y' ] , spy ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
validateListenerCall ( spy . getCall ( 1 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'one() can add a listener to one event type on this object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . one ( 'x' , spy ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'x' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'one() can add a listener to an array of event types on this object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . one ( [ 'x' , 'y' ] , spy ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
validateListenerCall ( spy . getCall ( 1 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
} ) ;
2019-06-17 20:04:25 +02:00
QUnit . test ( 'one() can add a listener to an array of event types on this object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . one ( [ 'x' , 'y' ] , spy ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
validateListenerCall ( spy . getCall ( 1 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'any() can add a listener to one event type on this object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . any ( 'x' , spy ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'x' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'any() can add a listener to an array of event types on this object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . any ( [ 'x' , 'y' ] , spy ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'on() can add a listener to one event type on a different target object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . on ( b , 'x' , spy ) ;
b . trigger ( 'x' ) ;
// Make sure we aren't magically binding a listener to "a".
a . trigger ( 'x' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'on() can add a listener to an array of event types on a different target object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . on ( b , [ 'x' , 'y' ] , spy ) ;
b . trigger ( 'x' ) ;
b . trigger ( 'y' ) ;
// Make sure we aren't magically binding a listener to "a".
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
validateListenerCall ( spy . getCall ( 1 ) , a , {
type : 'y' ,
target : b . eventBusEl _
} ) ;
} ) ;
2018-07-06 19:51:22 +02:00
QUnit . test ( 'one() can add a listener to one event type on a different target object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . one ( b , 'x' , spy ) ;
b . trigger ( 'x' ) ;
// Make sure we aren't magically binding a listener to "a".
a . trigger ( 'x' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
} ) ;
2019-06-17 20:04:25 +02:00
// TODO: This test is incorrect! this listener should be called twice,
2023-03-22 16:00:01 +02:00
// but instead all listeners are removed on the first trigger!
2019-06-17 20:04:25 +02:00
// see https://github.com/videojs/video.js/issues/5962
2018-07-06 19:51:22 +02:00
QUnit . test ( 'one() can add a listener to an array of event types on a different target object' , function ( assert ) {
2017-01-18 08:52:23 +02:00
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . one ( b , [ 'x' , 'y' ] , spy ) ;
b . trigger ( 'x' ) ;
b . trigger ( 'y' ) ;
b . trigger ( 'x' ) ;
b . trigger ( 'y' ) ;
// Make sure we aren't magically binding a listener to "a".
2019-06-17 20:04:25 +02:00
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'any() can add a listener to one event type on a different target object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . any ( b , 'x' , spy ) ;
b . trigger ( 'x' ) ;
// Make sure we aren't magically binding a listener to "a".
a . trigger ( 'x' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'any() can add a listener to an array of event types on a different target object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . any ( b , [ 'x' , 'y' ] , spy ) ;
b . trigger ( 'x' ) ;
b . trigger ( 'y' ) ;
b . trigger ( 'x' ) ;
b . trigger ( 'y' ) ;
// Make sure we aren't magically binding a listener to "a".
2017-01-18 08:52:23 +02:00
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'off() with no arguments will remove all listeners from all events on this object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const spyX = sinon . spy ( ) ;
const spyY = sinon . spy ( ) ;
a . on ( 'x' , spyX ) ;
a . on ( 'y' , spyY ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
a . off ( ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spyX . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spyX . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
assert . strictEqual ( spyY . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spyY . getCall ( 0 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'off() can remove all listeners from a single event on this object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const spyX = sinon . spy ( ) ;
const spyY = sinon . spy ( ) ;
a . on ( 'x' , spyX ) ;
a . on ( 'y' , spyY ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
a . off ( 'x' ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spyX . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spyX . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
assert . strictEqual ( spyY . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spyY . getCall ( 0 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
validateListenerCall ( spyY . getCall ( 1 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'off() can remove a listener from a single event on this object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const spyX1 = sinon . spy ( ) ;
const spyX2 = sinon . spy ( ) ;
const spyY = sinon . spy ( ) ;
a . on ( 'x' , spyX1 ) ;
a . on ( 'x' , spyX2 ) ;
a . on ( 'y' , spyY ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
a . off ( 'x' , spyX1 ) ;
a . trigger ( 'x' ) ;
a . trigger ( 'y' ) ;
assert . strictEqual ( spyX1 . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spyX1 . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
assert . strictEqual ( spyX2 . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spyX2 . getCall ( 0 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
validateListenerCall ( spyX2 . getCall ( 1 ) , a , {
type : 'x' ,
target : a . eventBusEl _
} ) ;
assert . strictEqual ( spyY . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spyY . getCall ( 0 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
validateListenerCall ( spyY . getCall ( 1 ) , a , {
type : 'y' ,
target : a . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'off() can remove a listener from a single event on a different target object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . on ( b , 'x' , spy ) ;
b . trigger ( 'x' ) ;
a . off ( b , 'x' , spy ) ;
b . trigger ( 'x' ) ;
assert . strictEqual ( spy . callCount , 1 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
} ) ;
QUnit . test ( 'off() can remove a listener from an array of events on a different target object' , function ( assert ) {
const a = this . targets . a = evented ( { } ) ;
const b = this . targets . b = evented ( { } ) ;
const spy = sinon . spy ( ) ;
a . on ( b , [ 'x' , 'y' ] , spy ) ;
b . trigger ( 'x' ) ;
b . trigger ( 'y' ) ;
a . off ( b , [ 'x' , 'y' ] , spy ) ;
b . trigger ( 'x' ) ;
b . trigger ( 'y' ) ;
assert . strictEqual ( spy . callCount , 2 , 'the listener was called the expected number of times' ) ;
validateListenerCall ( spy . getCall ( 0 ) , a , {
type : 'x' ,
target : b . eventBusEl _
} ) ;
validateListenerCall ( spy . getCall ( 1 ) , a , {
type : 'y' ,
target : b . eventBusEl _
} ) ;
} ) ;
2021-07-28 21:55:35 +02:00
QUnit . test ( 'Removes DomData on dispose' , function ( assert ) {
const el _ = Dom . createEl ( 'div' ) ;
const eventBusEl _ = Dom . createEl ( 'span' , { className : 'vjs-event-bus' } ) ;
const target = evented ( { el _ , eventBusEl _ } , { eventBusKey : 'eventBusEl_' } ) ;
assert . equal ( DomData . get ( eventBusEl _ ) . handlers . dispose . length , 1 , 'event bus has dispose handler' ) ;
assert . notOk ( DomData . get ( target ) , 'evented obj has no handlers' ) ;
assert . notOk ( DomData . get ( el _ ) , 'evented el_ has handlers' ) ;
target . on ( 'foo' , ( ) => { } ) ;
assert . equal ( DomData . get ( eventBusEl _ ) . handlers . foo . length , 1 , 'foo handler added to bus' ) ;
Events . on ( eventBusEl _ , 'bar' , ( ) => { } ) ;
assert . equal ( DomData . get ( eventBusEl _ ) . handlers . bar . length , 1 , 'bar handler added to bus' ) ;
Events . on ( el _ , 'foo' , ( ) => { } ) ;
assert . equal ( DomData . get ( el _ ) . handlers . foo . length , 1 , 'foo handler added to el_' ) ;
Events . on ( target , 'foo' , ( ) => { } ) ;
assert . equal ( DomData . get ( target ) . handlers . foo . length , 1 , 'foo handler added to evented object' ) ;
target . trigger ( 'dispose' ) ;
assert . notOk ( DomData . get ( eventBusEl _ ) , 'eventBusEl_ DomData deleted' ) ;
assert . notOk ( DomData . get ( target ) , 'evented object DomData deleted' ) ;
assert . notOk ( DomData . get ( el _ ) , 'el_ DomData deleted' ) ;
} ) ;