diff --git a/lib/ClassBuilder.js b/lib/ClassBuilder.js
index bb413d0..05a09a8 100644
--- a/lib/ClassBuilder.js
+++ b/lib/ClassBuilder.js
@@ -25,8 +25,7 @@
*/
var util = require( './util' ),
- warn = require( './warn' ),
- Warning = warn.Warning,
+ Warning = require( './warn' ).Warning,
hasOwn = Object.prototype.hasOwnProperty,
@@ -90,15 +89,23 @@ var util = require( './util' ),
* @constructor
*/
module.exports = exports =
-function ClassBuilder( member_builder, visibility_factory )
+function ClassBuilder( warn_handler, member_builder, visibility_factory )
{
// allow ommitting the 'new' keyword
if ( !( this instanceof exports ) )
{
// module.exports for Closure Compiler
- return new module.exports( member_builder, visibility_factory );
+ return new module.exports(
+ warn_handler, member_builder, visibility_factory
+ );
}
+ /**
+ * Determines how warnings should be handled
+ * @type {WarningHandler}
+ */
+ this._warnHandler = warn_handler;
+
/**
* Used for building class members
* @type {Object}
@@ -396,7 +403,7 @@ exports.prototype.build = function extend( _, __ )
// intercept warnings /only/
if ( e instanceof Warning )
{
- warn.handle( e );
+ this._warnHandler.handle( e );
}
else
{
diff --git a/lib/MemberBuilder.js b/lib/MemberBuilder.js
index 777fcf6..8c394a1 100644
--- a/lib/MemberBuilder.js
+++ b/lib/MemberBuilder.js
@@ -30,7 +30,6 @@
*/
var util = require( './util' ),
- Warning = require( './warn' ).Warning,
visibility = [ 'public', 'protected', 'private' ]
;
diff --git a/lib/class.js b/lib/class.js
index 9410dfb..ed7a64f 100644
--- a/lib/class.js
+++ b/lib/class.js
@@ -19,6 +19,19 @@
* along with this program. If not, see .
*/
+/**
+ * Console to use for logging
+ *
+ * This reference allows an alternative console to be used. Must contain
+ * warn() or log() methods.
+ *
+ * TODO: This needs to be moved into a facade, once more refactoring can be
+ * done; it was moved out of warn during its refactoring.
+ *
+ * @type {Object}
+ */
+var _console = ( typeof console !== 'undefined' ) ? console : undefined;
+
var util = require( './util' ),
ClassBuilder = require( './ClassBuilder' ),
@@ -29,6 +42,7 @@ var util = require( './util' ),
wrappers = require( './MethodWrappers' ).standard,
class_builder = ClassBuilder(
+ warn.LogHandler( _console ),
require( './MemberBuilder' )(
MethodWrapperFactory( wrappers.wrapNew ),
MethodWrapperFactory( wrappers.wrapOverride ),
diff --git a/lib/warn.js b/lib/warn.js
index 289e0a3..31185f2 100644
--- a/lib/warn.js
+++ b/lib/warn.js
@@ -1,7 +1,7 @@
/**
* ease.js warning system
*
- * Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright (C) 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
*
* This file is part of GNU ease.js.
*
@@ -19,130 +19,11 @@
* along with this program. If not, see .
*/
-/**
- * Active warning handler
- * @type {?function( Warning )}
- */
-var _handler = null;
+module.exports = {
+ Warning: require( './warn/Warning' ),
-/**
- * Console to use for logging
- *
- * This reference allows an alternative console to be used. Must contain warn()
- * or log() methods.
- *
- * @type {Object}
- */
-var _console = ( typeof console !== 'undefined' ) ? console : undefined;
-
-
-exports.Warning = require( './warn/Warning' );
-
-
-/**
- * Core warning handlers
- * @type {Object}
- */
-exports.handlers = {
- /**
- * Logs message to console
- *
- * Will attempt to log using console.warn(), falling back to console.log()
- * if necessary and aborting entirely if neither is available.
- *
- * This is useful as a default option to bring problems to the developer's
- * attention without affecting the control flow of the software.
- *
- * @param {Warning} warning to log
- *
- * @return {undefined}
- */
- log: function( warning )
- {
- var dest;
-
- _console && ( dest = _console.warn || _console.log ) &&
- dest.call( _console, ( 'Warning: ' + warning.message ) );
- },
-
-
- /**
- * Throws the error associated with the warning
- *
- * This handler is useful for development and will ensure that problems are
- * brought to the attention of the developer.
- *
- * @param {Warning} warning to log
- *
- * @return {undefined}
- */
- throwError: function( warning )
- {
- throw warning.getError();
- },
-
-
- /**
- * Ignores warnings
- *
- * This is useful in a production environment where (a) warnings will affect
- * the reputation of the software or (b) warnings may provide too much
- * insight into the software. If using this option, you should always
- * develop in a separate environment so that the system may bring warnings
- * to your attention.
- *
- * @param {Warning} warning to log
- *
- * @return {undefined}
- */
- dismiss: function( warning )
- {
- // do nothing
- },
+ DismissiveHandler: require( './warn/DismissiveHandler' ),
+ LogHandler: require( './warn/LogHandler' ),
+ ThrowHandler: require( './warn/ThrowHandler' ),
};
-
-/**
- * Sets the active warning handler
- *
- * You may use any of the predefined warning handlers or pass your own function.
- *
- * @param {function( Warning )} handler warning handler
- *
- * @return {undefined}
- */
-exports.setHandler = function( handler )
-{
- _handler = handler;
-};
-
-
-/**
- * Handles a warning using the active warning handler
- *
- * @param {Warning} warning warning to handle
- *
- * @return {undefined}
- */
-exports.handle = function( warning )
-{
- _handler( warning );
-}
-
-
-/**
- * Sets active console
- *
- * @param {Object} console containing warn() or log() method
- *
- * @return {undefined}
- */
-exports.setConsole = function( console )
-{
- _console = console;
-};
-
-
-// set the default handler
-_handler = exports.handlers.log;
-
diff --git a/lib/warn/DismissiveHandler.js b/lib/warn/DismissiveHandler.js
new file mode 100644
index 0000000..c54a64d
--- /dev/null
+++ b/lib/warn/DismissiveHandler.js
@@ -0,0 +1,51 @@
+/**
+ * Dismissive warning handler
+ *
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU ease.js.
+ *
+ * ease.js is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+/**
+ * Warning handler that dismisses (ignores) all warnings
+ *
+ * This is useful in a production environment.
+ */
+function DismissiveHandler()
+{
+ if ( !( this instanceof DismissiveHandler ) )
+ {
+ return new DismissiveHandler();
+ }
+}
+
+
+DismissiveHandler.prototype = {
+ /**
+ * Handle a warning
+ *
+ * @param {Warning} warning warning to handle
+ * @return {undefined}
+ */
+ handle: function( warning )
+ {
+ // intentionally do nothing
+ },
+}
+
+module.exports = DismissiveHandler;
+
diff --git a/lib/warn/LogHandler.js b/lib/warn/LogHandler.js
new file mode 100644
index 0000000..9934b50
--- /dev/null
+++ b/lib/warn/LogHandler.js
@@ -0,0 +1,64 @@
+/**
+ * Logging warning handler
+ *
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU ease.js.
+ *
+ * ease.js is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+/**
+ * Warning handler that logs all warnings to a console
+ *
+ * @param {Object} console console with a warn or log method
+ */
+function LogHandler( console )
+{
+ if ( !( this instanceof LogHandler ) )
+ {
+ return new LogHandler( console );
+ }
+
+ this._console = console || {};
+}
+
+
+LogHandler.prototype = {
+ /**
+ * Handle a warning
+ *
+ * Will attempt to log using console.warn(), falling back to
+ * console.log() if necessary and aborting entirely if neither is
+ * available.
+ *
+ * This is useful as a default option to bring problems to the
+ * developer's attention without affecting the control flow of the
+ * software.
+ *
+ * @param {Warning} warning warning to handle
+ * @return {undefined}
+ */
+ handle: function( warning )
+ {
+ var dest = this._console.warn || this._console.log;
+ dest && dest.call( this._console,
+ 'Warning: ' + warning.message
+ );
+ },
+}
+
+module.exports = LogHandler;
+
diff --git a/lib/warn/ThrowHandler.js b/lib/warn/ThrowHandler.js
new file mode 100644
index 0000000..9ac8c79
--- /dev/null
+++ b/lib/warn/ThrowHandler.js
@@ -0,0 +1,54 @@
+/**
+ * Throwing warning handler
+ *
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU ease.js.
+ *
+ * ease.js is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+/**
+ * Warning handler that throws all warnings as exceptions
+ */
+function ThrowHandler()
+{
+ if ( !( this instanceof ThrowHandler ) )
+ {
+ return new ThrowHandler();
+ }
+}
+
+
+ThrowHandler.prototype = {
+ /**
+ * Handle a warning
+ *
+ * Throws the error associated with the warning.
+ *
+ * This handler is useful for development and will ensure that problems
+ * are brought to the attention of the developer.
+ *
+ * @param {Warning} warning warning to handle
+ * @return {undefined}
+ */
+ handle: function( warning )
+ {
+ throw warning.getError();
+ },
+}
+
+module.exports = ThrowHandler;
+
diff --git a/test/ClassBuilder/ConstTest.js b/test/ClassBuilder/ConstTest.js
index 5bc5b95..b9881bf 100644
--- a/test/ClassBuilder/ConstTest.js
+++ b/test/ClassBuilder/ConstTest.js
@@ -23,8 +23,6 @@ require( 'common' ).testCase(
{
caseSetUp: function()
{
- // XXX: get rid of this disgusting mess; we're mid-refactor and all
- // these dependencies should not be necessary for testing
this.Sut = this.require( 'ClassBuilder' );
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
@@ -34,14 +32,17 @@ require( 'common' ).testCase(
setUp: function()
{
+ // XXX: get rid of this disgusting mess; we're mid-refactor and all
+ // these dependencies should not be necessary for testing
this.builder = this.Sut(
- this.require( '/MemberBuilder' )(
+ this.require( 'warn' ).DismissiveHandler(),
+ this.require( 'MemberBuilder' )(
this.MethodWrapperFactory( this.wrappers.wrapNew ),
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
this.MethodWrapperFactory( this.wrappers.wrapProxy ),
this.getMock( 'MemberBuilderValidator' )
),
- this.require( '/VisibilityObjectFactoryFactory' )
+ this.require( 'VisibilityObjectFactoryFactory' )
.fromEnvironment()
)
},
diff --git a/test/ClassBuilder/FinalTest.js b/test/ClassBuilder/FinalTest.js
index d171c7c..c2e429e 100644
--- a/test/ClassBuilder/FinalTest.js
+++ b/test/ClassBuilder/FinalTest.js
@@ -73,6 +73,7 @@ require( 'common' ).testCase(
{
// XXX: clean up this mess.
var builder = this.require( 'ClassBuilder' )(
+ this.require( 'warn' ).DismissiveHandler(),
this.require( 'MemberBuilder' )(),
this.require( 'VisibilityObjectFactoryFactory' )
.fromEnvironment()
diff --git a/test/ClassBuilder/MemberRestrictionTest.js b/test/ClassBuilder/MemberRestrictionTest.js
index eefe9a9..fa5b798 100644
--- a/test/ClassBuilder/MemberRestrictionTest.js
+++ b/test/ClassBuilder/MemberRestrictionTest.js
@@ -291,6 +291,7 @@ require( 'common' ).testCase(
build = this.require( 'MemberBuilder' )();
var sut = this.Sut(
+ this.require( 'warn' ).DismissiveHandler(),
build,
this.require( 'VisibilityObjectFactoryFactory' )
.fromEnvironment()
diff --git a/test/ClassBuilder/StaticTest.js b/test/ClassBuilder/StaticTest.js
index f2f6a5f..063dabb 100644
--- a/test/ClassBuilder/StaticTest.js
+++ b/test/ClassBuilder/StaticTest.js
@@ -26,8 +26,6 @@ require( 'common' ).testCase(
{
this.fallback = this.require( 'util' ).definePropertyFallback();
- // XXX: get rid of this disgusting mess; we're mid-refactor and all
- // these dependencies should not be necessary for testing
this.ClassBuilder = this.require( 'ClassBuilder' );
this.MemberBuilder = this.require( 'MemberBuilder' );
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
@@ -38,7 +36,10 @@ require( 'common' ).testCase(
setUp: function()
{
+ // XXX: get rid of this disgusting mess; we're mid-refactor and all
+ // these dependencies should not be necessary for testing
this.builder = this.ClassBuilder(
+ this.require( 'warn' ).DismissiveHandler(),
this.MemberBuilder(
this.MethodWrapperFactory( this.wrappers.wrapNew ),
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
diff --git a/test/ClassBuilder/VisibilityTest.js b/test/ClassBuilder/VisibilityTest.js
index d84706f..b98102e 100644
--- a/test/ClassBuilder/VisibilityTest.js
+++ b/test/ClassBuilder/VisibilityTest.js
@@ -25,8 +25,6 @@ require( 'common' ).testCase(
{
caseSetUp: function()
{
- // XXX: get rid of this disgusting mess; we're mid-refactor and all
- // these dependencies should not be necessary for testing
this.Sut = this.require( 'ClassBuilder' );
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
@@ -37,7 +35,10 @@ require( 'common' ).testCase(
setUp: function()
{
+ // XXX: get rid of this disgusting mess; we're mid-refactor and all
+ // these dependencies should not be necessary for testing
this.builder = this.Sut(
+ this.require( 'warn' ).DismissiveHandler(),
this.require( '/MemberBuilder' )(
this.MethodWrapperFactory( this.wrappers.wrapNew ),
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
diff --git a/test/WarnHandlersTest.js b/test/WarnHandlersTest.js
deleted file mode 100644
index c2753c0..0000000
--- a/test/WarnHandlersTest.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * Tests core warning handlers
- *
- * Copyright (C) 2014 Free Software Foundation, Inc.
- *
- * This file is part of GNU ease.js.
- *
- * ease.js is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-try { void console } catch ( e ) { console = undefined; }
-
-require( 'common' ).testCase(
-{
- caseSetUp: function()
- {
- // XXX: this has global state
- this.Sut = this.require( 'warn' );
- },
-
-
- setUp: function()
- {
- this.stubwarn = this.Sut.Warning( Error( 'gninraw' ) );
- },
-
-
- /**
- * The log warning handler should log warnings to the console
- */
- '`log\' warning handler logs messages to console': function()
- {
- var _self = this,
- logged = false;
-
- // mock console
- this.Sut.setConsole( {
- warn: function( message )
- {
- // should prefix with `Warning: '
- _self.assertEqual(
- ( 'Warning: ' + _self.stubwarn.message ),
- message
- );
-
- logged = true;
- },
- } );
-
- // call handler with the warning
- this.Sut.handlers.log( this.stubwarn );
-
- this.assertOk( logged, true,
- "Message should be logged to console"
- );
-
- // restore console (TODO: will not be necessary once global state is
- // removed)
- this.Sut.setConsole( console );
- },
-
-
- /**
- * Some environments may not have a console reference, or they may not
- * have console.warn. In this case, we just want to make sure we don't
- * throw an error when attempting to invoke undefined, or access a
- * property of undefined.
- */
- '`log\' warning handler handles missing console': function()
- {
- var Sut = this.Sut;
-
- // destroy it
- Sut.setConsole( undefined );
-
- // attempt to log
- var _self = this;
- this.assertDoesNotThrow( function()
- {
- Sut.handlers.log( _self.warnstub );
- } );
-
- // restore console
- Sut.setConsole( console );
- },
-
-
- /**
- * Furthermore, an environment may implement console.log(), but not
- * console.warn(). By default, we use warn(), so let's ensure we can
- * fall back to log() if warn() is unavailable.
- */
- '`log\' warning handler falls back to log if warn is missing':
- function()
- {
- var given = '';
-
- this.Sut.setConsole( {
- log: function( message )
- {
- given = message;
- }
- } );
-
- // attempt to log
- this.Sut.handlers.log( this.stubwarn );
-
- this.assertEqual( ( 'Warning: ' + this.stubwarn.message ), given,
- "Should fall back to log() and log proper message"
- );
-
- // restore console
- this.Sut.setConsole( console );
- },
-
-
- /**
- * The throwError warning handler should throw the wrapped error as an
- * exception
- */
- '`throwError\' warning handler throws wrapped error': function()
- {
- try
- {
- this.Sut.handlers.throwError( this.stubwarn );
- }
- catch ( e )
- {
- this.assertStrictEqual( e, this.stubwarn.getError(),
- "Wrapped exception should be thrown"
- );
-
- return;
- }
-
- this.assertFail( "Wrapped exception should be thrown" );
- },
-
-
- /**
- * The 'dismiss' error handler is a pretty basic concept: simply do
- * nothing. We don't want to log, we don't want to throw anything, we
- * just want to pretend nothing ever happened and move on our merry way.
- * This is intended for use in production environments where such
- * warnings are expected to already have been worked out and would only
- * confuse/concern the user.
- */
- '`dismiss\' warning handler does nothing': function()
- {
- var Sut = this.Sut;
-
- // destroy the console to ensure nothing is logged
- Sut.setConsole( undefined );
-
- // no errors should occur because it should not do anything.
- var _self = this;
- this.assertDoesNotThrow( function()
- {
- Sut.handlers.dismiss( _self.warnstub );
- } );
-
- // restore console
- Sut.setConsole( console );
- },
-} );
diff --git a/test/WarnTest.js b/test/WarnTest.js
deleted file mode 100644
index 7206155..0000000
--- a/test/WarnTest.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Tests warning system implementation
- *
- * Copyright (C) 2014 Free Software Foundation, Inc.
- *
- * This file is part of GNU ease.js.
- *
- * ease.js is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-try { void console } catch ( e ) { console = undefined; }
-
-require( 'common' ).testCase(
-{
- setUp: function()
- {
- // XXX: this uses global state; remove that requirement.
- this.Sut = this.require( 'warn' );
- },
-
-
- /**
- * The default warning handler should be the 'log' handler; this is a
- * friendly compromise that will allow the developer to be warned of
- * potential issues without affecting program execution.
- */
- 'Default warning handler is `log\'': function()
- {
- var called = false;
-
- // stub it
- this.Sut.setConsole( {
- warn: function()
- {
- called = true;
- },
- } );
-
- this.Sut.handle( this.Sut.Warning( Error( 'foo' ) ) );
- this.assertOk( called );
-
- // restore console (TODO: this will not be necessary once reliance
- // on global state is removed)
- this.Sut.setConsole( console );
- },
-
-
- /**
- * The warning handler can be altered at runtime; ensure we can set it
- * and call it appropriately. We do not need to use one of the
- * pre-defined handlers.
- */
- 'Can set and call arbitrary warning handler': function()
- {
- var given,
- warning = this.Sut.Warning( Error( 'foo' ) );
-
- // set a stub warning handler
- this.Sut.setHandler( function( warn )
- {
- given = warn;
- } );
-
- // trigger the handler
- this.Sut.handle( warning );
- this.assertDeepEqual( given, warning );
- },
-} );
diff --git a/test/warn/DismissiveHandlerTest.js b/test/warn/DismissiveHandlerTest.js
new file mode 100644
index 0000000..aef8653
--- /dev/null
+++ b/test/warn/DismissiveHandlerTest.js
@@ -0,0 +1,57 @@
+/**
+ * Tests dismissive warning handler
+ *
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU ease.js.
+ *
+ * ease.js is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+require( 'common' ).testCase(
+{
+ caseSetUp: function()
+ {
+ this.Sut = this.require( 'warn/DismissiveHandler' );
+ this.Warning = this.require( 'warn/Warning' );
+ },
+
+
+ 'Can be instantiated without `new` keyword': function()
+ {
+ this.assertOk( this.Sut() instanceof this.Sut );
+ },
+
+
+ /**
+ * Simply do nothing. We don't want to log, we don't want to throw
+ * anything, we just want to pretend nothing ever happened and move on
+ * our merry way. This is intended for use in production environments
+ * where such warnings are expected to already have been worked out and
+ * would only confuse/concern the user.
+ *
+ * Now, testing whether it does anything or not is difficult, since it
+ * could do, well, anything; that said, we are not passing it anything
+ * via the ctor, so assuming that it does not rely on or manipulate
+ * global state, we need only ensure that no exceptions are thrown.
+ */
+ 'Does nothing': function()
+ {
+ var _self = this;
+ this.assertDoesNotThrow( function()
+ {
+ _self.Sut().handle( _self.Warning( Error( "Ignore me!" ) ) );
+ } );
+ },
+} );
diff --git a/test/warn/LogHandlerTest.js b/test/warn/LogHandlerTest.js
new file mode 100644
index 0000000..46c84c1
--- /dev/null
+++ b/test/warn/LogHandlerTest.js
@@ -0,0 +1,126 @@
+/**
+ * Tests logging warning handler
+ *
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU ease.js.
+ *
+ * ease.js is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+require( 'common' ).testCase(
+{
+ caseSetUp: function()
+ {
+ this.Sut = this.require( 'warn/LogHandler' );
+ this.Warning = this.require( 'warn/Warning' );
+ },
+
+
+ setUp: function()
+ {
+ this.stubwarn = this.Warning( Error( 'gninraw' ) );
+ },
+
+
+ 'Can be instantiated without `new` keyword': function()
+ {
+ this.assertOk( this.Sut() instanceof this.Sut );
+ },
+
+
+ /**
+ * Warnings should be logged to the provided console. By default, the
+ * `warn` method is used (see below tests for fallbacks).
+ */
+ 'Logs messages to console': function()
+ {
+ var _self = this,
+ logged = false;
+
+ // mock console
+ this.Sut( {
+ warn: function( message )
+ {
+ // should prefix with `Warning: '
+ _self.assertEqual(
+ ( 'Warning: ' + _self.stubwarn.message ),
+ message
+ );
+
+ logged = true;
+ },
+ } ).handle( this.stubwarn );
+
+ this.assertOk( logged, true,
+ "Message should be logged to console"
+ );
+ },
+
+
+ /**
+ * Some environments may not have a console reference, or they may not
+ * have console.warn. In this case, we just want to make sure we don't
+ * throw an error when attempting to invoke undefined, or access a
+ * property of undefined.
+ */
+ 'Ignores missing console': function()
+ {
+ var _self = this;
+ this.assertDoesNotThrow( function()
+ {
+ _self.Sut( undefined ).handle( _self.warnstub );
+ } );
+ },
+
+
+ /**
+ * Furthermore, an environment may implement `console.log`, but not
+ * `console.warn`. By default, we use `warn`, so let's ensure we can
+ * fall back to `log` if `warn` is unavailable.
+ */
+ 'Falls back to log if warn is missing': function()
+ {
+ var given = '';
+
+ this.Sut( {
+ log: function( message )
+ {
+ given = message;
+ }
+ } ).handle( this.stubwarn );
+
+ this.assertEqual( ( 'Warning: ' + this.stubwarn.message ), given,
+ "Should fall back to log() and log proper message"
+ );
+ },
+
+
+ /**
+ * If both `console.warn` and `console.log` are defined (which is very
+ * likely to be the case), the former should take precedence.
+ */
+ '`warn` takes precedence over `log`': function()
+ {
+ var log = warn = false;
+
+ this.Sut( {
+ warn: function() { warn = true },
+ log: function() { log = true },
+ } ).handle( this.stubwarn );
+
+ this.assertOk( warn );
+ this.assertOk( !log );
+ },
+} );
diff --git a/test/warn/ThrowHandlerTest.js b/test/warn/ThrowHandlerTest.js
new file mode 100644
index 0000000..d0ce1d5
--- /dev/null
+++ b/test/warn/ThrowHandlerTest.js
@@ -0,0 +1,60 @@
+/**
+ * Tests throwing warning handler
+ *
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU ease.js.
+ *
+ * ease.js is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+require( 'common' ).testCase(
+{
+ caseSetUp: function()
+ {
+ this.Sut = this.require( 'warn/ThrowHandler' );
+ this.Warning = this.require( 'warn/Warning' );
+ },
+
+
+ 'Can be instantiated without `new` keyword': function()
+ {
+ this.assertOk( this.Sut() instanceof this.Sut );
+ },
+
+
+ /**
+ * The wrapped error should be thrown as an exception; this effectively
+ * undoes the warning wrapper.
+ */
+ '`throwError\' warning handler throws wrapped error': function()
+ {
+ var warn = this.Warning( Error( 'gninraw' ) );
+
+ try
+ {
+ this.Sut().handle( warn );
+ }
+ catch ( e )
+ {
+ this.assertStrictEqual( e, warn.getError(),
+ "Wrapped exception should be thrown"
+ );
+
+ return;
+ }
+
+ this.assertFail( "Wrapped exception should be thrown" );
+ },
+} );