Eventable common tests for #{on,{add,remove}Listener}

events
Mike Gerwitz 2014-08-10 22:57:47 -04:00
parent 0d40ca6f4a
commit b868a2da80
2 changed files with 117 additions and 90 deletions

View File

@ -230,17 +230,9 @@ module.exports = Trait( 'Evented' )
*/ */
on( ev, listener ) on( ev, listener )
{ {
if ( !( typeof ev === 'string' && ev ) ) { this._argValidate( ev, listener, 'hook' );
throw TypeError( "Missing event identifier" );
}
else if ( !( this._events[ ev ] ) ) {
throw ReferenceError( `Cannot hook undefined event \`${ev}'` );
}
if ( typeof listener !== 'function' ) { if ( this.hooksEvent( ev, listener ) )
throw TypeError( "Event listener must be a function" );
}
else if ( this.hooksEvent( ev, listener ) )
{ {
throw Error( throw Error(
`Listener has already been bound to event \`${ev}'` `Listener has already been bound to event \`${ev}'`
@ -252,6 +244,33 @@ module.exports = Trait( 'Evented' )
}, },
/**
* Ensures that EV and LISTENER conform to Eventable
*
* @O{1} constant time
*
* @param {string} ev event id
* @param {Function} listener hook function
*
* @return {undefined}
*/
_argValidate( ev, listener, action )
{
if ( !( typeof ev === 'string' && ev ) ) {
throw TypeError( "Missing event identifier" );
}
else if ( !( this._events[ ev ] ) ) {
throw ReferenceError(
`Cannot ${action} undefined event \`${ev}'`
);
}
if ( typeof listener !== 'function' ) {
throw TypeError( "Event listener must be a function" );
}
},
/** /**
* Adds event listener, ensuring that gaps created by removing listeners * Adds event listener, ensuring that gaps created by removing listeners
* are filled if available * are filled if available
@ -356,9 +375,7 @@ module.exports = Trait( 'Evented' )
*/ */
removeListener( ev, listener ) removeListener( ev, listener )
{ {
if ( !( this._events[ ev ] ) ) { this._argValidate( ev, listener, 'unhook' );
throw Error( `Cannot unhook undefined event \`${ev}'` );
}
this.unhookEvent( ev, listener ); this.unhookEvent( ev, listener );
return this; return this;

View File

@ -79,30 +79,21 @@ module.exports = ctor =>
[ 'on', 'addListener' ].forEach( x => [ 'on', 'addListener' ].forEach( x =>
_onTests( meta_ctor, x ) ); _onTests( meta_ctor, x ) );
_rmTests( meta_ctor );
} ); } );
}; };
function _onTests( ctor, on ) function _commonTests( ctor, method )
{
/**
* Note that by using _fvoid, we are implicitly testing the requirement
* that the listener shall not be required to declare any number of
* parameters (because we defined no parameters).
*/
describe( `#${on}`, () =>
{ {
/** /**
* We must test both inputs at once since we cannot otherwise say * We must test both inputs at once since we cannot otherwise say
* with confidence which parameter is non-conforming. * with confidence which parameter is non-conforming.
*/ */
it( 'accepts string event id with listener function', () => it( 'accepts string event id with listener function', () =>
{ expect( () => ctor()[ method ]( _ev, _fvoid ) )
expect( () => .to.not.throw( Error ) );
{
ctor()[ on ]( _ev, _fvoid );
} ).to.not.throw( Error );
} );
/** /**
@ -120,7 +111,7 @@ function _onTests( ctor, on )
*/ */
it( 'does not accept an empty event id', () => it( 'does not accept an empty event id', () =>
{ {
expect( () => ctor()[ on ]( '', _fvoid ) ) expect( () => ctor()[ method ]( '', _fvoid ) )
.to.throw( TypeError ); .to.throw( TypeError );
} ); } );
@ -134,7 +125,7 @@ function _onTests( ctor, on )
{ {
_nonstr.forEach( badev => _nonstr.forEach( badev =>
{ {
expect( () => ctor()[ on ]( badev, _fvoid ) ) expect( () => ctor()[ method ]( badev, _fvoid ) )
.to.throw( TypeError ); .to.throw( TypeError );
} ); } );
} ); } );
@ -147,7 +138,7 @@ function _onTests( ctor, on )
{ {
_nonf.forEach( badf => _nonf.forEach( badf =>
{ {
expect( () => ctor()[ on ]( _ev, badf ) ) expect( () => ctor()[ method ]( _ev, badf ) )
.to.throw( TypeError ); .to.throw( TypeError );
} ); } );
} ); } );
@ -166,9 +157,28 @@ function _onTests( ctor, on )
{ {
let inst = ctor(); let inst = ctor();
expect( inst[ on ]( _ev, _fvoid ) ) expect( inst[ method ]( _ev, _fvoid ) )
.to.equal( inst ); .to.equal( inst );
} ); } );
} ); }
function _onTests( ctor, on )
{
/**
* Note that by using _fvoid, we are implicitly testing the requirement
* that the listener shall not be required to declare any number of
* parameters (because we defined no parameters).
*/
describe( `#${on}`, () =>
{
_commonTests( ctor, on );
} );
}
function _rmTests( ctor )
{
_commonTests( ctor, 'removeListener' );
} }