mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'master' into runtime-api
This commit is contained in:
231
test/red/api/admin/context_spec.js
Normal file
231
test/red/api/admin/context_spec.js
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var request = require('supertest');
|
||||
var express = require('express');
|
||||
var bodyParser = require('body-parser');
|
||||
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");
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
@@ -20,8 +20,7 @@ var express = require('express');
|
||||
var sinon = require('sinon');
|
||||
|
||||
var locales = require("../../../../red/api/editor/locales");
|
||||
var i18n = require("../../../../red/util/i18n");
|
||||
|
||||
var i18n = require("../../../../red/util").i18n;
|
||||
|
||||
describe("api/editor/locales", function() {
|
||||
beforeEach(function() {
|
||||
@@ -31,18 +30,39 @@ describe("api/editor/locales", function() {
|
||||
describe('get named resource catalog',function() {
|
||||
var app;
|
||||
before(function() {
|
||||
// bit of a mess of internal workings
|
||||
// locales.init({
|
||||
// i18n: {
|
||||
// i: {
|
||||
// language: function() { return 'en-US'},
|
||||
// changeLanguage: function(lang,callback) {
|
||||
// if (callback) {
|
||||
// callback();
|
||||
// }
|
||||
// },
|
||||
// getResourceBundle: function(lang, namespace) {
|
||||
// return {namespace:namespace, lang:lang};
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// });
|
||||
locales.init({});
|
||||
sinon.stub(i18n.i,'lng',function() { return 'en-US'});
|
||||
sinon.stub(i18n.i,'setLng',function(lang,callback) { if (callback) {callback();}});
|
||||
sinon.stub(i18n,'catalog',function(namespace, lang) {return {namespace:namespace, lang:lang};});
|
||||
|
||||
// bit of a mess of internal workings
|
||||
sinon.stub(i18n.i,'changeLanguage',function(lang,callback) { if (callback) {callback();}});
|
||||
if (i18n.i.getResourceBundle) {
|
||||
sinon.stub(i18n.i,'getResourceBundle',function(lang, namespace) {return {namespace:namespace, lang:lang};});
|
||||
} else {
|
||||
// If i18n.init has not been called, then getResourceBundle isn't
|
||||
// defined - so hardcode a stub
|
||||
i18n.i.getResourceBundle = function(lang, namespace) {return {namespace:namespace, lang:lang};};
|
||||
i18n.i.getResourceBundle.restore = function() { delete i18n.i.getResourceBundle };
|
||||
}
|
||||
app = express();
|
||||
app.get(/locales\/(.+)\/?$/,locales.get);
|
||||
});
|
||||
after(function() {
|
||||
i18n.i.lng.restore();
|
||||
i18n.i.setLng.restore();
|
||||
i18n.catalog.restore();
|
||||
i18n.i.changeLanguage.restore();
|
||||
i18n.i.getResourceBundle.restore();
|
||||
})
|
||||
it('returns with default language', function(done) {
|
||||
request(app)
|
||||
|
20
test/red/runtime-api/context_spec.js
Normal file
20
test/red/runtime-api/context_spec.js
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
describe("runtime-api/context", function() {
|
||||
|
||||
|
||||
});
|
@@ -165,7 +165,7 @@ describe('nodes/registry/installer', function() {
|
||||
});
|
||||
});
|
||||
it("rejects when non-existant path is provided", function(done) {
|
||||
this.timeout(10000);
|
||||
this.timeout(20000);
|
||||
var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","NonExistant"));
|
||||
installer.installModule(resourcesDir).then(function() {
|
||||
done(new Error("Unexpected success"));
|
||||
|
@@ -89,6 +89,8 @@ describe("runtime", function() {
|
||||
var redNodesGetNodeList;
|
||||
var redNodesLoadFlows;
|
||||
var redNodesStartFlows;
|
||||
var redNodesLoadContextsPlugin;
|
||||
|
||||
beforeEach(function() {
|
||||
storageInit = sinon.stub(storage,"init",function(settings) {return Promise.resolve();});
|
||||
redNodesInit = sinon.stub(redNodes,"init", function() {});
|
||||
@@ -96,6 +98,7 @@ describe("runtime", function() {
|
||||
redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList",function(){});
|
||||
redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return Promise.resolve()});
|
||||
redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {});
|
||||
redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin",function() {return Promise.resolve()});
|
||||
});
|
||||
afterEach(function() {
|
||||
storageInit.restore();
|
||||
@@ -105,6 +108,7 @@ describe("runtime", function() {
|
||||
redNodesCleanModuleList.restore();
|
||||
redNodesLoadFlows.restore();
|
||||
redNodesStartFlows.restore();
|
||||
redNodesLoadContextsPlugin.restore();
|
||||
});
|
||||
it("reports errored/missing modules",function(done) {
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
||||
@@ -187,7 +191,7 @@ describe("runtime", function() {
|
||||
});
|
||||
|
||||
it("reports runtime metrics",function(done) {
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} );
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return Promise.resolve();} );
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []});
|
||||
var util = mockUtil(true);
|
||||
runtime.init({testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util);
|
||||
@@ -214,10 +218,19 @@ describe("runtime", function() {
|
||||
|
||||
});
|
||||
|
||||
it("stops components", function() {
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} );
|
||||
runtime.stop();
|
||||
stopFlows.called.should.be.true();
|
||||
stopFlows.restore();
|
||||
it("stops components", function(done) {
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return Promise.resolve();} );
|
||||
var closeContextsPlugin = sinon.stub(redNodes,"closeContextsPlugin",function() { return Promise.resolve();} );
|
||||
runtime.stop().then(function(){
|
||||
stopFlows.called.should.be.true();
|
||||
closeContextsPlugin.called.should.be.true();
|
||||
stopFlows.restore();
|
||||
closeContextsPlugin.restore();
|
||||
done();
|
||||
}).catch(function(err){
|
||||
stopFlows.restore();
|
||||
closeContextsPlugin.restore();
|
||||
return done(err)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
897
test/red/runtime/nodes/context/index_spec.js
Normal file
897
test/red/runtime/nodes/context/index_spec.js
Normal file
@@ -0,0 +1,897 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require('sinon');
|
||||
var path = require("path");
|
||||
var Context = require("../../../../../red/runtime/nodes/context/index");
|
||||
|
||||
describe('context', function() {
|
||||
describe('local memory',function() {
|
||||
beforeEach(function() {
|
||||
Context.init({});
|
||||
Context.load();
|
||||
});
|
||||
afterEach(function() {
|
||||
Context.clean({allNodes:{}});
|
||||
return Context.close();
|
||||
});
|
||||
it('stores local property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
should.not.exist(context1.get("foo"));
|
||||
context1.set("foo","test");
|
||||
context1.get("foo").should.equal("test");
|
||||
});
|
||||
it('stores local property - creates parent properties',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
context1.set("foo.bar","test");
|
||||
context1.get("foo").should.eql({bar:"test"});
|
||||
});
|
||||
it('deletes local property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
context1.set("foo.abc.bar1","test1");
|
||||
context1.set("foo.abc.bar2","test2");
|
||||
context1.get("foo.abc").should.eql({bar1:"test1",bar2:"test2"});
|
||||
context1.set("foo.abc.bar1",undefined);
|
||||
context1.get("foo.abc").should.eql({bar2:"test2"});
|
||||
context1.set("foo.abc",undefined);
|
||||
should.not.exist(context1.get("foo.abc"));
|
||||
context1.set("foo",undefined);
|
||||
should.not.exist(context1.get("foo"));
|
||||
});
|
||||
it('stores flow property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
should.not.exist(context1.flow.get("foo"));
|
||||
context1.flow.set("foo","test");
|
||||
context1.flow.get("foo").should.equal("test");
|
||||
});
|
||||
it('stores global property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
should.not.exist(context1.global.get("foo"));
|
||||
context1.global.set("foo","test");
|
||||
context1.global.get("foo").should.equal("test");
|
||||
});
|
||||
|
||||
it('keeps local context local', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowA");
|
||||
|
||||
should.not.exist(context1.get("foo"));
|
||||
should.not.exist(context2.get("foo"));
|
||||
context1.set("foo","test");
|
||||
|
||||
context1.get("foo").should.equal("test");
|
||||
should.not.exist(context2.get("foo"));
|
||||
});
|
||||
it('flow context accessible to all flow nodes', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowA");
|
||||
|
||||
should.not.exist(context1.flow.get("foo"));
|
||||
should.not.exist(context2.flow.get("foo"));
|
||||
|
||||
context1.flow.set("foo","test");
|
||||
context1.flow.get("foo").should.equal("test");
|
||||
context2.flow.get("foo").should.equal("test");
|
||||
});
|
||||
|
||||
it('flow context not shared to nodes on other flows', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowB");
|
||||
|
||||
should.not.exist(context1.flow.get("foo"));
|
||||
should.not.exist(context2.flow.get("foo"));
|
||||
|
||||
context1.flow.set("foo","test");
|
||||
context1.flow.get("foo").should.equal("test");
|
||||
should.not.exist(context2.flow.get("foo"));
|
||||
});
|
||||
|
||||
it('global context shared to all nodes', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowB");
|
||||
|
||||
should.not.exist(context1.global.get("foo"));
|
||||
should.not.exist(context2.global.get("foo"));
|
||||
|
||||
context1.global.set("foo","test");
|
||||
context1.global.get("foo").should.equal("test");
|
||||
context2.global.get("foo").should.equal("test");
|
||||
});
|
||||
|
||||
it('deletes context',function() {
|
||||
var context = Context.get("1","flowA");
|
||||
should.not.exist(context.get("foo"));
|
||||
context.set("foo","abc");
|
||||
context.get("foo").should.equal("abc");
|
||||
|
||||
return Context.delete("1","flowA").then(function(){
|
||||
context = Context.get("1","flowA");
|
||||
should.not.exist(context.get("foo"));
|
||||
});
|
||||
});
|
||||
|
||||
it('enumerates context keys - sync', function() {
|
||||
var context = Context.get("1","flowA");
|
||||
|
||||
var keys = context.keys();
|
||||
keys.should.be.an.Array();
|
||||
keys.should.be.empty();
|
||||
|
||||
context.set("foo","bar");
|
||||
keys = context.keys();
|
||||
keys.should.have.length(1);
|
||||
keys[0].should.equal("foo");
|
||||
|
||||
context.set("abc.def","bar");
|
||||
keys = context.keys();
|
||||
keys.should.have.length(2);
|
||||
keys[1].should.equal("abc");
|
||||
});
|
||||
|
||||
it('enumerates context keys - async', function(done) {
|
||||
var context = Context.get("1","flowA");
|
||||
|
||||
var keys = context.keys(function(err,keys) {
|
||||
keys.should.be.an.Array();
|
||||
keys.should.be.empty();
|
||||
context.set("foo","bar");
|
||||
keys = context.keys(function(err,keys) {
|
||||
keys.should.have.length(1);
|
||||
keys[0].should.equal("foo");
|
||||
|
||||
context.set("abc.def","bar");
|
||||
keys = context.keys(function(err,keys) {
|
||||
keys.should.have.length(2);
|
||||
keys[1].should.equal("abc");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should enumerate only context keys when GlobalContext was given - sync', function() {
|
||||
Context.init({functionGlobalContext: {foo:"bar"}});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flowA");
|
||||
context.global.set("foo2","bar2");
|
||||
var keys = context.global.keys();
|
||||
keys.should.have.length(2);
|
||||
keys[0].should.equal("foo");
|
||||
keys[1].should.equal("foo2");
|
||||
});
|
||||
});
|
||||
|
||||
it('should enumerate only context keys when GlobalContext was given - async', function(done) {
|
||||
Context.init({functionGlobalContext: {foo:"bar"}});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flowA");
|
||||
context.global.set("foo2","bar2");
|
||||
context.global.keys(function(err,keys) {
|
||||
keys.should.have.length(2);
|
||||
keys[0].should.equal("foo");
|
||||
keys[1].should.equal("foo2");
|
||||
done();
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
|
||||
|
||||
it('returns functionGlobalContext value if store value undefined', function() {
|
||||
Context.init({functionGlobalContext: {foo:"bar"}});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flowA");
|
||||
var v = context.global.get('foo');
|
||||
v.should.equal('bar');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('external context storage',function() {
|
||||
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
|
||||
var sandbox = sinon.sandbox.create();
|
||||
var stubGet = sandbox.stub();
|
||||
var stubSet = sandbox.stub();
|
||||
var stubKeys = sandbox.stub();
|
||||
var stubDelete = sandbox.stub().returns(Promise.resolve());
|
||||
var stubClean = sandbox.stub().returns(Promise.resolve());
|
||||
var stubOpen = sandbox.stub().returns(Promise.resolve());
|
||||
var stubClose = sandbox.stub().returns(Promise.resolve());
|
||||
var stubGet2 = sandbox.stub();
|
||||
var stubSet2 = sandbox.stub();
|
||||
var stubKeys2 = sandbox.stub();
|
||||
var stubDelete2 = sandbox.stub().returns(Promise.resolve());
|
||||
var stubClean2 = sandbox.stub().returns(Promise.resolve());
|
||||
var stubOpen2 = sandbox.stub().returns(Promise.resolve());
|
||||
var stubClose2 = sandbox.stub().returns(Promise.resolve());
|
||||
var testPlugin = function(config){
|
||||
function Test(){}
|
||||
Test.prototype.get = stubGet;
|
||||
Test.prototype.set = stubSet;
|
||||
Test.prototype.keys = stubKeys;
|
||||
Test.prototype.delete = stubDelete;
|
||||
Test.prototype.clean = stubClean;
|
||||
Test.prototype.open = stubOpen;
|
||||
Test.prototype.close = stubClose;
|
||||
return new Test(config);
|
||||
};
|
||||
var testPlugin2 = function(config){
|
||||
function Test2(){}
|
||||
Test2.prototype.get = stubGet2;
|
||||
Test2.prototype.set = stubSet2;
|
||||
Test2.prototype.keys = stubKeys2;
|
||||
Test2.prototype.delete = stubDelete2;
|
||||
Test2.prototype.clean = stubClean2;
|
||||
Test2.prototype.open = stubOpen2;
|
||||
Test2.prototype.close = stubClose2;
|
||||
return new Test2(config);
|
||||
};
|
||||
var contextStorage={
|
||||
test:{
|
||||
module: testPlugin,
|
||||
config:{}
|
||||
}
|
||||
};
|
||||
var contextDefaultStorage={
|
||||
default: {
|
||||
module: testPlugin2,
|
||||
config:{}
|
||||
},
|
||||
test:{
|
||||
module: testPlugin,
|
||||
config:{}
|
||||
}
|
||||
};
|
||||
var contextAlias={
|
||||
default: "test",
|
||||
test:{
|
||||
module: testPlugin,
|
||||
config:{}
|
||||
}
|
||||
};
|
||||
var memoryStorage ={
|
||||
memory:{
|
||||
module: "memory"
|
||||
}
|
||||
};
|
||||
|
||||
afterEach(function() {
|
||||
sandbox.reset();
|
||||
return Context.clean({allNodes:{}}).then(function(){
|
||||
return Context.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('load modules',function(){
|
||||
it('should call open()', function() {
|
||||
Context.init({contextStorage:contextDefaultStorage});
|
||||
Context.load().then(function(){
|
||||
stubOpen.called.should.be.true();
|
||||
stubOpen2.called.should.be.true();
|
||||
});
|
||||
});
|
||||
it('should load memory module', function() {
|
||||
Context.init({contextStorage:{memory:{module:"memory"}}});
|
||||
Context.load();
|
||||
});
|
||||
it('should load localfilesystem module', function() {
|
||||
Context.init({contextStorage:{file:{module:"localfilesystem",config:{dir:resourcesDir}}}});
|
||||
Context.load();
|
||||
});
|
||||
it('should ignore reserved storage name `_`', function(done) {
|
||||
Context.init({contextStorage:{_:{module:testPlugin}}});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){}
|
||||
context.set("foo","bar","_",cb);
|
||||
context.get("foo","_",cb);
|
||||
context.keys("_",cb);
|
||||
stubSet.called.should.be.false();
|
||||
stubGet.called.should.be.false();
|
||||
stubKeys.called.should.be.false();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('should fail when using invalid store name', function(done) {
|
||||
Context.init({contextStorage:{'Invalid name':{module:testPlugin}}});
|
||||
Context.load().then(function(){
|
||||
done("An error was not thrown");
|
||||
}).catch(function(){
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should fail when using invalid sign character', function (done) {
|
||||
Context.init({ contextStorage:{'abc-123':{module:testPlugin}}});
|
||||
Context.load().then(function () {
|
||||
done("An error was not thrown");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should fail when using invalid default context', function(done) {
|
||||
Context.init({contextStorage:{default:"noexist"}});
|
||||
Context.load().then(function(){
|
||||
done("An error was not thrown");
|
||||
}).catch(function(){
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should fail for the storage with no module', function(done) {
|
||||
Context.init({ contextStorage: { test: {}}});
|
||||
Context.load().then(function(){
|
||||
done("An error was not thrown");
|
||||
}).catch(function(){
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should fail to load non-existent module', function(done) {
|
||||
Context.init({contextStorage:{ file:{module:"nonexistent"} }});
|
||||
Context.load().then(function(){
|
||||
done("An error was not thrown");
|
||||
}).catch(function(){
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should fail to load invalid module', function (done) {
|
||||
Context.init({contextStorage: {
|
||||
test: {
|
||||
module: function (config) {
|
||||
throw new Error("invalid plugin was loaded.");
|
||||
}
|
||||
}
|
||||
}});
|
||||
Context.load().then(function () {
|
||||
done("An error was not thrown");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('close modules',function(){
|
||||
it('should call close()', function(done) {
|
||||
Context.init({contextStorage:contextDefaultStorage});
|
||||
Context.load().then(function(){
|
||||
return Context.close().then(function(){
|
||||
stubClose.called.should.be.true();
|
||||
stubClose2.called.should.be.true();
|
||||
done();
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('store context',function() {
|
||||
it('should store local property to external context storage',function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
var cb = function(){done("An error occurred")}
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set("foo","bar","test",cb);
|
||||
context.get("foo","test",cb);
|
||||
context.keys("test",cb);
|
||||
stubSet.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
|
||||
stubGet.calledWith("1:flow","foo").should.be.true();
|
||||
stubKeys.calledWithExactly("1:flow",cb).should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should store flow property to external context storage',function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.flow.set("foo","bar","test",cb);
|
||||
context.flow.get("foo","test",cb);
|
||||
context.flow.keys("test",cb);
|
||||
stubSet.calledWithExactly("flow","foo","bar",cb).should.be.true();
|
||||
stubGet.calledWith("flow","foo").should.be.true();
|
||||
stubKeys.calledWithExactly("flow",cb).should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should store global property to external context storage',function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.global.set("foo","bar","test",cb);
|
||||
context.global.get("foo","test",cb);
|
||||
context.global.keys("test",cb);
|
||||
stubSet.calledWithExactly("global","foo","bar",cb).should.be.true();
|
||||
stubGet.calledWith("global","foo").should.be.true();
|
||||
stubKeys.calledWith("global").should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should store data to the default context when non-existent context storage was specified', function(done) {
|
||||
Context.init({contextStorage:contextDefaultStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.set("foo","bar","nonexist",cb);
|
||||
context.get("foo","nonexist",cb);
|
||||
context.keys("nonexist",cb);
|
||||
stubGet.called.should.be.false();
|
||||
stubSet.called.should.be.false();
|
||||
stubKeys.called.should.be.false();
|
||||
stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
|
||||
stubGet2.calledWith("1:flow","foo").should.be.true();
|
||||
stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should use the default context', function(done) {
|
||||
Context.init({contextStorage:contextDefaultStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.set("foo","bar","default",cb);
|
||||
context.get("foo","default",cb);
|
||||
context.keys("default",cb);
|
||||
stubGet.called.should.be.false();
|
||||
stubSet.called.should.be.false();
|
||||
stubKeys.called.should.be.false();
|
||||
stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
|
||||
stubGet2.calledWith("1:flow","foo").should.be.true();
|
||||
stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should use the alias of default context', function(done) {
|
||||
Context.init({contextStorage:contextDefaultStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.set("foo","alias",cb);
|
||||
context.get("foo",cb);
|
||||
context.keys(cb);
|
||||
stubGet.called.should.be.false();
|
||||
stubSet.called.should.be.false();
|
||||
stubKeys.called.should.be.false();
|
||||
stubSet2.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
|
||||
stubGet2.calledWith("1:flow","foo").should.be.true();
|
||||
stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should use default as the alias of other context', function(done) {
|
||||
Context.init({contextStorage:contextAlias});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.set("foo","alias",cb);
|
||||
context.get("foo",cb);
|
||||
context.keys(cb);
|
||||
stubSet.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
|
||||
stubGet.calledWith("1:flow","foo").should.be.true();
|
||||
stubKeys.calledWithExactly("1:flow",cb).should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should not throw an error using undefined storage for local context', function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.get("local","nonexist",cb);
|
||||
done()
|
||||
}).catch(done);
|
||||
});
|
||||
it('should throw an error using undefined storage for flow context', function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
var cb = function(){done("An error occurred")}
|
||||
context.flow.get("flow","nonexist",cb);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('should return functionGlobalContext value as a default - synchronous', function(done) {
|
||||
var fGC = { "foo": 456 };
|
||||
Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
|
||||
Context.load().then(function() {
|
||||
var context = Context.get("1","flow");
|
||||
// Get foo - should be value from fGC
|
||||
var v = context.global.get("foo");
|
||||
v.should.equal(456);
|
||||
|
||||
// Update foo - should not touch fGC object
|
||||
context.global.set("foo","new value");
|
||||
fGC.foo.should.equal(456);
|
||||
|
||||
// Get foo - should be the updated value
|
||||
v = context.global.get("foo");
|
||||
v.should.equal("new value");
|
||||
done();
|
||||
}).catch(done);
|
||||
})
|
||||
|
||||
it('should return functionGlobalContext value as a default - async', function(done) {
|
||||
var fGC = { "foo": 456 };
|
||||
Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
|
||||
Context.load().then(function() {
|
||||
var context = Context.get("1","flow");
|
||||
// Get foo - should be value from fGC
|
||||
context.global.get("foo", function(err, v) {
|
||||
if (err) {
|
||||
done(err)
|
||||
} else {
|
||||
v.should.equal(456);
|
||||
// Update foo - should not touch fGC object
|
||||
context.global.set("foo","new value", function(err) {
|
||||
if (err) {
|
||||
done(err)
|
||||
} else {
|
||||
fGC.foo.should.equal(456);
|
||||
// Get foo - should be the updated value
|
||||
context.global.get("foo", function(err, v) {
|
||||
if (err) {
|
||||
done(err)
|
||||
} else {
|
||||
v.should.equal("new value");
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}).catch(done);
|
||||
})
|
||||
|
||||
it('should return multiple values if key is an array', function(done) {
|
||||
Context.init({contextStorage:memoryStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set("foo1","bar1","memory");
|
||||
context.set("foo2","bar2","memory");
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
foo1.should.be.equal("bar1");
|
||||
foo2.should.be.equal("bar2");
|
||||
should.not.exist(foo3);
|
||||
done();
|
||||
}
|
||||
});
|
||||
}).catch(function(err){ done(err); });
|
||||
});
|
||||
|
||||
it('should return multiple functionGlobalContext values if key is an array', function(done) {
|
||||
var fGC = { "foo1": 456, "foo2": 789 };
|
||||
Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.global.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
foo1.should.be.equal(456);
|
||||
foo2.should.be.equal(789);
|
||||
should.not.exist(foo3);
|
||||
done();
|
||||
}
|
||||
});
|
||||
}).catch(function(err){ done(err); });
|
||||
});
|
||||
|
||||
it('should return an error if an error occurs in getting multiple store values', function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
stubGet.onFirstCall().callsArgWith(2, "error2", "bar1");
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.global.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err === "error2") {
|
||||
done();
|
||||
} else {
|
||||
done("An error occurred");
|
||||
}
|
||||
});
|
||||
}).catch(function(err){ done(err); });
|
||||
});
|
||||
|
||||
it('should return a first error if some errors occur in getting multiple store values', function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
stubGet.onFirstCall().callsArgWith(2, "error1");
|
||||
stubGet.onSecondCall().callsArgWith(2, null, "bar2");
|
||||
stubGet.onThirdCall().callsArgWith(2, "error3");
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err === "error1") {
|
||||
done();
|
||||
} else {
|
||||
done("An error occurred");
|
||||
}
|
||||
});
|
||||
}).catch(function(err){ done(err); });
|
||||
});
|
||||
|
||||
it('should store multiple properties if key and value are arrays', function(done) {
|
||||
Context.init({contextStorage:memoryStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
foo1.should.be.equal("bar1");
|
||||
foo2.should.be.equal("bar2");
|
||||
foo3.should.be.equal("bar3");
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should deletes multiple properties', function(done) {
|
||||
Context.init({contextStorage:memoryStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
foo1.should.be.equal("bar1");
|
||||
foo2.should.be.equal("bar2");
|
||||
foo3.should.be.equal("bar3");
|
||||
context.set(["foo1","foo2","foo3"], new Array(3), "memory", function(err){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
should.not.exist(foo1);
|
||||
should.not.exist(foo2);
|
||||
should.not.exist(foo3);
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should use null for missing values if the value array is shorter than the key array', function(done) {
|
||||
Context.init({contextStorage:memoryStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set(["foo1","foo2","foo3"], ["bar1","bar2"], "memory", function(err){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
context.keys(function(err, keys){
|
||||
keys.should.have.length(3);
|
||||
keys.should.eql(["foo1","foo2","foo3"]);
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
foo1.should.be.equal("bar1");
|
||||
foo2.should.be.equal("bar2");
|
||||
should(foo3).be.null();
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should use null for missing values if the value is not array', function(done) {
|
||||
Context.init({contextStorage:memoryStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set(["foo1","foo2","foo3"], "bar1", "memory", function(err){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
context.keys(function(err, keys){
|
||||
keys.should.have.length(3);
|
||||
keys.should.eql(["foo1","foo2","foo3"]);
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
foo1.should.be.equal("bar1");
|
||||
should(foo2).be.null();
|
||||
should(foo3).be.null();
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should ignore the extra values if the value array is longer than the key array', function(done) {
|
||||
Context.init({contextStorage:memoryStorage});
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3","ignored"], "memory", function(err){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
context.keys(function(err, keys){
|
||||
keys.should.have.length(3);
|
||||
keys.should.eql(["foo1","foo2","foo3"]);
|
||||
context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
|
||||
if (err) {
|
||||
done(err);
|
||||
} else {
|
||||
foo1.should.be.equal("bar1");
|
||||
foo2.should.be.equal("bar2");
|
||||
foo3.should.be.equal("bar3");
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an error if an error occurs in storing multiple values', function(done) {
|
||||
Context.init({contextStorage:contextStorage});
|
||||
stubSet.onFirstCall().callsArgWith(3, "error2");
|
||||
Context.load().then(function(){
|
||||
var context = Context.get("1","flow");
|
||||
context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
|
||||
if (err === "error2") {
|
||||
done();
|
||||
} else {
|
||||
done("An error occurred");
|
||||
}
|
||||
});
|
||||
}).catch(function(err){ done(err); });
|
||||
});
|
||||
|
||||
it('should throw an error if callback of context.get is not a function', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get("foo", "memory", "callback");
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not throw an error if callback of context.get is not specified', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get("foo", "memory");
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('should throw an error if callback of context.set is not a function', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set("foo", "bar", "memory", "callback");
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not throw an error if callback of context.set is not specified', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set("foo", "bar", "memory");
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('should throw an error if callback of context.keys is not a function', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.keys("memory", "callback");
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not throw an error if callback of context.keys is not specified', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.keys("memory");
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('listStores', function () {
|
||||
it('should list context storages', function (done) {
|
||||
Context.init({ contextStorage: contextDefaultStorage });
|
||||
Context.load().then(function () {
|
||||
var list = Context.listStores();
|
||||
list.default.should.equal("default");
|
||||
list.stores.should.eql(["default", "test"]);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('should list context storages without default storage', function (done) {
|
||||
Context.init({ contextStorage: contextStorage });
|
||||
Context.load().then(function () {
|
||||
var list = Context.listStores();
|
||||
list.default.should.equal("test");
|
||||
list.stores.should.eql(["test"]);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete context',function(){
|
||||
it('should not call delete() when external context storage is used', function(done) {
|
||||
Context.init({contextStorage:contextDefaultStorage});
|
||||
Context.load().then(function(){
|
||||
Context.get("flowA");
|
||||
return Context.delete("flowA").then(function(){
|
||||
stubDelete.called.should.be.false();
|
||||
stubDelete2.called.should.be.false();
|
||||
done();
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clean context',function(){
|
||||
it('should call clean()', function(done) {
|
||||
Context.init({contextStorage:contextDefaultStorage});
|
||||
Context.load().then(function(){
|
||||
return Context.clean({allNodes:{}}).then(function(){
|
||||
stubClean.calledWithExactly([]).should.be.true();
|
||||
stubClean2.calledWithExactly([]).should.be.true();
|
||||
done();
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
774
test/red/runtime/nodes/context/localfilesystem_spec.js
Normal file
774
test/red/runtime/nodes/context/localfilesystem_spec.js
Normal file
@@ -0,0 +1,774 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require('should');
|
||||
var fs = require('fs-extra');
|
||||
var path = require("path");
|
||||
var LocalFileSystem = require('../../../../../red/runtime/nodes/context/localfilesystem');
|
||||
|
||||
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
|
||||
|
||||
describe('localfilesystem',function() {
|
||||
var context;
|
||||
|
||||
before(function() {
|
||||
return fs.remove(resourcesDir);
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
context = LocalFileSystem({dir: resourcesDir, cache: false});
|
||||
return context.open();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
return context.clean([]).then(function(){
|
||||
return context.close().then(function(){
|
||||
return fs.remove(resourcesDir);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#get/set',function() {
|
||||
it('should store property',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo","test",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.equal("test");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store property - creates parent properties',function(done) {
|
||||
context.set("nodeX","foo.bar","test",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.eql({bar:"test"});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store local scope property', function (done) {
|
||||
context.set("abc:def", "foo.bar", "test", function (err) {
|
||||
context.get("abc:def", "foo", function (err, value) {
|
||||
value.should.be.eql({ bar: "test" });
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete property',function(done) {
|
||||
context.set("nodeX","foo.abc.bar1","test1",function(err){
|
||||
context.set("nodeX","foo.abc.bar2","test2",function(err){
|
||||
context.get("nodeX","foo.abc",function(err, value){
|
||||
value.should.be.eql({bar1:"test1",bar2:"test2"});
|
||||
context.set("nodeX","foo.abc.bar1",undefined,function(err){
|
||||
context.get("nodeX","foo.abc",function(err, value){
|
||||
value.should.be.eql({bar2:"test2"});
|
||||
context.set("nodeX","foo.abc",undefined,function(err){
|
||||
context.get("nodeX","foo.abc",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",undefined,function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not shared context with other scope', function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo","testX",function(err){
|
||||
context.set("nodeY","foo","testY",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.equal("testX");
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
value.should.be.equal("testY");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store string',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo","bar",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.String();
|
||||
value.should.be.equal("bar");
|
||||
context.set("nodeX","foo","1",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.String();
|
||||
value.should.be.equal("1");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store number',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",1,function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.Number();
|
||||
value.should.be.equal(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store null',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",null,function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should(value).be.null();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store boolean',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",true,function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.Boolean().and.true();
|
||||
context.set("nodeX","foo",false,function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.Boolean().and.false();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store object',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",{obj:"bar"},function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.Object();
|
||||
value.should.eql({obj:"bar"});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store array',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",["a","b","c"],function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.Array();
|
||||
value.should.eql(["a","b","c"]);
|
||||
context.get("nodeX","foo[1]",function(err, value){
|
||||
value.should.be.String();
|
||||
value.should.equal("b");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store array of arrays',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",[["a","b","c"],[1,2,3,4],[true,false]],function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.Array();
|
||||
value.should.have.length(3);
|
||||
value[0].should.have.length(3);
|
||||
value[1].should.have.length(4);
|
||||
value[2].should.have.length(2);
|
||||
context.get("nodeX","foo[1]",function(err, value){
|
||||
value.should.be.Array();
|
||||
value.should.have.length(4);
|
||||
value.should.be.eql([1,2,3,4]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should store array of objects',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo",[{obj:"bar1"},{obj:"bar2"},{obj:"bar3"}],function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.Array();
|
||||
value.should.have.length(3);
|
||||
value[0].should.be.Object();
|
||||
value[1].should.be.Object();
|
||||
value[2].should.be.Object();
|
||||
context.get("nodeX","foo[1]",function(err, value){
|
||||
value.should.be.Object();
|
||||
value.should.be.eql({obj:"bar2"});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should set/get multiple values', function(done) {
|
||||
context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
|
||||
context.get("nodeX",["one","two"], function() {
|
||||
Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2"])
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
it('should set/get multiple values - get unknown', function(done) {
|
||||
context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
|
||||
context.get("nodeX",["one","two","unknown"], function() {
|
||||
Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2",undefined])
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
it('should set/get multiple values - single value providd', function(done) {
|
||||
context.set("nodeX",["one","two","three"],"test1", function(err) {
|
||||
context.get("nodeX",["one","two"], function() {
|
||||
Array.prototype.slice.apply(arguments).should.eql([undefined,"test1",null])
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
it('should throw error if bad key included in multiple keys - get', function(done) {
|
||||
context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
|
||||
context.get("nodeX",["one",".foo","three"], function(err) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
it('should throw error if bad key included in multiple keys - set', function(done) {
|
||||
context.set("nodeX",["one",".foo","three"],["test1","test2","test3"], function(err) {
|
||||
should.exist(err);
|
||||
// Check 'one' didn't get set as a result
|
||||
context.get("nodeX","one",function(err,one) {
|
||||
should.not.exist(one);
|
||||
done();
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
it('should throw an error when getting a value with invalid key', function (done) {
|
||||
context.set("nodeX","foo","bar",function(err) {
|
||||
context.get("nodeX"," ",function(err,value) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error when setting a value with invalid key',function (done) {
|
||||
context.set("nodeX"," ","bar",function (err) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error when callback of get() is not a function',function (done) {
|
||||
try {
|
||||
context.get("nodeX","foo","callback");
|
||||
done("should throw an error.");
|
||||
} catch (err) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error when callback of get() is not specified',function (done) {
|
||||
try {
|
||||
context.get("nodeX","foo");
|
||||
done("should throw an error.");
|
||||
} catch (err) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error when callback of set() is not a function',function (done) {
|
||||
try {
|
||||
context.set("nodeX","foo","bar","callback");
|
||||
done("should throw an error.");
|
||||
} catch (err) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('should not throw an error when callback of set() is not specified', function (done) {
|
||||
try {
|
||||
context.set("nodeX"," ","bar");
|
||||
done();
|
||||
} catch (err) {
|
||||
done("should not throw an error.");
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle empty context file', function (done) {
|
||||
fs.outputFile(path.join(resourcesDir,"contexts","nodeX","flow.json"),"",function(){
|
||||
context.get("nodeX", "foo", function (err, value) {
|
||||
should.not.exist(value);
|
||||
context.set("nodeX", "foo", "test", function (err) {
|
||||
context.get("nodeX", "foo", function (err, value) {
|
||||
value.should.be.equal("test");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error when reading corrupt context file', function (done) {
|
||||
fs.outputFile(path.join(resourcesDir, "contexts", "nodeX", "flow.json"),"{abc",function(){
|
||||
context.get("nodeX", "foo", function (err, value) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#keys',function() {
|
||||
it('should enumerate context keys', function(done) {
|
||||
context.keys("nodeX",function(err, value){
|
||||
value.should.be.an.Array();
|
||||
value.should.be.empty();
|
||||
context.set("nodeX","foo","bar",function(err){
|
||||
context.keys("nodeX",function(err, value){
|
||||
value.should.have.length(1);
|
||||
value[0].should.equal("foo");
|
||||
context.set("nodeX","abc.def","bar",function(err){
|
||||
context.keys("nodeX",function(err, value){
|
||||
value.should.have.length(2);
|
||||
value[1].should.equal("abc");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should enumerate context keys in each scopes', function(done) {
|
||||
context.keys("nodeX",function(err, value){
|
||||
value.should.be.an.Array();
|
||||
value.should.be.empty();
|
||||
context.keys("nodeY",function(err, value){
|
||||
value.should.be.an.Array();
|
||||
value.should.be.empty();
|
||||
context.set("nodeX","foo","bar",function(err){
|
||||
context.set("nodeY","hoge","piyo",function(err){
|
||||
context.keys("nodeX",function(err, value){
|
||||
value.should.have.length(1);
|
||||
value[0].should.equal("foo");
|
||||
context.keys("nodeY",function(err, value){
|
||||
value.should.have.length(1);
|
||||
value[0].should.equal("hoge");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error when callback of keys() is not a function', function (done) {
|
||||
try {
|
||||
context.keys("nodeX", "callback");
|
||||
done("should throw an error.");
|
||||
} catch (err) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error when callback of keys() is not specified', function (done) {
|
||||
try {
|
||||
context.keys("nodeX");
|
||||
done("should throw an error.");
|
||||
} catch (err) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete',function() {
|
||||
it('should delete context',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo","testX",function(err){
|
||||
context.set("nodeY","foo","testY",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.equal("testX");
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
value.should.be.equal("testY");
|
||||
context.delete("nodeX").then(function(){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
value.should.be.equal("testY");
|
||||
done();
|
||||
});
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clean',function() {
|
||||
it('should clean unnecessary context',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo","testX",function(err){
|
||||
context.set("nodeY","foo","testY",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.equal("testX");
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
value.should.be.equal("testY");
|
||||
context.clean([]).then(function(){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not clean active context',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo","testX",function(err){
|
||||
context.set("nodeY","foo","testY",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.equal("testX");
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
value.should.be.equal("testY");
|
||||
context.clean(["nodeX"]).then(function(){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.be.equal("testX");
|
||||
context.get("nodeY","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#if cache is enabled',function() {
|
||||
afterEach(function() {
|
||||
return context.clean([]).then(function(){
|
||||
return context.close().then(function(){
|
||||
return fs.remove(resourcesDir);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should load contexts into the cache',function() {
|
||||
var globalData = {key:"global"};
|
||||
var flowData = {key:"flow"};
|
||||
var nodeData = {key:"node"};
|
||||
return Promise.all([
|
||||
fs.outputFile(path.join(resourcesDir,"contexts","global","global.json"), JSON.stringify(globalData,null,4), "utf8"),
|
||||
fs.outputFile(path.join(resourcesDir,"contexts","flow","flow.json"), JSON.stringify(flowData,null,4), "utf8"),
|
||||
fs.outputFile(path.join(resourcesDir,"contexts","flow","node.json"), JSON.stringify(nodeData,null,4), "utf8")
|
||||
]).then(function(){
|
||||
context = LocalFileSystem({dir: resourcesDir, cache: true});
|
||||
return context.open();
|
||||
}).then(function(){
|
||||
return Promise.all([
|
||||
fs.remove(path.join(resourcesDir,"contexts","global","global.json")),
|
||||
fs.remove(path.join(resourcesDir,"contexts","flow","flow.json")),
|
||||
fs.remove(path.join(resourcesDir,"contexts","flow","node.json"))
|
||||
]);
|
||||
}).then(function(){
|
||||
context.get("global","key").should.be.equal("global");
|
||||
context.get("flow","key").should.be.equal("flow");
|
||||
context.get("node:flow","key").should.be.equal("node");
|
||||
});
|
||||
});
|
||||
|
||||
it('should store property to the cache',function() {
|
||||
context = LocalFileSystem({dir: resourcesDir, cache: true});
|
||||
return context.open().then(function(){
|
||||
return new Promise(function(resolve, reject){
|
||||
context.set("global","foo","bar",function(err){
|
||||
if(err){
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}).then(function(){
|
||||
return fs.remove(path.join(resourcesDir,"contexts","global","global.json"));
|
||||
}).then(function(){
|
||||
context.get("global","foo").should.be.equal("bar");
|
||||
})
|
||||
});
|
||||
|
||||
it('should enumerate context keys in the cache',function() {
|
||||
var globalData = {foo:"bar"};
|
||||
fs.outputFile(path.join(resourcesDir,"contexts","global","global.json"), JSON.stringify(globalData,null,4), "utf8").then(function(){
|
||||
context = LocalFileSystem({dir: resourcesDir, cache: true});
|
||||
return context.open()
|
||||
}).then(function(){
|
||||
return fs.remove(path.join(resourcesDir,"contexts","global","global.json"));
|
||||
}).then(function(){
|
||||
var keys = context.keys("global");
|
||||
keys.should.have.length(1);
|
||||
keys[0].should.equal("foo");
|
||||
return new Promise(function(resolve, reject){
|
||||
context.set("global","foo2","bar2",function(err){
|
||||
if(err){
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}).then(function(){
|
||||
return fs.remove(path.join(resourcesDir,"contexts","global","global.json"));
|
||||
}).then(function(){
|
||||
var keys = context.keys("global");
|
||||
keys.should.have.length(2);
|
||||
keys[1].should.equal("foo2");
|
||||
})
|
||||
});
|
||||
|
||||
it('should delete context in the cache',function() {
|
||||
context = LocalFileSystem({dir: resourcesDir, cache: true});
|
||||
return context.open().then(function(){
|
||||
return new Promise(function(resolve, reject){
|
||||
context.set("global","foo","bar",function(err){
|
||||
if(err){
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}).then(function(){
|
||||
context.get("global","foo").should.be.equal("bar");
|
||||
return context.delete("global");
|
||||
}).then(function(){
|
||||
should.not.exist(context.get("global","foo"))
|
||||
})
|
||||
});
|
||||
|
||||
it('should clean unnecessary context in the cache',function() {
|
||||
var flowAData = {key:"flowA"};
|
||||
var flowBData = {key:"flowB"};
|
||||
return Promise.all([
|
||||
fs.outputFile(path.join(resourcesDir,"contexts","flowA","flow.json"), JSON.stringify(flowAData,null,4), "utf8"),
|
||||
fs.outputFile(path.join(resourcesDir,"contexts","flowB","flow.json"), JSON.stringify(flowBData,null,4), "utf8")
|
||||
]).then(function(){
|
||||
context = LocalFileSystem({dir: resourcesDir, cache: true});
|
||||
return context.open();
|
||||
}).then(function(){
|
||||
context.get("flowA","key").should.be.equal("flowA");
|
||||
context.get("flowB","key").should.be.equal("flowB");
|
||||
return context.clean(["flowA"]);
|
||||
}).then(function(){
|
||||
context.get("flowA","key").should.be.equal("flowA");
|
||||
should.not.exist(context.get("flowB","key"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Configuration', function () {
|
||||
it('should change a base directory', function (done) {
|
||||
var differentBaseContext = LocalFileSystem({
|
||||
base: "contexts2",
|
||||
dir: resourcesDir,
|
||||
cache: false
|
||||
});
|
||||
differentBaseContext.open().then(function () {
|
||||
differentBaseContext.set("node2", "foo2", "bar2", function (err) {
|
||||
differentBaseContext.get("node2", "foo2", function (err, value) {
|
||||
value.should.be.equal("bar2");
|
||||
context.get("node2", "foo2", function(err, value) {
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should use userDir', function (done) {
|
||||
var userDirContext = LocalFileSystem({
|
||||
base: "contexts2",
|
||||
cache: false,
|
||||
settings: {
|
||||
userDir: resourcesDir
|
||||
}
|
||||
});
|
||||
userDirContext.open().then(function () {
|
||||
userDirContext.set("node2", "foo2", "bar2", function (err) {
|
||||
userDirContext.get("node2", "foo2", function (err, value) {
|
||||
value.should.be.equal("bar2");
|
||||
context.get("node2", "foo2", function (err, value) {
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should use NODE_RED_HOME', function (done) {
|
||||
var oldNRH = process.env.NODE_RED_HOME;
|
||||
process.env.NODE_RED_HOME = resourcesDir;
|
||||
fs.mkdirSync(resourcesDir);
|
||||
fs.writeFileSync(path.join(resourcesDir,".config.json"),"");
|
||||
var nrHomeContext = LocalFileSystem({
|
||||
base: "contexts2",
|
||||
cache: false
|
||||
});
|
||||
try {
|
||||
nrHomeContext.open().then(function () {
|
||||
nrHomeContext.set("node2", "foo2", "bar2", function (err) {
|
||||
nrHomeContext.get("node2", "foo2", function (err, value) {
|
||||
value.should.be.equal("bar2");
|
||||
context.get("node2", "foo2", function (err, value) {
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
process.env.NODE_RED_HOME = oldNRH;
|
||||
}
|
||||
});
|
||||
|
||||
it('should use HOME_PATH', function (done) {
|
||||
var oldNRH = process.env.NODE_RED_HOME;
|
||||
var oldHOMEPATH = process.env.HOMEPATH;
|
||||
process.env.NODE_RED_HOME = resourcesDir;
|
||||
process.env.HOMEPATH = resourcesDir;
|
||||
var homePath = path.join(resourcesDir, ".node-red");
|
||||
fs.outputFile(path.join(homePath, ".config.json"),"",function(){
|
||||
var homeContext = LocalFileSystem({
|
||||
base: "contexts2",
|
||||
cache: false
|
||||
});
|
||||
try {
|
||||
homeContext.open().then(function () {
|
||||
homeContext.set("node2", "foo2", "bar2", function (err) {
|
||||
homeContext.get("node2", "foo2", function (err, value) {
|
||||
value.should.be.equal("bar2");
|
||||
context.get("node2", "foo2", function (err, value) {
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
process.env.NODE_RED_HOME = oldNRH;
|
||||
process.env.HOMEPATH = oldHOMEPATH;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should use HOME_PATH', function (done) {
|
||||
var oldNRH = process.env.NODE_RED_HOME;
|
||||
var oldHOMEPATH = process.env.HOMEPATH;
|
||||
var oldHOME = process.env.HOME;
|
||||
process.env.NODE_RED_HOME = resourcesDir;
|
||||
process.env.HOMEPATH = resourcesDir;
|
||||
process.env.HOME = resourcesDir;
|
||||
var homeContext = LocalFileSystem({
|
||||
base: "contexts2",
|
||||
cache: false
|
||||
});
|
||||
try {
|
||||
homeContext.open().then(function () {
|
||||
homeContext.set("node2", "foo2", "bar2", function (err) {
|
||||
homeContext.get("node2", "foo2", function (err, value) {
|
||||
value.should.be.equal("bar2");
|
||||
context.get("node2", "foo2", function (err, value) {
|
||||
should.not.exist(value);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
process.env.NODE_RED_HOME = oldNRH;
|
||||
process.env.HOMEPATH = oldHOMEPATH;
|
||||
process.env.HOME = oldHOME;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
319
test/red/runtime/nodes/context/memory_spec.js
Normal file
319
test/red/runtime/nodes/context/memory_spec.js
Normal file
@@ -0,0 +1,319 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require('should');
|
||||
var Memory = require('../../../../../red/runtime/nodes/context/memory');
|
||||
|
||||
describe('memory',function() {
|
||||
var context;
|
||||
|
||||
beforeEach(function() {
|
||||
context = Memory({});
|
||||
return context.open();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
return context.clean([]).then(function(){
|
||||
return context.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#get/set',function() {
|
||||
describe('sync',function() {
|
||||
it('should store property',function() {
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
context.set("nodeX","foo","test");
|
||||
context.get("nodeX","foo").should.equal("test");
|
||||
});
|
||||
|
||||
it('should store property - creates parent properties',function() {
|
||||
context.set("nodeX","foo.bar","test");
|
||||
context.get("nodeX","foo").should.eql({bar:"test"});
|
||||
});
|
||||
|
||||
it('should delete property',function() {
|
||||
context.set("nodeX","foo.abc.bar1","test1");
|
||||
context.set("nodeX","foo.abc.bar2","test2");
|
||||
context.get("nodeX","foo.abc").should.eql({bar1:"test1",bar2:"test2"});
|
||||
context.set("nodeX","foo.abc.bar1",undefined);
|
||||
context.get("nodeX","foo.abc").should.eql({bar2:"test2"});
|
||||
context.set("nodeX","foo.abc",undefined);
|
||||
should.not.exist(context.get("nodeX","foo.abc"));
|
||||
context.set("nodeX","foo",undefined);
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
});
|
||||
|
||||
it('should not shared context with other scope', function() {
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
should.not.exist(context.get("nodeY","foo"));
|
||||
context.set("nodeX","foo","testX");
|
||||
context.set("nodeY","foo","testY");
|
||||
|
||||
context.get("nodeX","foo").should.equal("testX");
|
||||
context.get("nodeY","foo").should.equal("testY");
|
||||
});
|
||||
|
||||
it('should throw the error if the error occurs', function() {
|
||||
try{
|
||||
context.set("nodeX",".foo","test");
|
||||
should.fail("Error was not thrown");
|
||||
}catch(err){
|
||||
should.exist(err);
|
||||
try{
|
||||
context.get("nodeX",".foo");
|
||||
should.fail("Error was not thrown");
|
||||
}catch(err){
|
||||
should.exist(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should get multiple values - all known', function() {
|
||||
context.set("nodeX","one","test1");
|
||||
context.set("nodeX","two","test2");
|
||||
context.set("nodeX","three","test3");
|
||||
context.set("nodeX","four","test4");
|
||||
|
||||
var values = context.get("nodeX",["one","two","four"]);
|
||||
values.should.eql(["test1","test2","test4"])
|
||||
})
|
||||
it('should get multiple values - include unknown', function() {
|
||||
context.set("nodeX","one","test1");
|
||||
context.set("nodeX","two","test2");
|
||||
context.set("nodeX","three","test3");
|
||||
context.set("nodeX","four","test4");
|
||||
|
||||
var values = context.get("nodeX",["one","unknown"]);
|
||||
values.should.eql(["test1",undefined])
|
||||
})
|
||||
it('should throw error if bad key included in multiple keys', function() {
|
||||
context.set("nodeX","one","test1");
|
||||
context.set("nodeX","two","test2");
|
||||
context.set("nodeX","three","test3");
|
||||
context.set("nodeX","four","test4");
|
||||
|
||||
try{
|
||||
var values = context.get("nodeX",["one",".foo","three"]);
|
||||
should.fail("Error was not thrown");
|
||||
}catch(err){
|
||||
should.exist(err);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe('async',function() {
|
||||
it('should store property',function(done) {
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
should.not.exist(value);
|
||||
context.set("nodeX","foo","test",function(err){
|
||||
context.get("nodeX","foo",function(err, value){
|
||||
value.should.equal("test");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass the error to callback if the error occurs',function(done) {
|
||||
context.set("nodeX",".foo","test",function(err, value){
|
||||
should.exist(err);
|
||||
context.get("nodeX",".foo",function(err){
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should get multiple values - all known', function(done) {
|
||||
context.set("nodeX","one","test1");
|
||||
context.set("nodeX","two","test2");
|
||||
context.set("nodeX","three","test3");
|
||||
context.set("nodeX","four","test4");
|
||||
|
||||
context.get("nodeX",["one","two","four"],function() {
|
||||
Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2","test4"])
|
||||
done();
|
||||
});
|
||||
})
|
||||
it('should get multiple values - include unknown', function(done) {
|
||||
context.set("nodeX","one","test1");
|
||||
context.set("nodeX","two","test2");
|
||||
context.set("nodeX","three","test3");
|
||||
context.set("nodeX","four","test4");
|
||||
|
||||
context.get("nodeX",["one","unknown"],function() {
|
||||
Array.prototype.slice.apply(arguments).should.eql([undefined,"test1",undefined])
|
||||
done();
|
||||
});
|
||||
})
|
||||
it('should throw error if bad key included in multiple keys', function(done) {
|
||||
context.set("nodeX","one","test1");
|
||||
context.set("nodeX","two","test2");
|
||||
context.set("nodeX","three","test3");
|
||||
context.set("nodeX","four","test4");
|
||||
|
||||
context.get("nodeX",["one",".foo","three"], function(err) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('#keys',function() {
|
||||
describe('sync',function() {
|
||||
it('should enumerate context keys', function() {
|
||||
var keys = context.keys("nodeX");
|
||||
keys.should.be.an.Array();
|
||||
keys.should.be.empty();
|
||||
|
||||
context.set("nodeX","foo","bar");
|
||||
keys = context.keys("nodeX");
|
||||
keys.should.have.length(1);
|
||||
keys[0].should.equal("foo");
|
||||
|
||||
context.set("nodeX","abc.def","bar");
|
||||
keys = context.keys("nodeX");
|
||||
keys.should.have.length(2);
|
||||
keys[1].should.equal("abc");
|
||||
});
|
||||
|
||||
it('should enumerate context keys in each scopes', function() {
|
||||
var keysX = context.keys("nodeX");
|
||||
keysX.should.be.an.Array();
|
||||
keysX.should.be.empty();
|
||||
|
||||
var keysY = context.keys("nodeY");
|
||||
keysY.should.be.an.Array();
|
||||
keysY.should.be.empty();
|
||||
|
||||
context.set("nodeX","foo","bar");
|
||||
context.set("nodeY","hoge","piyo");
|
||||
keysX = context.keys("nodeX");
|
||||
keysX.should.have.length(1);
|
||||
keysX[0].should.equal("foo");
|
||||
|
||||
keysY = context.keys("nodeY");
|
||||
keysY.should.have.length(1);
|
||||
keysY[0].should.equal("hoge");
|
||||
});
|
||||
|
||||
it('should enumerate global context keys', function () {
|
||||
var keys = context.keys("global");
|
||||
keys.should.be.an.Array();
|
||||
keys.should.be.empty();
|
||||
|
||||
context.set("global", "foo", "bar");
|
||||
keys = context.keys("global");
|
||||
keys.should.have.length(1);
|
||||
keys[0].should.equal("foo");
|
||||
|
||||
context.set("global", "abc.def", "bar");
|
||||
keys = context.keys("global");
|
||||
keys.should.have.length(2);
|
||||
keys[1].should.equal("abc");
|
||||
});
|
||||
|
||||
it('should not return specific keys as global context keys', function () {
|
||||
var keys = context.keys("global");
|
||||
|
||||
context.set("global", "set", "bar");
|
||||
context.set("global", "get", "bar");
|
||||
context.set("global", "keys", "bar");
|
||||
keys = context.keys("global");
|
||||
keys.should.have.length(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('async',function() {
|
||||
it('should enumerate context keys', function(done) {
|
||||
context.keys("nodeX", function(err, keys) {
|
||||
keys.should.be.an.Array();
|
||||
keys.should.be.empty();
|
||||
context.set("nodeX", "foo", "bar", function(err) {
|
||||
context.keys("nodeX", function(err, keys) {
|
||||
keys.should.have.length(1);
|
||||
keys[0].should.equal("foo");
|
||||
context.set("nodeX","abc.def","bar",function(err){
|
||||
context.keys("nodeX",function(err, keys){
|
||||
keys.should.have.length(2);
|
||||
keys[1].should.equal("abc");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete',function() {
|
||||
it('should delete context',function() {
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
should.not.exist(context.get("nodeY","foo"));
|
||||
context.set("nodeX","foo","abc");
|
||||
context.set("nodeY","foo","abc");
|
||||
context.get("nodeX","foo").should.equal("abc");
|
||||
context.get("nodeY","foo").should.equal("abc");
|
||||
|
||||
return context.delete("nodeX").then(function(){
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
should.exist(context.get("nodeY","foo"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clean',function() {
|
||||
it('should clean unnecessary context',function() {
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
should.not.exist(context.get("nodeY","foo"));
|
||||
context.set("nodeX","foo","abc");
|
||||
context.set("nodeY","foo","abc");
|
||||
context.get("nodeX","foo").should.equal("abc");
|
||||
context.get("nodeY","foo").should.equal("abc");
|
||||
|
||||
return context.clean([]).then(function(){
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
should.not.exist(context.get("nodeY","foo"));
|
||||
});
|
||||
});
|
||||
it('should not clean active context',function() {
|
||||
should.not.exist(context.get("nodeX","foo"));
|
||||
should.not.exist(context.get("nodeY","foo"));
|
||||
context.set("nodeX","foo","abc");
|
||||
context.set("nodeY","foo","abc");
|
||||
context.get("nodeX","foo").should.equal("abc");
|
||||
context.get("nodeY","foo").should.equal("abc");
|
||||
|
||||
return context.clean(["nodeX"]).then(function(){
|
||||
should.exist(context.get("nodeX","foo"));
|
||||
should.not.exist(context.get("nodeY","foo"));
|
||||
});
|
||||
});
|
||||
it('should not clean global context', function () {
|
||||
context.set("global", "foo", "abc");
|
||||
context.get("global", "foo").should.equal("abc");
|
||||
|
||||
return context.clean(["global"]).then(function () {
|
||||
should.exist(context.get("global", "foo"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@@ -1,144 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require('sinon');
|
||||
var Context = require("../../../../red/runtime/nodes/context");
|
||||
|
||||
describe('context', function() {
|
||||
beforeEach(function() {
|
||||
Context.init({});
|
||||
});
|
||||
afterEach(function() {
|
||||
Context.clean({allNodes:{}});
|
||||
});
|
||||
it('stores local property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
should.not.exist(context1.get("foo"));
|
||||
context1.set("foo","test");
|
||||
context1.get("foo").should.eql("test");
|
||||
});
|
||||
it('stores local property - creates parent properties',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
context1.set("foo.bar","test");
|
||||
context1.get("foo").should.eql({bar:"test"});
|
||||
});
|
||||
it('deletes local property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
context1.set("foo.abc.bar1","test1");
|
||||
context1.set("foo.abc.bar2","test2");
|
||||
context1.get("foo.abc").should.eql({bar1:"test1",bar2:"test2"});
|
||||
context1.set("foo.abc.bar1",undefined);
|
||||
context1.get("foo.abc").should.eql({bar2:"test2"});
|
||||
context1.set("foo.abc",undefined);
|
||||
should.not.exist(context1.get("foo.abc"));
|
||||
context1.set("foo",undefined);
|
||||
should.not.exist(context1.get("foo"));
|
||||
});
|
||||
it('stores flow property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
should.not.exist(context1.flow.get("foo"));
|
||||
context1.flow.set("foo","test");
|
||||
context1.flow.get("foo").should.eql("test");
|
||||
});
|
||||
it('stores global property',function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
should.not.exist(context1.global.get("foo"));
|
||||
context1.global.set("foo","test");
|
||||
context1.global.get("foo").should.eql("test");
|
||||
});
|
||||
|
||||
it('keeps local context local', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowA");
|
||||
|
||||
should.not.exist(context1.get("foo"));
|
||||
should.not.exist(context2.get("foo"));
|
||||
context1.set("foo","test");
|
||||
|
||||
context1.get("foo").should.eql("test");
|
||||
should.not.exist(context2.get("foo"));
|
||||
});
|
||||
it('flow context accessible to all flow nodes', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowA");
|
||||
|
||||
should.not.exist(context1.flow.get("foo"));
|
||||
should.not.exist(context2.flow.get("foo"));
|
||||
|
||||
context1.flow.set("foo","test");
|
||||
context1.flow.get("foo").should.eql("test");
|
||||
context2.flow.get("foo").should.eql("test");
|
||||
});
|
||||
|
||||
it('flow context not shared to nodes on other flows', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowB");
|
||||
|
||||
should.not.exist(context1.flow.get("foo"));
|
||||
should.not.exist(context2.flow.get("foo"));
|
||||
|
||||
context1.flow.set("foo","test");
|
||||
context1.flow.get("foo").should.eql("test");
|
||||
should.not.exist(context2.flow.get("foo"));
|
||||
});
|
||||
|
||||
it('global context shared to all nodes', function() {
|
||||
var context1 = Context.get("1","flowA");
|
||||
var context2 = Context.get("2","flowB");
|
||||
|
||||
should.not.exist(context1.global.get("foo"));
|
||||
should.not.exist(context2.global.get("foo"));
|
||||
|
||||
context1.global.set("foo","test");
|
||||
context1.global.get("foo").should.eql("test");
|
||||
context2.global.get("foo").should.eql("test");
|
||||
});
|
||||
|
||||
it('deletes context',function() {
|
||||
var context = Context.get("1","flowA");
|
||||
should.not.exist(context.get("foo"));
|
||||
context.set("foo","abc");
|
||||
context.get("foo").should.eql("abc");
|
||||
|
||||
Context.delete("1","flowA");
|
||||
context = Context.get("1","flowA");
|
||||
should.not.exist(context.get("foo"));
|
||||
})
|
||||
|
||||
it('enumerates context keys', function() {
|
||||
var context = Context.get("1","flowA");
|
||||
|
||||
var keys = context.keys();
|
||||
keys.should.be.an.Array();
|
||||
keys.should.be.empty();
|
||||
|
||||
context.set("foo","bar");
|
||||
keys = context.keys();
|
||||
keys.should.have.length(1);
|
||||
keys[0].should.eql("foo");
|
||||
|
||||
context.set("abc.def","bar");
|
||||
keys = context.keys();
|
||||
keys.should.have.length(2);
|
||||
keys[1].should.eql("abc");
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
});
|
@@ -287,7 +287,7 @@ describe("storage/localfilesystem/projects/ssh", function() {
|
||||
});
|
||||
|
||||
it('should generate sshkey file with size data', function(done) {
|
||||
this.timeout(10000);
|
||||
this.timeout(20000);
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
@@ -311,7 +311,7 @@ describe("storage/localfilesystem/projects/ssh", function() {
|
||||
});
|
||||
|
||||
it('should generate sshkey file with password & size data', function(done) {
|
||||
this.timeout(10000);
|
||||
this.timeout(20000);
|
||||
var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
|
||||
var username = 'test';
|
||||
var options = {
|
||||
|
@@ -141,7 +141,15 @@ describe("red/util", function() {
|
||||
cloned.res.should.equal(msg.res);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getObjectProperty', function() {
|
||||
it('gets a property beginning with "msg."', function() {
|
||||
// getMessageProperty strips off `msg.` prefixes.
|
||||
// getObjectProperty does not
|
||||
var obj = { msg: { a: "foo"}, a: "bar"};
|
||||
var v = util.getObjectProperty(obj,"msg.a");
|
||||
v.should.eql("foo");
|
||||
})
|
||||
});
|
||||
describe('getMessageProperty', function() {
|
||||
it('retrieves a simple property', function() {
|
||||
var v = util.getMessageProperty({a:"foo"},"msg.a");
|
||||
@@ -169,7 +177,16 @@ describe("red/util", function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('setObjectProperty', function() {
|
||||
it('set a property beginning with "msg."', function() {
|
||||
// setMessageProperty strips off `msg.` prefixes.
|
||||
// setObjectProperty does not
|
||||
var obj = {};
|
||||
util.setObjectProperty(obj,"msg.a","bar");
|
||||
obj.should.have.property("msg");
|
||||
obj.msg.should.have.property("a","bar");
|
||||
})
|
||||
});
|
||||
describe('setMessageProperty', function() {
|
||||
it('sets a property', function() {
|
||||
var msg = {a:"foo"};
|
||||
@@ -191,6 +208,11 @@ describe("red/util", function() {
|
||||
util.setMessageProperty(msg,"msg.a.b.c","bar",false);
|
||||
should.not.exist(msg.a.b);
|
||||
})
|
||||
it('does not create missing parent properties with array', function () {
|
||||
var msg = {a:{}};
|
||||
util.setMessageProperty(msg, "msg.a.b[1].c", "bar", false);
|
||||
should.not.exist(msg.a.b);
|
||||
})
|
||||
it('deletes property if value is undefined', function() {
|
||||
var msg = {a:{b:{c:"foo"}}};
|
||||
util.setMessageProperty(msg,"msg.a.b.c",undefined);
|
||||
@@ -227,6 +249,11 @@ describe("red/util", function() {
|
||||
msg.a[2].should.be.instanceOf(Array);
|
||||
msg.a[2][2].should.eql("bar");
|
||||
});
|
||||
it('does not create missing array elements - mid property', function () {
|
||||
var msg = {a:[]};
|
||||
util.setMessageProperty(msg, "msg.a[1][1]", "bar", false);
|
||||
msg.a.should.empty();
|
||||
});
|
||||
it('does not create missing array elements - final property', function() {
|
||||
var msg = {a:{}};
|
||||
util.setMessageProperty(msg,"msg.a.b[2]","bar",false);
|
||||
@@ -275,10 +302,23 @@ describe("red/util", function() {
|
||||
var result = util.evaluateNodeProperty('','date');
|
||||
(Date.now() - result).should.be.approximately(0,50);
|
||||
});
|
||||
it('returns bin', function () {
|
||||
var result = util.evaluateNodeProperty('[1, 2]','bin');
|
||||
result[0].should.eql(1);
|
||||
result[1].should.eql(2);
|
||||
});
|
||||
it('returns msg property',function() {
|
||||
var result = util.evaluateNodeProperty('foo.bar','msg',{},{foo:{bar:"123"}});
|
||||
result.should.eql("123");
|
||||
});
|
||||
it('throws an error if callback is not defined', function (done) {
|
||||
try {
|
||||
util.evaluateNodeProperty(' ','msg',{},{foo:{bar:"123"}});
|
||||
done("should throw an error");
|
||||
} catch (err) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
it('returns flow property',function() {
|
||||
var result = util.evaluateNodeProperty('foo.bar','flow',{
|
||||
context:function() { return {
|
||||
@@ -307,6 +347,14 @@ describe("red/util", function() {
|
||||
},{});
|
||||
result.should.eql("123");
|
||||
});
|
||||
it('returns jsonata result', function () {
|
||||
var result = util.evaluateNodeProperty('$abs(-1)','jsonata',{},{});
|
||||
result.should.eql(1);
|
||||
});
|
||||
it('returns null', function() {
|
||||
var result = util.evaluateNodeProperty(null,'null');
|
||||
(result === null).should.be.true();
|
||||
})
|
||||
describe('environment variable', function() {
|
||||
before(function() {
|
||||
process.env.NR_TEST_A = "foo";
|
||||
@@ -444,6 +492,12 @@ describe("red/util", function() {
|
||||
var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
|
||||
result.should.eql("bar");
|
||||
});
|
||||
it('accesses environment variable from an expression', function() {
|
||||
process.env.UTIL_ENV = 'foo';
|
||||
var expr = util.prepareJSONataExpression('$env("UTIL_ENV")',{});
|
||||
var result = util.evaluateJSONataExpression(expr,{});
|
||||
result.should.eql('foo');
|
||||
});
|
||||
it('handles non-existant flow context variable', function() {
|
||||
var expr = util.prepareJSONataExpression('$flowContext("nonExistant")',{context:function() { return {flow:{get: function(key) { return {'foo':'bar'}[key]}}}}});
|
||||
var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
|
||||
@@ -454,7 +508,267 @@ describe("red/util", function() {
|
||||
var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
|
||||
should.not.exist(result);
|
||||
});
|
||||
|
||||
it('handles async flow context access', function(done) {
|
||||
var expr = util.prepareJSONataExpression('$flowContext("foo")',{context:function() { return {flow:{get: function(key,store,callback) { setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
|
||||
util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
value.should.eql("bar");
|
||||
done();
|
||||
} catch(err2) {
|
||||
done(err2);
|
||||
}
|
||||
});
|
||||
})
|
||||
it('handles async global context access', function(done) {
|
||||
var expr = util.prepareJSONataExpression('$globalContext("foo")',{context:function() { return {global:{get: function(key,store,callback) { setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
|
||||
util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
value.should.eql("bar");
|
||||
done();
|
||||
} catch(err2) {
|
||||
done(err2);
|
||||
}
|
||||
});
|
||||
})
|
||||
it('handles persistable store in flow context access', function(done) {
|
||||
var storeName;
|
||||
var expr = util.prepareJSONataExpression('$flowContext("foo", "flowStoreName")',{context:function() { return {flow:{get: function(key,store,callback) { storeName = store;setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
|
||||
util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
value.should.eql("bar");
|
||||
storeName.should.equal("flowStoreName");
|
||||
done();
|
||||
} catch(err2) {
|
||||
done(err2);
|
||||
}
|
||||
});
|
||||
})
|
||||
it('handles persistable store in global context access', function(done) {
|
||||
var storeName;
|
||||
var expr = util.prepareJSONataExpression('$globalContext("foo", "globalStoreName")',{context:function() { return {global:{get: function(key,store,callback) { storeName = store;setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
|
||||
util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
value.should.eql("bar");
|
||||
storeName.should.equal("globalStoreName");
|
||||
done();
|
||||
} catch(err2) {
|
||||
done(err2);
|
||||
}
|
||||
});
|
||||
})
|
||||
it('callbacks with error when invalid expression was specified', function (done) {
|
||||
var expr = util.prepareJSONataExpression('$abc(1)',{});
|
||||
var result = util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value){
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('encodeObject', function () {
|
||||
it('encodes Error with message', function() {
|
||||
var err = new Error("encode error");
|
||||
err.name = 'encodeError';
|
||||
var msg = {msg:err};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("error");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.name.should.eql('encodeError');
|
||||
resultJson.message.should.eql('encode error');
|
||||
});
|
||||
it('encodes Error without message', function() {
|
||||
var err = new Error();
|
||||
err.name = 'encodeError';
|
||||
err.toString = function(){return 'error message';}
|
||||
var msg = {msg:err};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("error");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.name.should.eql('encodeError');
|
||||
resultJson.message.should.eql('error message');
|
||||
});
|
||||
it('encodes Buffer', function() {
|
||||
var msg = {msg:Buffer.from("abc")};
|
||||
var result = util.encodeObject(msg,{maxLength:4});
|
||||
result.format.should.eql("buffer[3]");
|
||||
result.msg[0].should.eql('6');
|
||||
result.msg[1].should.eql('1');
|
||||
result.msg[2].should.eql('6');
|
||||
result.msg[3].should.eql('2');
|
||||
});
|
||||
it('encodes function', function() {
|
||||
var msg = {msg:function(){}};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("function");
|
||||
result.msg.should.eql('[function]');
|
||||
});
|
||||
it('encodes boolean', function() {
|
||||
var msg = {msg:true};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("boolean");
|
||||
result.msg.should.eql('true');
|
||||
});
|
||||
it('encodes number', function() {
|
||||
var msg = {msg:123};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("number");
|
||||
result.msg.should.eql('123');
|
||||
});
|
||||
it('encodes 0', function() {
|
||||
var msg = {msg:0};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("number");
|
||||
result.msg.should.eql('0');
|
||||
});
|
||||
it('encodes null', function() {
|
||||
var msg = {msg:null};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("null");
|
||||
result.msg.should.eql('(undefined)');
|
||||
});
|
||||
it('encodes undefined', function() {
|
||||
var msg = {msg:undefined};
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("undefined");
|
||||
result.msg.should.eql('(undefined)');
|
||||
});
|
||||
it('encodes string', function() {
|
||||
var msg = {msg:'1234567890'};
|
||||
var result = util.encodeObject(msg,{maxLength:6});
|
||||
result.format.should.eql("string[10]");
|
||||
result.msg.should.eql('123456...');
|
||||
});
|
||||
describe('encode object', function() {
|
||||
it('object', function() {
|
||||
var msg = { msg:{"foo":"bar"} };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.foo.should.eql('bar');
|
||||
});
|
||||
it('object whose name includes error', function() {
|
||||
function MyErrorObj(){
|
||||
this.name = 'my error obj';
|
||||
this.message = 'my error message';
|
||||
};
|
||||
var msg = { msg:new MyErrorObj() };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("MyErrorObj");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.name.should.eql('my error obj');
|
||||
resultJson.message.should.eql('my error message');
|
||||
});
|
||||
it('constructor of IncomingMessage', function() {
|
||||
function IncomingMessage(){};
|
||||
var msg = { msg:new IncomingMessage() };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.should.empty();
|
||||
});
|
||||
it('_req key in msg', function() {
|
||||
function Socket(){};
|
||||
var msg = { msg:{"_req":123} };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson._req.__enc__.should.eql(true);
|
||||
resultJson._req.type.should.eql('internal');
|
||||
});
|
||||
it('_res key in msg', function() {
|
||||
function Socket(){};
|
||||
var msg = { msg:{"_res":123} };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson._res.__enc__.should.eql(true);
|
||||
resultJson._res.type.should.eql('internal');
|
||||
});
|
||||
it('array of error', function() {
|
||||
var msg = { msg:[new Error("encode error")] };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("array[1]");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson[0].should.eql('Error: encode error');
|
||||
});
|
||||
it('long array in msg', function() {
|
||||
var msg = {msg:{array:[1,2,3,4]}};
|
||||
var result = util.encodeObject(msg,{maxLength:2});
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.array.__enc__.should.eql(true);
|
||||
resultJson.array.data[0].should.eql(1);
|
||||
resultJson.array.data[1].should.eql(2);
|
||||
resultJson.array.length.should.eql(4);
|
||||
});
|
||||
it('array of string', function() {
|
||||
var msg = { msg:["abcde","12345"] };
|
||||
var result = util.encodeObject(msg,{maxLength:3});
|
||||
result.format.should.eql("array[2]");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson[0].should.eql('abc...');
|
||||
resultJson[1].should.eql('123...');
|
||||
});
|
||||
it('array of function', function() {
|
||||
var msg = { msg:[function(){}] };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("array[1]");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson[0].__enc__.should.eql(true);
|
||||
resultJson[0].type.should.eql('function');
|
||||
});
|
||||
it('array of number', function() {
|
||||
var msg = { msg:[1,2,3] };
|
||||
var result = util.encodeObject(msg,{maxLength:2});
|
||||
result.format.should.eql("array[3]");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.__enc__.should.eql(true);
|
||||
resultJson.data[0].should.eql(1);
|
||||
resultJson.data[1].should.eql(2);
|
||||
resultJson.data.length.should.eql(2);
|
||||
resultJson.length.should.eql(3);
|
||||
});
|
||||
it('array of special number', function() {
|
||||
var msg = { msg:[NaN,Infinity,-Infinity] };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("array[3]");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson[0].__enc__.should.eql(true);
|
||||
resultJson[0].type.should.eql('number');
|
||||
resultJson[0].data.should.eql('NaN');
|
||||
resultJson[1].data.should.eql('Infinity');
|
||||
resultJson[2].data.should.eql('-Infinity');
|
||||
});
|
||||
it('constructor of Buffer in msg', function() {
|
||||
var msg = { msg:{buffer:new Buffer([1,2,3,4])} };
|
||||
var result = util.encodeObject(msg,{maxLength:2});
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.buffer.__enc__.should.eql(true);
|
||||
resultJson.buffer.length.should.eql(4);
|
||||
resultJson.buffer.data[0].should.eql(1);
|
||||
resultJson.buffer.data[1].should.eql(2);
|
||||
});
|
||||
it('constructor of ServerResponse', function() {
|
||||
function ServerResponse(){};
|
||||
var msg = { msg: new ServerResponse() };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.should.eql('[internal]');
|
||||
});
|
||||
it('constructor of Socket in msg', function() {
|
||||
function Socket(){};
|
||||
var msg = { msg: { socket: new Socket() } };
|
||||
var result = util.encodeObject(msg);
|
||||
result.format.should.eql("Object");
|
||||
var resultJson = JSON.parse(result.msg);
|
||||
resultJson.socket.should.eql('[internal]');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user