diff --git a/red.js b/red.js index b877e6bae..6162addae 100755 --- a/red.js +++ b/red.js @@ -25,7 +25,6 @@ var nopt = require("nopt"); var path = require("path"); var fs = require("fs-extra"); var RED = require("./red/red.js"); -var log = require("./red/log"); var server; var app = express(); @@ -205,7 +204,7 @@ function basicAuthMiddleware(user,pass) { } if (settings.httpAdminRoot !== false && settings.httpAdminAuth) { - RED.log.warn(log._("server.httpadminauth-deprecated")); + RED.log.warn(RED.log._("server.httpadminauth-deprecated")); app.use(settings.httpAdminRoot, basicAuthMiddleware(settings.httpAdminAuth.user,settings.httpAdminAuth.pass)); } @@ -243,10 +242,10 @@ RED.start().then(function() { if (settings.httpAdminRoot !== false || settings.httpNodeRoot !== false || settings.httpStatic) { server.on('error', function(err) { if (err.errno === "EADDRINUSE") { - RED.log.error(log._("server.unable-to-listen", {listenpath:getListenPath()})); - RED.log.error(log._("server.port-in-use")); + RED.log.error(RED.log._("server.unable-to-listen", {listenpath:getListenPath()})); + RED.log.error(RED.log._("server.port-in-use")); } else { - RED.log.error(log._("server.uncaught-exception")); + RED.log.error(RED.log._("server.uncaught-exception")); if (err.stack) { RED.log.error(err.stack); } else { @@ -257,16 +256,16 @@ RED.start().then(function() { }); server.listen(settings.uiPort,settings.uiHost,function() { if (settings.httpAdminRoot === false) { - RED.log.info(log._("server.admin-ui-disabled")); + RED.log.info(RED.log._("server.admin-ui-disabled")); } process.title = 'node-red'; - RED.log.info(log._("server.now-running", {listenpath:getListenPath()})); + RED.log.info(RED.log._("server.now-running", {listenpath:getListenPath()})); }); } else { - RED.log.info(log._("server.headless-mode")); + RED.log.info(RED.log._("server.headless-mode")); } }).otherwise(function(err) { - RED.log.error(log._("server.failed-to-start")); + RED.log.error(RED.log._("server.failed-to-start")); if (err.stack) { RED.log.error(err.stack); } else { diff --git a/red/api/auth/index.js b/red/api/auth/index.js index ea69c6dbc..1152ce76e 100644 --- a/red/api/auth/index.js +++ b/red/api/auth/index.js @@ -25,7 +25,7 @@ var permissions = require("./permissions"); var theme = require("../theme"); var settings = null; -var log = require("../../log"); +var log = null passport.use(strategies.bearerStrategy.BearerStrategy); @@ -36,11 +36,13 @@ var server = oauth2orize.createServer(); server.exchange(oauth2orize.exchange.password(strategies.passwordTokenExchange)); -function init(_settings,storage) { - settings = _settings; +function init(runtime) { + settings = runtime.settings; + log = runtime.log; if (settings.adminAuth) { Users.init(settings.adminAuth); - Tokens.init(settings.adminAuth,storage); + Tokens.init(settings.adminAuth,runtime.storage); + strategies.init(runtime); } } diff --git a/red/api/auth/strategies.js b/red/api/auth/strategies.js index 6a61b77e0..247d24d2e 100644 --- a/red/api/auth/strategies.js +++ b/red/api/auth/strategies.js @@ -26,7 +26,7 @@ var Users = require("./users"); var Clients = require("./clients"); var permissions = require("./permissions"); -var log = require("../../log"); +var log; var bearerStrategy = function (accessToken, done) { // is this a valid token? @@ -124,6 +124,9 @@ AnonymousStrategy.prototype.authenticate = function(req) { } module.exports = { + init: function(runtime) { + log = runtime.log; + }, bearerStrategy: bearerStrategy, clientPasswordStrategy: clientPasswordStrategy, passwordTokenExchange: passwordTokenExchange, diff --git a/red/api/credentials.js b/red/api/credentials.js index f2cc601e8..ae3123b3b 100644 --- a/red/api/credentials.js +++ b/red/api/credentials.js @@ -14,10 +14,14 @@ * limitations under the License. **/ -var log = require("../log"); -var api = require("../nodes"); +var log; +var api; module.exports = { + init: function(runtime) { + log = runtime.log; + api = runtime.api; + }, get: function (req, res) { // TODO: It should verify the given node id is of the type specified - // but that would add a dependency from this module to the diff --git a/red/api/flows.js b/red/api/flows.js index 72cc6ae9f..9167f3e8d 100644 --- a/red/api/flows.js +++ b/red/api/flows.js @@ -14,12 +14,16 @@ * limitations under the License. **/ -var log = require("../log"); - -var redNodes = require("../nodes"); -var settings = require("../settings"); +var log; +var redNodes; +var settings; module.exports = { + init: function(runtime) { + settings = runtime.settings; + redNodes = runtime.api; + log = runtime.log; + }, get: function(req,res) { log.audit({event: "flows.get"},req); res.json(redNodes.getFlows()); diff --git a/red/api/index.js b/red/api/index.js index a01fca399..e2cc5f92a 100644 --- a/red/api/index.js +++ b/red/api/index.js @@ -29,12 +29,12 @@ var theme = require("./theme"); var locales = require("./locales"); var credentials = require("./credentials"); -var log = require("../log"); - var auth = require("./auth"); var needsPermission = auth.needsPermission; -var settings = require("../settings"); +var log; +var adminApp; +var nodeApp; var errorHandler = function(err,req,res,next) { if (err.message === "request entity too large") { @@ -46,71 +46,92 @@ var errorHandler = function(err,req,res,next) { res.status(400).json({error:"unexpected_error", message:err.toString()}); }; -function init(adminApp,storage) { +function init(runtime) { + var settings = runtime.settings; + log = runtime.log; + if (settings.httpNodeRoot !== false) { + nodeApp = express(); + } + if (settings.httpAdminRoot !== false) { + adminApp = express(); + auth.init(runtime); + credentials.init(runtime); + flows.init(runtime); + info.init(runtime); + library.init(adminApp,runtime); + locales.init(runtime); + nodes.init(runtime); - auth.init(settings,storage); - // Editor - if (!settings.disableEditor) { - ui.init(settings); - var editorApp = express(); - editorApp.get("/",ui.ensureSlash,ui.editor); - editorApp.get("/icons/:icon",ui.icon); - if (settings.editorTheme) { - editorApp.use("/theme",theme.init(settings)); + // Editor + if (!settings.disableEditor) { + ui.init(runtime); + var editorApp = express(); + editorApp.get("/",ui.ensureSlash,ui.editor); + editorApp.get("/icons/:icon",ui.icon); + if (settings.editorTheme) { + editorApp.use("/theme",theme.init(runtime)); + } + editorApp.use("/",ui.editorResources); + adminApp.use(editorApp); } - editorApp.use("/",ui.editorResources); - adminApp.use(editorApp); + var maxApiRequestSize = settings.apiMaxLength || '1mb'; + adminApp.use(bodyParser.json({limit:maxApiRequestSize})); + adminApp.use(bodyParser.urlencoded({limit:maxApiRequestSize,extended:true})); + + adminApp.get("/auth/login",auth.login); + + if (settings.adminAuth) { + //TODO: all passport references ought to be in ./auth + adminApp.use(passport.initialize()); + adminApp.post("/auth/token", + auth.ensureClientSecret, + auth.authenticateClient, + auth.getToken, + auth.errorHandler + ); + adminApp.post("/auth/revoke",needsPermission(""),auth.revoke); + } + + // Flows + adminApp.get("/flows",needsPermission("flows.read"),flows.get); + adminApp.post("/flows",needsPermission("flows.write"),flows.post); + + // Nodes + adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll); + adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post); + + adminApp.get("/nodes/:mod",needsPermission("nodes.read"),nodes.getModule); + adminApp.put("/nodes/:mod",needsPermission("nodes.write"),nodes.putModule); + adminApp.delete("/nodes/:mod",needsPermission("nodes.write"),nodes.delete); + + adminApp.get("/nodes/:mod/:set",needsPermission("nodes.read"),nodes.getSet); + adminApp.put("/nodes/:mod/:set",needsPermission("nodes.write"),nodes.putSet); + + adminApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get); + + adminApp.get(/locales\/(.+)\/?$/,locales.get); + + // Library + adminApp.post(new RegExp("/library/flows\/(.*)"),needsPermission("library.write"),library.post); + adminApp.get("/library/flows",needsPermission("library.read"),library.getAll); + adminApp.get(new RegExp("/library/flows\/(.*)"),needsPermission("library.read"),library.get); + + // Settings + adminApp.get("/settings",needsPermission("settings.read"),info.settings); + + // Error Handler + adminApp.use(errorHandler); } - var maxApiRequestSize = settings.apiMaxLength || '1mb'; - adminApp.use(bodyParser.json({limit:maxApiRequestSize})); - adminApp.use(bodyParser.urlencoded({limit:maxApiRequestSize,extended:true})); - - adminApp.get("/auth/login",auth.login); - - if (settings.adminAuth) { - //TODO: all passport references ought to be in ./auth - adminApp.use(passport.initialize()); - adminApp.post("/auth/token", - auth.ensureClientSecret, - auth.authenticateClient, - auth.getToken, - auth.errorHandler - ); - adminApp.post("/auth/revoke",needsPermission(""),auth.revoke); - } - - // Flows - adminApp.get("/flows",needsPermission("flows.read"),flows.get); - adminApp.post("/flows",needsPermission("flows.write"),flows.post); - - // Nodes - adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll); - adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post); - - adminApp.get("/nodes/:mod",needsPermission("nodes.read"),nodes.getModule); - adminApp.put("/nodes/:mod",needsPermission("nodes.write"),nodes.putModule); - adminApp.delete("/nodes/:mod",needsPermission("nodes.write"),nodes.delete); - - adminApp.get("/nodes/:mod/:set",needsPermission("nodes.read"),nodes.getSet); - adminApp.put("/nodes/:mod/:set",needsPermission("nodes.write"),nodes.putSet); - - adminApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get); - - adminApp.get(/locales\/(.+)\/?$/,locales.get); - - // Library - library.init(adminApp); - adminApp.post(new RegExp("/library/flows\/(.*)"),needsPermission("library.write"),library.post); - adminApp.get("/library/flows",needsPermission("library.read"),library.getAll); - adminApp.get(new RegExp("/library/flows\/(.*)"),needsPermission("library.read"),library.get); - - // Settings - adminApp.get("/settings",needsPermission("settings.read"),info.settings); - - // Error Handler - adminApp.use(errorHandler); } module.exports = { - init: init + init: init, + library: { + register: library.register + }, + auth: { + needsPermission: auth.needsPermission + }, + adminApp: function() { return adminApp; }, + nodeApp: function() { return nodeApp; } }; diff --git a/red/api/info.js b/red/api/info.js index 6cdd20b94..a9f79a0d4 100644 --- a/red/api/info.js +++ b/red/api/info.js @@ -13,28 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var settings = require('../settings'); var theme = require("./theme"); - var util = require('util'); +var settings; module.exports = { + init: function(runtime) { + settings = runtime.settings; + }, settings: function(req,res) { var safeSettings = { httpNodeRoot: settings.httpNodeRoot, version: settings.version, user: req.user } - + var themeSettings = theme.settings(); if (themeSettings) { safeSettings.editorTheme = themeSettings; } - + if (util.isArray(settings.paletteCategories)) { safeSettings.paletteCategories = settings.paletteCategories; } - + res.json(safeSettings); } } diff --git a/red/api/library.js b/red/api/library.js index a257b4fe6..a73c1dd47 100644 --- a/red/api/library.js +++ b/red/api/library.js @@ -15,9 +15,8 @@ **/ var redApp = null; -var storage = require("../storage"); -var log = require("../log"); - +var storage; +var log; var needsPermission = require("./auth").needsPermission; function createLibrary(type) { @@ -70,8 +69,10 @@ function createLibrary(type) { } } module.exports = { - init: function(app) { + init: function(app,runtime) { redApp = app; + log = runtime.log; + storage = runtime.storage; }, register: createLibrary, @@ -90,7 +91,7 @@ module.exports = { }).otherwise(function(err) { if (err) { log.warn(log._("api.library.error-load-flow",{path:req.params[0],message:err.toString()})); - if (err.code === 'forbidden') { + if (err.code === 'forbidden') { log.audit({event: "library.get",type:"flow",path:req.params[0],error:"forbidden"},req); res.status(403).end(); return; diff --git a/red/api/locales.js b/red/api/locales.js index 28dc37f99..53520f221 100644 --- a/red/api/locales.js +++ b/red/api/locales.js @@ -13,9 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var i18n = require("../i18n"); - +var i18n; module.exports = { + init: function(runtime) { + i18n = runtime.i18n; + }, get: function(req,res) { var namespace = req.params[0]; namespace = namespace.replace(/\.json$/,""); diff --git a/red/api/nodes.js b/red/api/nodes.js index 47e42be32..8153fcadb 100644 --- a/red/api/nodes.js +++ b/red/api/nodes.js @@ -13,16 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var redNodes = require("../nodes"); -var comms = require("../comms"); -var log = require("../log"); -var i18n = require("../i18n"); var when = require("when"); - -var settings = require("../settings"); +var redNodes; +var comms; +var log; +var i18n; +var settings; module.exports = { + init: function(runtime) { + redNodes = runtime.api; + comms = runtime.comms; + log = runtime.log; + i18n = runtime.i18n; + settings = runtime.settings; + }, getAll: function(req,res) { if (req.get("accept") == "application/json") { log.audit({event: "nodes.list.get"},req); diff --git a/red/api/theme.js b/red/api/theme.js index c3de9a86e..1104976ee 100644 --- a/red/api/theme.js +++ b/red/api/theme.js @@ -53,7 +53,8 @@ function serveFile(app,baseUrl,file) { } module.exports = { - init: function(settings) { + init: function(runtime) { + var settings = runtime.settings; var i; var url; themeContext = clone(defaultContext); diff --git a/red/api/ui.js b/red/api/ui.js index 9bdca4f56..01fbc7007 100644 --- a/red/api/ui.js +++ b/red/api/ui.js @@ -1,5 +1,5 @@ /** - * Copyright 2013, 2014 IBM Corp. + * Copyright 2013, 2015 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,26 +21,26 @@ var theme = require("./theme"); var Mustache = require("mustache"); -var events = require("../events"); -var settings; - var icon_paths = [path.resolve(__dirname + '/../../public/icons')]; var iconCache = {}; //TODO: create a default icon var defaultIcon = path.resolve(__dirname + '/../../public/icons/arrow-in.png'); - -events.on("node-icon-dir",function(dir) { - icon_paths.push(path.resolve(dir)); -}); - var templateDir = path.resolve(__dirname+"/../../editor/templates"); var editorTemplate; +function nodeIconDir(dir) { + icon_paths.push(path.resolve(dir)); +} + module.exports = { - init: function(_settings) { - settings = _settings; + init: function(runtime) { editorTemplate = fs.readFileSync(path.join(templateDir,"index.mst"),"utf8"); Mustache.parse(editorTemplate); + // TODO: this allows init to be called multiple times without + // registering multiple instances of the listener. + // It isn't.... ideal. + runtime.events.removeListener("node-icon-dir",nodeIconDir); + runtime.events.on("node-icon-dir",nodeIconDir); }, ensureSlash: function(req,res,next) { diff --git a/red/red.js b/red/red.js index c96888224..aead539fa 100644 --- a/red/red.js +++ b/red/red.js @@ -14,22 +14,18 @@ * limitations under the License. **/ -var server = require("./server"); -var nodes = require("./nodes"); -var library = require("./api/library"); -var comms = require("./comms"); -var log = require("./log"); -var util = require("./util"); -var i18n = require("./i18n"); var fs = require("fs"); -var settings = require("./settings"); -var credentials = require("./nodes/credentials"); -var auth = require("./api/auth"); var path = require('path'); -var events = require("events"); + +var runtime = require("./runtime"); +var api = require("./api"); process.env.NODE_RED_HOME = process.env.NODE_RED_HOME || path.resolve(__dirname+"/.."); +var nodeApp = null; +var adminApp = null; +var server = null; + function checkBuild() { var editorFile = path.resolve(path.join(__dirname,"..","public","red","red.min.js")); try { @@ -43,40 +39,44 @@ function checkBuild() { var RED = { init: function(httpServer,userSettings) { + server = httpServer; + if (!userSettings.SKIP_BUILD_CHECK) { checkBuild(); } - userSettings.version = this.version(); - log.init(userSettings); - settings.init(userSettings); - server.init(httpServer,settings); - return server.app; - }, - start: server.start, - stop: server.stop, - nodes: nodes, - library: { register: library.register }, - credentials: credentials, - events: events, - log: log, - comms: comms, - settings:settings, - util: util, - auth: { - needsPermission: auth.needsPermission - }, - version: function () { - var p = require(path.join(process.env.NODE_RED_HOME,"package.json")).version; - /* istanbul ignore else */ - if (fs.existsSync(path.join(process.env.NODE_RED_HOME,".git"))) { - p += "-git"; + runtime.init(httpServer,userSettings); + if (userSettings.httpAdminRoot !== false || userSettings.httpNodeRoot !== false) { + api.init(runtime); + adminApp = api.adminApp(); + nodeApp = api.nodeApp(); } - return p; + + if (adminApp === null) { + adminApp = { + get:function(){}, + post: function(){}, + put: function(){}, + delete: function(){} + } + } + return runtime.app; }, - get app() { console.log("Deprecated use of RED.app - use RED.httpAdmin instead"); return server.app }, - get httpAdmin() { return server.app }, - get httpNode() { return server.nodeApp }, - get server() { return server.server } + start: runtime.start, + stop: runtime.stop, + nodes: runtime.api, + events: runtime.events, + log: runtime.log, + comms: runtime.comms, + settings:runtime.settings, + util: runtime.util, + version: runtime.version, + library: api.library, + auth: api.auth, + + get app() { console.log("Deprecated use of RED.app - use RED.httpAdmin instead"); return runtime.app }, + get httpAdmin() { return adminApp }, + get httpNode() { return nodeApp }, + get server() { return server } }; module.exports = RED; diff --git a/red/comms.js b/red/runtime/comms.js similarity index 97% rename from red/comms.js rename to red/runtime/comms.js index d5df4ef7f..59c8d0e11 100644 --- a/red/comms.js +++ b/red/runtime/comms.js @@ -37,9 +37,9 @@ function init(_server,_settings) { function start() { - var Tokens = require("./api/auth/tokens"); - var Users = require("./api/auth/users"); - var Permissions = require("./api/auth/permissions"); + var Tokens = require("../api/auth/tokens"); + var Users = require("../api/auth/users"); + var Permissions = require("../api/auth/permissions"); if (!settings.disableEditor) { Users.default().then(function(anonymousUser) { var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000; diff --git a/red/events.js b/red/runtime/events.js similarity index 100% rename from red/events.js rename to red/runtime/events.js diff --git a/red/i18n.js b/red/runtime/i18n.js similarity index 97% rename from red/i18n.js rename to red/runtime/i18n.js index 83e5fd273..eaa9189f0 100644 --- a/red/i18n.js +++ b/red/runtime/i18n.js @@ -24,11 +24,11 @@ var supportedLangs = []; var resourceMap = { "runtime": { - basedir: path.resolve(__dirname+"/../locales"), + basedir: path.resolve(__dirname+"/../../locales"), file:"runtime.json" }, "editor": { - basedir: path.resolve(__dirname+"/../locales"), + basedir: path.resolve(__dirname+"/../../locales"), file: "editor.json" } } diff --git a/red/server.js b/red/runtime/index.js similarity index 86% rename from red/server.js rename to red/runtime/index.js index ced1652ec..85935660b 100644 --- a/red/server.js +++ b/red/runtime/index.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var express = require('express'); var when = require('when'); var redNodes = require("./nodes"); @@ -22,23 +21,27 @@ var comms = require("./comms"); var storage = require("./storage"); var log = require("./log"); var i18n = require("./i18n"); - -var app = null; -var nodeApp = null; -var server = null; -var settings = null; +var events = require("./events"); +var settings = require("./settings"); +var path = require('path'); +var fs = require("fs"); var runtimeMetricInterval = null; +function init(server,userSettings) { + userSettings.version = version(); + log.init(userSettings); + settings.init(userSettings); + comms.init(server,settings); +} -function init(_server,_settings) { - server = _server; - settings = _settings; - - comms.init(_server,_settings); - - nodeApp = express(); - app = express(); +function version() { + var p = require(path.join(process.env.NODE_RED_HOME,"package.json")).version; + /* istanbul ignore else */ + if (fs.existsSync(path.join(process.env.NODE_RED_HOME,".git"))) { + p += "-git"; + } + return p; } function start() { @@ -46,9 +49,6 @@ function start() { .then(function() { return storage.init(settings)}) .then(function() { return settings.load(storage)}) .then(function() { - if (settings.httpAdminRoot !== false) { - require("./api").init(app,storage); - } if (log.metric()) { runtimeMetricInterval = setInterval(function() { @@ -141,12 +141,19 @@ function stop() { comms.stop(); } -var serverAPI = module.exports = { +var runtime = module.exports = { init: init, start: start, stop: stop, - get app() { return app }, - get nodeApp() { return nodeApp }, - get server() { return server } + version: version, + + log: log, + i18n: i18n, + settings: settings, + storage: storage, + comms: comms, + events: events, + api: redNodes, + util: require("./util") } diff --git a/red/log.js b/red/runtime/log.js similarity index 100% rename from red/log.js rename to red/runtime/log.js diff --git a/red/nodes/Node.js b/red/runtime/nodes/Node.js similarity index 100% rename from red/nodes/Node.js rename to red/runtime/nodes/Node.js diff --git a/red/nodes/credentials.js b/red/runtime/nodes/credentials.js similarity index 98% rename from red/nodes/credentials.js rename to red/runtime/nodes/credentials.js index 57a0da054..aeab852b6 100644 --- a/red/nodes/credentials.js +++ b/red/runtime/nodes/credentials.js @@ -18,8 +18,6 @@ var when = require("when"); var log = require("../log"); -var needsPermission = require("../api/auth").needsPermission; - var credentialCache = {}; var storage = null; var credentialsDef = {}; diff --git a/red/nodes/flows/Flow.js b/red/runtime/nodes/flows/Flow.js similarity index 100% rename from red/nodes/flows/Flow.js rename to red/runtime/nodes/flows/Flow.js diff --git a/red/nodes/flows/index.js b/red/runtime/nodes/flows/index.js similarity index 100% rename from red/nodes/flows/index.js rename to red/runtime/nodes/flows/index.js diff --git a/red/nodes/flows/util.js b/red/runtime/nodes/flows/util.js similarity index 100% rename from red/nodes/flows/util.js rename to red/runtime/nodes/flows/util.js diff --git a/red/nodes/index.js b/red/runtime/nodes/index.js similarity index 100% rename from red/nodes/index.js rename to red/runtime/nodes/index.js diff --git a/red/nodes/registry/deprecated.js b/red/runtime/nodes/registry/deprecated.js similarity index 100% rename from red/nodes/registry/deprecated.js rename to red/runtime/nodes/registry/deprecated.js diff --git a/red/nodes/registry/index.js b/red/runtime/nodes/registry/index.js similarity index 100% rename from red/nodes/registry/index.js rename to red/runtime/nodes/registry/index.js diff --git a/red/nodes/registry/installer.js b/red/runtime/nodes/registry/installer.js similarity index 100% rename from red/nodes/registry/installer.js rename to red/runtime/nodes/registry/installer.js diff --git a/red/nodes/registry/loader.js b/red/runtime/nodes/registry/loader.js similarity index 99% rename from red/nodes/registry/loader.js rename to red/runtime/nodes/registry/loader.js index 265abe71f..2cc57fc41 100644 --- a/red/nodes/registry/loader.js +++ b/red/runtime/nodes/registry/loader.js @@ -36,9 +36,7 @@ events.on("node-locales-dir", function(info) { function init(_settings) { settings = _settings; localfilesystem.init(settings); - - RED = require('../../red'); - + RED = require('../../../red'); } function load(defaultNodesDir,disableNodePathScan) { diff --git a/red/nodes/registry/localfilesystem.js b/red/runtime/nodes/registry/localfilesystem.js similarity index 99% rename from red/nodes/registry/localfilesystem.js rename to red/runtime/nodes/registry/localfilesystem.js index 92998dbf5..28d8bf5d4 100644 --- a/red/nodes/registry/localfilesystem.js +++ b/red/runtime/nodes/registry/localfilesystem.js @@ -22,7 +22,7 @@ var events = require("../../events"); var log = require("../../log"); var settings; -var defaultNodesDir = path.resolve(path.join(__dirname,"..","..","..","nodes")); +var defaultNodesDir = path.resolve(path.join(__dirname,"..","..","..","..","nodes")); var disableNodePathScan = false; function init(_settings,_defaultNodesDir,_disableNodePathScan) { @@ -133,7 +133,7 @@ function scanDirForNodesModules(dir,moduleName) { * @return a list of node modules: {dir,package} */ function scanTreeForNodesModules(moduleName) { - var dir = __dirname+"/../../nodes"; + var dir = __dirname+"/../../../../nodes"; var results = []; var userDir; diff --git a/red/nodes/registry/registry.js b/red/runtime/nodes/registry/registry.js similarity index 99% rename from red/nodes/registry/registry.js rename to red/runtime/nodes/registry/registry.js index 886be8767..ebd7d4cf0 100644 --- a/red/nodes/registry/registry.js +++ b/red/runtime/nodes/registry/registry.js @@ -256,7 +256,7 @@ function getFullNodeInfo(typeOrId) { var module = moduleConfigs[getModule(id)]; if (module) { return module.nodes[getNode(id)]; - } + } } return null; } @@ -292,7 +292,7 @@ function getModuleList() { //} //return list; return moduleConfigs; - + } function getModuleInfo(module) { @@ -358,7 +358,7 @@ function getNodeConfig(id,lang) { if (config) { var result = config.config; result += loader.getNodeHelp(config,lang||"en-US") - + //if (config.script) { // result += ''; //} @@ -490,9 +490,9 @@ var registry = module.exports = { addNodeSet: addNodeSet, enableNodeSet: enableNodeSet, disableNodeSet: disableNodeSet, - + removeModule: removeModule, - + getNodeInfo: getNodeInfo, getFullNodeInfo: getFullNodeInfo, getNodeList: getNodeList, diff --git a/red/settings.js b/red/runtime/settings.js similarity index 100% rename from red/settings.js rename to red/runtime/settings.js diff --git a/red/storage/index.js b/red/runtime/storage/index.js similarity index 100% rename from red/storage/index.js rename to red/runtime/storage/index.js diff --git a/red/storage/localfilesystem.js b/red/runtime/storage/localfilesystem.js similarity index 100% rename from red/storage/localfilesystem.js rename to red/runtime/storage/localfilesystem.js diff --git a/red/util.js b/red/runtime/util.js similarity index 100% rename from red/util.js rename to red/runtime/util.js diff --git a/test/red/api/auth/index_spec.js b/test/red/api/auth/index_spec.js index bb6a33be2..1dd8119e5 100644 --- a/test/red/api/auth/index_spec.js +++ b/test/red/api/auth/index_spec.js @@ -24,12 +24,14 @@ var auth = require("../../../../red/api/auth"); var Users = require("../../../../red/api/auth/users"); var Tokens = require("../../../../red/api/auth/tokens"); -var settings = require("../../../../red/settings"); - - describe("api auth middleware",function() { + + describe("ensureClientSecret", function() { + before(function() { + auth.init({settings:{},log:{audit:function(){}}}) + }); it("leaves client_secret alone if not present",function(done) { var req = { body: { @@ -83,7 +85,7 @@ describe("api auth middleware",function() { Users.init.restore(); }); it("returns login details - credentials", function(done) { - auth.init({adminAuth:{}},null); + auth.init({settings:{adminAuth:{}},log:{audit:function(){}}}) auth.login(null,{json: function(resp) { resp.should.have.a.property("type","credentials"); resp.should.have.a.property("prompts"); @@ -92,7 +94,7 @@ describe("api auth middleware",function() { }}); }); it("returns login details - none", function(done) { - auth.init({},null); + auth.init({settings:{},log:{audit:function(){}}}) auth.login(null,{json: function(resp) { resp.should.eql({}); done(); diff --git a/test/red/api/auth/strategies_spec.js b/test/red/api/auth/strategies_spec.js index 3e46db0c0..5dc6fb7c0 100644 --- a/test/red/api/auth/strategies_spec.js +++ b/test/red/api/auth/strategies_spec.js @@ -24,8 +24,10 @@ var Tokens = require("../../../../red/api/auth/tokens"); var Clients = require("../../../../red/api/auth/clients"); describe("Auth strategies", function() { + before(function() { + strategies.init({log:{audit:function(){}}}) + }); describe("Password Token Exchange", function() { - var userAuthentication; afterEach(function() { if (userAuthentication) { @@ -49,7 +51,7 @@ describe("Auth strategies", function() { } }); }); - + it('Handles scope overreach',function(done) { userAuthentication = sinon.stub(Users,"authenticate",function(username,password) { return when.resolve({username:"user",permissions:"read"}); diff --git a/test/red/api/credentials_spec.js b/test/red/api/credentials_spec.js index 70e62c796..b4fc14e48 100644 --- a/test/red/api/credentials_spec.js +++ b/test/red/api/credentials_spec.js @@ -20,8 +20,6 @@ var express = require('express'); var sinon = require('sinon'); var when = require('when'); - -var nodeApi = require("../../../red/nodes"); var credentials = require("../../../red/api/credentials"); describe('credentials api', function() { @@ -30,26 +28,26 @@ describe('credentials api', function() { before(function() { app = express(); app.get('/credentials/:type/:id',credentials.get); - - sinon.stub(nodeApi,"getCredentials",function(id) { - if (id === "n1") { - return {user1:"abc",password1:"123"}; - } else { - return null; - } - }); - sinon.stub(nodeApi,"getCredentialDefinition",function(type) { - if (type === "known-type") { - return {user1:{type:"text"},password1:{type:"password"}}; - } else { - return null; + credentials.init({ + log:{audit:function(){}}, + api:{ + getCredentials: function(id) { + if (id === "n1") { + return {user1:"abc",password1:"123"}; + } else { + return null; + } + }, + getCredentialDefinition:function(type) { + if (type === "known-type") { + return {user1:{type:"text"},password1:{type:"password"}}; + } else { + return null; + } + } } }); }); - after(function() { - nodeApi.getCredentials.restore(); - nodeApi.getCredentialDefinition.restore(); - }) it('returns empty credentials if unknown type',function(done) { request(app) .get("/credentials/unknown-type/n1") diff --git a/test/red/api/flows_spec.js b/test/red/api/flows_spec.js index f2b7fe2e9..a39806eb3 100644 --- a/test/red/api/flows_spec.js +++ b/test/red/api/flows_spec.js @@ -21,8 +21,6 @@ var bodyParser = require('body-parser'); var sinon = require('sinon'); var when = require('when'); -var redNodes = require("../../../red/nodes"); - var flows = require("../../../red/api/flows"); describe("flows api", function() { @@ -37,15 +35,17 @@ describe("flows api", function() { }); it('returns flow', function(done) { - var getFlows = sinon.stub(redNodes,'getFlows', function() { - return [1,2,3]; + flows.init({ + log:{warn:function(){},_:function(){},audit:function(){}}, + api:{ + getFlows: function() { return [1,2,3]; } + } }); request(app) .get('/flows') .set('Accept', 'application/json') .expect(200) .end(function(err,res) { - getFlows.restore(); if (err) { throw err; } @@ -55,15 +55,17 @@ describe("flows api", function() { }); it('sets flows', function(done) { - var setFlows = sinon.stub(redNodes,'setFlows', function() { - return when.resolve(); + flows.init({ + log:{warn:function(){},_:function(){},audit:function(){}}, + api:{ + setFlows: function() { return when.resolve(); } + } }); request(app) .post('/flows') .set('Accept', 'application/json') .expect(204) .end(function(err,res) { - setFlows.restore(); if (err) { throw err; } @@ -71,15 +73,17 @@ describe("flows api", function() { }); }); it('returns error when set fails', function(done) { - var setFlows = sinon.stub(redNodes,'setFlows', function() { - return when.reject(new Error("expected error")); + flows.init({ + log:{warn:function(){},_:function(){},audit:function(){}}, + api:{ + setFlows: function() { return when.reject(new Error("expected error")); } + } }); request(app) .post('/flows') .set('Accept', 'application/json') .expect(500) .end(function(err,res) { - setFlows.restore(); if (err) { throw err; } diff --git a/test/red/api/index_spec.js b/test/red/api/index_spec.js index 4117ae6a5..d53633a4a 100644 --- a/test/red/api/index_spec.js +++ b/test/red/api/index_spec.js @@ -15,12 +15,12 @@ **/ var should = require("should"); +var sinon = require("sinon"); var request = require("supertest"); var express = require("express"); var when = require("when"); var fs = require("fs"); var path = require("path"); -var settings = require("../../../red/settings"); var api = require("../../../red/api"); describe("api index", function() { @@ -28,12 +28,13 @@ describe("api index", function() { describe("disables editor", function() { before(function() { - settings.init({disableEditor:true}); app = express(); - api.init(app); - }); - after(function() { - settings.reset(); + api.init(app,{ + settings:{disableEditor:true}, + api:{ + + } + }); }); it('does not serve the editor', function(done) { @@ -54,14 +55,25 @@ describe("api index", function() { }); describe("can serve auth", function() { + var mockList = [ + 'ui','nodes','flows','library','info','theme','locales','credentials' + ] before(function() { - //settings.init({disableEditor:true}); - settings.init({adminAuth:{type: "credentials",users:[],default:{permissions:"read"}}}); - app = express(); - api.init(app,{getSessions:function(){return when.resolve({})}}); + mockList.forEach(function(m) { + sinon.stub(require("../../../red/api/"+m),"init",function(){}); + }); }); after(function() { - settings.reset(); + mockList.forEach(function(m) { + require("../../../red/api/"+m).init.restore(); + }) + }); + before(function() { + app = express(); + api.init(app,{ + settings:{adminAuth:{type: "credentials",users:[],default:{permissions:"read"}}}, + storage:{getSessions:function(){return when.resolve({})}} + }); }); it('it now serves auth', function(done) { @@ -77,15 +89,29 @@ describe("api index", function() { }); describe("enables editor", function() { + + var mockList = [ + 'nodes','flows','library','info','theme','locales','credentials' + ] before(function() { - settings.init({disableEditor:false}); - app = express(); - api.init(app); + mockList.forEach(function(m) { + sinon.stub(require("../../../red/api/"+m),"init",function(){}); + }); }); after(function() { - settings.reset(); + mockList.forEach(function(m) { + require("../../../red/api/"+m).init.restore(); + }) }); + before(function() { + app = express(); + api.init(app,{ + log:{audit:function(){}}, + settings:{disableEditor:false}, + events:{on:function(){},removeListener:function(){}} + }); + }); it('serves the editor', function(done) { request(app) .get("/") diff --git a/test/red/api/info_spec.js b/test/red/api/info_spec.js index f7124c661..2d522a576 100644 --- a/test/red/api/info_spec.js +++ b/test/red/api/info_spec.js @@ -21,30 +21,26 @@ var sinon = require('sinon'); var when = require('when'); var app = express(); -var settings = require("../../../red/settings"); var info = require("../../../red/api/info"); - var theme = require("../../../red/api/theme"); describe("info api", function() { describe("settings handler", function() { before(function() { - var userSettings = { - foo: 123, - httpNodeRoot: "testHttpNodeRoot", - version: "testVersion", - paletteCategories :["red","blue","green"] - } - settings.init(userSettings); - sinon.stub(theme,"settings",function() { return { test: 456 };}); - + info.init({ + settings: { + foo: 123, + httpNodeRoot: "testHttpNodeRoot", + version: "testVersion", + paletteCategories :["red","blue","green"] + } + }) app = express(); app.get("/settings",info.settings); }); after(function() { - settings.reset(); theme.settings.restore(); }); diff --git a/test/red/api/library_spec.js b/test/red/api/library_spec.js index 46561be74..50713a58e 100644 --- a/test/red/api/library_spec.js +++ b/test/red/api/library_spec.js @@ -21,19 +21,18 @@ var bodyParser = require('body-parser'); var when = require('when'); -var app = express(); -var RED = require("../../../red/red.js"); -var storage = require("../../../red/storage"); +var app; var library = require("../../../red/api/library"); var auth = require("../../../red/api/auth"); describe("library api", function() { - function initStorage(_flows,_libraryEntries) { + function initLibrary(_flows,_libraryEntries) { var flows = _flows; var libraryEntries = _libraryEntries; - storage.init({ - storageModule: { + library.init(app,{ + log:{audit:function(){},_:function(){},warn:function(){}}, + storage: { init: function() { return when.resolve(); }, @@ -43,15 +42,29 @@ describe("library api", function() { getFlow: function(fn) { if (flows[fn]) { return when.resolve(flows[fn]); + } else if (fn.indexOf("..")!==-1) { + var err = new Error(); + err.code = 'forbidden'; + return when.reject(err); } else { return when.reject(); } }, saveFlow: function(fn,data) { + if (fn.indexOf("..")!==-1) { + var err = new Error(); + err.code = 'forbidden'; + return when.reject(err); + } flows[fn] = data; return when.resolve(); }, getLibraryEntry: function(type,path) { + if (path.indexOf("..")!==-1) { + var err = new Error(); + err.code = 'forbidden'; + return when.reject(err); + } if (libraryEntries[type] && libraryEntries[type][path]) { return when.resolve(libraryEntries[type][path]); } else { @@ -59,6 +72,11 @@ describe("library api", function() { } }, saveLibraryEntry: function(type,path,meta,body) { + if (path.indexOf("..")!==-1) { + var err = new Error(); + err.code = 'forbidden'; + return when.reject(err); + } libraryEntries[type][path] = body; return when.resolve(); } @@ -67,8 +85,6 @@ describe("library api", function() { } describe("flows", function() { - var app; - before(function() { app = express(); app.use(bodyParser.json()); @@ -77,7 +93,7 @@ describe("library api", function() { app.get(new RegExp("/library/flows\/(.*)"),library.get); }); it('returns empty result', function(done) { - initStorage({},{flows:{}}); + initLibrary({},{flows:{}}); request(app) .get('/library/flows') .expect(200) @@ -92,7 +108,7 @@ describe("library api", function() { }); it('returns 404 for non-existent entry', function(done) { - initStorage({},{flows:{}}); + initLibrary({},{flows:{}}); request(app) .get('/library/flows/foo') .expect(404) @@ -101,7 +117,7 @@ describe("library api", function() { it('can store and retrieve item', function(done) { - initStorage({},{flows:{}}); + initLibrary({},{flows:{}}); var flow = '[]'; request(app) .post('/library/flows/foo') @@ -125,7 +141,7 @@ describe("library api", function() { }); it('lists a stored item', function(done) { - initStorage({f:["bar"]}); + initLibrary({f:["bar"]}); request(app) .get('/library/flows') .expect(200) @@ -140,7 +156,7 @@ describe("library api", function() { }); it('returns 403 for malicious get attempt', function(done) { - initStorage({}); + initLibrary({}); // without the userDir override the malicious url would be // http://127.0.0.1:1880/library/flows/../../package to // obtain package.json from the node-red root. @@ -150,7 +166,7 @@ describe("library api", function() { .end(done); }); it('returns 403 for malicious post attempt', function(done) { - initStorage({}); + initLibrary({}); // without the userDir override the malicious url would be // http://127.0.0.1:1880/library/flows/../../package to // obtain package.json from the node-red root. @@ -162,18 +178,17 @@ describe("library api", function() { }); describe("type", function() { - var app; - before(function() { + app = express(); app.use(bodyParser.json()); - library.init(app); - auth.init({}); - RED.library.register("test"); + initLibrary({},{}); + auth.init({settings:{}}); + library.register("test"); }); it('returns empty result', function(done) { - initStorage({},{'test':{"":[]}}); + initLibrary({},{'test':{"":[]}}); request(app) .get('/library/test') .expect(200) @@ -187,7 +202,7 @@ describe("library api", function() { }); it('returns 404 for non-existent entry', function(done) { - initStorage({},{}); + initLibrary({},{}); request(app) .get('/library/test/foo') .expect(404) @@ -195,7 +210,7 @@ describe("library api", function() { }); it('can store and retrieve item', function(done) { - initStorage({},{'test':{}}); + initLibrary({},{'test':{}}); var flow = {text:"test content"}; request(app) .post('/library/test/foo') @@ -219,7 +234,7 @@ describe("library api", function() { }); it('lists a stored item', function(done) { - initStorage({},{'test':{'a':['abc','def']}}); + initLibrary({},{'test':{'a':['abc','def']}}); request(app) .get('/library/test/a') .expect(200) diff --git a/test/red/api/locales_spec.js b/test/red/api/locales_spec.js index e69de29bb..31d5fd673 100644 --- a/test/red/api/locales_spec.js +++ b/test/red/api/locales_spec.js @@ -0,0 +1,19 @@ +/** + * Copyright 2015 IBM Corp. + * + * 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("locales api", function() { + it.skip("works",function(){}); +}); diff --git a/test/red/api/nodes_spec.js b/test/red/api/nodes_spec.js index f82e39a65..695d8b669 100644 --- a/test/red/api/nodes_spec.js +++ b/test/red/api/nodes_spec.js @@ -21,7 +21,6 @@ var bodyParser = require('body-parser'); var sinon = require('sinon'); var when = require('when'); -var redNodes = require("../../../red/nodes"); var settings = require("../../../red/settings"); var nodes = require("../../../red/api/nodes"); @@ -29,6 +28,16 @@ var nodes = require("../../../red/api/nodes"); describe("nodes api", function() { var app; + function initNodes(runtime) { + runtime.log = { + audit:function(e){},//console.log(e)}, + _:function(){}, + info: function(){}, + warn: function(){} + } + runtime.comms = { publish:function(){}} + nodes.init(runtime); + } before(function() { app = express(); @@ -44,15 +53,18 @@ describe("nodes api", function() { describe('get nodes', function() { it('returns node list', function(done) { - var getNodeList = sinon.stub(redNodes,'getNodeList', function() { - return [1,2,3]; + initNodes({ + api:{ + getNodeList: function() { + return [1,2,3]; + } + } }); request(app) .get('/nodes') .set('Accept', 'application/json') .expect(200) .end(function(err,res) { - getNodeList.restore(); if (err) { throw err; } @@ -62,8 +74,15 @@ describe("nodes api", function() { }); it('returns node configs', function(done) { - var getNodeConfigs = sinon.stub(redNodes,'getNodeConfigs', function() { - return ""; + initNodes({ + api:{ + getNodeConfigs: function() { + return ""; + } + }, + i18n: { + determineLangFromHeaders: function(){} + } }); request(app) .get('/nodes') @@ -71,7 +90,6 @@ describe("nodes api", function() { .expect(200) .expect("") .end(function(err,res) { - getNodeConfigs.restore(); if (err) { throw err; } @@ -80,14 +98,17 @@ describe("nodes api", function() { }); it('returns node module info', function(done) { - var getNodeInfo = sinon.stub(redNodes,'getModuleInfo', function(id) { - return {"node-red":{name:"node-red"}}[id]; + initNodes({ + api:{ + getModuleInfo: function(id) { + return {"node-red":{name:"node-red"}}[id]; + } + } }); request(app) .get('/nodes/node-red') .expect(200) .end(function(err,res) { - getNodeInfo.restore(); if (err) { throw err; } @@ -97,14 +118,17 @@ describe("nodes api", function() { }); it('returns 404 for unknown module', function(done) { - var getNodeInfo = sinon.stub(redNodes,'getModuleInfo', function(id) { - return {"node-red":{name:"node-red"}}[id]; + initNodes({ + api:{ + getModuleInfo: function(id) { + return {"node-red":{name:"node-red"}}[id]; + } + } }); request(app) .get('/nodes/node-blue') .expect(404) .end(function(err,res) { - getNodeInfo.restore(); if (err) { throw err; } @@ -113,15 +137,18 @@ describe("nodes api", function() { }); it('returns individual node info', function(done) { - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) { - return {"node-red/123":{id:"node-red/123"}}[id]; + initNodes({ + api:{ + getNodeInfo: function(id) { + return {"node-red/123":{id:"node-red/123"}}[id]; + } + } }); request(app) .get('/nodes/node-red/123') .set('Accept', 'application/json') .expect(200) .end(function(err,res) { - getNodeInfo.restore(); if (err) { throw err; } @@ -131,8 +158,15 @@ describe("nodes api", function() { }); it('returns individual node configs', function(done) { - var getNodeConfig = sinon.stub(redNodes,'getNodeConfig', function(id) { - return {"node-red/123":""}[id]; + initNodes({ + api:{ + getNodeConfig: function(id) { + return {"node-red/123":""}[id]; + } + }, + i18n: { + determineLangFromHeaders: function(){} + } }); request(app) .get('/nodes/node-red/123') @@ -140,7 +174,6 @@ describe("nodes api", function() { .expect(200) .expect("") .end(function(err,res) { - getNodeConfig.restore(); if (err) { throw err; } @@ -149,15 +182,18 @@ describe("nodes api", function() { }); it('returns 404 for unknown node', function(done) { - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) { - return {"node-red/123":{id:"node-red/123"}}[id]; + initNodes({ + api:{ + getNodeInfo: function(id) { + return {"node-red/123":{id:"node-red/123"}}[id]; + } + } }); request(app) .get('/nodes/node-red/456') .set('Accept', 'application/json') .expect(404) .end(function(err,res) { - getNodeInfo.restore(); if (err) { throw err; } @@ -169,14 +205,13 @@ describe("nodes api", function() { describe('install', function() { it('returns 400 if settings are unavailable', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return false; + initNodes({ + settings:{available:function(){return false}} }); request(app) .post('/nodes') .expect(400) .end(function(err,res) { - settingsAvailable.restore(); if (err) { throw err; } @@ -185,15 +220,14 @@ describe("nodes api", function() { }); it('returns 400 if request is invalid', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}} }); request(app) .post('/nodes') .send({}) .expect(400) .end(function(err,res) { - settingsAvailable.restore(); if (err) { throw err; } @@ -203,26 +237,23 @@ describe("nodes api", function() { describe('by module', function() { it('installs the module and returns module info', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return null; }, + installModule: function() { + return when.resolve({ + name:"foo", + nodes:[{id:"123"}] + }); + } + } }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo'); - getModuleInfo.onCall(0).returns(null); - var installModule = sinon.stub(redNodes,'installModule', function() { - return when.resolve({ - name:"foo", - nodes:[{id:"123"}] - }); - }); - request(app) .post('/nodes') .send({module: 'foo'}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); - installModule.restore(); if (err) { throw err; } @@ -234,24 +265,20 @@ describe("nodes api", function() { }); it('fails the install if already installed', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return {nodes:{id:"123"}}; }, + installModule: function() { + return when.resolve({id:"123"}); + } + } }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return {nodes:{id:"123"}}; - }); - var installModule = sinon.stub(redNodes,'installModule', function() { - return when.resolve({id:"123"}); - }); - request(app) .post('/nodes') .send({module: 'foo'}) .expect(400) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); - installModule.restore(); if (err) { throw err; } @@ -260,24 +287,20 @@ describe("nodes api", function() { }); it('fails the install if module error', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return null }, + installModule: function() { + return when.reject(new Error("test error")); + } + } }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return null; - }); - var installModule = sinon.stub(redNodes,'installModule', function() { - return when.reject(new Error("test error")); - }); - request(app) .post('/nodes') .send({module: 'foo'}) .expect(400) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); - installModule.restore(); if (err) { throw err; } @@ -286,26 +309,22 @@ describe("nodes api", function() { }); }); it('fails the install if module not found', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return null }, + installModule: function() { + var err = new Error("test error"); + err.code = 404; + return when.reject(err); + } + } }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return null; - }); - var installModule = sinon.stub(redNodes,'installModule', function() { - var err = new Error("test error"); - err.code = 404; - return when.reject(err); - }); - request(app) .post('/nodes') .send({module: 'foo'}) .expect(404) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); - installModule.restore(); if (err) { throw err; } @@ -319,6 +338,10 @@ describe("nodes api", function() { var settingsAvailable = sinon.stub(settings,'available', function() { return false; }); + initNodes({ + settings:{available:function(){return false}} + }); + request(app) .del('/nodes/123') .expect(400) @@ -333,27 +356,18 @@ describe("nodes api", function() { describe('by module', function() { it('uninstalls the module', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return {nodes:[{id:"123"}]} }, + getNodeInfo: function() { return null }, + uninstallModule: function() { return when.resolve({id:"123"});} + } }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return null; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return {nodes:[{id:"123"}]}; - }); - var uninstallModule = sinon.stub(redNodes,'uninstallModule', function() { - return when.resolve({id:"123"}); - }); - request(app) .del('/nodes/foo') .expect(204) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); - getModuleInfo.restore(); - uninstallModule.restore(); if (err) { throw err; } @@ -362,23 +376,17 @@ describe("nodes api", function() { }); it('fails the uninstall if the module is not installed', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return null }, + getNodeInfo: function() { return null } + } }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return null; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return null; - }); - request(app) .del('/nodes/foo') .expect(404) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); - getModuleInfo.restore(); if (err) { throw err; } @@ -387,27 +395,18 @@ describe("nodes api", function() { }); it('fails the uninstall if the module is not installed', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return {nodes:[{id:"123"}]} }, + getNodeInfo: function() { return null }, + uninstallModule: function() { return when.reject(new Error("test error"));} + } }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return null; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return {nodes:[{id:"123"}]}; - }); - var uninstallModule = sinon.stub(redNodes,'uninstallModule', function() { - return when.reject(new Error("test error")); - }); - request(app) .del('/nodes/foo') .expect(400) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); - getModuleInfo.restore(); - uninstallModule.restore(); if (err) { throw err; } @@ -421,14 +420,13 @@ describe("nodes api", function() { describe('enable/disable', function() { it('returns 400 if settings are unavailable', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return false; + initNodes({ + settings:{available:function(){return false}} }); request(app) .put('/nodes/123') .expect(400) .end(function(err,res) { - settingsAvailable.restore(); if (err) { throw err; } @@ -437,16 +435,14 @@ describe("nodes api", function() { }); it('returns 400 for invalid node payload', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}} }); - request(app) .put('/nodes/node-red/foo') .send({}) .expect(400) .end(function(err,res) { - settingsAvailable.restore(); if (err) { throw err; } @@ -456,16 +452,14 @@ describe("nodes api", function() { }); it('returns 400 for invalid module payload', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}} }); - request(app) .put('/nodes/foo') .send({}) .expect(400) .end(function(err,res) { - settingsAvailable.restore(); if (err) { throw err; } @@ -476,11 +470,11 @@ describe("nodes api", function() { }); it('returns 404 for unknown node', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return null; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getNodeInfo: function() { return null } + } }); request(app) @@ -488,8 +482,6 @@ describe("nodes api", function() { .send({enabled:false}) .expect(404) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); if (err) { throw err; } @@ -498,11 +490,11 @@ describe("nodes api", function() { }); it('returns 404 for unknown module', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return null; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function(id) { return null } + } }); request(app) @@ -510,8 +502,6 @@ describe("nodes api", function() { .send({enabled:false}) .expect(404) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); if (err) { throw err; } @@ -520,24 +510,18 @@ describe("nodes api", function() { }); it('enables disabled node', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getNodeInfo: function() { return {id:"123",enabled: false} }, + enableNode: function() { return when.resolve({id:"123",enabled: true,types:['a']}); } + } }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return {id:"123",enabled: false}; - }); - var enableNode = sinon.stub(redNodes,'enableNode',function(id) { - return when.resolve({id:"123",enabled: true,types:['a']}); - }); - request(app) .put('/nodes/node-red/foo') .send({enabled:true}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); - enableNode.restore(); if (err) { throw err; } @@ -549,24 +533,18 @@ describe("nodes api", function() { }); it('disables enabled node', function(done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; + initNodes({ + settings:{available:function(){return true}}, + api:{ + getNodeInfo: function() { return {id:"123",enabled: true} }, + disableNode: function() { return when.resolve({id:"123",enabled: false,types:['a']}); } + } }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return {id:"123",enabled: true}; - }); - var disableNode = sinon.stub(redNodes,'disableNode',function(id) { - return when.resolve({id:"123",enabled: false,types:['a']}); - }); - request(app) .put('/nodes/node-red/foo') .send({enabled:false}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); - disableNode.restore(); if (err) { throw err; } @@ -579,31 +557,24 @@ describe("nodes api", function() { describe('no-ops if already in the right state', function() { function run(state,done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return {id:"123",enabled: state}; - }); - var enableNode = sinon.stub(redNodes,'enableNode',function(id) { - return when.resolve({id:"123",enabled: true,types:['a']}); - }); + var enableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: true,types:['a']}) }); + var disableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: false,types:['a']}) }); - var disableNode = sinon.stub(redNodes,'disableNode',function(id) { - return when.resolve({id:"123",enabled: false,types:['a']}); + initNodes({ + settings:{available:function(){return true}}, + api:{ + getNodeInfo: function() { return {id:"123",enabled: state} }, + enableNode: enableNode, + disableNode: disableNode + } }); - request(app) .put('/nodes/node-red/foo') .send({enabled:state}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); var enableNodeCalled = enableNode.called; var disableNodeCalled = disableNode.called; - enableNode.restore(); - disableNode.restore(); if (err) { throw err; } @@ -625,31 +596,24 @@ describe("nodes api", function() { describe('does not no-op if err on node', function() { function run(state,done) { - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getNodeInfo = sinon.stub(redNodes,'getNodeInfo',function(id) { - return {id:"123",enabled: state, err:"foo" }; - }); - var enableNode = sinon.stub(redNodes,'enableNode',function(id) { - return when.resolve({id:"123",enabled: true,types:['a']}); - }); + var enableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: true,types:['a']}) }); + var disableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: false,types:['a']}) }); - var disableNode = sinon.stub(redNodes,'disableNode',function(id) { - return when.resolve({id:"123",enabled: false,types:['a']}); + initNodes({ + settings:{available:function(){return true}}, + api:{ + getNodeInfo: function() { return {id:"123",enabled: state, err:"foo"} }, + enableNode: enableNode, + disableNode: disableNode + } }); - request(app) .put('/nodes/node-red/foo') .send({enabled:state}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getNodeInfo.restore(); var enableNodeCalled = enableNode.called; var disableNodeCalled = disableNode.called; - enableNode.restore(); - disableNode.restore(); if (err) { throw err; } @@ -672,14 +636,7 @@ describe("nodes api", function() { it('enables disabled module', function(done) { var n1 = {id:"123",enabled:false,types:['a']}; var n2 = {id:"456",enabled:false,types:['b']}; - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(name) { - return {name:"node-red", nodes:[n1, n2]}; - }); - - var enableNode = sinon.stub(redNodes,'enableNode'); + var enableNode = sinon.stub(); enableNode.onFirstCall().returns((function() { n1.enabled = true; return when.resolve(n1); @@ -689,15 +646,19 @@ describe("nodes api", function() { return when.resolve(n2); })()); enableNode.returns(null); + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} }, + enableNode: enableNode + } + }); request(app) .put('/nodes/node-red') .send({enabled:true}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); - enableNode.restore(); if (err) { throw err; } @@ -713,14 +674,7 @@ describe("nodes api", function() { it('disables enabled module', function(done) { var n1 = {id:"123",enabled:true,types:['a']}; var n2 = {id:"456",enabled:true,types:['b']}; - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(name) { - return {name:"node-red", nodes:[n1, n2]}; - }); - - var disableNode = sinon.stub(redNodes,'disableNode'); + var disableNode = sinon.stub(); disableNode.onFirstCall().returns((function() { n1.enabled = false; return when.resolve(n1); @@ -730,15 +684,19 @@ describe("nodes api", function() { return when.resolve(n2); })()); disableNode.returns(null); + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} }, + disableNode: disableNode + } + }); request(app) .put('/nodes/node-red') .send({enabled:false}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); - disableNode.restore(); if (err) { throw err; } @@ -754,32 +712,30 @@ describe("nodes api", function() { describe('no-ops if a node in module already in the right state', function() { function run(state,done) { var node = {id:"123",enabled:state,types:['a']}; - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return {name:"node-red", nodes:[node]}; - }); - var enableNode = sinon.stub(redNodes,'enableNode',function(id) { + var enableNode = sinon.spy(function(id) { node.enabled = true; return when.resolve(node); }); - var disableNode = sinon.stub(redNodes,'disableNode',function(id) { + var disableNode = sinon.spy(function(id) { node.enabled = false; return when.resolve(node); }); + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function() { return {name:"node-red", nodes:[node]}; }, + enableNode: enableNode, + disableNode: disableNode + } + }); request(app) .put('/nodes/node-red') .send({enabled:state}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); var enableNodeCalled = enableNode.called; var disableNodeCalled = disableNode.called; - enableNode.restore(); - disableNode.restore(); if (err) { throw err; } @@ -803,32 +759,31 @@ describe("nodes api", function() { describe('does not no-op if err on a node in module', function() { function run(state,done) { var node = {id:"123",enabled:state,types:['a'],err:"foo"}; - var settingsAvailable = sinon.stub(settings,'available', function() { - return true; - }); - var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) { - return {name:"node-red", nodes:[node]}; - }); - var enableNode = sinon.stub(redNodes,'enableNode',function(id) { + var enableNode = sinon.spy(function(id) { node.enabled = true; return when.resolve(node); }); - var disableNode = sinon.stub(redNodes,'disableNode',function(id) { + var disableNode = sinon.spy(function(id) { node.enabled = false; return when.resolve(node); }); + initNodes({ + settings:{available:function(){return true}}, + api:{ + getModuleInfo: function() { return {name:"node-red", nodes:[node]}; }, + enableNode: enableNode, + disableNode: disableNode + } + }); + request(app) .put('/nodes/node-red') .send({enabled:state}) .expect(200) .end(function(err,res) { - settingsAvailable.restore(); - getModuleInfo.restore(); var enableNodeCalled = enableNode.called; var disableNodeCalled = disableNode.called; - enableNode.restore(); - disableNode.restore(); if (err) { throw err; } diff --git a/test/red/api/theme_spec.js b/test/red/api/theme_spec.js index 6421bdbdd..00d400965 100644 --- a/test/red/api/theme_spec.js +++ b/test/red/api/theme_spec.js @@ -31,13 +31,13 @@ describe("theme handler", function() { sinon.stub(fs,"statSync",function() { return true; }); }); afterEach(function() { - theme.init({}); + theme.init({settings:{}}); fs.statSync.restore(); }); it("applies the default theme", function() { - var result = theme.init({}); + var result = theme.init({settings:{}}); should.not.exist(result); - + var context = theme.context(); context.should.have.a.property("page"); context.page.should.have.a.property("title","Node-RED"); @@ -45,12 +45,12 @@ describe("theme handler", function() { context.should.have.a.property("header"); context.header.should.have.a.property("title","Node-RED"); context.header.should.have.a.property("image","red/images/node-red.png"); - + should.not.exist(theme.settings()); }); - + it("picks up custom theme", function() { - var result = theme.init({ + var result = theme.init({settings:{ editorTheme: { page: { title: "Test Page Title", @@ -61,13 +61,13 @@ describe("theme handler", function() { title: "Test Header Title", image: "/absolute/path/to/header/image" // or null to remove image }, - + deployButton: { type:"simple", label:"Save", icon: "/absolute/path/to/deploy/button/image" // or null to remove image }, - + menu: { // Hide unwanted menu items by id. see editor/js/main.js:loadEditor for complete list "menu-item-import-library": false, "menu-item-export-library": false, @@ -77,27 +77,27 @@ describe("theme handler", function() { url: "http://example.com" } }, - + userMenu: false, // Hide the user-menu even if adminAuth is enabled - + login: { image: "/absolute/path/to/login/page/big/image" // a 256x256 image - } + } } - }); + }}); should.exist(result); - + var context = theme.context(); context.should.have.a.property("page"); context.page.should.have.a.property("title","Test Page Title"); context.should.have.a.property("header"); context.header.should.have.a.property("title","Test Header Title"); - + var settings = theme.settings(); settings.should.have.a.property("deployButton"); settings.should.have.a.property("userMenu"); settings.should.have.a.property("menu"); - + }); -}); \ No newline at end of file +}); diff --git a/test/red/api/ui_spec.js b/test/red/api/ui_spec.js index b076c57e4..f68be04a4 100644 --- a/test/red/api/ui_spec.js +++ b/test/red/api/ui_spec.js @@ -20,14 +20,17 @@ var express = require("express"); var fs = require("fs"); var path = require("path"); -var events = require("../../../red/events"); +var EventEmitter = require('events').EventEmitter; +var events = new EventEmitter(); var ui = require("../../../red/api/ui"); describe("ui api", function() { var app; - + before(function() { + ui.init({events:events}); + }); describe("slash handler", function() { before(function() { app = express(); diff --git a/test/red/nodes/flows/Flow_spec.js b/test/red/nodes/flows/Flow_spec.js index 727351930..5fca9fea7 100644 --- a/test/red/nodes/flows/Flow_spec.js +++ b/test/red/nodes/flows/Flow_spec.js @@ -959,7 +959,7 @@ describe('Flow', function() { done(); }); }); - it("moves any existing error object sideways",function(){ + it("moves any existing error object sideways",function(done){ var config = flowUtils.parseConfig([ {id:"t1",type:"tab"}, {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]}, diff --git a/test/red/nodes/index_spec.js b/test/red/nodes/index_spec.js index 3815e6795..a6c349f14 100644 --- a/test/red/nodes/index_spec.js +++ b/test/red/nodes/index_spec.js @@ -145,7 +145,7 @@ describe("red/nodes/index", function() { var registry = require("../../../red/nodes/registry"); var randomNodeInfo = {id:"5678",types:["random"]}; - before(function() { + beforeEach(function() { sinon.stub(registry,"getNodeInfo",function(id) { if (id == "test") { return {id:"1234",types:["test"]}; @@ -159,7 +159,7 @@ describe("red/nodes/index", function() { return randomNodeInfo; }); }); - after(function() { + afterEach(function() { registry.getNodeInfo.restore(); registry.disableNode.restore(); }); diff --git a/test/red/server_spec.js b/test/red/runtime_spec.js similarity index 77% rename from test/red/server_spec.js rename to test/red/runtime_spec.js index 3211d3b3d..91d58bc89 100644 --- a/test/red/server_spec.js +++ b/test/red/runtime_spec.js @@ -20,18 +20,23 @@ var sinon = require("sinon"); var comms = require("../../red/comms"); var redNodes = require("../../red/nodes"); var api = require("../../red/api"); -var server = require("../../red/server"); +var runtime = require("../../red/runtime"); var storage = require("../../red/storage"); var settings = require("../../red/settings"); var log = require("../../red/log"); -describe("red/server", function() { +describe("red/runtime", function() { var commsMessages = []; var commsPublish; beforeEach(function() { commsMessages = []; }); + afterEach(function() { + if (console.log.restore) { + console.log.restore(); + } + }) before(function() { commsPublish = sinon.stub(comms,"publish", function(topic,msg,retained) { @@ -42,26 +47,48 @@ describe("red/server", function() { commsPublish.restore(); }); - it("initialises components", function() { - var commsInit = sinon.stub(comms,"init",function() {}); - var dummyServer = {}; - server.init(dummyServer,{testSettings: true, httpAdminRoot:"/", load:function() { return when.resolve();}}); + describe("init", function() { + var commsInit; + var apiInit; + beforeEach(function() { + commsInit = sinon.stub(comms,"init",function() {}); + apiInit = sinon.stub(api,"init",function() {}); + }); + afterEach(function() { + commsInit.restore(); + apiInit.restore(); + }) - commsInit.called.should.be.true; + it("initialises components", function() { + var dummyServer = {}; + runtime.init(dummyServer,{testSettings: true, httpAdminRoot:"/", load:function() { return when.resolve();}}); + commsInit.called.should.be.true; + apiInit.called.should.be.true; - should.exist(server.app); - should.exist(server.nodeApp); + should.exist(runtime.app); + should.exist(runtime.nodeApp); - server.server.should.equal(dummyServer); + runtime.server.should.equal(dummyServer); + }); - commsInit.restore(); + it("doesn't init api if httpAdminRoot set to false",function() { + + var dummyServer = {}; + runtime.init(dummyServer,{testSettings: true, httpAdminRoot:false, load:function() { return when.resolve();}}); + commsInit.called.should.be.true; + apiInit.called.should.be.false; + + should.exist(runtime.app); + should.exist(runtime.nodeApp); + + runtime.server.should.equal(dummyServer); + }); }); describe("start",function() { var commsInit; var storageInit; var settingsLoad; - var apiInit; var logMetric; var logWarn; var logInfo; @@ -77,7 +104,6 @@ describe("red/server", function() { beforeEach(function() { commsInit = sinon.stub(comms,"init",function() {}); storageInit = sinon.stub(storage,"init",function(settings) {return when.resolve();}); - apiInit = sinon.stub(api,"init",function() {}); logMetric = sinon.stub(log,"metric",function() { return false; }); logWarn = sinon.stub(log,"warn",function() { }); logInfo = sinon.stub(log,"info",function() { }); @@ -92,7 +118,6 @@ describe("red/server", function() { afterEach(function() { commsInit.restore(); storageInit.restore(); - apiInit.restore(); logMetric.restore(); logWarn.restore(); logInfo.restore(); @@ -112,10 +137,11 @@ describe("red/server", function() { { module:"module",enabled:true,loaded:false,types:["typeA","typeB"]} // missing ].filter(cb); }); - server.init({},{testSettings: true, httpAdminRoot:"/", load:function() { return when.resolve();}}); - server.start().then(function() { + runtime.init({},{testSettings: true, httpAdminRoot:"/", load:function() { return when.resolve();}}); + sinon.stub(console,"log"); + runtime.start().then(function() { + console.log.restore(); try { - apiInit.calledOnce.should.be.true; storageInit.calledOnce.should.be.true; redNodesInit.calledOnce.should.be.true; redNodesLoad.calledOnce.should.be.true; @@ -142,10 +168,11 @@ describe("red/server", function() { ].filter(cb); }); var serverInstallModule = sinon.stub(redNodes,"installModule",function(name) { return when.resolve();}); - server.init({},{testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return when.resolve();}}); - server.start().then(function() { + runtime.init({},{testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return when.resolve();}}); + sinon.stub(console,"log"); + runtime.start().then(function() { + console.log.restore(); try { - apiInit.calledOnce.should.be.true; logWarn.calledWithMatch("Failed to register 2 node types"); logWarn.calledWithMatch("Missing node modules"); logWarn.calledWithMatch(" - module: typeA, typeB"); @@ -167,11 +194,11 @@ describe("red/server", function() { { err:"errored",name:"errName" } // error ].filter(cb); }); - server.init({},{testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return when.resolve();}}); - server.start().then(function() { - + runtime.init({},{testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return when.resolve();}}); + sinon.stub(console,"log"); + runtime.start().then(function() { + console.log.restore(); try { - apiInit.calledOnce.should.be.true; logWarn.neverCalledWithMatch("Failed to register 1 node type"); logWarn.calledWithMatch("[errName] errored"); done(); @@ -187,11 +214,12 @@ describe("red/server", function() { redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []}); logMetric.restore(); logMetric = sinon.stub(log,"metric",function() { return true; }); - server.init({},{testSettings: true, runtimeMetricInterval:400, httpAdminRoot:"/", load:function() { return when.resolve();}}); - server.start().then(function() { + runtime.init({},{testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return when.resolve();}}); + sinon.stub(console,"log"); + runtime.start().then(function() { + console.log.restore(); setTimeout(function() { try { - apiInit.calledOnce.should.be.true; logLog.args.should.have.lengthOf(3); logLog.args[0][0].should.have.property("level",log.METRIC); logLog.args[0][0].should.have.property("event","runtime.memory.rss"); @@ -203,35 +231,22 @@ describe("red/server", function() { } catch(err) { done(err); } finally { - server.stop(); + runtime.stop(); commsStop.restore(); stopFlows.restore(); } - },500); + },300); }); }); - it("doesn't init api if httpAdminRoot set to false",function(done) { - redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []}); - server.init({},{testSettings: true, httpAdminRoot:false, load:function() { return when.resolve();}}); - server.start().then(function() { - setTimeout(function() { - try { - apiInit.calledOnce.should.be.false; - done(); - } catch(err) { - done(err); - } - },500); - }); - }); + }); it("stops components", function() { var commsStop = sinon.stub(comms,"stop",function() {} ); var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} ); - server.stop(); + runtime.stop(); commsStop.called.should.be.true; stopFlows.called.should.be.true; diff --git a/test/red/settings_spec.js b/test/red/settings_spec.js index 7e7e3f4b2..bf1b05df5 100644 --- a/test/red/settings_spec.js +++ b/test/red/settings_spec.js @@ -20,11 +20,11 @@ var settings = require("../../red/settings"); describe("red/settings", function() { - + afterEach(function() { settings.reset(); }); - + it('wraps the user settings as read-only properties', function() { var userSettings = { a: 123, @@ -32,22 +32,22 @@ describe("red/settings", function() { c: [1,2,3] } settings.init(userSettings); - + settings.available().should.be.false; - + settings.a.should.equal(123); settings.b.should.equal("test"); settings.c.should.be.an.Array.with.lengthOf(3); - + settings.get("a").should.equal(123); settings.get("b").should.equal("test"); settings.get("c").should.be.an.Array.with.lengthOf(3); - + /*jshint immed: false */ (function() { settings.a = 456; }).should.throw(); - + settings.c.push(5); settings.c.should.be.an.Array.with.lengthOf(4); @@ -55,7 +55,7 @@ describe("red/settings", function() { (function() { settings.set("a",456); }).should.throw(); - + /*jshint immed: false */ (function() { settings.set("a",456); @@ -70,9 +70,9 @@ describe("red/settings", function() { (function() { settings.set("unknown",456); }).should.throw(); - + }); - + it('loads global settings from storage', function(done) { var userSettings = { a: 123, @@ -94,7 +94,7 @@ describe("red/settings", function() { settings.init(userSettings); settings.available().should.be.false; - + /*jshint immed: false */ (function() { settings.get("unknown"); @@ -117,7 +117,7 @@ describe("red/settings", function() { done(err); }); }); - + it('removes persistent settings when reset', function() { var userSettings = { a: 123, @@ -125,18 +125,18 @@ describe("red/settings", function() { c: [1,2,3] } settings.init(userSettings); - + settings.available().should.be.false; - + settings.should.have.property("a",123); settings.should.have.property("b","test"); settings.c.should.be.an.Array.with.lengthOf(3); - + settings.reset(); - + settings.should.not.have.property("a"); settings.should.not.have.property("d"); settings.should.not.have.property("c"); - + }); });