mirror of
				https://github.com/JuanCanham/HackMyResume.git
				synced 2025-10-31 05:07:26 +00:00 
			
		
		
		
	Refactor error handling.
Work towards better debug/log/stack trace options for error cases.
This commit is contained in:
		| @@ -28,102 +28,122 @@ Error-handling routines for HackMyResume. | |||||||
|  |  | ||||||
|  |  | ||||||
|     err: function( ex, shouldExit ) { |     err: function( ex, shouldExit ) { | ||||||
|       var msg = '', exitCode; |  | ||||||
|  |  | ||||||
|  |       var msg = '', exitCode, log = console.log, showStack = false; | ||||||
|  |  | ||||||
|  |       // If the exception has been handled elsewhere and shouldExit is true, | ||||||
|  |       // let's get out of here, otherwise silently return. | ||||||
|       if( ex.handled ) { |       if( ex.handled ) { | ||||||
|         if( shouldExit ) |         if( shouldExit ) | ||||||
|           process.exit( exitCode ); |           process.exit( exitCode ); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       // Get an error message -- either a HackMyResume error message or the | ||||||
|  |       // exception's associated error message | ||||||
|       if( ex.fluenterror ){ |       if( ex.fluenterror ){ | ||||||
|  |         var errInfo = get_error_msg( ex ); | ||||||
|         switch( ex.fluenterror ) { |         msg = errInfo.msg; | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.themeNotFound: |  | ||||||
|             msg = "The specified theme couldn't be found: " + ex.data; |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.copyCSS: |  | ||||||
|             msg = "Couldn't copy CSS file to destination folder"; |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.resumeNotFound: |  | ||||||
|             msg = chalk.yellow('Please ') + chalk.yellow.bold('feed me a resume') + |  | ||||||
|               chalk.yellow(' in FRESH or JSON Resume format.'); |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.missingCommand: |  | ||||||
|             msg = chalk.yellow("Please ") + chalk.yellow.bold("give me a command") + |  | ||||||
|               chalk.yellow(" ("); |  | ||||||
|  |  | ||||||
|             msg += Object.keys( FCMD.verbs ).map( function(v, idx, ar) { |  | ||||||
|               return (idx === ar.length - 1 ? chalk.yellow('or ') : '') + |  | ||||||
|                 chalk.yellow.bold(v.toUpperCase()); |  | ||||||
|             }).join( chalk.yellow(', ')) + chalk.yellow(").\n\n"); |  | ||||||
|  |  | ||||||
|             msg += chalk.gray(FS.readFileSync( PATH.resolve(__dirname, '../use.txt'), 'utf8' )); |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.invalidCommand: |  | ||||||
|             msg = chalk.yellow('Invalid command: "') + chalk.yellow.bold(ex.attempted) + chalk.yellow('"'); |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.resumeNotFoundAlt: |  | ||||||
|             msg = chalk.yellow('Please ') + chalk.yellow.bold('feed me a resume') + |  | ||||||
|               chalk.yellow(' in either FRESH or JSON Resume format.'); |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.inputOutputParity: |  | ||||||
|             msg = chalk.yellow('Please ') + chalk.yellow.bold('specify an output file name') + |  | ||||||
|               chalk.yellow(' for every input file you wish to convert.'); |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.createNameMissing: |  | ||||||
|             msg = chalk.yellow('Please ') + chalk.yellow.bold('specify the filename of the resume') + |  | ||||||
|               chalk.yellow(' to create.'); |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.wkhtmltopdf: |  | ||||||
|             msg = chalk.red.bold('ERROR: PDF generation failed. ') + chalk.red('Make sure wkhtmltopdf is ' + |  | ||||||
|             'installed and accessible from your path.'); |  | ||||||
|             if( ex.inner ) msg += chalk.red('\n' + ex.inner); |  | ||||||
|             break; |  | ||||||
|  |  | ||||||
|           case HACKMYSTATUS.invalid: |  | ||||||
|             msg = chalk.red.bold('ERROR: Validation failed and the --assert option was specified.'); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         exitCode = ex.fluenterror; |         exitCode = ex.fluenterror; | ||||||
|  |         showStack = errInfo.showStack; | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         msg = ex.toString(); |         msg = ex.toString(); | ||||||
|         exitCode = 4; |         exitCode = -1; | ||||||
|  |         // Deal with pesky 'Error:' prefix. | ||||||
|  |         var idx = msg.indexOf('Error: '); | ||||||
|  |         msg = idx === -1 ? msg : msg.substring( idx + 7 ); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // Deal with pesky 'Error:' prefix. |       // Log non-HackMyResume-handled errors in red with ERROR prefix. Log HMR | ||||||
|       var idx = msg.indexOf('Error: '); |       // errors as-is. | ||||||
|       var trimmed = idx === -1 ? msg : msg.substring( idx + 7 ); |       ex.fluenterror ? | ||||||
|  |         log( msg.toString() ) : | ||||||
|  |         log( chalk.red.bold('ERROR: ' + msg.toString()) ); | ||||||
|  |  | ||||||
|       // If this is an unhandled error, or a specific class of handled error, |       // Usually emit the stack | ||||||
|       // output the error message and stack. |       ( showStack && ex.code !== 'ENOENT' ) && log( chalk.gray(ex.stack) ); | ||||||
|       if( !ex.fluenterror || ex.fluenterror < 3 ) { // TODO: magic #s |  | ||||||
|         console.log( chalk.red.bold('ERROR: ' + trimmed.toString()) ); |  | ||||||
|         if( ex.code !== 'ENOENT' ) // Don't emit stack for common stuff |  | ||||||
|           console.log( chalk.gray(ex.stack) ); |  | ||||||
|       } |  | ||||||
|       else { |  | ||||||
|         console.log( trimmed.toString() ); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       // Let the error code be the process's return code. |       // Let the error code be the process's return code. | ||||||
|       if( shouldExit || ex.shouldExit ) |       ( shouldExit || ex.shouldExit ) && process.exit( exitCode ); | ||||||
|         process.exit( exitCode ); |  | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   function get_error_msg( ex ) { | ||||||
|  |     var msg = '', withStack = false; | ||||||
|  |     switch( ex.fluenterror ) { | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.themeNotFound: | ||||||
|  |         msg = "The specified theme couldn't be found: " + ex.data; | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.copyCSS: | ||||||
|  |         msg = "Couldn't copy CSS file to destination folder"; | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.resumeNotFound: | ||||||
|  |         msg = chalk.yellow('Please ') + chalk.yellow.bold('feed me a resume') + | ||||||
|  |           chalk.yellow(' in FRESH or JSON Resume format.'); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.missingCommand: | ||||||
|  |         msg = chalk.yellow("Please ") + chalk.yellow.bold("give me a command") + | ||||||
|  |           chalk.yellow(" ("); | ||||||
|  |  | ||||||
|  |         msg += Object.keys( FCMD.verbs ).map( function(v, idx, ar) { | ||||||
|  |           return (idx === ar.length - 1 ? chalk.yellow('or ') : '') + | ||||||
|  |             chalk.yellow.bold(v.toUpperCase()); | ||||||
|  |         }).join( chalk.yellow(', ')) + chalk.yellow(").\n\n"); | ||||||
|  |  | ||||||
|  |         msg += chalk.gray(FS.readFileSync( PATH.resolve(__dirname, '../use.txt'), 'utf8' )); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.invalidCommand: | ||||||
|  |         msg = chalk.yellow('Invalid command: "') + chalk.yellow.bold(ex.attempted) + chalk.yellow('"'); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.resumeNotFoundAlt: | ||||||
|  |         msg = chalk.yellow('Please ') + chalk.yellow.bold('feed me a resume') + | ||||||
|  |           chalk.yellow(' in either FRESH or JSON Resume format.'); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.inputOutputParity: | ||||||
|  |         msg = chalk.yellow('Please ') + chalk.yellow.bold('specify an output file name') + | ||||||
|  |           chalk.yellow(' for every input file you wish to convert.'); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.createNameMissing: | ||||||
|  |         msg = chalk.yellow('Please ') + chalk.yellow.bold('specify the filename of the resume') + | ||||||
|  |           chalk.yellow(' to create.'); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.wkhtmltopdf: | ||||||
|  |         msg = chalk.red.bold('ERROR: PDF generation failed. ') + chalk.red('Make sure wkhtmltopdf is ' + | ||||||
|  |         'installed and accessible from your path.'); | ||||||
|  |         if( ex.inner ) msg += chalk.red('\n' + ex.inner); | ||||||
|  |         withStack = true; | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.invalid: | ||||||
|  |         msg = chalk.red.bold('ERROR: Validation failed and the --assert option was specified.'); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case HACKMYSTATUS.invalidTarget: | ||||||
|  |         ex.data.forEach(function(d){ | ||||||
|  |           msg += chalk.red.bold('The ' + ex.theme.name + " theme doesn't support the " + d.format + " format.\n"); | ||||||
|  |         }); | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |     return { | ||||||
|  |       msg: msg, | ||||||
|  |       withStack: withStack | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| }()); | }()); | ||||||
|   | |||||||
| @@ -18,7 +18,8 @@ Status codes for HackMyResume. | |||||||
|     createNameMissing: 8, |     createNameMissing: 8, | ||||||
|     wkhtmltopdf: 9, |     wkhtmltopdf: 9, | ||||||
|     missingPackageJSON: 10, |     missingPackageJSON: 10, | ||||||
|     invalid: 11 |     invalid: 11, | ||||||
|  |     invalidTarget: 12 | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| }()); | }()); | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ Implementation of the 'generate' verb for HackMyResume. | |||||||
|     , MD = require('marked') |     , MD = require('marked') | ||||||
|     , MKDIRP = require('mkdirp') |     , MKDIRP = require('mkdirp') | ||||||
|     , EXTEND = require('../utils/extend') |     , EXTEND = require('../utils/extend') | ||||||
|  |     , HACKMYSTATUS = require('../core/status-codes') | ||||||
|     , parsePath = require('parse-filepath') |     , parsePath = require('parse-filepath') | ||||||
|     , _opts = require('../core/default-options') |     , _opts = require('../core/default-options') | ||||||
|     , FluentTheme = require('../core/fresh-theme') |     , FluentTheme = require('../core/fresh-theme') | ||||||
| @@ -48,30 +49,19 @@ Implementation of the 'generate' verb for HackMyResume. | |||||||
|   */ |   */ | ||||||
|   function build( src, dst, opts, logger, errHandler ) { |   function build( src, dst, opts, logger, errHandler ) { | ||||||
|  |  | ||||||
|     // Housekeeping |     prep( src, dst, opts, logger, errHandler ); | ||||||
|     //_opts = extend( true, _opts, opts ); |  | ||||||
|     _log = logger || console.log; |  | ||||||
|     _err = errHandler || error; |  | ||||||
|     _opts.theme = (opts.theme && opts.theme.toLowerCase().trim())|| 'modern'; |  | ||||||
|     _opts.prettify = opts.prettify === true ? _opts.prettify : false; |  | ||||||
|     _opts.css = opts.css || 'embed'; |  | ||||||
|     _opts.pdf = opts.pdf; |  | ||||||
|     _opts.wrap = opts.wrap || 60; |  | ||||||
|     _opts.stitles = opts.sectionTitles; |  | ||||||
|     _opts.tips = opts.tips; |  | ||||||
|     //_opts.noTips = opts.noTips; |  | ||||||
|  |  | ||||||
|     // If two or more files are passed to the GENERATE command and the TO |  | ||||||
|     // keyword is omitted, the last file specifies the output file. |  | ||||||
|     if( src.length > 1 && ( !dst || !dst.length ) ) { |  | ||||||
|       dst.push( src.pop() ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Load the theme...we do this first because the theme choice (FRESH or |     // Load the theme...we do this first because the theme choice (FRESH or | ||||||
|     // JSON Resume) determines what format we'll convert the resume to. |     // JSON Resume) determines what format we'll convert the resume to. | ||||||
|     var tFolder = verify_theme( _opts.theme ); |     var tFolder = verify_theme( _opts.theme ); | ||||||
|     var theme = load_theme( tFolder ); |     var theme = load_theme( tFolder ); | ||||||
|  |  | ||||||
|  |     // Check for invalid outputs | ||||||
|  |     var inv = verify_outputs( dst, theme ); | ||||||
|  |     if( inv && inv.length ) { | ||||||
|  |       throw { fluenterror: HACKMYSTATUS.invalidTarget, data: inv, theme: theme }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Load input resumes... |     // Load input resumes... | ||||||
|     if( !src || !src.length ) { throw { fluenterror: 3 }; } |     if( !src || !src.length ) { throw { fluenterror: 3 }; } | ||||||
|     var sheets = ResumeFactory.load(src, { |     var sheets = ResumeFactory.load(src, { | ||||||
| @@ -134,6 +124,33 @@ Implementation of the 'generate' verb for HackMyResume. | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |   Prepare for a BUILD run. | ||||||
|  |   */ | ||||||
|  |   function prep( src, dst, opts, logger, errHandler ) { | ||||||
|  |  | ||||||
|  |     // Housekeeping | ||||||
|  |     _log = logger || console.log; | ||||||
|  |     _err = errHandler || error; | ||||||
|  |  | ||||||
|  |     //_opts = extend( true, _opts, opts ); | ||||||
|  |     _opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern'; | ||||||
|  |     _opts.prettify = opts.prettify === true; | ||||||
|  |     _opts.css = opts.css || 'embed'; | ||||||
|  |     _opts.pdf = opts.pdf; | ||||||
|  |     _opts.wrap = opts.wrap || 60; | ||||||
|  |     _opts.stitles = opts.sectionTitles; | ||||||
|  |     _opts.tips = opts.tips; | ||||||
|  |     _opts.noTips = opts.noTips; | ||||||
|  |  | ||||||
|  |     // If two or more files are passed to the GENERATE command and the TO | ||||||
|  |     // keyword is omitted, the last file specifies the output file. | ||||||
|  |     ( src.length > 1 && ( !dst || !dst.length ) ) && dst.push( src.pop() ); | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   Generate a single target resume such as "out/rez.html" or "out/rez.doc". |   Generate a single target resume such as "out/rez.html" or "out/rez.doc". | ||||||
|   @param targInfo Information for the target resume. |   @param targInfo Information for the target resume. | ||||||
| @@ -147,6 +164,9 @@ Implementation of the 'generate' verb for HackMyResume. | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|  |       if( !targInfo.fmt ) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|       var f = targInfo.file |       var f = targInfo.file | ||||||
|         , fType = targInfo.fmt.outFormat |         , fType = targInfo.fmt.outFormat | ||||||
|         , fName = PATH.basename(f, '.' + fType) |         , fName = PATH.basename(f, '.' + fType) | ||||||
| @@ -242,6 +262,27 @@ Implementation of the 'generate' verb for HackMyResume. | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |   Ensure that user-specified outputs/targets are valid. | ||||||
|  |   */ | ||||||
|  |   function verify_outputs( targets, theme ) { | ||||||
|  |  | ||||||
|  |     return _.reject( | ||||||
|  |       targets.map( function( t ) { | ||||||
|  |         var pathInfo = parsePath( t ); | ||||||
|  |         return { | ||||||
|  |           format: pathInfo.extname.substr(1) | ||||||
|  |         }; | ||||||
|  |       }), | ||||||
|  |       function(t) { | ||||||
|  |         return t.format === 'all' || theme.hasFormat( parsePath( t.format ).extname.substr(1)); | ||||||
|  |       } | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   Expand output files. For example, "foo.all" should be expanded to |   Expand output files. For example, "foo.all" should be expanded to | ||||||
|   ["foo.html", "foo.doc", "foo.pdf", "etc"]. |   ["foo.html", "foo.doc", "foo.pdf", "etc"]. | ||||||
|   | |||||||
| @@ -36,47 +36,42 @@ describe('Testing CLI interface', function () { | |||||||
|     var ft = 'node_modules/fresh-test-resumes/src/'; |     var ft = 'node_modules/fresh-test-resumes/src/'; | ||||||
|  |  | ||||||
|     [ |     [ | ||||||
|       [ 'new', [sb + 'new-fresh-resume.json'], [], opts, ' (FRESH format)' ], |  | ||||||
|       [ 'new', [sb + 'new-jrs-resume.json'], [], opts2, ' (JRS format)'], |       [ 'new',      [sb + 'new-fresh-resume.json'], [], opts, ' (FRESH format)' ], | ||||||
|       [ 'new', [sb + 'new-1.json', sb + 'new-2.json', sb + 'new-3.json'], [], opts, ' (multiple FRESH resumes)' ], |       [ 'new',      [sb + 'new-jrs-resume.json'], [], opts2, ' (JRS format)'], | ||||||
|       [ 'new', [sb + 'new-jrs-1.json', sb + 'new-jrs-2.json', sb + 'new-jrs-3.json'], [], opts, ' (multiple JRS resumes)' ], |       [ 'new',      [sb + 'new-1.json', sb + 'new-2.json', sb + 'new-3.json'], [], opts, ' (multiple FRESH resumes)' ], | ||||||
|  |       [ 'new',      [sb + 'new-jrs-1.json', sb + 'new-jrs-2.json', sb + 'new-jrs-3.json'], [], opts, ' (multiple JRS resumes)' ], | ||||||
|       [ 'validate', [ft + 'jane-fullstacker.fresh.json'], [], opts, ' (jane-q-fullstacker|FRESH)' ], |       [ 'validate', [ft + 'jane-fullstacker.fresh.json'], [], opts, ' (jane-q-fullstacker|FRESH)' ], | ||||||
|       [ 'validate', [ft + 'johnny-trouble.fresh.json'], [], opts, ' (johnny-trouble|FRESH)' ], |       [ 'validate', [ft + 'johnny-trouble.fresh.json'], [], opts, ' (johnny-trouble|FRESH)' ], | ||||||
|       [ 'validate', [sb + 'new-fresh-resume.json'], [], opts, ' (new-fresh-resume|FRESH)' ], |       [ 'validate', [sb + 'new-fresh-resume.json'], [], opts, ' (new-fresh-resume|FRESH)' ], | ||||||
|       [ 'validate', ['test/resumes/jrs-0.0.0/richard-hendriks.json'], [], opts2, ' (richard-hendriks.json|JRS)' ], |       [ 'validate', ['test/resumes/jrs-0.0.0/richard-hendriks.json'], [], opts2, ' (richard-hendriks.json|JRS)' ], | ||||||
|       [ 'validate', ['test/resumes/jrs-0.0.0/jane-incomplete.json'], [], opts2, ' (jane-incomplete.json|JRS)' ], |       [ 'validate', ['test/resumes/jrs-0.0.0/jane-incomplete.json'], [], opts2, ' (jane-incomplete.json|JRS)' ], | ||||||
|       [ 'validate', [sb + 'new-1.json', sb + 'new-jrs-resume.json', sb + 'new-1.json', sb + 'new-2.json', sb + 'new-3.json'], [], opts, ' (5|BOTH)' ], |       [ 'validate', [sb + 'new-1.json', sb + 'new-jrs-resume.json', sb + 'new-1.json', sb + 'new-2.json', sb + 'new-3.json'], [], opts, ' (5|BOTH)' ], | ||||||
|       [ 'analyze', [ft + 'jane-fullstacker.json'], [], opts, ' (jane-q-fullstacker|FRESH)' ], |       [ 'analyze',  [ft + 'jane-fullstacker.json'], [], opts, ' (jane-q-fullstacker|FRESH)' ], | ||||||
|       [ 'analyze', ['test/resumes/jrs-0.0.0/richard-hendriks.json'], [], opts2, ' (richard-hendriks|JRS)' ], |       [ 'analyze',  ['test/resumes/jrs-0.0.0/richard-hendriks.json'], [], opts2, ' (richard-hendriks|JRS)' ], | ||||||
|       [ 'build', |       [ 'build',    [ ft + 'jane-fullstacker.fresh.json', ft + 'override/jane-fullstacker-override.fresh.json' ], [ sb + 'merged/jane-fullstacker-gamedev.fresh.all'], opts, ' (jane-q-fullstacker w/ override|FRESH)' ], | ||||||
|         [ ft + 'jane-fullstacker.fresh.json', |       [ '!build',   [ ft + 'jane-fullstacker.fresh.json'], [ sb + 'shouldnt-exist.pdf' ], EXTEND(true, opts, { theme: 'awesome' }), ' (jane-q-fullstacker + Awesome + PDF|FRESH)' ], | ||||||
|           ft + 'override/jane-fullstacker-override.fresh.json' ], |       [ '!new',     [], [], opts, " (when a filename isn't specified)" ] | ||||||
|         [ sb + 'merged/jane-fullstacker-gamedev.fresh.all'], opts, ' (jane-q-fullstacker w/ override|FRESH)' ], |  | ||||||
|       [ 'build', |  | ||||||
|         [ ft + 'jane-fullstacker.fresh.json'], |  | ||||||
|         [ sb + 'shouldnt-exist.pdf' ], |  | ||||||
|         EXTEND(true, opts, { theme: 'awesome' }), |  | ||||||
|         ' (jane-q-fullstacker + Awesome + PDF|FRESH)' ] |  | ||||||
|     ].forEach( function(a) { |     ].forEach( function(a) { | ||||||
|       run.apply( null, a ); |  | ||||||
|  |       run.apply( /* The players of */ null, a ); | ||||||
|  |  | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     fail( 'new', [], [], opts, " (when a filename isn't specified)" ); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     function logMsg() { |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     function run( verb, src, dst, opts, msg ) { |     function run( verb, src, dst, opts, msg ) { | ||||||
|       msg = msg || '.'; |       msg = msg || '.'; | ||||||
|       it( 'The ' + verb.toUpperCase() + ' command should SUCCEED' + msg, function () { |       var shouldSucceed = true; | ||||||
|  |       if( verb[0] === '!' ) { | ||||||
|  |         verb = verb.substr(1); | ||||||
|  |         shouldSucceed = false; | ||||||
|  |       } | ||||||
|  |       it( 'The ' + verb.toUpperCase() + ' command should ' + (shouldSucceed ? ' SUCCEED' : ' FAIL') + msg, function () { | ||||||
|         function runIt() { |         function runIt() { | ||||||
|           try { |           try { | ||||||
|             FCMD.verbs[verb]( src, dst, opts, opts.silent ? |             FCMD.verbs[verb]( src, dst, opts, opts.silent ? | ||||||
|               logMsg : function(msg){ msg = msg || ''; console.log(msg); } ); |               function(){} : function(msg){ msg = msg || ''; console.log(msg); } ); | ||||||
|           } |           } | ||||||
|           catch(ex) { |           catch(ex) { | ||||||
|             console.error(ex); |             console.error(ex); | ||||||
| @@ -84,19 +79,10 @@ describe('Testing CLI interface', function () { | |||||||
|             throw ex; |             throw ex; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         runIt.should.not.Throw(); |         if( shouldSucceed ) | ||||||
|       }); |           runIt.should.not.Throw(); | ||||||
|     } |         else | ||||||
|  |           runIt.should.Throw(); | ||||||
|  |  | ||||||
|  |  | ||||||
|     function fail( verb, src, dst, opts, msg ) { |  | ||||||
|       msg = msg || '.'; |  | ||||||
|       it( 'The ' + verb.toUpperCase() + ' command should FAIL' + msg, function () { |  | ||||||
|         function runIt() { |  | ||||||
|           FCMD.verbs[verb]( src, dst, opts, logMsg ); |  | ||||||
|         } |  | ||||||
|         runIt.should.Throw(); |  | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user