nlint
Version:
Full project linting.
733 lines (619 loc) • 28.5 kB
JavaScript
var Slice = Array.prototype.slice,
// Add setup to create common Nlint test object
// (remember nlint.run gets triggered in the constructor)
setupOptions = {
setup: function( assert, callback ) {
assert.data.runSpy = assert.spy( Nlint.prototype, 'run' );
assert.data.nlint = new Nlint( __dirname );
assert.data.runSpy.restore();
callback();
}
},
// Shortcut to triggering the last argument of a function call
// (useful for spies)
triggerLastArgument = function(){
var args = Slice.call( arguments );
return function(){
Slice.call( arguments ).pop().apply( this, args );
};
};
// Core types
munit( 'Nlint', { priority: munit.PRIORITY_HIGHEST }, {
'static': function( assert ) {
assert.isFunction( 'Nlint', Nlint )
.isFunction( 'FileResult', Nlint.FileResult )
.isFunction( 'MatchPath', Nlint.MatchPath )
.isFunction( 'Cli', Nlint.Cli )
.isFunction( 'Linter', Nlint.Linter )
.isArray( 'Linters', Nlint.Linters )
.isFunction( 'Settings', Nlint.Settings )
.isFunction( 'render', Nlint.render );
},
init: function( assert ) {
var spy = assert.spy( Nlint.prototype, 'run' ),
nlint = new Nlint( __dirname );
// Init values
assert.deepEqual( 'files', nlint.files, [ __dirname ] )
.isObject( 'options', nlint.options )
.isObject( 'settings', nlint.settings )
.deepEqual( 'results', nlint.results, [] )
.deepEqual( 'ignored', nlint.ignored, [] )
.deepEqual( 'nodelints', nlint.nodelints, [] )
.deepEqual( '_nodelints', nlint._nodelints, {} )
.deepEqual( '_forks', nlint._forks, [] )
.deepEqual( '_queue', nlint._queue, [] )
.deepEqual( '_jobs', nlint._jobs, {} )
.equal( 'fileCount', nlint.fileCount, 0 )
.equal( 'fileComplete', nlint.fileComplete, 0 )
.equal( 'run triggered', spy.count, 1 );
// Test for error when no file is passed
assert.throws( 'No file', /No Files Argument/, function(){
nlint = new Nlint();
});
// Test for error when no array/string passed
assert.throws( 'Invalid File Type', /No Files Argument/, function(){
nlint = new Nlint({ test: true });
});
// Make sure you can actually pass an array
assert.doesNotThrow( 'Array Init', function(){
nlint = new Nlint( [ __dirname ] );
});
}
});
// Testing each method on Nlint
munit( 'Nlint', setupOptions, {
run: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
fakeSettings = new Nlint.Settings({ fork: 199 }),
// Forks creator
forkSpy = assert.spy( nlint, 'forks' ),
// Pass through the close method without doing anything
closeSpy = assert.spy( nlint, 'close', { onCall: triggerLastArgument() }),
// nlint callbacks
updateSpy = assert.spy( nlint.settings, 'update' ),
nodelintSpy = assert.spy( nlint, 'nodelint', { onCall: triggerLastArgument( null, fakeSettings ) } ),
dirSpy = assert.spy( nlint, 'dir', { onCall: triggerLastArgument() }),
singleSpy = assert.spy( nlint, 'single', { onCall: triggerLastArgument() }),
// Watch for internal fs.stat call
fs = require( 'fs' ),
statSpy = assert.spy( fs, 'stat', {
onCall: triggerLastArgument( null, {
isDirectory: function(){
return true;
}
})
});
// Trigger project run
nlint.run( callback );
// Internal calls
assert.equal( 'run .forks triggered', forkSpy.count, 1 );
assert.equal( 'run fs.stat trigger', statSpy.count, 1 );
assert.equal( 'run nlint.settings reassigned', nlint.settings, fakeSettings );
assert.equal( 'run nodelint trigger', nodelintSpy.count, 1 );
assert.equal( 'run dir trigger', dirSpy.count, 1 );
assert.equal( 'run single not triggered', singleSpy.count, 0 );
// Callback stats
assert.equal( 'run callback', callback.count, 1 );
assert.equal( 'run callback args', callback.args.length, 2 );
assert.empty( 'run callback args error', callback.args[ 0 ] );
assert.equal( 'run callback args nlint', callback.args[ 1 ], nlint );
// Convert stat spy to trigger a single() call
// Also create new call spy for counters
statSpy.option( 'onCall', triggerLastArgument( null, {
isDirectory: function(){
return false;
}
}));
nlint.run( callback );
assert.equal( 'run dir trigger not triggered', dirSpy.count, 1 );
assert.equal( 'run single triggered', singleSpy.count, 1 );
// Force an error from single()
singleSpy.option( 'onCall', triggerLastArgument( "Test Single Error" ) );
nlint.run( callback );
assert.equal( 'single error', callback.args[ 0 ], "Test Single Error" );
assert.equal( 'single error no dir call', dirSpy.count, 1 );
assert.equal( 'single error called', singleSpy.count, 2 );
// Force an error from dir()
statSpy.option( 'onCall', function( path, callback ) {
callback( null, {
isDirectory: function(){
return true;
}
});
});
dirSpy.option( 'onCall', triggerLastArgument( "Test Dir Error" ) );
nlint.run( callback );
assert.equal( 'dir error', callback.args[ 0 ], "Test Dir Error" );
assert.equal( 'dir error dir call', dirSpy.count, 2 );
assert.equal( 'dir error no single called', singleSpy.count, 2 );
// Force an error from fs.stat
statSpy.option( 'onCall', triggerLastArgument( "Test Error" ) );
nlint.run( callback );
assert.equal( 'fs.stat error', callback.args[ 0 ], "Test Error" );
assert.equal( 'fs.stat error no dir call', dirSpy.count, 2 );
assert.equal( 'fs.stat error no single call', singleSpy.count, 2 );
},
forks: function( assert ) {
var nlint = assert.data.nlint,
checkSpy = assert.spy( nlint, '_checkQueue' ),
callback = assert.spy(),
event,
// Fake child object
EventEmitter = require( 'events' ).EventEmitter,
emitter = new EventEmitter(),
onSpy = assert.spy( emitter, 'on' ),
// Watch forking
child_process = require( 'child_process' ),
forkSpy = assert.spy( child_process, 'fork', { returnValue: emitter } );
// Test fork creation
nlint.settings.fork = 1;
nlint._forks = [];
nlint.forks();
assert.equal( 'fork triggered', forkSpy.count, 1 );
assert.equal( 'on called for error, message, exit, and close', onSpy.count, 4 );
assert.deepEqual( 'child fork objects', nlint._forks, [ emitter ] );
// Test quick return if forks already exist
nlint.forks();
assert.equal( 'fork not triggered when forks exist', forkSpy.count, 1 );
// Error event
event = onSpy.history[ 0 ];
assert.equal( 'error event arg name', event.args[ 0 ], 'error' );
assert.throws( 'error callback throws', "Test Error Emit", function(){
event.args[ 1 ]( "Test Error Emit" );
});
// Message Event
nlint._forks = [];
nlint._jobs = { 123: { id: 123, callback: callback } };
event = onSpy.history[ 1 ];
assert.equal( 'message event arg name', event.args[ 0 ], 'message' );
event.args[ 1 ]({ id: 123, args: [ 1, true, 'a' ] });
assert.equal( 'job callback triggered', callback.count, 1 );
assert.deepEqual( 'job callback argurments', callback.args, [ 1, true, 'a' ] );
assert.equal( 'all jobs removed', Object.keys( nlint._jobs ).length, 0 );
assert.deepEqual( 'child put back on fork queue', nlint._forks, [ emitter ] );
assert.equal( 'check queue triggered', checkSpy.count, 1 );
// Exit event
nlint._forks = [ emitter, {} ];
event = onSpy.history[ 2 ];
assert.equal( 'exit event arg name', event.args[ 0 ], 'exit' );
assert.doesNotThrow( 'exit event with multiple forks shouldnt throw', function(){
event.args[ 1 ]();
});
assert.deepEqual( 'triggering close should remove child', nlint._forks, [ {} ] );
nlint._forks = [];
assert.throws( "exit throws when no forks are left (fatal error)", "All forks have failed", function(){
event.args[ 1 ]();
});
// Close event
nlint._forks = [];
event = onSpy.history[ 3 ];
assert.equal( 'close event arg name', event.args[ 0 ], 'close' );
assert.throws( "close throws when no forks are left (fatal error)", "All forks have failed", function(){
event.args[ 1 ]();
});
},
close: function( assert ) {
var spies = [],
nlint = assert.data.nlint,
callback = assert.spy(),
child = {},
removeSpy = child.removeAllListeners = assert.spy({ returnValue: child }),
onSpy = child.on = assert.spy(),
killSpy = child.kill = assert.spy();
// Test for event attachments
nlint._forks = [ child ];
nlint.close( callback );
assert.equal( 'close callback not triggered, async', callback.count, 0 );
assert.equal( 'removeAllListeners triggered only once', removeSpy.count, 1 );
assert.equal( 'kill triggered only once', killSpy.count, 1 );
assert.equal( 'on triggered for both exit & close', onSpy.count, 2 );
assert.equal( 'on exit is first call', onSpy.history[ 0 ].args[ 0 ], 'exit' );
assert.equal( 'on close is second call', onSpy.history[ 1 ].args[ 0 ], 'close' );
// Callback trigger
onSpy.args[ 1 ]();
assert.equal( 'callback triggered', callback.count, 1 );
assert.empty( 'callback no error', callback.args[ 0 ] );
},
render: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
runLint = assert.spy( nlint, '_runLint', { onCall: triggerLastArgument() } ),
// Settings for path matching
settings = new Nlint.Settings({ ignore: [ "/a/b/" ] }),
useSpy = assert.spy( settings, 'use', { returnValue: true } ),
// Add a spy to watch the path matching calls of each linter
// (The linter tests will handle argument tests, this just needs to know it was called)
spies = Nlint.Linters.map(function( linter ) {
var spy = assert.spy( linter, 'isMatch', { returnValue: true });
spy._linterName = linter.name;
return spy;
});
// Test ignore path
nlint.render( "/a/b/c/test.js", settings, callback );
assert.equal( 'ignore callback triggered', callback.count, 1 );
assert.equal( 'ignore still no results', nlint.results.length, 0 );
assert.equal( 'ignore runLint not trigered', runLint.count, 0 );
// Test going through a successful path, and callback gets triggered with no errors
nlint.render( "/sub/test.js", settings, callback );
assert.equal( 'callback triggered', callback.count, 2 );
assert.equal( 'result count', nlint.results.length, 1 );
assert.equal( 'first runLint argument should be result argument', nlint.results[ 0 ], runLint.args[ 0 ] );
assert.equal( 'runLint trigered', runLint.count, Nlint.Linters.length );
assert.equal( 'settings.use trigered', useSpy.count, Nlint.Linters.length );
spies.forEach(function( spy ) {
assert.equal( 'spy ' + spy._linterName + ' called', spy.count, 1 );
});
// Test no file match path
useSpy.option( 'returnValue', false );
nlint.render( "/sub/test.js", settings, callback );
assert.equal( 'callback still triggered with no match', callback.count, 3 );
assert.equal( 'runLint not triggered', runLint.count, Nlint.Linters.length );
},
_runLint: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
emitSpy = assert.spy( nlint, 'emit' ),
times = {},
job = {},
// Result object
result = new Nlint.FileResult( "/test.js" ),
addSpy = assert.spy( result, 'addResults' ),
// Settings object
settings = new Nlint.Settings(),
optionSpy = assert.spy( settings, 'linters', { returnValue: {} } ),
// Queue check spy
checkSpy = assert.spy( nlint, '_checkQueue' ),
// Setup linter and it's spy
linter = Nlint.Linters[ 0 ],
renderSpy = assert.spy( linter, 'render' );
// We override queue object, so make sure it gets restored once complete
assert.spy( nlint, '_queue' );
// Testing basic run with queue addition
nlint._queue = [];
nlint._runLint( result, settings, linter, callback );
assert.equal( 'callback not triggered', callback.count, 0 );
assert.equal( 'settings.linter triggered', optionSpy.count, 1 );
assert.equal( 'fileCount', nlint.fileCount, 1 );
assert.equal( 'emit', emitSpy.count, 1 );
assert.equal( 'emit key', emitSpy.args[ 0 ], 'progress' );
assert.empty( 'emit path not initially passed', emitSpy.args[ 1 ] );
assert.equal( '_queue added to', nlint._queue.length, 1 );
assert.equal( '_checkQueue triggered', checkSpy.count, 1 );
// Test job added to the queue
job = nlint._queue[ 0 ];
assert.equal( 'job id', job.id, nlint.fileCount );
assert.isFunction( 'job callback', job.callback );
assert.isObject( 'job send', job.send );
assert.equal( 'job send.id', job.send.id, nlint.fileCount );
assert.equal( 'job send.path', job.send.path, result.path );
assert.equal( 'job send.linter', job.send.linter, linter.path );
assert.deepEqual( 'job send.settings', job.send.settings, {} );
// Test basic run with direct linter rendering
nlint.settings.fork = 0;
nlint._runLint( result, settings, linter, callback );
assert.equal( 'linter.render triggered', renderSpy.count, 1 );
// Testing Success Render
renderSpy.option( 'onCall', triggerLastArgument( null, null, null, times ) );
addSpy.option( 'onCall', munit.noop );
nlint._runLint( result, settings, linter, callback );
assert.equal( 'success emit path', emitSpy.args[ 1 ], "/test.js" );
assert.equal( 'success callback triggered', callback.count, 1 );
assert.empty( 'success callback triggered no error', callback.args[ 0 ] );
// Testing fatal error from linter rendering
renderSpy.option( 'onCall', triggerLastArgument( 'Test Error' ) );
nlint._runLint( result, settings, linter, callback );
assert.equal( 'error callback triggered', callback.count, 2 );
assert.equal( 'error callback arg', callback.args[ 0 ], 'Test Error' );
// Testing format error from rendering results
renderSpy.option( 'onCall', triggerLastArgument( null, null, null, times ) );
addSpy.option( 'onCall', function(){
throw "Format Test Error";
});
nlint._runLint( result, settings, linter, callback );
assert.equal( 'callback triggered with format error', callback.args[ 0 ], "Format Test Error" );
},
_checkQueue: function( assert ) {
var nlint = assert.data.nlint,
sendSpy = assert.spy(),
child = { send: sendSpy },
job = { id: 321, send: { linter: '/a/b/c/test/js' } };
// Test drainage
nlint._forks = [ child ];
nlint._queue = [ job ];
nlint._checkQueue();
assert.equal( 'send triggered', sendSpy.count, 1 );
assert.deepEqual( 'send arguments', sendSpy.args, [ job.send ] );
assert.equal( 'forks drained', nlint._forks.length, 0 );
assert.equal( 'queue drained', nlint._queue.length, 0 );
// Ensure both a job and fork exists for drainage
nlint._forks = [ child ];
nlint._queue = [];
nlint._checkQueue();
assert.equal( 'send not triggered again', sendSpy.count, 1 );
assert.deepEqual( 'fork queue not changed', nlint._forks, [ child ] );
},
single: function( assert ) {
var nlint = assert.data.nlint,
fakeSettings = {},
callback = assert.spy(),
renderSpy = assert.spy( nlint, 'render' ),
nodelintSpy = assert.spy( nlint, 'nodelint', {
onCall: triggerLastArgument( null, fakeSettings )
});
// Testing successful nodelint
nlint.single( "/a/b/c/test.js", callback );
assert.equal( 'nodelint called', nodelintSpy.count, 1 );
assert.equal( 'render triggered', renderSpy.count, 1 );
assert.equal( 'render arg path', renderSpy.args[ 0 ], "/a/b/c/test.js" );
assert.equal( 'render arg settings', renderSpy.args[ 1 ], fakeSettings );
assert.equal( 'render arg callback', renderSpy.args[ 2 ], callback );
assert.equal( 'callback not triggered due to render spy', callback.count, 0 );
// Testing nodelint error
nodelintSpy.option( 'onCall', triggerLastArgument( "Nlint Test Error" ) );
nlint.single( "/a/b/c/test.js", callback );
assert.equal( 'nodelint arg path', nodelintSpy.args[ 0 ], "/a/b/c/" );
assert.isFunction( 'nodelint arg callback', nodelintSpy.args[ 1 ] );
assert.equal( 'nodelint callback triggered', callback.count, 1 );
assert.equal( 'nodelint error', callback.args[ 0 ], "Nlint Test Error" );
assert.equal( 'render not called on error', renderSpy.count, 1 );
},
dir: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
dirSpy = assert.spy( nlint, '_dir', {
onCall: triggerLastArgument()
}),
// .nodelint spy
fakeSettings = {},
nodelintSpy = assert.spy( nlint, 'nodelint', {
onCall: triggerLastArgument( null, fakeSettings )
}),
// fs.readdir spy
fs = require( 'fs' ),
readSpy = assert.spy( fs, 'readdir', {
onCall: triggerLastArgument( null, [ 'test1.js', 'test2.js' ] )
});
// Testing successful path
nlint.dir( '/a/b/c/', callback );
assert.equal( 'readdir called', readSpy.count, 1 );
assert.equal( 'readdir arg path', readSpy.args[ 0 ], '/a/b/c/' );
assert.isFunction( 'readdir arg callback', readSpy.args[ 1 ] );
assert.equal( 'nodelint called', nodelintSpy.count, 1 );
assert.equal( 'nodelint arg path', nodelintSpy.args[ 0 ], '/a/b/c/' );
assert.isFunction( 'nodelint arg callback', nodelintSpy.args[ 1 ] );
assert.equal( '_dir called', dirSpy.count, 1 );
assert.equal( '_dir arg path', dirSpy.args[ 0 ], '/a/b/c/' );
assert.deepEqual( '_dir arg files', dirSpy.args[ 1 ], [ 'test1.js', 'test2.js' ] );
assert.equal( '_dir arg settings', dirSpy.args[ 2 ], fakeSettings );
assert.equal( '_dir arg callback', dirSpy.args[ 3 ], callback );
assert.equal( '_dir callback triggered', callback.count, 1 );
// Testing readdir error
readSpy.option( 'onCall', triggerLastArgument( "Readdir Test Error" ) );
nlint.dir( '/a/b/c/', callback );
assert.equal( 'readdir error', callback.args[ 0 ], "Readdir Test Error" );
assert.equal( 'readdir error no _dir trigger', dirSpy.count, 1 );
// Testing nodelint error
readSpy.option( 'onCall', triggerLastArgument() );
nodelintSpy.option( 'onCall', triggerLastArgument( "Nlint Test Error" ) );
nlint.dir( '/a/b/c/', callback );
assert.equal( 'nodelint error', callback.args[ 0 ], "Nlint Test Error" );
assert.equal( 'nodelint error no _dir trigger', dirSpy.count, 1 );
},
_dir: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
// Mock settings object
settings = new Nlint.Settings(),
ignoreSpy = assert.spy( settings, 'ignore', { returnValue: false } ),
// .dir
dirSpy = assert.spy( nlint, 'dir', {
onCall: triggerLastArgument()
}),
// .render
renderSpy = assert.spy( nlint, 'render', {
onCall: triggerLastArgument()
}),
// fs.stat spy
fs = require( 'fs' ),
statSpy = assert.spy( fs, 'stat', {
onCall: triggerLastArgument( null, {
isDirectory: function(){
return true;
}
})
});
// Test Success Path
nlint._dir( '/a/b/c/', [ 'd' ], settings, callback );
assert.equal( 'fs.stat triggered', statSpy.count, 1 );
assert.equal( 'fs.stat arg file path', statSpy.args[ 0 ], '/a/b/c/d' );
assert.equal( 'settings.ignore triggered', ignoreSpy.count, 1 );
assert.equal( 'dir triggered', dirSpy.count, 1 );
assert.equal( 'dir arg path', dirSpy.args[ 0 ], '/a/b/c/d/' );
assert.equal( 'dir success callback triggered', callback.count, 1 );
assert.empty( 'dir success callback no error', callback.args[ 0 ] );
assert.equal( 'dir success render not triggered', renderSpy.count, 0 );
// Testing ignored directory
ignoreSpy.option( 'returnValue', true );
nlint._dir( '/a/b/c/', [ 'd' ], settings, callback );
assert.equal( 'settings.ignore triggered again', ignoreSpy.count, 2 );
assert.equal( 'ignore path dir not triggered', dirSpy.count, 1 );
assert.equal( 'ignore path callback triggered', callback.count, 2 );
assert.empty( 'ignore path callback no error', callback.args[ 0 ] );
ignoreSpy.option( 'returnValue', false );
// Testing single file render
statSpy.option( 'onCall', triggerLastArgument( null, {
isDirectory: function(){
return false;
}
}));
nlint._dir( '/a/b/c/', [ 'd' ], settings, callback );
assert.equal( 'render path triggered', renderSpy.count, 1 );
assert.equal( 'render path dir not triggered', dirSpy.count, 1 );
assert.equal( 'render path callback triggered', callback.count, 3 );
assert.empty( 'render path callback no error', callback.args[ 0 ] );
// Testing single file render error
renderSpy.option( 'onCall', triggerLastArgument( "render error" ) );
nlint._dir( '/a/b/c/', [ 'd' ], settings, callback );
assert.equal( 'render error path triggered', renderSpy.count, 2 );
assert.equal( 'render error path dir not triggered', dirSpy.count, 1 );
assert.equal( 'render error path callback triggered', callback.count, 4 );
assert.equal( 'render error path callback error', callback.args[ 0 ], "render error" );
// Testing dir error
dirSpy.option( 'onCall', triggerLastArgument( "dir error" ) );
statSpy.option( 'onCall', triggerLastArgument( null, {
isDirectory: function(){
return true;
}
}));
nlint._dir( '/a/b/c/', [ 'd' ], settings, callback );
assert.equal( 'dir error path triggered', dirSpy.count, 2 );
assert.equal( 'dir error path render not triggered', renderSpy.count, 2 );
assert.equal( 'dir error path callback triggered', callback.count, 5 );
assert.equal( 'dir error path callback error', callback.args[ 0 ], "dir error" );
// Testing fs.stat error
statSpy.option( 'onCall', triggerLastArgument( "fs.stat Test Error" ) );
nlint._dir( '/a/b/c/', [ 'd' ], settings, callback );
assert.equal( 'fs.stat error callback triggered', callback.count, 6 );
assert.equal( 'fs.stat error callback error', callback.args[ 0 ], "fs.stat Test Error" );
assert.equal( 'fs.stat error path dir not triggered', dirSpy.count, 2 );
assert.equal( 'fs.stat error path render not triggered', renderSpy.count, 2 );
},
nodelint: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
// _renderSettings handle
settings = new Nlint.Settings(),
renderSpy = assert.spy( nlint, '_renderSettings', { returnValue: settings } ),
// _nodelint handle
nodelintSpy = assert.spy( nlint, '_nodelint', {
onCall: triggerLastArgument()
});
// Test successful path
nlint.nodelint( '/a/b/c/', callback );
assert.equal( '_nodelint triggered for each subpath', nodelintSpy.count, 4 );
assert.equal( 'callback triggered', callback.count, 1 );
assert.empty( 'callback arg no error', callback.args[ 0 ] );
assert.equal( 'callback arg settings', callback.args[ 1 ], settings );
// Test error in _nodelint
nodelintSpy.option( 'onCall', triggerLastArgument( "Test _nodelint Error" ) );
nlint.nodelint( '/a/b/c/', callback );
assert.equal( '_nodelint fail callback triggered', callback.count, 2 );
assert.equal( '_nodelint fail callback arg error', callback.args[ 0 ], "Test _nodelint Error" );
},
_nodelint: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
// Mark nodelint files as read to mimick _renderNodelint
renderSpy = assert.spy( nlint, '_renderNodelint', {
onCall: function( path, callback ) {
nlint._nodelints[ path ] = null;
callback();
}
});
// Test path that triggers _renderNodelint on every nodelint file
nlint._nodelint( '/a/b/c/', callback );
assert.equal( 'render triggered on every file type', renderSpy.count, 4 );
assert.equal( 'callback triggered through render', callback.count, 1 );
// Previous test marked all entries as read, test that
nlint._nodelint( '/a/b/c/', callback );
assert.equal( '_renderNodelint should not have been called', renderSpy.count, 4 );
assert.equal( 'callback still triggered', callback.count, 2 );
},
_renderNodelint: function( assert ) {
var nlint = assert.data.nlint,
callback = assert.spy(),
fakeOptions = {},
// Watch for internal fs.stat call
fs = require( 'fs' ),
statSpy = assert.spy( fs, 'stat', {
onCall: triggerLastArgument()
}),
readSpy = assert.spy( fs, 'readFile', {
onCall: triggerLastArgument()
}),
// JSON parsing spy
JSON5 = require( 'json5' ),
jsonSpy = assert.spy( JSON5, 'parse', { returnValue: fakeOptions } ),
// Require spy
requireSpy = assert.spy( Nlint, 'require', { returnValue: { result: fakeOptions } } );
// Test successful json parse path, along with all triggers inbetween
nlint._renderNodelint( '/a/b/c/.nlint.json', callback );
assert.equal( 'json fs.stat triggered', statSpy.count, 1 );
assert.equal( 'json nodelint path added for logging', nlint.nodelints[ nlint.nodelints.length - 1 ], '/a/b/c/.nlint.json' );
assert.equal( 'json fs.readFile triggered', readSpy.count, 1 );
assert.equal( 'json JSON5 called', jsonSpy.count, 1 );
assert.equal( 'json require not triggered', requireSpy.count, 0 );
assert.equal( 'json _nodelints path added', nlint._nodelints[ '/a/b/c/.nlint.json' ], fakeOptions );
assert.equal( 'json callback triggered', callback.count, 1 );
assert.empty( 'json callback no error', callback.args[ 0 ] );
// Test successful json5 parse path
nlint._renderNodelint( '/a/b/c/.nlint.json5', callback );
assert.equal( 'json5 parser still called', jsonSpy.count, 2 );
assert.equal( 'json5 require not triggered', requireSpy.count, 0 );
assert.equal( 'json5 added to _nodelints', nlint._nodelints[ '/a/b/c/.nlint.json5' ], fakeOptions );
assert.equal( 'json5 callback triggered', callback.count, 2 );
assert.empty( 'json5 callback no error', callback.args[ 0 ] );
// Test successful js parse path
nlint._renderNodelint( '/a/b/c/.nlint.js', callback );
assert.equal( 'js require triggered', requireSpy.count, 1 );
assert.equal( 'js JSON5 not called', jsonSpy.count, 2 );
assert.equal( 'js added to _nodelints', nlint._nodelints[ '/a/b/c/.nlint.js' ], fakeOptions );
assert.equal( 'js callback triggered', callback.count, 3 );
assert.empty( 'js callback no error', callback.args[ 0 ] );
// Test successful root parse path
nlint._renderNodelint( '/a/b/c/.nlint', callback );
assert.equal( 'root require triggered', requireSpy.count, 2 );
assert.equal( 'root JSON5 not called', jsonSpy.count, 2 );
assert.equal( 'root added to _nodelints', nlint._nodelints[ '/a/b/c/.nlint' ], fakeOptions );
assert.equal( 'root callback triggered', callback.count, 4 );
assert.empty( 'root callback no error', callback.args[ 0 ] );
// Test root parse error path
requireSpy.option( 'returnValue', { error: "Require Test Error" } );
nlint._renderNodelint( '/a/b/c/.nlint', callback );
assert.equal( 'root error callback triggered', callback.count, 5 );
assert.equal( 'root error callback error string', callback.args[ 0 ], "Require Test Error" );
// Test json parse error path
jsonSpy.option( 'onCall', function(){
throw "JSON Test Error";
});
nlint._renderNodelint( '/a/b/c/.nlint.json', callback );
assert.equal( 'json error callback triggered', callback.count, 6 );
assert.equal( 'json error callback error string', callback.args[ 0 ], "JSON Test Error" );
// Test json read error path
readSpy.option( 'onCall', triggerLastArgument( "JSON Read Test Error" ) );
nlint._renderNodelint( '/a/b/c/.nlint.json', callback );
assert.equal( 'json read error callback triggered', callback.count, 7 );
assert.equal( 'json read error callback error string', callback.args[ 0 ], "JSON Read Test Error" );
// Test stat error (no error passback)
statSpy.option( 'onCall', triggerLastArgument( "fs.stat Test Error" ) );
nlint._renderNodelint( '/a/b/c/.nlint', callback );
assert.equal( 'fs.stat error callback triggered', callback.count, 8 );
assert.empty( 'fs.stat error callback no error', callback.args[ 0 ] );
assert.equal( 'fs.stat error JSON5 not called', jsonSpy.count, 3 );
assert.equal( 'fs.stat error require not triggered', requireSpy.count, 3 );
},
_renderSettings: function( assert ) {
var nlint = assert.data.nlint,
settings;
nlint.options = {};
nlint._nodelints = {
"/a/.nlint": { fork: 4 },
"/a/b/.nlint": { fork: 10 }
};
// Check default values hold
settings = nlint._renderSettings( '/foo/bar' );
assert.equal( 'Default fork value', settings.fork, Nlint.Defaults.Settings.fork );
// Test passed in options overriding defaults
nlint.options = { fork: 0 };
settings = nlint._renderSettings( '/foo/bar' );
assert.equal( 'Options Overwrite', settings.fork, nlint.options.fork );
nlint.options = {};
// Testing '/a/' path
settings = nlint._renderSettings( '/a/' );
assert.equal( '/a/ fork is 4', settings.fork, 4 );
// Testing '/a/b/' path overriding '/a/' path
settings = nlint._renderSettings( '/a/b/' );
assert.equal( '/a/b/ fork is 10', settings.fork, 10 );
}
});