| 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('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' |
| } |
| } |
| } |