mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge branch 'dev' of github.com:node-red/node-red into dev
This commit is contained in:
		| @@ -19,22 +19,15 @@ var request = require('supertest'); | ||||
| var express = require('express'); | ||||
| var bodyParser = require('body-parser'); | ||||
| var sinon = require('sinon'); | ||||
| var when = require('when'); | ||||
|  | ||||
| var NR_TEST_UTILS = require("nr-test-utils"); | ||||
|  | ||||
| var context = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/context"); | ||||
| // var Context = require("../../../../red/runtime/nodes/context"); | ||||
| // var Util = require("../../../../red/runtime/util"); | ||||
|  | ||||
| describe("api/admin/context", function() { | ||||
|     it.skip("NEEDS TESTS WRITING",function() {}); | ||||
| }); | ||||
| /* | ||||
| describe("api/admin/context", function () { | ||||
|     var app = undefined; | ||||
|  | ||||
|     before(function (done) { | ||||
|         var node_context = undefined; | ||||
|     before(function () { | ||||
|         app = express(); | ||||
|         app.use(bodyParser.json()); | ||||
|         app.get("/context/:scope(global)", context.get); | ||||
| @@ -42,196 +35,196 @@ describe("api/admin/context", function() { | ||||
|         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(); | ||||
|         }); | ||||
|  | ||||
|         app.delete("/context/:scope(global)/*", context.delete); | ||||
|         app.delete("/context/:scope(node|flow)/:id/*", context.delete); | ||||
|     }); | ||||
|  | ||||
|     after(function () { | ||||
|         Context.clean({allNodes:{}}); | ||||
|         Context.close(); | ||||
|     }); | ||||
|     describe("get", function () { | ||||
|         var gContext = { | ||||
|             default: { abc: { msg: '111', format: 'number' } }, | ||||
|             file: { abc: { msg: '222', format: 'number' } } | ||||
|         }; | ||||
|         var fContext = { | ||||
|             default: { bool: { msg: 'true', format: 'boolean' } }, | ||||
|             file: { string: { msg: 'aaaa', format: 'string[7]' } } | ||||
|         }; | ||||
|         var nContext = { msg: "1", format: "number" }; | ||||
|         var stub = sinon.stub(); | ||||
|  | ||||
|     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"); | ||||
|                     }); | ||||
|         before(function () { | ||||
|             context.init({ | ||||
|                 context: { | ||||
|                     getValue: stub | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     check_scope("global", "g", undefined); | ||||
|     check_scope("node", "n", "NID"); | ||||
|     check_scope("flow", "f", "FID"); | ||||
|         afterEach(function () { | ||||
|             stub.reset(); | ||||
|         }); | ||||
|  | ||||
|     describe("# errors", function () { | ||||
|         it('should cause error for unknown scope', function (done) { | ||||
|         it('should call context.getValue to get global contexts', function (done) { | ||||
|             stub.returns(Promise.resolve(gContext)); | ||||
|             request(app) | ||||
|                 .get('/context/scope') | ||||
|                 .get('/context/global') | ||||
|                 .set('Accept', 'application/json') | ||||
|                 .expect(200) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(); | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     done("unexpected"); | ||||
|                     stub.args[0][0].should.have.property('user', undefined); | ||||
|                     stub.args[0][0].should.have.property('scope', 'global'); | ||||
|                     stub.args[0][0].should.have.property('id', undefined); | ||||
|                     stub.args[0][0].should.have.property('key', undefined); | ||||
|                     stub.args[0][0].should.have.property('store', undefined); | ||||
|                     var body = res.body; | ||||
|                     body.should.eql(gContext); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         it('should call context.getValue to get flow contexts', function (done) { | ||||
|             stub.returns(Promise.resolve(fContext)); | ||||
|             request(app) | ||||
|                 .get('/context/flow/1234/') | ||||
|                 .set('Accept', 'application/json') | ||||
|                 .expect(200) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     stub.args[0][0].should.have.property('user', undefined); | ||||
|                     stub.args[0][0].should.have.property('scope', 'flow'); | ||||
|                     stub.args[0][0].should.have.property('id', '1234'); | ||||
|                     stub.args[0][0].should.have.property('key', undefined); | ||||
|                     stub.args[0][0].should.have.property('store', undefined); | ||||
|                     var body = res.body; | ||||
|                     body.should.eql(fContext); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         it('should call context.getValue to get a node context', function (done) { | ||||
|             stub.returns(Promise.resolve(nContext)); | ||||
|             request(app) | ||||
|                 .get('/context/node/5678/foo?store=file') | ||||
|                 .set('Accept', 'application/json') | ||||
|                 .expect(200) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     stub.args[0][0].should.have.property('user', undefined); | ||||
|                     stub.args[0][0].should.have.property('scope', 'node'); | ||||
|                     stub.args[0][0].should.have.property('id', '5678'); | ||||
|                     stub.args[0][0].should.have.property('key', 'foo'); | ||||
|                     stub.args[0][0].should.have.property('store', 'file'); | ||||
|                     var body = res.body; | ||||
|                     body.should.eql(nContext); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         it('should handle error which context.getValue causes', function (done) { | ||||
|             stub.returns(Promise.reject('error')); | ||||
|             request(app) | ||||
|                 .get('/context/global') | ||||
|                 .set('Accept', 'application/json') | ||||
|                 .expect(400) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     res.body.should.has.a.property('code', 'unexpected_error'); | ||||
|                     res.body.should.has.a.property('message', 'error'); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe("delete", function () { | ||||
|         var stub = sinon.stub(); | ||||
|  | ||||
|         before(function () { | ||||
|             context.init({ | ||||
|                 context: { | ||||
|                     delete: stub | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         afterEach(function () { | ||||
|             stub.reset(); | ||||
|         }); | ||||
|  | ||||
|         it('should call context.delete to delete a global context', function (done) { | ||||
|             stub.returns(Promise.resolve()); | ||||
|             request(app) | ||||
|                 .delete('/context/global/abc?store=default') | ||||
|                 .expect(204) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     stub.args[0][0].should.have.property('user', undefined); | ||||
|                     stub.args[0][0].should.have.property('scope', 'global'); | ||||
|                     stub.args[0][0].should.have.property('id', undefined); | ||||
|                     stub.args[0][0].should.have.property('key', 'abc'); | ||||
|                     stub.args[0][0].should.have.property('store', 'default'); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         it('should call context.delete to delete a flow context', function (done) { | ||||
|             stub.returns(Promise.resolve()); | ||||
|             request(app) | ||||
|                 .delete('/context/flow/1234/abc?store=file') | ||||
|                 .expect(204) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     stub.args[0][0].should.have.property('user', undefined); | ||||
|                     stub.args[0][0].should.have.property('scope', 'flow'); | ||||
|                     stub.args[0][0].should.have.property('id', '1234'); | ||||
|                     stub.args[0][0].should.have.property('key', 'abc'); | ||||
|                     stub.args[0][0].should.have.property('store', 'file'); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         it('should call context.delete to delete a node context', function (done) { | ||||
|             stub.returns(Promise.resolve()); | ||||
|             request(app) | ||||
|                 .delete('/context/node/5678/foo?store=file') | ||||
|                 .expect(204) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     stub.args[0][0].should.have.property('user', undefined); | ||||
|                     stub.args[0][0].should.have.property('scope', 'node'); | ||||
|                     stub.args[0][0].should.have.property('id', '5678'); | ||||
|                     stub.args[0][0].should.have.property('key', 'foo'); | ||||
|                     stub.args[0][0].should.have.property('store', 'file'); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         it('should handle error which context.delete causes', function (done) { | ||||
|             stub.returns(Promise.reject('error')); | ||||
|             request(app) | ||||
|                 .delete('/context/global/abc?store=default') | ||||
|                 .expect(400) | ||||
|                 .end(function (err, res) { | ||||
|                     if (err) { | ||||
|                         return done(err); | ||||
|                     } | ||||
|                     res.body.should.has.a.property('code', 'unexpected_error'); | ||||
|                     res.body.should.has.a.property('message', 'error'); | ||||
|                     done(); | ||||
|                 }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| */ | ||||
|   | ||||
| @@ -26,6 +26,7 @@ var auth = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth"); | ||||
| var nodes = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/nodes"); | ||||
| var flows = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/flows"); | ||||
| var flow = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/flow"); | ||||
| var context = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/context"); | ||||
|  | ||||
| /** | ||||
| * Ensure all API routes are correctly mounted, with the expected permissions checks | ||||
| @@ -34,8 +35,8 @@ describe("api/admin/index", function() { | ||||
|     describe("Ensure all API routes are correctly mounted, with the expected permissions checks", function() { | ||||
|         var app; | ||||
|         var mockList = [ | ||||
|             flows,flow,nodes | ||||
|         ] | ||||
|             flows,flow,nodes,context | ||||
|         ]; | ||||
|         var permissionChecks = {}; | ||||
|         var lastRequest; | ||||
|         var stubApp = function(req,res,next) { | ||||
| @@ -50,7 +51,7 @@ describe("api/admin/index", function() { | ||||
|                 return function(req,res,next) { | ||||
|                     permissionChecks[permission] = (permissionChecks[permission]||0)+1; | ||||
|                     next(); | ||||
|                 } | ||||
|                 }; | ||||
|             }); | ||||
|  | ||||
|             sinon.stub(flows,"get",stubApp); | ||||
| @@ -70,6 +71,9 @@ describe("api/admin/index", function() { | ||||
|             sinon.stub(nodes,"putSet",stubApp); | ||||
|             sinon.stub(nodes,"getModuleCatalog",stubApp); | ||||
|             sinon.stub(nodes,"getModuleCatalogs",stubApp); | ||||
|  | ||||
|             sinon.stub(context,"get",stubApp); | ||||
|             sinon.stub(context,"delete",stubApp); | ||||
|         }); | ||||
|         after(function() { | ||||
|             mockList.forEach(function(m) { | ||||
| @@ -92,15 +96,19 @@ describe("api/admin/index", function() { | ||||
|             nodes.putSet.restore(); | ||||
|             nodes.getModuleCatalog.restore(); | ||||
|             nodes.getModuleCatalogs.restore(); | ||||
|             context.get.restore(); | ||||
|             context.delete.restore(); | ||||
|  | ||||
|         }); | ||||
|  | ||||
|         before(function() { | ||||
|             app = adminApi.init({}); | ||||
|         }); | ||||
|  | ||||
|         beforeEach(function() { | ||||
|             permissionChecks = {}; | ||||
|         }) | ||||
|         }); | ||||
|  | ||||
|         it('GET /flows', function(done) { | ||||
|             request(app).get("/flows").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
| @@ -108,8 +116,9 @@ describe("api/admin/index", function() { | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('flows.read',1); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('POST /flows', function(done) { | ||||
|             request(app).post("/flows").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
| @@ -117,7 +126,7 @@ describe("api/admin/index", function() { | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('flows.write',1); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /flow/1234', function(done) { | ||||
| @@ -126,10 +135,11 @@ describe("api/admin/index", function() { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('flows.read',1); | ||||
|                 lastRequest.params.should.have.property('id','1234') | ||||
|                 lastRequest.params.should.have.property('id','1234'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('POST /flow', function(done) { | ||||
|             request(app).post("/flow").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
| @@ -137,27 +147,29 @@ describe("api/admin/index", function() { | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('flows.write',1); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('DELETE /flow/1234', function(done) { | ||||
|             request(app).del("/flow/1234").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('flows.write',1); | ||||
|                 lastRequest.params.should.have.property('id','1234') | ||||
|                 lastRequest.params.should.have.property('id','1234'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('PUT /flow/1234', function(done) { | ||||
|             request(app).put("/flow/1234").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('flows.write',1); | ||||
|                 lastRequest.params.should.have.property('id','1234') | ||||
|                 lastRequest.params.should.have.property('id','1234'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes', function(done) { | ||||
| @@ -167,8 +179,9 @@ describe("api/admin/index", function() { | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('POST /nodes', function(done) { | ||||
|             request(app).post("/nodes").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
| @@ -176,27 +189,29 @@ describe("api/admin/index", function() { | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.write',1); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes/module', function(done) { | ||||
|             request(app).get("/nodes/module").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|                 lastRequest.params.should.have.property(0,'module') | ||||
|                 lastRequest.params.should.have.property(0,'module'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes/@scope/module', function(done) { | ||||
|             request(app).get("/nodes/@scope/module").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module') | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('PUT /nodes/module', function(done) { | ||||
| @@ -205,19 +220,20 @@ describe("api/admin/index", function() { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.write',1); | ||||
|                 lastRequest.params.should.have.property(0,'module') | ||||
|                 lastRequest.params.should.have.property(0,'module'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('PUT /nodes/@scope/module', function(done) { | ||||
|             request(app).put("/nodes/@scope/module").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.write',1); | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module') | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('DELETE /nodes/module', function(done) { | ||||
| @@ -226,19 +242,20 @@ describe("api/admin/index", function() { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.write',1); | ||||
|                 lastRequest.params.should.have.property(0,'module') | ||||
|                 lastRequest.params.should.have.property(0,'module'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('DELETE /nodes/@scope/module', function(done) { | ||||
|             request(app).del("/nodes/@scope/module").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.write',1); | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module') | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes/module/set', function(done) { | ||||
| @@ -247,21 +264,22 @@ describe("api/admin/index", function() { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|                 lastRequest.params.should.have.property(0,'module') | ||||
|                 lastRequest.params.should.have.property(2,'set') | ||||
|                 lastRequest.params.should.have.property(0,'module'); | ||||
|                 lastRequest.params.should.have.property(2,'set'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes/@scope/module/set', function(done) { | ||||
|             request(app).get("/nodes/@scope/module/set").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module') | ||||
|                 lastRequest.params.should.have.property(2,'set') | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module'); | ||||
|                 lastRequest.params.should.have.property(2,'set'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('PUT /nodes/module/set', function(done) { | ||||
| @@ -270,21 +288,22 @@ describe("api/admin/index", function() { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.write',1); | ||||
|                 lastRequest.params.should.have.property(0,'module') | ||||
|                 lastRequest.params.should.have.property(2,'set') | ||||
|                 lastRequest.params.should.have.property(0,'module'); | ||||
|                 lastRequest.params.should.have.property(2,'set'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('PUT /nodes/@scope/module/set', function(done) { | ||||
|             request(app).put("/nodes/@scope/module/set").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.write',1); | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module') | ||||
|                 lastRequest.params.should.have.property(2,'set') | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module'); | ||||
|                 lastRequest.params.should.have.property(2,'set'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes/messages', function(done) { | ||||
| @@ -293,10 +312,10 @@ describe("api/admin/index", function() { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|  | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes/module/set/messages', function(done) { | ||||
|             request(app).get("/nodes/module/set/messages").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
| @@ -305,8 +324,9 @@ describe("api/admin/index", function() { | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|                 lastRequest.params.should.have.property(0,'module/set'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /nodes/@scope/module/set/messages', function(done) { | ||||
|             request(app).get("/nodes/@scope/module/set/messages").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
| @@ -315,7 +335,124 @@ describe("api/admin/index", function() { | ||||
|                 permissionChecks.should.have.property('nodes.read',1); | ||||
|                 lastRequest.params.should.have.property(0,'@scope/module/set'); | ||||
|                 done(); | ||||
|             }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /context/global', function(done) { | ||||
|             request(app).get("/context/global").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.read',1); | ||||
|                 lastRequest.params.should.have.property('scope','global'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /context/global/key?store=memory', function(done) { | ||||
|             request(app).get("/context/global/key?store=memory").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.read',1); | ||||
|                 lastRequest.params.should.have.property('scope','global'); | ||||
|                 lastRequest.params.should.have.property(0,'key'); | ||||
|                 lastRequest.query.should.have.property('store','memory'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /context/flow/1234', function(done) { | ||||
|             request(app).get("/context/flow/1234").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.read',1); | ||||
|                 lastRequest.params.should.have.property('scope','flow'); | ||||
|                 lastRequest.params.should.have.property('id','1234'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /context/flow/1234/key?store=memory', function(done) { | ||||
|             request(app).get("/context/flow/1234/key?store=memory").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.read',1); | ||||
|                 lastRequest.params.should.have.property('scope','flow'); | ||||
|                 lastRequest.params.should.have.property('id','1234'); | ||||
|                 lastRequest.params.should.have.property(0,'key'); | ||||
|                 lastRequest.query.should.have.property('store','memory'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /context/node/5678', function(done) { | ||||
|             request(app).get("/context/node/5678").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.read',1); | ||||
|                 lastRequest.params.should.have.property('scope','node'); | ||||
|                 lastRequest.params.should.have.property('id','5678'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('GET /context/node/5678/foo?store=memory', function(done) { | ||||
|             request(app).get("/context/node/5678/foo?store=memory").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.read',1); | ||||
|                 lastRequest.params.should.have.property('scope','node'); | ||||
|                 lastRequest.params.should.have.property('id','5678'); | ||||
|                 lastRequest.params.should.have.property(0,'foo'); | ||||
|                 lastRequest.query.should.have.property('store','memory'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('DELETE /context/global/key?store=memory', function(done) { | ||||
|             request(app).del("/context/global/key?store=memory").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.write',1); | ||||
|                 lastRequest.params.should.have.property('scope','global'); | ||||
|                 lastRequest.params.should.have.property(0,'key'); | ||||
|                 lastRequest.query.should.have.property('store','memory'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('DELETE /context/flow/1234/key?store=memory', function(done) { | ||||
|             request(app).del("/context/flow/1234/key?store=memory").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.write',1); | ||||
|                 lastRequest.params.should.have.property('scope','flow'); | ||||
|                 lastRequest.params.should.have.property('id','1234'); | ||||
|                 lastRequest.params.should.have.property(0,'key'); | ||||
|                 lastRequest.query.should.have.property('store','memory'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('DELETE /context/node/5678/foo?store=memory', function(done) { | ||||
|             request(app).del("/context/node/5678/foo?store=memory").expect(200).end(function(err,res) { | ||||
|                 if (err) { | ||||
|                     return done(err); | ||||
|                 } | ||||
|                 permissionChecks.should.have.property('context.write',1); | ||||
|                 lastRequest.params.should.have.property('scope','node'); | ||||
|                 lastRequest.params.should.have.property('id','5678'); | ||||
|                 lastRequest.params.should.have.property(0,'foo'); | ||||
|                 lastRequest.query.should.have.property('store','memory'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
| @@ -19,7 +19,7 @@ var should = require("should"); | ||||
| var sinon = require("sinon"); | ||||
|  | ||||
| var NR_TEST_UTILS = require("nr-test-utils"); | ||||
| var context = NR_TEST_UTILS.require("@node-red/runtime/lib/api/context") | ||||
| var context = NR_TEST_UTILS.require("@node-red/runtime/lib/api/context"); | ||||
|  | ||||
| var mockLog = () => ({ | ||||
|     log: sinon.stub(), | ||||
| @@ -29,8 +29,8 @@ var mockLog = () => ({ | ||||
|     info: sinon.stub(), | ||||
|     metric: sinon.stub(), | ||||
|     audit: sinon.stub(), | ||||
|     _: function() { return "abc"} | ||||
| }) | ||||
|     _: function() { return "abc";} | ||||
| }); | ||||
|  | ||||
| var mockContext = function(contents) { | ||||
|     return { | ||||
| @@ -41,51 +41,65 @@ var mockContext = function(contents) { | ||||
|                 callback(null,undefined); | ||||
|             } | ||||
|         }, | ||||
|         keys: function(store,callback) { | ||||
|         set: function (key, value, store, callback) { | ||||
|             if (contents.hasOwnProperty(store)) { | ||||
|                 callback(null,Object.keys(contents[store])); | ||||
|                 if (!value) { | ||||
|                     delete contents[store][key]; | ||||
|                     callback(null); | ||||
|                 } | ||||
|             } else { | ||||
|                 callback("err store"); | ||||
|             } | ||||
|         }, | ||||
|         keys: function (store, callback) { | ||||
|             if (contents.hasOwnProperty(store)) { | ||||
|                 callback(null, Object.keys(contents[store])); | ||||
|             } else { | ||||
|                 callback("err store"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| describe("runtime-api/context", function() { | ||||
|     describe("getValue", function() { | ||||
|         var contexts = { | ||||
|             global: mockContext({ default: {abc:111}, file: {abc:222}}), | ||||
|             flow1: mockContext({ default: {abc:333}, file: {abc:444}}) | ||||
|         } | ||||
|         var nodeContext = mockContext({ default: {abc:555}, file: {abc:666}}) | ||||
|     var globalContext, flowContext, nodeContext, contexts; | ||||
|  | ||||
|         beforeEach(function() { | ||||
|             context.init({ | ||||
|                 nodes: { | ||||
|                     listContextStores: function() { | ||||
|                         return { default: 'default', stores: [ 'default', 'file' ] } | ||||
|                     }, | ||||
|                     getContext: function(id) { | ||||
|                         return contexts[id] | ||||
|                     }, | ||||
|                     getNode: function(id) { | ||||
|                         if (id === 'known') { | ||||
|                             return { | ||||
|                                 context: function() { return nodeContext } | ||||
|                             } | ||||
|                         } else { | ||||
|                             return null; | ||||
|                         } | ||||
|                     } | ||||
|     beforeEach(function() { | ||||
|         globalContext = { default: { abc: 111 }, file: { abc: 222 } }; | ||||
|         flowContext = { default: { abc: 333 }, file: { abc: 444 } }; | ||||
|         nodeContext = { default: { abc: 555 }, file: { abc: 666 } }; | ||||
|         contexts = { | ||||
|             global: mockContext(globalContext), | ||||
|             flow1: mockContext(flowContext) | ||||
|         }; | ||||
|         context.init({ | ||||
|             nodes: { | ||||
|                 listContextStores: function() { | ||||
|                     return { default: 'default', stores: [ 'default', 'file' ] }; | ||||
|                 }, | ||||
|                 settings: { | ||||
|                     functionGlobalContext: { | ||||
|                         fgc:1234 | ||||
|                     } | ||||
|                 getContext: function(id) { | ||||
|                     return contexts[id]; | ||||
|                 }, | ||||
|                 log: mockLog() | ||||
|             }) | ||||
|                 getNode: function(id) { | ||||
|                     if (id === 'known') { | ||||
|                         return { | ||||
|                             context: function() { return mockContext(nodeContext); } | ||||
|                         }; | ||||
|                     } else { | ||||
|                         return null; | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             settings: { | ||||
|                 functionGlobalContext: { | ||||
|                     fgc:1234 | ||||
|                 } | ||||
|             }, | ||||
|             log: mockLog() | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe("getValue", function() { | ||||
|         it('gets global value of default store', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'global', | ||||
| @@ -95,8 +109,9 @@ describe("runtime-api/context", function() { | ||||
|             }).then(function(result) { | ||||
|                 result.should.have.property('msg','111'); | ||||
|                 result.should.have.property('format','number'); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets global value of specified store', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'global', | ||||
| @@ -106,8 +121,9 @@ describe("runtime-api/context", function() { | ||||
|             }).then(function(result) { | ||||
|                 result.should.have.property('msg','222'); | ||||
|                 result.should.have.property('format','number'); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets flow value of default store', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'flow', | ||||
| @@ -117,8 +133,9 @@ describe("runtime-api/context", function() { | ||||
|             }).then(function(result) { | ||||
|                 result.should.have.property('msg','333'); | ||||
|                 result.should.have.property('format','number'); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets flow value of specified store', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'flow', | ||||
| @@ -128,8 +145,9 @@ describe("runtime-api/context", function() { | ||||
|             }).then(function(result) { | ||||
|                 result.should.have.property('msg','444'); | ||||
|                 result.should.have.property('format','number'); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets node value of default store', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'node', | ||||
| @@ -139,8 +157,9 @@ describe("runtime-api/context", function() { | ||||
|             }).then(function(result) { | ||||
|                 result.should.have.property('msg','555'); | ||||
|                 result.should.have.property('format','number'); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets node value of specified store', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'node', | ||||
| @@ -150,8 +169,8 @@ describe("runtime-api/context", function() { | ||||
|             }).then(function(result) { | ||||
|                 result.should.have.property('msg','666'); | ||||
|                 result.should.have.property('format','number'); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('404s for unknown store', function(done) { | ||||
|             context.getValue({ | ||||
| @@ -162,12 +181,11 @@ describe("runtime-api/context", function() { | ||||
|             }).then(function(result) { | ||||
|                 done("getValue for unknown store should not resolve"); | ||||
|             }).catch(function(err) { | ||||
|                 err.should.have.property('code','not_found') | ||||
|                 err.should.have.property('code','not_found'); | ||||
|                 err.should.have.property('status',404); | ||||
|                 done(); | ||||
|             }) | ||||
|         }) | ||||
|  | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets all global value properties', function() { | ||||
|             return context.getValue({ | ||||
| @@ -180,8 +198,9 @@ describe("runtime-api/context", function() { | ||||
|                     default: { abc: { msg: '111', format: 'number' } }, | ||||
|                     file: { abc: { msg: '222', format: 'number' } } | ||||
|                 }); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets all flow value properties', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'flow', | ||||
| @@ -193,8 +212,9 @@ describe("runtime-api/context", function() { | ||||
|                     default: { abc: { msg: '333', format: 'number' } }, | ||||
|                     file: { abc: { msg: '444', format: 'number' } } | ||||
|                 }); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('gets all node value properties', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'node', | ||||
| @@ -206,8 +226,128 @@ describe("runtime-api/context", function() { | ||||
|                     default: { abc: { msg: '555', format: 'number' } }, | ||||
|                     file: { abc: { msg: '666', format: 'number' } } | ||||
|                 }); | ||||
|             }) | ||||
|         }) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|     }) | ||||
|         it('gets empty object when specified context doesn\'t exist', function() { | ||||
|             return context.getValue({ | ||||
|                 scope: 'node', | ||||
|                 id: 'non-existent', | ||||
|                 store: 'file', | ||||
|                 key: 'abc' | ||||
|             }).then(function(result) { | ||||
|                 result.should.be.an.Object(); | ||||
|                 result.should.be.empty(); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe("delete", function () { | ||||
|         it('deletes global value of default store', function () { | ||||
|             return context.delete({ | ||||
|                 scope: 'global', | ||||
|                 id: undefined, | ||||
|                 store: undefined, // use default | ||||
|                 key: 'abc' | ||||
|             }).then(function () { | ||||
|                 globalContext.should.eql({ | ||||
|                     default: {}, file: { abc: 222 } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('deletes global value of specified store', function () { | ||||
|             return context.delete({ | ||||
|                 scope: 'global', | ||||
|                 id: undefined, | ||||
|                 store: 'file', | ||||
|                 key: 'abc' | ||||
|             }).then(function () { | ||||
|                 globalContext.should.eql({ | ||||
|                     default: { abc: 111 }, file: {} | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('deletes flow value of default store', function () { | ||||
|             return context.delete({ | ||||
|                 scope: 'flow', | ||||
|                 id: 'flow1', | ||||
|                 store: undefined, // use default | ||||
|                 key: 'abc' | ||||
|             }).then(function () { | ||||
|                 flowContext.should.eql({ | ||||
|                     default: {}, file: { abc: 444 } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('deletes flow value of specified store', function () { | ||||
|             return context.delete({ | ||||
|                 scope: 'flow', | ||||
|                 id: 'flow1', | ||||
|                 store: 'file', | ||||
|                 key: 'abc' | ||||
|             }).then(function () { | ||||
|                 flowContext.should.eql({ | ||||
|                     default: { abc: 333 }, file: {} | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('deletes node value of default store', function () { | ||||
|             return context.delete({ | ||||
|                 scope: 'node', | ||||
|                 id: 'known', | ||||
|                 store: undefined, // use default | ||||
|                 key: 'abc' | ||||
|             }).then(function () { | ||||
|                 nodeContext.should.eql({ | ||||
|                     default: {}, file: { abc: 666 } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('deletes node value of specified store', function () { | ||||
|             return context.delete({ | ||||
|                 scope: 'node', | ||||
|                 id: 'known', | ||||
|                 store: 'file', | ||||
|                 key: 'abc' | ||||
|             }).then(function () { | ||||
|                 nodeContext.should.eql({ | ||||
|                     default: { abc: 555 }, file: {} | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('does nothing when specified context doesn\'t exist', function() { | ||||
|             return context.delete({ | ||||
|                 scope: 'node', | ||||
|                 id: 'non-existent', | ||||
|                 store: 'file', | ||||
|                 key: 'abc' | ||||
|             }).then(function(result) { | ||||
|                 should.not.exist(result); | ||||
|                 nodeContext.should.eql({ | ||||
|                     default: { abc: 555 }, file: { abc: 666 } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('404s for unknown store', function (done) { | ||||
|             context.delete({ | ||||
|                 scope: 'global', | ||||
|                 id: undefined, | ||||
|                 store: 'unknown', | ||||
|                 key: 'abc' | ||||
|             }).then(function () { | ||||
|                 done("delete for unknown store should not resolve"); | ||||
|             }).catch(function (err) { | ||||
|                 err.should.have.property('code', 'not_found'); | ||||
|                 err.should.have.property('status', 404); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user