UNPKG

bastian

Version:

Handles partial cache misses, generically, using Redis as a cache store

237 lines (200 loc) 5.27 kB
var async = require('async'); var Redis = require('redis'); var test = require('tape'); var request = require('./helper/request-single.js'); var Bastian = require('../index.js'); test('get(): Normal successful usage', function(t) { var redis = Redis.createClient(); var cache = new Bastian(redis); cache.on('error', function(err) { t.error(err); }); redis.del([ 'TEST-cuisine-en-US-v4:1', 'TEST-cuisine-en-US-v4:2', 'TEST-cuisine-es-MX-v4:1', 'TEST-cuisine-es-MX-v4:2', ]); var testRun = 0; var cuisineService = { getItem: function(id, language, callback) { testRun += 1; const VERSION = 'v4'; cache.get({ keyPrefix: 'TEST-cuisine-' + language + '-' + VERSION, id: id, expiration: 60 * 60 * 24, handler: function(id, cb) { var options = { url: 'http://restaurant.api.opentable.com/' + VERSION + '/restaurants/?id=' + id, json: true, headers: { "Accept-Language": language } }; t.comment(options.url); if (testRun === 1) { t.equal(id, 1); } else if (testRun === 2) { t.equal(id, 2); } else if (testRun === 3) { t.equal(id, 1); } else if (testRun === 4) { t.error(new Error('should not execute as the data for this request is in cache')); } request(options, function(err, response, body) { if (err) { return cb(err); } if (response.statusCode > 299) { return cb(response.statusCode); } cb(null, body); }); } }, callback); } }; async.series([ function(callback) { cuisineService.getItem(1, 'en-US', function(err, data) { t.error(err, 'no error'); t.equal(data.id, 1); callback(err, data); }); }, function(callback) { cuisineService.getItem(2, 'en-US', function(err, data) { t.error(err, 'no error'); t.equal(data.id, 2); callback(err, data); }); }, function(callback) { cuisineService.getItem(1, 'es-MX', function(err, data) { t.error(err, 'no error'); t.equal(data.id, 1); callback(err, data); }); }, function(callback) { cuisineService.getItem(1, 'en-US', function(err, data) { t.error(err, 'no error'); t.equal(data.id, 1); callback(err, data); }); } ], function(err, result) { t.error(err, 'no error'); t.ok(result[0]); t.ok(result[1]); t.ok(result[2]); t.ok(result[3]); redis.quit(); t.end(err); }); }); test('get(): No redis, go directly to handler', function(t) { var cache = new Bastian(); cache.get({ keyPrefix: 'no-store', id: 1, handler: function(id, cb) { t.equal(id, 1); cb(null, id * 10); } }, function(err, data) { t.deepEqual(data, 10, 'received data'); t.end(err); }); }); test('get(): When handler fails, overall operation should fail', function(t) { var cache = new Bastian(); cache.get({ keyPrefix: 'no-store', id: 1, handler: function(id, cb) { cb(new Error('uh oh')); } }, function(err, data) { t.ok(err instanceof Error, 'end in error, no data in cache or handler'); t.end(); }); }); test('get(): When no ID is provided, operation should run normally', function(t) { var cache = new Bastian(); cache.get({ keyPrefix: 'no-data', handler: function(id, cb) { t.notOk(id); setImmediate(function() { cb(null, 'ok'); }); } }, function(err, data) { t.deepEqual(data, 'ok', 'asked for no id, received data'); t.end(err); }); }); test('get(): When Redis.GET fails, still run the handler', function(t) { var failureGetRedis = { get: function(data, cb) { setImmediate(function() { cb(new Error('mget failed')); }); } }; var cache = new Bastian(failureGetRedis); var didEmitError = false; cache.on('error', function(err) { didEmitError = true; t.ok(err, 'does have error'); }); cache.get({ keyPrefix: 'no-data', id: 100, handler: function(id, cb) { cb(null, 'good stuff'); } }, function(err, data) { t.ok(didEmitError, 'did emit error'); t.end(err); }); }); test('get(): With redis, no expiration', function(t) { var redis = Redis.createClient(); redis.del([ 'no-expire:1', ]); var cache = new Bastian(redis); cache.get({ keyPrefix: 'no-expire', id: 1, handler: function(id, cb) { t.equal(id, 1); cb(null, id * 10); } }, function(err, data) { t.deepEqual(data, 10, 'received data'); redis.quit(); t.end(err); }); }); test('get(): With redis, no id', function(t) { var redis = Redis.createClient(); redis.del([ 'no-expire', ]); var cache = new Bastian(redis); cache.get({ keyPrefix: 'no-expire', handler: function(id, cb) { t.equal(id, null, 'id should be null'); cb(null, 100); } }, function(err, data) { t.deepEqual(data, 100, 'received data'); redis.quit(); t.end(err); }); });