diff --git a/red/runtime/nodes/context/index.js b/red/runtime/nodes/context/index.js index cb61ca187..709945bf0 100644 --- a/red/runtime/nodes/context/index.js +++ b/red/runtime/nodes/context/index.js @@ -54,7 +54,10 @@ function logStore(name, module) { function init(_settings) { settings = _settings; + contexts = {}; stores = {}; + storeList = []; + hasConfiguredStore = false; var seed = settings.functionGlobalContext || {}; contexts['global'] = createContext("global",seed); stores["_"] = new memory(); diff --git a/test/red/api/admin/context_spec.js b/test/red/api/admin/context_spec.js index e8e8f17dd..3bf4ed543 100644 --- a/test/red/api/admin/context_spec.js +++ b/test/red/api/admin/context_spec.js @@ -22,6 +22,210 @@ var sinon = require('sinon'); var when = require('when'); var context = require("../../../../red/api/admin/context"); +var Context = require("../../../../red/runtime/nodes/context"); +var Util = require("../../../../red/runtime/util"); describe("api/admin/context", function() { + var app = undefined; + + before(function (done) { + var node_context = undefined; + app = express(); + app.use(bodyParser.json()); + app.get("/context/:scope(global)", context.get); + app.get("/context/:scope(global)/*", context.get); + app.get("/context/:scope(node|flow)/:id", context.get); + app.get("/context/:scope(node|flow)/:id/*", context.get); + + context.init({ + settings: { + }, + log:{warn:function(){},_:function(){},audit:function(){}}, + nodes: { + listContextStores: Context.listStores, + getContext: Context.get, + getNode: function(id) { + if (id === 'NID') { + return { + id: 'NID', + context: function () { + return node_context; + } + }; + } + return null; + } + }, + util: Util + }); + + Context.init({ + contextStorage: { + memory0: { + module: "memory" + }, + memory1: { + module: "memory" + } + } + }); + Context.load().then(function () { + var ctx = Context.get("NID", "FID"); + node_context = ctx; + ctx.set("foo", "n_v00", "memory0"); + ctx.set("bar", "n_v01", "memory0"); + ctx.set("baz", "n_v10", "memory1"); + ctx.set("bar", "n_v11", "memory1"); + ctx.flow.set("foo", "f_v00", "memory0"); + ctx.flow.set("bar", "f_v01", "memory0"); + ctx.flow.set("baz", "f_v10", "memory1"); + ctx.flow.set("bar", "f_v11", "memory1"); + ctx.global.set("foo", "g_v00", "memory0"); + ctx.global.set("bar", "g_v01", "memory0"); + ctx.global.set("baz", "g_v10", "memory1"); + ctx.global.set("bar", "g_v11", "memory1"); + done(); + }); + + }); + + after(function () { + Context.clean({allNodes:{}}); + Context.close(); + }); + + function check_mem(body, mem, name, val) { + var mem0 = body[mem]; + mem0.should.have.property(name); + mem0[name].should.deepEqual(val); + } + + function check_scope(scope, prefix, id) { + describe('# '+scope, function () { + var xid = id ? ("/"+id) : ""; + + it('should return '+scope+' contexts', function (done) { + request(app) + .get('/context/'+scope+xid) + .set('Accept', 'application/json') + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + var body = res.body; + body.should.have.key('memory0', 'memory1'); + check_mem(body, 'memory0', + 'foo', {msg:prefix+'_v00', format:'string[5]'}); + check_mem(body, 'memory0', + 'bar', {msg:prefix+'_v01', format:'string[5]'}); + check_mem(body, 'memory1', + 'baz', {msg:prefix+'_v10', format:'string[5]'}); + check_mem(body, 'memory1', + 'bar', {msg:prefix+'_v11', format:'string[5]'}); + done(); + }); + }); + + it('should return a value from default '+scope+' context', function (done) { + request(app) + .get('/context/'+scope+xid+'/foo') + .set('Accept', 'application/json') + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + var body = res.body; + body.should.deepEqual({msg: prefix+'_v00', format: 'string[5]'}); + done(); + }); + }); + + it('should return a value from specified '+scope+' context', function (done) { + request(app) + .get('/context/'+scope+xid+'/bar?store=memory1') + .set('Accept', 'application/json') + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + var body = res.body; + body.should.deepEqual({msg: prefix+'_v11', format: 'string[5]', store: 'memory1'}); + done(); + }); + }); + + it('should return specified '+scope+' store', function (done) { + request(app) + .get('/context/'+scope+xid+'?store=memory1') + .set('Accept', 'application/json') + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + var body = res.body; + body.should.deepEqual({ + memory1: { + baz: { msg: prefix+'_v10', format: 'string[5]' }, + bar: { msg: prefix+'_v11', format: 'string[5]' } + } + }); + done(); + }); + }); + + it('should return undefined for unknown key of default '+scope+' store', function (done) { + request(app) + .get('/context/'+scope+xid+'/unknown') + .set('Accept', 'application/json') + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + var body = res.body; + body.should.deepEqual({msg:'(undefined)', format:'undefined'}); + done(); + + }); + }); + + it('should cause error for unknown '+scope+' store', function (done) { + request(app) + .get('/context/'+scope+xid+'?store=unknown') + .set('Accept', 'application/json') + .expect(200) + .end(function (err, res) { + if (err) { + return done(); + } + done("unexpected"); + }); + }); + }); + } + + check_scope("global", "g", undefined); + check_scope("node", "n", "NID"); + check_scope("flow", "f", "FID"); + + describe("# errors", function () { + it('should cause error for unknown scope', function (done) { + request(app) + .get('/context/scope') + .set('Accept', 'application/json') + .expect(200) + .end(function (err, res) { + if (err) { + return done(); + } + done("unexpected"); + }); + }); + + }); + });