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" ); + }, +} );