var fs = require ( 'graceful-fs' )
var path = require ( 'path' )
var mkdirp = require ( 'mkdirp' )
var mr = require ( 'npm-registry-mock' )
var osenv = require ( 'osenv' )
var rimraf = require ( 'rimraf' )
var test = require ( 'tap' ) . test
var common = require ( '../common-tap.js' )
var pkg = path . resolve ( __ dirname , 'search' )
var cache = path . resolve ( pkg , 'cache' )
var registryCache = path . resolve ( cache , 'localhost_1337' , '-' , 'all' )
var cacheJsonFile = path . resolve ( registryCache , '.cache.json' )
var timeMock = {
epoch : 1411727900 ,
future : 1411727900 + 100 ,
all : 1411727900 + 25 ,
since : 0 // filled by since server callback
}
var EXEC_OPTS = { }
var mocks = {
/* Since request, always response with an _update time > the time requested */
sinceFuture : function ( server ) {
server . filteringPathRegEx ( /startkey=[^&]*/g , function ( s ) {
var _ allMock = JSON . parse ( JSON . stringify ( allMock ) )
timeMock . since = _ allMock . _ updated = s . replace ( 'startkey=' , '' )
server . get ( '/-/all/since?stale=update_after&' + s )
. reply ( 200 , _ allMock )
return s
} )
} ,
allFutureUpdatedOnly : function ( server ) {
server . get ( '/-/all' )
. reply ( 200 , stringifyUpdated ( timeMock . future ) )
} ,
all : function ( server ) {
server . get ( '/-/all' )
. reply ( 200 , allMock )
}
}
test ( 'No previous cache, init cache triggered by first search' , function ( t ) {
cleanup ( )
mr ( { port : common . port , plugin : mocks . allFutureUpdatedOnly } , function ( err , s ) {
t . ifError ( err , 'mock registry started' )
common . npm ( [
'search' , 'do not do extra search work on my behalf' ,
'--registry' , common . registry ,
'--cache' , cache ,
'--loglevel' , 'silent' ,
'--color' , 'always'
] ,
EXEC_OPTS ,
function ( err , code ) {
s . close ( )
t . equal ( code , 0 , 'search finished successfully' )
t . ifErr ( err , 'search finished successfully' )
t . ok (
fs . existsSync ( cacheJsonFile ) ,
cacheJsonFile + ' expected to have been created'
)
var cacheData = JSON . parse ( fs . readFileSync ( cacheJsonFile , 'utf8' ) )
t . equal ( cacheData . _ updated , String ( timeMock . future ) )
t . end ( )
} )
} )
} )
test ( 'no arguments provided should error' , function ( t ) {
common . npm ( [ 'search' ] , [ ] , function ( err , code , stdout , stderr ) {
if ( err ) throw err
t . equal ( code , 1 , 'search finished unsuccessfully' )
t . match (
stderr ,
/search must be called with arguments/ ,
'should have correct error message'
)
t . end ( )
} )
} )
test ( 'previous cache, _updated set, should trigger since request' , function ( t ) {
setupCache ( )
function m ( server ) {
[ mocks . all , mocks . sinceFuture ] . forEach ( function ( m ) {
m ( server )
} )
}
mr ( { port : common . port , plugin : m } , function ( err , s ) {
t . ifError ( err , 'mock registry started' )
common . npm ( [
'search' , 'do not do extra search work on my behalf' ,
'--registry' , common . registry ,
'--cache' , cache ,
'--loglevel' , 'silly' ,
'--color' , 'always'
] ,
EXEC_OPTS ,
function ( err , code ) {
s . close ( )
t . equal ( code , 0 , 'search finished successfully' )
t . ifErr ( err , 'search finished successfully' )
var cacheData = JSON . parse ( fs . readFileSync ( cacheJsonFile , 'utf8' ) )
t . equal (
cacheData . _ updated ,
timeMock . since ,
'cache update time gotten from since response'
)
t . end ( )
} )
} )
} )
var searches = [
{
term : 'f36b6a6123da50959741e2ce4d634f96ec668c56' ,
description : 'non-regex' ,
location : 241
} ,
{
term : '/f36b6a6123da50959741e2ce4d634f96ec668c56/' ,
description : 'regex' ,
location : 241
}
]
searches . forEach ( function ( search ) {
test ( search . description + ' search in color' , function ( t ) {
cleanup ( )
mr ( { port : common . port , plugin : mocks . all } , function ( er , s ) {
common . npm ( [
'search' , search . term ,
'--registry' , common . registry ,
'--cache' , cache ,
'--loglevel' , 'silent' ,
'--color' , 'always'
] ,
EXEC_OPTS ,
function ( err , code , stdout ) {
s . close ( )
t . equal ( code , 0 , 'search finished successfully' )
t . ifErr ( err , 'search finished successfully' )
// \033 == \u001B
var markStart = '\u001B\\[[0-9][0-9]m'
var markEnd = '\u001B\\[0m'
var re = new RegExp ( markStart + '.*?' + markEnd )
var cnt = stdout . search ( re )
t . equal (
cnt ,
search . location ,
search . description + ' search for ' + search . term
)
t . end ( )
} )
} )
} )
} )
test ( 'cleanup' , function ( t ) {
cleanup ( )
t . end ( )
} )
function cleanup ( ) {
process . chdir ( osenv . tmpdir ( ) )
rimraf . sync ( pkg )
}
function setupCache ( ) {
cleanup ( )
mkdirp . sync ( cache )
mkdirp . sync ( registryCache )
var res = fs . writeFileSync ( cacheJsonFile , stringifyUpdated ( timeMock . epoch ) )
if ( res ) throw new Error ( 'Creating cache file failed' )
}
function stringifyUpdated ( time ) {
return JSON . stringify ( { _ updated : String ( time ) } )
}
var allMock = {
'_updated' : timeMock . all ,
'generator-frontcow' : {
'name' : 'generator-frontcow' ,
'description' : 'f36b6a6123da50959741e2ce4d634f96ec668c56 This is a fake description to ensure we do not accidentally search the real npm registry or use some kind of cache' ,
'dist-tags' : {
'latest' : '0.1.19'
} ,
'maintainers' : [
{
'name' : 'bcabanes' ,
'email' : 'contact@benjamincabanes.com'
}
] ,
'homepage' : 'https://github.com/bcabanes/generator-frontcow' ,
'keywords' : [
'sass' ,
'frontend' ,
'yeoman-generator' ,
'atomic' ,
'design' ,
'sass' ,
'foundation' ,
'foundation5' ,
'atomic design' ,
'bourbon' ,
'polyfill' ,
'font awesome'
] ,
'repository' : {
'type' : 'git' ,
'url' : 'https://github.com/bcabanes/generator-frontcow'
} ,
'author' : {
'name' : 'ben' ,
'email' : 'contact@benjamincabanes.com' ,
'url' : 'https://github.com/bcabanes'
} ,
'bugs' : {
'url' : 'https://github.com/bcabanes/generator-frontcow/issues'
} ,
'license' : 'MIT' ,
'readmeFilename' : 'README.md' ,
'time' : {
'modified' : '2014-10-03T02:26:18.406Z'
} ,
'versions' : {
'0.1.19' : 'latest'
}
} ,
'marko' : {
'name' : 'marko' ,
'description' : 'Marko is an extensible, streaming, asynchronous, high performance, HTML-based templating language that can be used in Node.js or in the browser.' ,
'dist-tags' : {
'latest' : '1.2.16'
} ,
'maintainers' : [
{
'name' : 'pnidem' ,
'email' : 'pnidem@gmail.com'
} ,
{
'name' : 'philidem' ,
'email' : 'phillip.idem@gmail.com'
}
] ,
'homepage' : 'https://github.com/raptorjs/marko' ,
'keywords' : [
'templating' ,
'template' ,
'async' ,
'streaming'
] ,
'repository' : {
'type' : 'git' ,
'url' : 'https://github.com/raptorjs/marko.git'
} ,
'author' : {
'name' : 'Patrick Steele-Idem' ,
'email' : 'pnidem@gmail.com'
} ,
'bugs' : {
'url' : 'https://github.com/raptorjs/marko/issues'
} ,
'license' : 'Apache License v2.0' ,
'readmeFilename' : 'README.md' ,
'users' : {
'pnidem' : true
} ,
'time' : {
'modified' : '2014-10-03T02:27:31.775Z'
} ,
'versions' : {
'1.2.16' : 'latest'
}
}
}