Using ES6 features through Traceur to cut down on verbosity

It will take some getting used to (and it's a little sad to see some of the
long-standing conventions of ECMAScript vanish before my eyes), but it's
great thus far.
events
Mike Gerwitz 2014-05-05 00:19:44 -04:00 committed by Mike Gerwitz
parent 2942f153db
commit 7baff379ce
5 changed files with 91 additions and 170 deletions

View File

@ -57,7 +57,7 @@ module.exports = Trait( 'Evented',
* @throws {TypeError} if an array is not provided
* @throws {Error} on duplicate id conflict
*/
'protected defineEvents': function( ids )
'protected defineEvents'( ids )
{
if ( !isArray( ids ) ) {
throw TypeError( "Expected array of event ids" );
@ -78,14 +78,14 @@ module.exports = Trait( 'Evented',
*
* @throws {Error} on duplicate id definition
*/
_mergeDfn: function( ids )
_mergeDfn( ids )
{
var i = ids.length;
while ( i-- ) {
var id = ids[ i ];
if ( this._events[ id ] ) {
throw Error( "Duplicate definition of event `" + id + "'" );
throw Error( `Duplicate definition of event \`${id}'` );
}
// will contain each callback associated with this event
@ -103,10 +103,10 @@ module.exports = Trait( 'Evented',
* @param {string} ev defined event id
* @return {Evented} self
*/
'protected emit': function( ev )
'protected emit'( ev )
{
if ( !( this._events[ ev ] ) ) {
throw Error( "Cannot emit undefined event `" + ev + "'" );
throw Error( `Cannot emit undefined event \`${ev}'` );
}
var args = [],
@ -136,7 +136,7 @@ module.exports = Trait( 'Evented',
*
* @return {Evented} self
*/
'virtual protected scheduleCallbacks': function( ev, evc, args )
'virtual protected scheduleCallbacks'( ev, evc, args )
{
var i = evc.length;
@ -160,7 +160,7 @@ module.exports = Trait( 'Evented',
*
* @return {Evented} self
*/
on: function( ev, callback )
on( ev, callback )
{
if ( !( this._events[ ev ] ) ) {
throw Error( "Cannot hook undefined event `" + ev + "'" );

View File

@ -38,11 +38,7 @@ module.exports = {
* @param {*} arr value to check
* @return {boolean} whether the given value is an array primitive
*/
_isArray: function( arr )
{
return (
Object.prototype.toString.call( arr ) === '[object Array]'
);
},
_isArray: ( arr ) =>
Object.prototype.toString.call( arr ) === '[object Array]',
};

View File

@ -27,74 +27,68 @@ var Sut = require( '../../' ).event.Evented,
EvStub = Class.use( Sut ).extend(
{
// defineEvents is protected
evDefineEvents: function( ids )
evDefineEvents( ids )
{
return this.defineEvents( ids );
},
// emit is protected
evEmit: function( ev )
evEmit( ev )
{
return this.emit.apply( this, arguments );
}
} );
describe( 'event.Evented', function()
describe( 'event.Evented', () =>
{
var stub;
beforeEach( function()
beforeEach( () =>
{
stub = EvStub();
} );
describe( '#defineEvents', function()
describe( '#defineEvents', () =>
{
/**
* We aren't going to bother testing every possibly value; let's
* just see if the most common case (probably) is caught.
*/
it( 'rejects non-array argument', function()
it( 'rejects non-array argument', () =>
{
expect( function()
{
stub.evDefineEvents( 'string' );
} ).to.throw( TypeError, "array" );
expect( () => stub.evDefineEvents( 'string' ) )
.to.throw( TypeError, "array" );
} );
it( 'accepts array argument', function()
it( 'accepts array argument', () =>
{
expect( function()
{
stub.evDefineEvents( [] );
} ).to.not.throw( TypeError );
expect( () => stub.evDefineEvents( [] ) )
.to.not.throw( TypeError );
} );
it( 'returns self', function()
it( 'returns self', () =>
{
expect( stub.evDefineEvents( [] ) ).to.equal( stub );
} );
/**
* This relies on functionality proven below
* This relies on functionality proved below
*/
it( 'defines each event in provided list', function()
it( 'defines each event in provided list', () =>
{
var events = [ 'a', 'b' ];
stub.evDefineEvents( events );
var i = events.length;
while ( i-- ) {
expect( function()
{
// will fail if event did not register
stub.on( events[ i ], function() {} );
} ).to.not.throw( Error );
// will fail if event did not register
expect( () => stub.on( events[ i ], ()=>{} ) )
.to.not.throw( Error );
}
} );
@ -104,7 +98,7 @@ describe( 'event.Evented', function()
* do, this will come in useful when exposed via an API that defines
* events individually.
*/
it( 'merges definitions in multiple calls', function()
it( 'merges definitions in multiple calls', () =>
{
var evs = [ 'a', 'b' ];
@ -112,11 +106,9 @@ describe( 'event.Evented', function()
for ( var i = 0; i < evs.length; i++ ) {
stub.evDefineEvents( [ evs[ i ] ] );
expect( function()
{
// will fail if event did not register
stub.on( evs[ i ], function() {} );
} ).to.not.throw( Error );
// will fail if event did not register
expect( () => stub.on( evs[ i ], ()=>{} ) )
.to.not.throw( Error );
}
} );
@ -126,113 +118,96 @@ describe( 'event.Evented', function()
* is free, which risks mixing handlers from what is supposed to be
* two separate events.
*/
describe( 'throws exception on duplicate events', function()
describe( 'throws exception on duplicate events', () =>
{
it( 'in separate calls', function()
it( 'in separate calls', () =>
{
var name = 'ev';
stub.evDefineEvents( [ name ] );
expect( function()
{
stub.evDefineEvents( [ name ] );
} ).to.throw( Error, name );
expect( () => stub.evDefineEvents( [ name ] ) )
.to.throw( Error, name );
} );
it( 'in a single call', function()
it( 'in a single call', () =>
{
var dup = 'foo';
expect( function()
{
stub.evDefineEvents( [ 'a', dup, 'b', dup ] );
} ).to.throw( Error, dup );
expect( () => stub.evDefineEvents( [ dup, 'a', dup ] ) )
.to.throw( Error, dup );
} );
} );
} );
describe( '#on', function()
describe( '#on', () =>
{
it( 'does not allow hooking undeclared events', function()
it( 'does not allow hooking undeclared events', () =>
{
var badevent = 'bazbar';
expect( function()
{
stub.on( badevent, function() {} );
} ).to.throw( Error, badevent );
expect( () => stub.on( badevent, ()=>{} ) )
.to.throw( Error, badevent );
} );
it( 'allows hooking declared events', function()
it( 'allows hooking declared events', () =>
{
var name = 'testev';
stub.evDefineEvents( [ name ] )
.on( name, function() {} );
.on( name, ()=>{} );
} );
it( 'returns self', function()
it( 'returns self', () =>
{
var name = 'testev';
var ret = stub.evDefineEvents( [ name ] )
.on( name, function() {} );
.on( name, ()=>{} );
expect( ret ).to.equal( stub );
} );
it( 'requires that callback is a function', function()
it( 'requires that callback is a function', () =>
{
var ev = 'foo';
stub.evDefineEvents( [ ev ] );
// OK
expect( function()
{
stub.on( ev, function() {} );
} ).to.not.throw( TypeError );
expect( () => stub.on( ev, ()=>{} ) )
.to.not.throw( TypeError );
// bad
expect( function()
{
stub.on( ev, "kittens" );
} ).to.throw( TypeError );
expect( () => stub.on( ev, "kittens" ) )
.to.throw( TypeError );
} );
} );
describe( '#emit', function()
describe( '#emit', () =>
{
it( 'cannot emit undefined events', function()
it( 'cannot emit undefined events', () =>
{
var ev = 'unknown';
expect( function()
{
stub.evEmit( ev );
} ).to.throw( Error, ev );
expect( () => stub.evEmit( ev ) )
.to.throw( Error, ev );
} );
it( 'invokes all callbacks attached with #on', function()
it( 'invokes all callbacks attached with #on', () =>
{
var ev = 'foo',
called = 0;
stub.evDefineEvents( [ ev ] )
.on( ev, function()
{
called++;
} );
.on( ev, () => called++ );
expect( function()
{
stub.evEmit( ev );
} ).to.not.throw( Error );
expect( () => stub.evEmit( ev ) )
.to.not.throw( Error );
// make sure the callback was invoked only once
expect( called ).to.equal( 1 );
@ -244,14 +219,14 @@ describe( 'event.Evented', function()
* are given. Otherwise, the emitter must take care to clone or
* encapsulate the values if this is a concern.
*/
it( 'passes all emit args by reference to callbacks', function( done )
it( 'passes all emit args by reference to callbacks', ( done ) =>
{
var ev = 'foo',
a = {},
b = [];
stub.evDefineEvents( [ ev ] )
.on( ev, function( givena, givenb )
.on( ev, ( givena, givenb ) =>
{
expect( givena ).to.equal( a );
expect( givenb ).to.equal( b );
@ -267,7 +242,7 @@ describe( 'event.Evented', function()
* future). This is not desirable for all cases, but that's not the
* point here.
*/
it( 'invokes multiple callbacks synchronously', function()
it( 'invokes multiple callbacks synchronously', () =>
{
var ev = 'foo',
called = [],
@ -276,14 +251,8 @@ describe( 'event.Evented', function()
stub.evDefineEvents( [ ev ] );
// add N callbacks for EV
for ( var i = 0; i < n; i++ ) {
( function( i )
{
stub.on( ev, function()
{
called[ i ] = true;
} );
} )( i );
for ( let i = 0; i < n; i++ ) {
stub.on( ev, () => called[ i ] = true );
}
// trigger callbacks
@ -302,7 +271,7 @@ describe( 'event.Evented', function()
* When we emit an event, only the callbacks for that specific event
* should be invoked.
*/
it( 'does not mix callbacks from other events', function()
it( 'does not mix callbacks from other events', () =>
{
var ev = 'foo',
wrongev = 'bar';
@ -310,8 +279,8 @@ describe( 'event.Evented', function()
stub.evDefineEvents( [ ev, wrongev ] );
var called = false;
stub.on( ev, function() { called = true; } );
stub.on( wrongev, function() { throw Error( "Thar be demons" ); } );
stub.on( ev, () => called = true );
stub.on( wrongev, () => { throw Error( "Thar be demons" ) } );
// wrongev callback should *not* be called
stub.evEmit( ev );
@ -322,18 +291,15 @@ describe( 'event.Evented', function()
/**
* It is common to leave events unhooked.
*/
it( 'does not fail when emitting unhooked events', function()
it( 'does not fail when emitting unhooked events', () =>
{
var ev = 'foo';
expect( function()
{
// no hooks, but emit
stub.evDefineEvents( [ ev ] ).evEmit( ev );
} ).to.not.throw( Error );
expect( () => stub.evDefineEvents( [ ev ] ).evEmit( ev ) )
.to.not.throw( Error );
} );
it( 'returns self', function()
it( 'returns self', () =>
{
var ev = 'foo';
expect( stub.evDefineEvents( [ ev ] ).evEmit( ev ) )
@ -345,16 +311,16 @@ describe( 'event.Evented', function()
/**
* This is important to support stackable traits for custom schedulers.
*/
describe( '#scheduleCallbacks', function()
describe( '#scheduleCallbacks', () =>
{
var ev = 'foo',
a = 'bar',
b = 'baz';
it( 'can be overridden by subtypes', function( done )
it( 'can be overridden by subtypes', ( done ) =>
{
common.checkOverride( EvStub, 'scheduleCallbacks',
function( given_ev, _, given_args )
( given_ev, _, given_args ) =>
{
expect( given_ev ).to.equal( ev );
expect( given_args ).to.deep.equal( [ a, b ] );
@ -368,13 +334,13 @@ describe( 'event.Evented', function()
* The listeners are encapsulated within the trait, so they must be
* passed to us for processing.
*/
it( 'is provided with callbacks to invoke', function( done )
it( 'is provided with callbacks to invoke', ( done ) =>
{
var a = function() {},
b = function() {};
common.checkOverride( EvStub, 'scheduleCallbacks',
function( _, evc, __ )
( _, evc, __ ) =>
{
expect( evc ).to.include( a );
expect( evc ).to.include( b );

View File

@ -35,17 +35,12 @@ var expect = require( 'chai' ).expect;
*
* @return {Class} generated subtype
*/
exports.checkOverride = function( C, name, mock )
exports.checkOverride = ( C, name, mock ) =>
{
var SubC;
expect( function()
{
var dfn = {};
dfn[ 'override ' + name ] = mock;
SubC = C.extend( dfn );
} ).to.not.throw( Error );
expect( () => SubC = C.extend( { [ `override ${name}` ]: mock } ) )
.to.not.throw( Error );
// allows performing actions to trigger function for mock
return SubC;

View File

@ -23,15 +23,15 @@ var Sut = require( '../../' ).std.Array,
expect = require( 'chai' ).expect;
describe( 'std.Array', function()
describe( 'std.Array', () =>
{
describe( '#isArray', function()
describe( '#isArray', () =>
{
/**
* The idea is that this should succeed in whatever environment this
* test case is being run.
*/
it( 'uses either ES5 Array.isArray or std.Array._isArray', function()
it( 'uses either ES5 Array.isArray or std.Array._isArray', () =>
{
expect( [ Array.isArray, Sut._isArray ] )
.to.include( Sut.isArray );
@ -45,53 +45,17 @@ describe( 'std.Array', function()
* Many of these tests exist not because there are holes in the
* implementation, but to prevent regressions.
*/
describe( '#_isArray', function()
describe( '#_isArray', () =>
{
it( 'recognizes array primitive', function()
{
_ischk( [], true );
} );
it( 'rejects objects', function()
{
// 0 key is to be tricky
_ischk( { 0: true }, false );
} );
it( 'rejects functions', function()
{
_ischk( function() {}, false );
} );
it( 'rejects strings', function()
{
_ischk( "", false );
} );
it( 'rejects numbers', function()
{
_ischk( 0, false );
} );
it( 'rejects infinity', function()
{
_ischk( Infinity, false );
} );
it( 'rejects NaN', function()
{
_ischk( NaN, false );
} );
it( 'rejects undefined', function()
{
_ischk( undefined, false );
} );
it( 'rejects null', function()
{
_ischk( null, false );
} );
it( 'recognizes array', () => _ischk( [], true ) );
it( 'rejects objects', () => _ischk( { 0: true }, false ) );
it( 'rejects functions', () => _ischk( ()=>{}, false ) );
it( 'rejects strings', () => _ischk( "", false ) );
it( 'rejects numbers', () => _ischk( 0, false ) );
it( 'rejects infinity', () => _ischk( Infinity, false ) );
it( 'rejects NaN', () => _ischk( NaN, false ) );
it( 'rejects undefined', () => _ischk( undefined, false ) );
it( 'rejects null', () => _ischk( null, false ) );
} );
} );