diff --git a/dadi/lib/cache/index.js b/dadi/lib/cache/index.js index a2ce174f..34b54c55 100755 --- a/dadi/lib/cache/index.js +++ b/dadi/lib/cache/index.js @@ -1,24 +1,23 @@ -var _ = require('underscore') -var crypto = require('crypto') -var path = require('path') -var pathToRegexp = require('path-to-regexp') -var url = require('url') - -var config = require(path.join(__dirname, '/../../../config')) -var log = require('@dadi/logger') -var DadiCache = require('@dadi/cache') -var cache - -var Cache = function (server) { +const crypto = require('crypto') +const path = require('path') +const pathToRegexp = require('path-to-regexp') +const url = require('url') + +const config = require(path.join(__dirname, '/../../../config')) +const utils = require('../utils') +const log = require('@dadi/logger') +const DadiCache = require('@dadi/cache') +let cache + +const Cache = function (server) { this.cache = cache = new DadiCache(config.get('caching')) this.server = server this.enabled = config.get('caching.directory.enabled') || config.get('caching.redis.enabled') - this.encoding = 'utf8' this.options = {} } -var instance +let instance module.exports = function (server) { if (!instance) { instance = new Cache(server) @@ -26,12 +25,19 @@ module.exports = function (server) { return instance } +/** + * Locate the endpoint relating to the current request in the loaded + * system components (collection models and custom endpoints) to determine + * if caching is enabled. + * + * @param {http.IncomingMessage} req - the current HTTP request + */ Cache.prototype.cachingEnabled = function (req) { - var options = {} - var endpoints = this.server.components - var requestPath = url.parse(req.url, true).pathname + let options = {} + let endpoints = this.server.components + let requestPath = url.parse(req.url, true).pathname - var endpointKey = _.find(_.keys(endpoints), function (k) { return pathToRegexp(k).exec(requestPath) }) + let endpointKey = Object.keys(endpoints).find(key => pathToRegexp(key).exec(requestPath)) if (!endpointKey) return false @@ -42,9 +48,13 @@ Cache.prototype.cachingEnabled = function (req) { return (this.enabled && (options.cache || false)) } +/** + * Return the content type for the current endpoint. Only two possible types: JavaScript or JSON. + * + * @param {http.IncomingMessage} req - the current HTTP request + */ Cache.prototype.getEndpointContentType = function (req) { - // there are only two possible types javascript or json - var query = url.parse(req.url, true).query + let query = url.parse(req.url, true).query return query.callback ? 'text/javascript' : 'application/json' } @@ -52,84 +62,98 @@ Cache.prototype.getEndpointContentType = function (req) { * Adds the Cache middleware to the stack */ Cache.prototype.init = function () { - var self = this - this.server.app.use((req, res, next) => { - var enabled = self.cachingEnabled(req) + let enabled = this.cachingEnabled(req) if (!enabled) return next() - // only cache GET requests + // Only cache GET requests. if (req.method && req.method.toLowerCase() !== 'get') return next() - var query = url.parse(req.url, true).query + let query = url.parse(req.url, true).query - // allow query string param to bypass cache - var noCache = query.cache && query.cache.toString().toLowerCase() === 'false' + // Allow query string param to bypass cache. + let noCache = query.cache && query.cache.toString().toLowerCase() === 'false' delete query.cache - // we build the filename with a hashed hex string so we can be unique - // and avoid using file system reserved characters in the name. - var modelDir = crypto.createHash('sha1').update(url.parse(req.url).pathname).digest('hex') - var filename = crypto.createHash('sha1').update(url.parse(req.url).pathname + JSON.stringify(query)).digest('hex') + // Build the filename with a hashed hex string so it is unique + // and avoids using file system reserved characters in the name. + let modelDir = crypto.createHash('sha1').update(url.parse(req.url).pathname).digest('hex') + let filename = crypto.createHash('sha1').update(url.parse(req.url).pathname + JSON.stringify(query)).digest('hex') // Prepend the model's name/folder hierarchy to the filename so it can be used // later to flush the cache for this model - var cacheKey = modelDir + '_' + filename + let cacheKey = `${modelDir}_${filename}` - // get contentType that current endpoint requires - var contentType = self.getEndpointContentType(req) + let acceptEncoding = req.headers['accept-encoding'] - // attempt to get from the cache - cache.get(cacheKey).then((stream) => { - res.setHeader('X-Cache-Lookup', 'HIT') + if (acceptEncoding && acceptEncoding !== 'gzip, deflate' && /\bgzip\b/.test(acceptEncoding)) { + acceptEncoding = 'gzip' + cacheKey += '.gz' + } - if (noCache) { - res.setHeader('X-Cache', 'MISS') - return next() - } + // Get contentType that current endpoint requires. + let contentType = this.getEndpointContentType(req) - log.info({module: 'cache'}, 'Serving ' + req.url + ' from cache') + // Attempt to get from the cache. + cache.get(cacheKey).then(stream => { + cache.getMetadata(cacheKey).then(metadata => { + res.setHeader('X-Cache-Lookup', 'HIT') - res.statusCode = 200 - res.setHeader('X-Cache', 'HIT') - res.setHeader('Content-Type', contentType) - // res.setHeader('Content-Length', stats.size) + let compressed = false + if (metadata && metadata.compression === 'gzip') { + compressed = true + } - stream.pipe(res) + if (noCache) { + res.setHeader('X-Cache', 'MISS') + return next() + } + + log.info({module: 'cache'}, 'Serving ' + req.url + ' from cache') + + res.statusCode = 200 + res.setHeader('X-Cache', 'HIT') + res.setHeader('Content-Type', contentType) + + return utils.pipeStream(stream, false, compressed, res) + }) }).catch(() => { + if (noCache) { + return next() + } + // not found in cache res.setHeader('X-Cache', 'MISS') res.setHeader('X-Cache-Lookup', 'MISS') + return cacheResponse() }) /** - * cacheResponse - * Writes the current response body to either the filesystem or a Redis server, - * depending on the configuration settings + * Write the current response body to either the filesystem or a Redis server, + * depending on the configuration settings. */ function cacheResponse () { // file is expired or does not exist, wrap res.end and res.write to save to cache - var _end = res.end - var _write = res.write - - var data = '' + let _end = res.end + let _write = res.write res.write = function (chunk) { _write.apply(res, arguments) } - res.end = function (chunk) { - // respond before attempting to cache + res.end = function (data) { + // Respond before attempting to cache. _end.apply(res, arguments) - if (chunk) data += chunk - - // if response is not 200 don't cache if (res.statusCode !== 200) return - // cache the content - cache.set(cacheKey, data).then(() => { + // Cache the content. + cache.set(cacheKey, data, { + metadata: { + compression: !acceptEncoding ? 'none' : acceptEncoding + } + }).then(() => { }) } @@ -144,14 +168,17 @@ module.exports.reset = function () { } /** + * Passes the specified pattern to the cache module to delete + * cached items with matching keys. * + * @param {string} pattern - the cache key pattern to match */ module.exports.delete = function (pattern, callback) { if (!cache) return callback(null) cache.flush(pattern).then(() => { return callback(null) - }).catch((err) => { + }).catch(err => { console.log(err) return callback(null) }) diff --git a/dadi/lib/controller/index.js b/dadi/lib/controller/index.js index 5db1414c..40b2d637 100755 --- a/dadi/lib/controller/index.js +++ b/dadi/lib/controller/index.js @@ -256,7 +256,7 @@ Controller.prototype.get = function (req, res, next) { options: queryOptions, req }).then(results => { - return done(null, results) + return done(null, results, req) }).catch(error => { return done(error) }) diff --git a/dadi/lib/help.js b/dadi/lib/help.js index af94316b..e34fd219 100755 --- a/dadi/lib/help.js +++ b/dadi/lib/help.js @@ -1,6 +1,8 @@ const crypto = require('crypto') const formatError = require('@dadi/format-error') const path = require('path') +const Readable = require('stream').Readable +const utils = require(path.join(__dirname, '/utils')) const cache = require(path.join(__dirname, '/cache')) const config = require(path.join(__dirname, '/../../config')) @@ -8,7 +10,7 @@ const log = require('@dadi/logger') // helper that sends json response module.exports.sendBackJSON = function (successCode, res, next) { - return function (err, results) { + return function (err, results, originalRequest) { let body = results let statusCode = successCode @@ -40,17 +42,25 @@ module.exports.sendBackJSON = function (successCode, res, next) { let resBody = JSON.stringify(body) // log response if it's already been sent - if (res.finished) { - log.info({res: res}, 'Response already sent. Attempting to send results: ' + resBody) - return + // if (res.finished) { + // log.info({res: res}, 'Response already sent. Attempting to send results: ' + resBody) + // return + // } + let compress = false + let acceptEncoding = originalRequest && originalRequest.headers['accept-encoding'] ? originalRequest.headers['accept-encoding'] : '' + + if (acceptEncoding !== 'gzip, deflate') { + compress = acceptEncoding.match(/\bgzip\b/) } - res.setHeader('content-type', 'application/json') - res.setHeader('content-length', Buffer.byteLength(resBody)) + let stream = new Readable() + stream.push(resBody) + stream.push(null) + res.setHeader('Content-Type', 'application/json') res.statusCode = statusCode - res.end(resBody) + return utils.pipeStream(stream, compress, compress, res) } } @@ -205,7 +215,7 @@ module.exports.validateCollectionSchema = function (obj) { * Remove each file in the specified cache folder. */ module.exports.clearCache = function (pathname, callback) { - var pattern = '' + let pattern = '' pattern = crypto.createHash('sha1').update(pathname).digest('hex') diff --git a/dadi/lib/utils.js b/dadi/lib/utils.js new file mode 100755 index 00000000..7bebda89 --- /dev/null +++ b/dadi/lib/utils.js @@ -0,0 +1,34 @@ +const concat = require('concat-stream') +const lengthStream = require('length-stream') +const zlib = require('zlib') + +module.exports.pipeStream = function (stream, compress, isCompressed, res) { + let contentLength = 0 + + // Set the content length after the stream has passed through. + function lengthListener (length) { + contentLength = length + } + + // Receive the concatenated buffer and send the response. + function sendBuffer (buffer) { + res.setHeader('Content-Length', contentLength) + res.end(buffer) + } + + if (compress || isCompressed) { + res.setHeader('Content-Encoding', 'gzip') + } + + let concatStream = concat(sendBuffer) + + if (compress) { + console.log('gzipping', compress, isCompressed) + console.trace() + stream = stream.pipe(zlib.createGzip()) + } + + stream = stream.pipe(lengthStream(lengthListener)) + + return stream.pipe(concatStream) +} diff --git a/package.json b/package.json index b6d386c4..bf39e0c3 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,9 @@ ] }, "dependencies": { + "@dadi/api-mongodb": "^4.1.0", "@dadi/boot": "^1.0.0", - "@dadi/cache": "1.5.x", + "@dadi/cache": "~2.0.0", "@dadi/et": "^2.0.0", "@dadi/format-error": "^1.6.0", "@dadi/logger": "^1.3.0", diff --git a/test/acceptance/cache.js b/test/acceptance/cache.js index 23f6e83a..aa94d44b 100755 --- a/test/acceptance/cache.js +++ b/test/acceptance/cache.js @@ -1,69 +1,67 @@ -var crypto = require('crypto'); -var fs = require('fs'); -var path = require('path'); -var should = require('should'); -var request = require('supertest'); -//var redis = require('redis'); -var fakeredis = require('fakeredis'); -var sinon = require('sinon'); -var proxyquire = require('proxyquire'); -var url = require('url'); -var _ = require('underscore'); - -var config = require(__dirname + '/../../config.js'); -var app = require(__dirname + '/../../dadi/lib/'); -var api = require(__dirname + '/../../dadi/lib/api'); -var Server = require(__dirname + '/../../dadi/lib'); -var cache = require(__dirname + '/../../dadi/lib/cache'); -var help = require(__dirname + '/help'); - -var testConfigString; +var crypto = require('crypto') +var fs = require('fs') +var path = require('path') +var should = require('should') +var request = require('supertest') +// var redis = require('redis'); +var fakeredis = require('fakeredis') +var sinon = require('sinon') +var proxyquire = require('proxyquire') +var url = require('url') +var _ = require('underscore') + +var config = require(__dirname + '/../../config.js') +var app = require(__dirname + '/../../dadi/lib/') +var api = require(__dirname + '/../../dadi/lib/api') +var Server = require(__dirname + '/../../dadi/lib') +var cache = require(__dirname + '/../../dadi/lib/cache') +var help = require(__dirname + '/help') + +var testConfigString var cacheKeys = [] -var bearerToken; +var bearerToken describe('Cache', function (done) { this.timeout(4000) - after(function(done) { - testConfigString = fs.readFileSync(config.configPath()); + after(function (done) { + testConfigString = fs.readFileSync(config.configPath()) - var newTestConfig = JSON.parse(testConfigString); - newTestConfig.caching.directory.enabled = true; - newTestConfig.caching.redis.enabled = false; - fs.writeFileSync(config.configPath(), JSON.stringify(newTestConfig, null, 2)); - done(); - }); + var newTestConfig = JSON.parse(testConfigString) + newTestConfig.caching.directory.enabled = true + newTestConfig.caching.redis.enabled = false + fs.writeFileSync(config.configPath(), JSON.stringify(newTestConfig, null, 2)) + done() + }) - beforeEach(function(done) { + beforeEach(function (done) { try { cache.reset() - done(); + done() + } catch (err) { + done() } - catch (err) { - done(); - } - }); + }) it.skip('should use cache if available', function (done) { - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); + if (err) return done(err) help.getBearerToken(function (err, token) { - if (err) return done(err); + if (err) return done(err) - bearerToken = token; - help.clearCache(); + bearerToken = token + help.clearCache() - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res1) { - if (err) return done(err); - + if (err) return done(err) client .post('/vtest/testdb/test-schema') @@ -71,52 +69,52 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, res) { - if (err) return done(err); + if (err) return done(err) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res2) { - if (err) return done(err); + if (err) return done(err) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res3) { - if (err) return done(err); + if (err) return done(err) - res2.text.should.equal(res3.text); + res2.text.should.equal(res3.text) should.exist(res3.headers['x-cache']) res3.headers['x-cache'].should.eql('HIT') - help.removeTestClients(function() { - help.clearCache(); - app.stop(done); - }); - }); - }); - }); - }); - }); - }); - }); - }); + help.removeTestClients(function () { + help.clearCache() + app.stop(done) + }) + }) + }) + }) + }) + }) + }) + }) + }) it.skip('should allow bypassing cache with query string flag', function (done) { - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); + if (err) return done(err) help.getBearerToken(function (err, token) { - if (err) return done(err); + if (err) return done(err) - bearerToken = token; - help.clearCache(); + bearerToken = token + help.clearCache() - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .post('/vtest/testdb/test-schema') @@ -124,77 +122,77 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, res) { - if (err) return done(err); + if (err) return done(err) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res1) { - if (err) return done(err); + if (err) return done(err) - res1.body['results'].length.should.equal(1); + res1.body['results'].length.should.equal(1) client .get('/vtest/testdb/test-schema?cache=false') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res2) { - if (err) return done(err); - - should.exist(res2.headers['x-cache']); - res2.headers['x-cache'].should.eql('MISS'); - should.exist(res2.headers['x-cache-lookup']); - res2.headers['x-cache-lookup'].should.eql('HIT'); - - help.removeTestClients(function() { - help.clearCache(); - app.stop(done); - }); - }); - }); - }); - }); - }); - }); - }); + if (err) return done(err) + + should.exist(res2.headers['x-cache']) + res2.headers['x-cache'].should.eql('MISS') + should.exist(res2.headers['x-cache-lookup']) + res2.headers['x-cache-lookup'].should.eql('HIT') + + help.removeTestClients(function () { + help.clearCache() + app.stop(done) + }) + }) + }) + }) + }) + }) + }) + }) it('should allow disabling through config', function (done) { - testConfigString = fs.readFileSync(config.configPath()); + testConfigString = fs.readFileSync(config.configPath()) - var newTestConfig = JSON.parse(testConfigString); - newTestConfig.caching.directory.enabled = false; - newTestConfig.caching.redis.enabled = false; + var newTestConfig = JSON.parse(testConfigString) + newTestConfig.caching.directory.enabled = false + newTestConfig.caching.redis.enabled = false - fs.writeFileSync(config.configPath(), JSON.stringify(newTestConfig, null, 2)); + fs.writeFileSync(config.configPath(), JSON.stringify(newTestConfig, null, 2)) - cache.reset(); + cache.reset() - delete require.cache[__dirname + '/../../config']; - delete require.cache[__dirname + '/../../dadi/lib/']; - config = require(__dirname + '/../../config'); - config.loadFile(config.configPath()); + delete require.cache[__dirname + '/../../config'] + delete require.cache[__dirname + '/../../dadi/lib/'] + config = require(__dirname + '/../../config') + config.loadFile(config.configPath()) - var spy = sinon.spy(fs, 'createWriteStream'); + var spy = sinon.spy(fs, 'createWriteStream') - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); - help.getBearerToken(function (err, token) { - if (err) return done(err); - bearerToken = token; - help.clearCache(); + if (err) return done(err) + help.getBearerToken(function (err, token) { + if (err) return done(err) + bearerToken = token + help.clearCache() - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) - client + client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res1) { - if (err) return done(err); + if (err) return done(err) - res1.body['results'].length.should.equal(0); + res1.body['results'].length.should.equal(0) client .post('/vtest/testdb/test-schema') @@ -202,38 +200,37 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, res) { - if (err) return done(err); + if (err) return done(err) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res2) { - if (err) return done(err); - - - res2.body['results'].length.should.equal(1); + if (err) return done(err) - var called = spy.called; - spy.restore(); - called.should.be.false; + res2.body['results'].length.should.equal(1) - fs.writeFileSync(config.configPath(), testConfigString); - cache.reset(); - delete require.cache[__dirname + '/../../config']; - config = require(__dirname + '/../../config'); - config.loadFile(config.configPath()); + var called = spy.called + spy.restore() + called.should.be.false - app.stop(done); - }); - }); - }); - }); - }); - }); - }); + fs.writeFileSync(config.configPath(), testConfigString) + cache.reset() + delete require.cache[__dirname + '/../../config'] + config = require(__dirname + '/../../config') + config.loadFile(config.configPath()) - describe('Filesystem', function(done) { + app.stop(done) + }) + }) + }) + }) + }) + }) + }) + + describe('Filesystem', function (done) { beforeEach(function (done) { var testConfigString = fs.readFileSync(config.configPath()) @@ -247,118 +244,116 @@ describe('Cache', function (done) { config.loadFile(config.configPath()) - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); + if (err) return done(err) help.getBearerToken(function (err, token) { - if (err) return done(err); + if (err) return done(err) - bearerToken = token; - help.clearCache(); - done(); - }); - }); - }); - }); + bearerToken = token + help.clearCache() + done() + }) + }) + }) + }) afterEach(function (done) { - help.removeTestClients(function() { - //help.clearCache(); - app.stop(done); - }); - }); + help.removeTestClients(function () { + // help.clearCache(); + app.stop(done) + }) + }) it('should save responses to the file system', function (done) { - var spy = sinon.spy(fs, 'createWriteStream'); + var spy = sinon.spy(fs, 'createWriteStream') request('http://' + config.get('server.host') + ':' + config.get('server.port')) .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res) { - if (err) return done(err); - - setTimeout(function() { - spy.called.should.be.true; - var args = spy.getCall(0).args; + if (err) return done(err) - args[0].indexOf('cache/api').should.be.above(-1); + setTimeout(function () { + spy.called.should.be.true + var args = spy.getCall(0).args - spy.restore(); - done(); + args[0].indexOf('cache/api').should.be.above(-1) - }, 1000); - }); - }); + spy.restore() + done() + }, 1000) + }) + }) it('should invalidate based on TTL', function (done) { - this.timeout(4000); + this.timeout(4000) - var oldTTL = config.get('caching.ttl'); - config.set('caching.ttl', 1); + var oldTTL = config.get('caching.ttl') + config.set('caching.ttl', 1) cache.reset() - var _done = done; + var _done = done done = function (err) { - config.set('caching.ttl', oldTTL); - _done(err); - }; + config.set('caching.ttl', oldTTL) + _done(err) + } - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res1) { - if (err) return done(err); + if (err) return done(err) client .post('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .send({field1: 'foo!'}) .expect(200) .end(function (err, res) { - if (err) return done(err); + if (err) return done(err) setTimeout(function () { - // ttl should have expired client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res2) { - if (err) return done(err); + if (err) return done(err) - res1.body['results'].length.should.equal(0); - res2.body['results'].length.should.equal(1); - res2.text.should.not.equal(res1.text); + res1.body['results'].length.should.equal(0) + res2.body['results'].length.should.equal(1) + res2.text.should.not.equal(res1.text) - done(); - }); - }, 1000); - }); - }); - }); + done() + }) + }, 1000) + }) + }) + }) it('should flush on POST create request', function (done) { - this.timeout(4000); + this.timeout(4000) help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res1) { - if (err) return done(err); + if (err) return done(err) client .post('/vtest/testdb/test-schema') @@ -366,40 +361,39 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, res2) { - if (err) return done(err); + if (err) return done(err) setTimeout(function () { - client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res3) { - if (err) return done(err); + if (err) return done(err) - res1.body.results.length.should.eql(2); - res3.body.results.length.should.eql(3); - res3.text.should.not.equal(res1.text); + res1.body.results.length.should.eql(2) + res3.body.results.length.should.eql(3) + res3.text.should.not.equal(res1.text) - done(); - }); - }, 300); - }); - }); - }); - }); - }); + done() + }) + }, 300) + }) + }) + }) + }) + }) it('should flush on PUT update request', function (done) { - this.timeout(4000); + this.timeout(4000) help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) // GET client @@ -407,7 +401,7 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes1) { - if (err) return done(err); + if (err) return done(err) // CREATE client @@ -416,10 +410,10 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, postRes1) { - if (err) return done(err); + if (err) return done(err) // save id for updating - var id = postRes1.body.results[0]._id; + var id = postRes1.body.results[0]._id // GET AGAIN - should cache new results client @@ -427,10 +421,9 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes2) { - if (err) return done(err); + if (err) return done(err) setTimeout(function () { - // UPDATE again client .put('/vtest/testdb/test-schema/' + id) @@ -438,43 +431,42 @@ describe('Cache', function (done) { .send({field1: 'foo bar baz!'}) .expect(200) .end(function (err, postRes2) { - if (err) return done(err); + if (err) return done(err) // WAIT, then GET again setTimeout(function () { - client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes3) { - if (err) return done(err); + if (err) return done(err) - var result = _.findWhere(getRes3.body.results, { "_id": id }); + var result = _.findWhere(getRes3.body.results, { '_id': id }) - result.field1.should.eql('foo bar baz!'); + result.field1.should.eql('foo bar baz!') - done(); - }); - }, 200); - }); - }, 300); - }); - }); - }); - }); - }); - }); + done() + }) + }, 200) + }) + }, 300) + }) + }) + }) + }) + }) + }) it('should flush on DELETE request', function (done) { - this.timeout(4000); + this.timeout(4000) help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) // GET client @@ -482,7 +474,7 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes1) { - if (err) return done(err); + if (err) return done(err) // CREATE client @@ -491,10 +483,10 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, postRes1) { - if (err) return done(err); + if (err) return done(err) // save id for deleting - var id = postRes1.body.results[0]._id; + var id = postRes1.body.results[0]._id // GET AGAIN - should cache new results client @@ -502,46 +494,44 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes2) { - if (err) return done(err); + if (err) return done(err) setTimeout(function () { - // DELETE client .delete('/vtest/testdb/test-schema/' + id) .set('Authorization', 'Bearer ' + bearerToken) .expect(204) .end(function (err, postRes2) { - if (err) return done(err); + if (err) return done(err) // WAIT, then GET again setTimeout(function () { - client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes3) { - if (err) return done(err); + if (err) return done(err) - var result = _.findWhere(getRes3.body.results, { "_id": id }); + var result = _.findWhere(getRes3.body.results, { '_id': id }) - should.not.exist(result); + should.not.exist(result) - done(); - }); - }, 300); - }); - }, 700); - }); - }); - }); - }); - }); - }); + done() + }) + }, 300) + }) + }, 700) + }) + }) + }) + }) + }) + }) it('should preserve content-type', function (done) { - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .get('/vtest/testdb/test-schema?callback=myCallback') @@ -549,7 +539,7 @@ describe('Cache', function (done) { .expect(200) .expect('content-type', 'text/javascript') .end(function (err, res1) { - if (err) return done(err); + if (err) return done(err) client .post('/vtest/testdb/test-schema') @@ -557,7 +547,7 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, res) { - if (err) return done(err); + if (err) return done(err) client .get('/vtest/testdb/test-schema?callback=myCallback') @@ -565,17 +555,17 @@ describe('Cache', function (done) { .expect(200) .expect('content-type', 'text/javascript') .end(function (err, res2) { - if (err) return done(err); + if (err) return done(err) - res2.text.should.not.equal(res1.text); - done(); - }); - }); - }); - }); - }); + res2.text.should.not.equal(res1.text) + done() + }) + }) + }) + }) + }) - describe('Redis', function(done) { + describe('Redis', function (done) { beforeEach(function (done) { testConfigString = fs.readFileSync(config.configPath()) @@ -595,115 +585,112 @@ describe('Cache', function (done) { // cache = require(__dirname + '/../../dadi/lib/cache'); // delete require.cache[__dirname + '/../../config']; // config = require(__dirname + '/../../config'); - done(); - }); + done() + }) - afterEach(function(done) { - fs.writeFileSync(config.configPath(), testConfigString); - done(); - }); + afterEach(function (done) { + fs.writeFileSync(config.configPath(), testConfigString) + done() + }) - it.skip('should throw error if can\'t connect to Redis client', function(done) { - delete require.cache[__dirname + '/../../config.js']; - delete require.cache[__dirname + '/../../dadi/lib/']; + it.skip('should throw error if can\'t connect to Redis client', function (done) { + delete require.cache[__dirname + '/../../config.js'] + delete require.cache[__dirname + '/../../dadi/lib/'] - config.loadFile(config.configPath()); + config.loadFile(config.configPath()) - should.throws(function() { app.start(function(){}); }, Error); + should.throws(function () { app.start(function () {}) }, Error) app.stop(done) + }) - }); - - it.skip('should initialise Redis client', function(done) { - delete require.cache[__dirname + '/../../config.js']; - config.loadFile(config.configPath()); + it.skip('should initialise Redis client', function (done) { + delete require.cache[__dirname + '/../../config.js'] + config.loadFile(config.configPath()) - //sinon.stub(redis, 'createClient', fakeredis.createClient); + // sinon.stub(redis, 'createClient', fakeredis.createClient); - delete require.cache[__dirname + '/../../dadi/lib/']; - cache.reset(); + delete require.cache[__dirname + '/../../dadi/lib/'] + cache.reset() try { - app.stop(function(){}); - //app.start(function(){}); - } - catch (err) { + app.stop(function () {}) + // app.start(function(){}); + } catch (err) { } - var c = cache(app); - //redis.createClient.restore(); - //c.redisClient.should.not.be.null; - //app.stop(function(){}); - done(); - }); + var c = cache(app) + // redis.createClient.restore(); + // c.redisClient.should.not.be.null; + // app.stop(function(){}); + done() + }) - it.skip('should fallback to directory cache if Redis client fails', function(done) { - delete require.cache[__dirname + '/../../config.js']; - config.loadFile(config.configPath()); + it.skip('should fallback to directory cache if Redis client fails', function (done) { + delete require.cache[__dirname + '/../../config.js'] + config.loadFile(config.configPath()) - var EventEmitter = require('events'); - var util = require('util'); + var EventEmitter = require('events') + var util = require('util') /* Fake redis client */ - function Client() { - this.end = function(reallyEnd) { } - EventEmitter.call(this); + function Client () { + this.end = function (reallyEnd) { } + EventEmitter.call(this) } - util.inherits(Client, EventEmitter); - var redisClient = new Client(); + util.inherits(Client, EventEmitter) + var redisClient = new Client() /* End Fake redis client */ - sinon.stub(redis, 'createClient').returns(redisClient); + sinon.stub(redis, 'createClient').returns(redisClient) - delete require.cache[__dirname + '/../../dadi/lib/']; - cache.reset(); + delete require.cache[__dirname + '/../../dadi/lib/'] + cache.reset() - var c = cache(app); + var c = cache(app) // redis.createClient.restore(); - setTimeout(function() { + setTimeout(function () { // emit an error event - redisClient.emit('error', { code: 'CONNECTION_BROKEN'}); + redisClient.emit('error', { code: 'CONNECTION_BROKEN'}) config.get('caching.directory.enabled').should.eql(true) try { - app.stop(done); + app.stop(done) } catch (err) { - done(); + done() } }, 1000) + }) - }); - - it('should check key exists in Redis', function(done) { - delete require.cache[__dirname + '/../../config.js']; - config.loadFile(config.configPath()); + it('should check key exists in Redis', function (done) { + delete require.cache[__dirname + '/../../config.js'] + config.loadFile(config.configPath()) delete require.cache[__dirname + '/../../dadi/lib/'] cache.reset() - var c = cache(app); + var c = cache(app) c.cache.cacheHandler.redisClient = fakeredis.createClient() c.cache.cacheHandler.redisClient.status = 'ready' var spy = sinon.spy(c.cache.cacheHandler.redisClient, 'exists') // generate expected cacheKey - var requestUrl = '/vtest/testdb/test-schema'; - var query = url.parse(requestUrl, true).query; - var modelDir = crypto.createHash('sha1').update(url.parse(requestUrl).pathname).digest('hex'); - var filename = crypto.createHash('sha1').update(url.parse(requestUrl).pathname + JSON.stringify(query)).digest('hex'); - var cacheKey = modelDir + '_' + filename; + var requestUrl = '/vtest/testdb/test-schema' + var query = url.parse(requestUrl, true).query + var modelDir = crypto.createHash('sha1').update(url.parse(requestUrl).pathname).digest('hex') + var filename = crypto.createHash('sha1').update(url.parse(requestUrl).pathname + JSON.stringify(query)).digest('hex') + var cacheKey = modelDir + '_' + filename try { - app.start(function() { - help.getBearerToken(function (err, token) { - if (err) return done(err); - bearerToken = token; + app.start(function () { + help.getBearerToken(function (err, token) { + if (err) return done(err) + bearerToken = token - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .get(requestUrl) @@ -712,88 +699,84 @@ describe('Cache', function (done) { .end(function (err, res) { if (err) return done(err) - spy.called.should.eql(true); - spy.args[0][0].should.eql(cacheKey); + spy.called.should.eql(true) + spy.args[0][0].should.eql(cacheKey) c.cache.cacheHandler.redisClient.exists.restore() - app.stop(done); - }); - - }); - }); - } - catch (err) { + app.stop(done) + }) + }) + }) + } catch (err) { console.log(err) - done(); + done() } - }); + }) - it('should return data if key exists in Redis, with correct headers', function(done) { - delete require.cache[__dirname + '/../../config.js']; - config.loadFile(config.configPath()); + it('should return data if key exists in Redis, with correct headers', function (done) { + delete require.cache[__dirname + '/../../config.js'] + config.loadFile(config.configPath()) - delete require.cache[__dirname + '/../../dadi/lib/']; + delete require.cache[__dirname + '/../../dadi/lib/'] // generate expected cacheKey - var requestUrl = '/vtest/testdb/test-schema'; - var query = url.parse(requestUrl, true).query; - var modelDir = crypto.createHash('sha1').update(url.parse(requestUrl).pathname).digest('hex'); - var filename = crypto.createHash('sha1').update(url.parse(requestUrl).pathname + JSON.stringify(query)).digest('hex'); - var cacheKey = modelDir + '_' + filename; + var requestUrl = '/vtest/testdb/test-schema' + var query = url.parse(requestUrl, true).query + var modelDir = crypto.createHash('sha1').update(url.parse(requestUrl).pathname).digest('hex') + var filename = crypto.createHash('sha1').update(url.parse(requestUrl).pathname + JSON.stringify(query)).digest('hex') + var cacheKey = modelDir + '_' + filename cache.reset() - var c = cache(app); + var c = cache(app) c.cache.cacheHandler.redisClient = fakeredis.createClient() c.cache.cacheHandler.redisClient.status = 'ready' c.cache.cacheHandler.redisClient.set(cacheKey, 'DATA') try { - app.start(function() { - help.getBearerToken(function (err, token) { - if (err) return done(err); - bearerToken = token; + app.start(function () { + help.getBearerToken(function (err, token) { + if (err) return done(err) + bearerToken = token - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .get(requestUrl) .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res) { - if (err) return done(err); - - res.text.should.eql('DATA'); - res.headers['x-cache'].should.eql('HIT'); + if (err) return done(err) - app.stop(done); - }); + res.text.should.eql('DATA') + res.headers['x-cache'].should.eql('HIT') - }); - }); - } - catch (err) { + app.stop(done) + }) + }) + }) + } catch (err) { console.log(err) - done(); + done() } - }); + }) - it('should invalidate based on TTL', function(done) { - this.timeout(6000); + it('should invalidate based on TTL', function (done) { + this.timeout(6000) - var configString = fs.readFileSync(config.configPath()); - var newTestConfig = JSON.parse(configString); - newTestConfig.caching.ttl = 1; - fs.writeFileSync(config.configPath(), JSON.stringify(newTestConfig, null, 2)); - delete require.cache[__dirname + '/../../config']; - //config = require(__dirname + '/../../config'); + var configString = fs.readFileSync(config.configPath()) + var newTestConfig = JSON.parse(configString) + newTestConfig.caching.ttl = 1 + fs.writeFileSync(config.configPath(), JSON.stringify(newTestConfig, null, 2)) + delete require.cache[__dirname + '/../../config'] + // config = require(__dirname + '/../../config'); - delete require.cache[__dirname + '/../../config.js']; - delete require.cache[__dirname + '/../../dadi/lib/']; + delete require.cache[__dirname + '/../../config.js'] + delete require.cache[__dirname + '/../../dadi/lib/'] - config.loadFile(config.configPath()); + config.loadFile(config.configPath()) cache.reset() - var c = cache(app); + var c = cache(app) c.cache.cacheHandler.redisClient = fakeredis.createClient() c.cache.cacheHandler.redisClient.status = 'ready' @@ -802,7 +785,7 @@ describe('Cache', function (done) { var stream = new Readable({objectMode: true}) for (var i = 0; i < cacheKeys.length; i++) { - if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length-1)) === 0) { + if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length - 1)) === 0) { stream.push([cacheKeys[i]]) } else { // console.log('rejected key: ', cacheKeys[i]) @@ -814,15 +797,15 @@ describe('Cache', function (done) { } try { - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); + if (err) return done(err) - help.getBearerToken(function (err, token) { - if (err) return done(err); - bearerToken = token; + help.getBearerToken(function (err, token) { + if (err) return done(err) + bearerToken = token - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .post('/vtest/testdb/test-schema') @@ -830,7 +813,7 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, res) { - if (err) return done(err); + if (err) return done(err) client .get('/vtest/testdb/test-schema') @@ -849,39 +832,37 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res2) { - if (err) return done(err); - - res2.headers['x-cache'].should.eql('MISS'); - res2.headers['x-cache-lookup'].should.eql('MISS'); - - app.stop(done); - - }); - }, 1500); - }); - }, 1500); - }); - }); - }); - }); - }); - } - catch (err) { - console.log(err); - done(); + if (err) return done(err) + + res2.headers['x-cache'].should.eql('MISS') + res2.headers['x-cache-lookup'].should.eql('MISS') + + app.stop(done) + }) + }, 1500) + }) + }, 1500) + }) + }) + }) + }) + }) + } catch (err) { + console.log(err) + done() } - }); + }) - it('should flush on POST create request', function(done) { + it('should flush on POST create request', function (done) { this.timeout(8000) - delete require.cache[__dirname + '/../../config.js']; - delete require.cache[__dirname + '/../../dadi/lib/']; + delete require.cache[__dirname + '/../../config.js'] + delete require.cache[__dirname + '/../../dadi/lib/'] - config.loadFile(config.configPath()); + config.loadFile(config.configPath()) cache.reset() - var c = cache(app); + var c = cache(app) c.cache.cacheHandler.redisClient = fakeredis.createClient() c.cache.cacheHandler.redisClient.status = 'ready' @@ -890,7 +871,7 @@ describe('Cache', function (done) { var stream = new Readable({objectMode: true}) for (var i = 0; i < cacheKeys.length; i++) { - if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length-1)) === 0) { + if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length - 1)) === 0) { stream.push([cacheKeys[i]]) } else { // console.log('rejected key: ', cacheKeys[i]) @@ -902,31 +883,30 @@ describe('Cache', function (done) { } try { - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); + if (err) return done(err) help.getBearerToken(function (err, token) { - if (err) return done(err); - bearerToken = token; + if (err) return done(err) + bearerToken = token help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + if (err) return done(err) - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res1) { - if (err) return done(err); - - setTimeout(function() { + if (err) return done(err) + setTimeout(function () { // get the cache keys c.cache.cacheHandler.redisClient.KEYS('*', (err, keys) => { cacheKeys = keys @@ -937,47 +917,46 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, res2) { - if (err) return done(err); + if (err) return done(err) - setTimeout(function() { + setTimeout(function () { client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, res3) { - if (err) return done(err); + if (err) return done(err) cache.reset() - res1.body.results.length.should.eql(2); - res3.body.results.length.should.eql(3); - res3.text.should.not.equal(res1.text); + res1.body.results.length.should.eql(2) + res3.body.results.length.should.eql(3) + res3.text.should.not.equal(res1.text) - app.stop(done); - }); + app.stop(done) + }) }, 500) - }); + }) }) }, 500) - }); - }); - }); - }); - }); - }); - } - catch (err) { - console.log(err); - done(); + }) + }) + }) + }) + }) + }) + } catch (err) { + console.log(err) + done() } - }); + }) - it('should flush on PUT update request', function(done) { + it('should flush on PUT update request', function (done) { this.timeout(8000) - delete require.cache[__dirname + '/../../config.js']; - delete require.cache[__dirname + '/../../dadi/lib/']; + delete require.cache[__dirname + '/../../config.js'] + delete require.cache[__dirname + '/../../dadi/lib/'] - config.loadFile(config.configPath()); + config.loadFile(config.configPath()) cache.reset() var c = cache(app) @@ -989,7 +968,7 @@ describe('Cache', function (done) { var stream = new Readable({objectMode: true}) for (var i = 0; i < cacheKeys.length; i++) { - if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length-1)) === 0) { + if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length - 1)) === 0) { stream.push([cacheKeys[i]]) } else { // console.log('rejected key: ', cacheKeys[i]) @@ -1001,29 +980,29 @@ describe('Cache', function (done) { } try { - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); + if (err) return done(err) help.getBearerToken(function (err, token) { - if (err) return done(err); - bearerToken = token; + if (err) return done(err) + bearerToken = token - help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + help.createDoc(bearerToken, function (err, doc) { + if (err) return done(err) - help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + help.createDoc(bearerToken, function (err, doc) { + if (err) return done(err) - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) // GET - client + client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes1) { - if (err) return done(err); + if (err) return done(err) // CREATE client @@ -1032,10 +1011,10 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, postRes1) { - if (err) return done(err); + if (err) return done(err) // save id for updating - var id = postRes1.body.results[0]._id; + var id = postRes1.body.results[0]._id // GET AGAIN - should cache new results client @@ -1043,9 +1022,9 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes2) { - if (err) return done(err); + if (err) return done(err) - setTimeout(function() { + setTimeout(function () { // get the cache keys c.cache.cacheHandler.redisClient.KEYS('*', (err, keys) => { cacheKeys = keys @@ -1057,7 +1036,6 @@ describe('Cache', function (done) { .send({field1: 'foo bar baz!'}) .expect(200) .end(function (err, postRes2) { - // WAIT, then GET again setTimeout(function () { client @@ -1065,36 +1043,35 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes3) { - var result = _.findWhere(getRes3.body.results, { "_id": id }); - result.field1.should.eql('foo bar baz!'); - app.stop(done); - }); - }, 500); - }); - }) - }, 500) - }); - }); - }); - }); - }); - }); - }); - }); - } - catch (err) { - console.log(err); - done(); + var result = _.findWhere(getRes3.body.results, { '_id': id }) + result.field1.should.eql('foo bar baz!') + app.stop(done) + }) + }, 500) + }) + }) + }, 500) + }) + }) + }) + }) + }) + }) + }) + }) + } catch (err) { + console.log(err) + done() } - }); + }) - it('should flush on DELETE request', function(done) { + it('should flush on DELETE request', function (done) { this.timeout(8000) - delete require.cache[__dirname + '/../../config.js']; - delete require.cache[__dirname + '/../../dadi/lib/']; + delete require.cache[__dirname + '/../../config.js'] + delete require.cache[__dirname + '/../../dadi/lib/'] - config.loadFile(config.configPath()); + config.loadFile(config.configPath()) cache.reset() var c = cache(app) @@ -1106,7 +1083,7 @@ describe('Cache', function (done) { var stream = new Readable({objectMode: true}) for (var i = 0; i < cacheKeys.length; i++) { - if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length-1)) === 0) { + if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length - 1)) === 0) { stream.push([cacheKeys[i]]) } else { // console.log('rejected key: ', cacheKeys[i]) @@ -1118,29 +1095,29 @@ describe('Cache', function (done) { } try { - app.start(function() { + app.start(function () { help.dropDatabase('testdb', function (err) { - if (err) return done(err); + if (err) return done(err) help.getBearerToken(function (err, token) { - if (err) return done(err); - bearerToken = token; + if (err) return done(err) + bearerToken = token - help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + help.createDoc(bearerToken, function (err, doc) { + if (err) return done(err) - help.createDoc(bearerToken, function (err, doc) { - if (err) return done(err); + help.createDoc(bearerToken, function (err, doc) { + if (err) return done(err) - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) // GET - client + client .get('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes1) { - if (err) return done(err); + if (err) return done(err) // CREATE client @@ -1149,10 +1126,10 @@ describe('Cache', function (done) { .send({field1: 'foo!'}) .expect(200) .end(function (err, postRes1) { - if (err) return done(err); + if (err) return done(err) // save id for deleting - var id = postRes1.body.results[0]._id; + var id = postRes1.body.results[0]._id // GET AGAIN - should cache new results client @@ -1160,7 +1137,6 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes2) { - setTimeout(function () { // get the cache keys c.cache.cacheHandler.redisClient.KEYS('*', (err, keys) => { @@ -1180,35 +1156,34 @@ describe('Cache', function (done) { .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end(function (err, getRes3) { - var result = _.findWhere(getRes3.body.results, { "_id": id }); - should.not.exist(result); - app.stop(done); - }); - }, 300); - }); - }, 700); + var result = _.findWhere(getRes3.body.results, { '_id': id }) + should.not.exist(result) + app.stop(done) + }) + }, 300) + }) + }, 700) }) }, 500) - }); - }); - }); - }); - }); - }); - }); - }); - } - catch (err) { - console.log(err); - done(); + }) + }) + }) + }) + }) + }) + }) + }) + } catch (err) { + console.log(err) + done() } - }); + }) - it('should preserve content-type', function(done) { - delete require.cache[__dirname + '/../../config.js']; - delete require.cache[__dirname + '/../../dadi/lib/']; + it('should preserve content-type', function (done) { + delete require.cache[__dirname + '/../../config.js'] + delete require.cache[__dirname + '/../../dadi/lib/'] - config.loadFile(config.configPath()); + config.loadFile(config.configPath()) cache.reset() var c = cache(app) @@ -1220,7 +1195,7 @@ describe('Cache', function (done) { var stream = new Readable({objectMode: true}) for (var i = 0; i < cacheKeys.length; i++) { - if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length-1)) === 0) { + if (pattern.match === '*' || cacheKeys[i].indexOf(pattern.match.substring(0, pattern.match.length - 1)) === 0) { stream.push([cacheKeys[i]]) } else { // console.log('rejected key: ', cacheKeys[i]) @@ -1232,31 +1207,30 @@ describe('Cache', function (done) { } try { - app.start(function() { - - var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')); + app.start(function () { + var client = request('http://' + config.get('server.host') + ':' + config.get('server.port')) - client + client .get('/vtest/testdb/test-schema?callback=myCallback') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .expect('content-type', 'text/javascript') .end(function (err, res1) { - if (err) return done(err); + if (err) return done(err) - setTimeout(function() { + setTimeout(function () { // get the cache keys c.cache.cacheHandler.redisClient.KEYS('*', (err, keys) => { cacheKeys = keys - setTimeout(function() { + setTimeout(function () { client .post('/vtest/testdb/test-schema') .set('Authorization', 'Bearer ' + bearerToken) .send({field1: 'foo!'}) .expect(200) .end(function (err, res) { - if (err) return done(err); + if (err) return done(err) client .get('/vtest/testdb/test-schema?callback=myCallback') @@ -1264,21 +1238,20 @@ describe('Cache', function (done) { .expect(200) .expect('content-type', 'text/javascript') .end(function (err, res2) { - if (err) return done(err); + if (err) return done(err) - res2.text.should.not.equal(res1.text); - app.stop(done); - }); - }); + res2.text.should.not.equal(res1.text) + app.stop(done) + }) + }) }, 500) }) }, 500) - }); - }); - } - catch(err) { + }) + }) + } catch (err) { - } - }); - }); -}); + } + }) + }) +}) diff --git a/test/acceptance/fields/datetime.js b/test/acceptance/fields/datetime.js index 2ca70483..bc54ad03 100644 --- a/test/acceptance/fields/datetime.js +++ b/test/acceptance/fields/datetime.js @@ -239,7 +239,7 @@ describe('DateTime Field', function () { if (err) return done(err) client - .get('/v1/library/event_unix_date?compose=true') + .get('/v1/library/event_unix_date?compose=true&cache=false') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end((err, res) => { @@ -293,12 +293,11 @@ describe('DateTime Field', function () { if (err) return done(err) client - .get('/v1/library/event_unix_date?compose=true') + .get('/v1/library/event_unix_date?compose=true&cache=false') .set('Authorization', 'Bearer ' + bearerToken) .expect(200) .end((err, res) => { if (err) return done(err) - should.exist(res.body.results) res.body.results.length.should.eql(1) res.body.results[0].datetime.should.eql(date) diff --git a/test/pretest.js b/test/pretest.js index 9668566e..e701c996 100644 --- a/test/pretest.js +++ b/test/pretest.js @@ -1,52 +1,58 @@ -var exec = require('child_process').exec -var fs = require('fs') -var path = require('path') -var colors = require('colors') +const exec = require('child_process').exec +const fs = require('fs') +const path = require('path') +const colors = require('colors') -var testConfigPath = './config/config.test.json' -var testConfigSamplePath = './config/config.test.json.sample' +const testConfigPath = './config/config.test.json' +const testConfigSamplePath = './config/config.test.json.sample' -var testConfigSample = fs.readFileSync(testConfigSamplePath, { encoding: 'utf-8'}).toString(); +const testConfigSample = fs.readFileSync(testConfigSamplePath, { encoding: 'utf-8'}).toString() -function loadConfig(done) { +let cleanup = function (dir) { + exec('rm -r ' + dir, (err, stdout, stderr) => { + exec('mkdir -p ' + dir) + }) +} +function loadConfig (done) { try { - var testConfig = fs.readFileSync(testConfigPath, { encoding: 'utf-8'}); + var testConfig = fs.readFileSync(testConfigPath, { encoding: 'utf-8'}) var conf = JSON.parse(testConfig) console.log('\n Running test suite using the in-memory test connector'.green) + cleanup(path.resolve(conf.caching.directory.path || './cache/api')) + return done(conf) - } - catch (err) { + } catch (err) { if (err.code === 'ENOENT') { - fs.writeFileSync(testConfigPath, testConfigSample); - console.log(); - console.log("Created file at '" + testConfigPath + "'"); - loadConfig(function(config) { - testDatabaseSetting(config); - }); + fs.writeFileSync(testConfigPath, testConfigSample) + console.log() + console.log("Created file at '" + testConfigPath + "'") + loadConfig(function (config) { + testDatabaseSetting(config) + }) } } } -function stop() { - process.exit(1); +function stop () { + process.exit(1) } -function testDatabaseSetting(config) { - var database = config.database.database; - var authDatabase = config.auth.database.database; +function testDatabaseSetting (config) { + var database = config.database.database + var authDatabase = config.auth.database.database if (database !== 'test' || authDatabase !== 'test') { - var message = '\nWARNING: The test suite requires the use of a `test` database. The databases for authentication and data can be configured in the file ' + testConfigPath + '.'; - console.log(message.bold.red); - console.log(''); - console.log('Tests will not be run with the current configuration.\n'.bold.red); - stop(); + var message = '\nWARNING: The test suite requires the use of a `test` database. The databases for authentication and data can be configured in the file ' + testConfigPath + '.' + console.log(message.bold.red) + console.log('') + console.log('Tests will not be run with the current configuration.\n'.bold.red) + stop() } } -loadConfig(function(config) { - testDatabaseSetting(config); -}); +loadConfig(config => { + testDatabaseSetting(config) +})