From ba22b07dcea0bf5bdbd93e25e58632733597925e Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Thu, 16 Jun 2022 10:57:29 +0100 Subject: [PATCH 1/2] align functionality of `nodesDir` with coreNodesDir and userDir --- .../@node-red/registry/lib/localfilesystem.js | 195 +++++++++++++----- 1 file changed, 146 insertions(+), 49 deletions(-) diff --git a/packages/node_modules/@node-red/registry/lib/localfilesystem.js b/packages/node_modules/@node-red/registry/lib/localfilesystem.js index 62080b4a8..da4006ecc 100644 --- a/packages/node_modules/@node-red/registry/lib/localfilesystem.js +++ b/packages/node_modules/@node-red/registry/lib/localfilesystem.js @@ -88,9 +88,10 @@ function getLocalFile(file) { /** * Synchronously walks the directory looking for node files. * @param dir the directory to search + * @param skipValidNodeRedModules a flag to skip lading icons & files if the directory a valid node-red module * @return an array of fully-qualified paths to .js files */ -function getLocalNodeFiles(dir) { +function getLocalNodeFiles(dir, skipValidNodeRedModules) { dir = path.resolve(dir); var result = []; @@ -102,6 +103,14 @@ function getLocalNodeFiles(dir) { return {files: [], icons: []}; } files.sort(); + // when loading local files, if the path is a valid node-red module + // dont include it (will be picked up in scanTreeForNodesModules) + if(skipValidNodeRedModules && files.indexOf("package.json") >= 0) { + const package = getPackageDetails(dir) + if(package.isNodeRedModule) { + return {files: [], icons: []}; + } + } files.forEach(function(fn) { var stats = fs.statSync(path.join(dir,fn)); if (stats.isFile()) { @@ -114,7 +123,7 @@ function getLocalNodeFiles(dir) { } else if (stats.isDirectory()) { // Ignore /.dirs/, /lib/ /node_modules/ if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) { - var subDirResults = getLocalNodeFiles(path.join(dir,fn)); + var subDirResults = getLocalNodeFiles(path.join(dir,fn), skipValidNodeRedModules); result = result.concat(subDirResults.files); icons = icons.concat(subDirResults.icons); } else if (fn === "icons") { @@ -126,21 +135,30 @@ function getLocalNodeFiles(dir) { return {files: result, icons: icons} } -function scanDirForNodesModules(dir,moduleName) { - var results = []; - var scopeName; +function scanDirForNodesModules(dir,moduleName,package) { + let results = []; + let scopeName; + let files try { - var files = fs.readdirSync(dir); - if (moduleName) { - var m = /^(?:(@[^/]+)[/])?([^@/]+)/.exec(moduleName); - if (m) { - scopeName = m[1]; - moduleName = m[2]; + let isNodeRedModule = false + if(package) { + dir = path.join(package.moduleDir,'..') + files = [path.basename(package.moduleDir)] + moduleName = (package.package ? package.package.name : null) || moduleName + isNodeRedModule = package.isNodeRedModule + } else { + files = fs.readdirSync(dir); + if (moduleName) { + var m = /^(?:(@[^/]+)[/])?([^@/]+)/.exec(moduleName); + if (m) { + scopeName = m[1]; + moduleName = m[2]; + } } } - for (var i=0;i look for node_modules + 2. exist(package.json) && package.json.has(node-red) => load this only + 3. in original scan of nodesDir, ignore if:(exist(package.json) && package.json.has(node-red)) + */ + if (nodesDir) { + for (let dirIndex = 0; dirIndex < nodesDir.length; dirIndex++) { + const nodeDir = nodesDir[dirIndex]; + const packageDetails = getPackageDetails(nodeDir) + if(packageDetails.isNodeRedModule) { + //we have found a node-red module, scan it + const nrModules = scanDirForNodesModules(nodeDir, packageDetails.package.name, packageDetails); + results = results.concat(nrModules); + + } else if (packageDetails.has_node_modules) { + //If this dir has a `node_modues` dir, scan it + const nodeModulesDir = path.join(nodeDir, 'node_modules') + const nrModules = scanDirForNodesModules(nodeModulesDir, moduleName ); + results = results.concat(nrModules); + + } else { + //If this is not a node-red module AND it does NOT have a node_modules dir, + //it may be a directory of project directories or a node_modules dir? + //scan this instead + const nrModules = scanDirForNodesModules(nodeDir, moduleName); + results = results.concat(nrModules); + } } } return results; @@ -274,24 +328,26 @@ function getModuleNodeFiles(module) { } function getNodeFiles(disableNodePathScan) { - var dir; // Find all of the nodes to load - var nodeFiles = []; - var results; - - var dir; - var iconList = []; + let results; + let nodesDir; + if(settings.nodesDir) { + nodesDir = Array.isArray(settings.nodesDir) ? settings.nodesDir : [settings.nodesDir] + } + let dir; + let nodeFiles = []; + let iconList = []; if (settings.coreNodesDir) { results = getLocalNodeFiles(path.resolve(settings.coreNodesDir)); nodeFiles = nodeFiles.concat(results.files); iconList = iconList.concat(results.icons); - var defaultLocalesPath = path.join(settings.coreNodesDir,"locales"); + let defaultLocalesPath = path.join(settings.coreNodesDir,"locales"); i18n.registerMessageCatalog("node-red",defaultLocalesPath,"messages.json"); } if (settings.userDir) { dir = path.join(settings.userDir,"lib","icons"); - var icons = scanIconDir(dir); + let icons = scanIconDir(dir); if (icons.length > 0) { iconList.push({path:dir,icons:icons}); } @@ -301,13 +357,9 @@ function getNodeFiles(disableNodePathScan) { nodeFiles = nodeFiles.concat(results.files); iconList = iconList.concat(results.icons); } - if (settings.nodesDir) { - dir = settings.nodesDir; - if (typeof settings.nodesDir == "string") { - dir = [dir]; - } - for (var i=0;i Date: Thu, 16 Jun 2022 11:00:31 +0100 Subject: [PATCH 2/2] =?UTF-8?q?improve=20tests=20for=20nodeDir=20Adds=20ne?= =?UTF-8?q?w=20resources=20(loose=20files,=20non=20NR=20pkgs,=20NR=20modul?= =?UTF-8?q?es,=20NR=20Plugins)=20Adds=20new=20tests=20#getNodeFiles=20-=20?= =?UTF-8?q?new=20tests=20below=20=20=20=E2=88=9A=20Finds=20nodes=20and=20i?= =?UTF-8?q?cons=20only=20in=20nodesDir=20with=20files,=20icons=20and=20val?= =?UTF-8?q?id=20node-red=20packages=20=20=20=E2=88=9A=20Should=20not=20fin?= =?UTF-8?q?d=20node-red=20node=20in=20nodesDir=20with=20files,=20icons=20a?= =?UTF-8?q?nd=20valid=20node-red=20packages=20=20=20=E2=88=9A=20Should=20n?= =?UTF-8?q?ot=20find=20node-red=20node=20in=20nodesDir=20when=20regular=20?= =?UTF-8?q?package=20and=20valid=20node-red=20packages=20#getModuleFiles?= =?UTF-8?q?=20-=20new=20tests=20below=20=20=20=E2=88=9A=20gets=20a=20nodes?= =?UTF-8?q?=20module=20files=20=20=20=E2=88=9A=20Finds=20only=201=20node-r?= =?UTF-8?q?ed=20node=20in=20nodesDir=20amongst=20legacy=20nodes=20and=20re?= =?UTF-8?q?gular=20nodes=20=20=20=E2=88=9A=20Finds=20a=20node-red=20node?= =?UTF-8?q?=20in=20nodesDir=20with=20a=20sub=20dir=20containing=20valid=20?= =?UTF-8?q?node-red=20package=20=20=20=E2=88=9A=20Finds=202=20node-red=20n?= =?UTF-8?q?ode=20and=201=20plugin=20in=20nodesDir=20(in=20root=20of=20dir)?= =?UTF-8?q?=20=20=20=E2=88=9A=20Finds=202=20node-red=20node=20and=201=20pl?= =?UTF-8?q?ugin=20in=20nodesDir=20pointing=20to=20a=20node=5Fmodules=20dir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../registry/lib/localfilesystem_spec.js | 226 ++++++++++++++---- .../lib/resources/nodesDir1/icons/loose1.svg | 1 + .../lib/resources/nodesDir1/loose1.html | 5 + .../lib/resources/nodesDir1/loose1.js | 4 + .../nodesDir1/loose2/icons/loose2.svg | 1 + .../nodesDir1/loose2/icons/loose2b.svg | 1 + .../resources/nodesDir1/loose2/loose2.html | 5 + .../lib/resources/nodesDir1/loose2/loose2.js | 4 + .../node-red-node-testnode/icons/test.svg | 1 + .../nodesDir1/node-red-node-testnode/main.js | 4 + .../node-red-node-testnode/package.json | 19 ++ .../nodesDir1/regular_module/icons/test.svg | 1 + .../nodesDir1/regular_module/main.js | 4 + .../nodesDir1/regular_module/package.json | 14 ++ .../nodesDir2/@test/testnode/index.html | 5 + .../nodesDir2/@test/testnode/index.js | 4 + .../nodesDir2/@test/testnode/package.json | 20 ++ .../resources/nodesDir2/testnode2/index.html | 5 + .../resources/nodesDir2/testnode2/index.js | 4 + .../nodesDir2/testnode2/package.json | 20 ++ .../theme-plugin2/files/clientside.js | 3 + .../nodesDir2/theme-plugin2/files/plugin.js | 14 ++ .../nodesDir2/theme-plugin2/files/theme.css | 1 + .../nodesDir2/theme-plugin2/package.json | 24 ++ .../node_modules/@test/testnode/index.html | 5 + .../node_modules/@test/testnode/index.js | 4 + .../node_modules/@test/testnode/package.json | 20 ++ .../@test/theme-plugin3/files/clientside.js | 3 + .../@test/theme-plugin3/files/plugin.js | 14 ++ .../@test/theme-plugin3/files/theme.css | 1 + .../@test/theme-plugin3/package.json | 24 ++ .../node_modules/testnode3/index.html | 5 + .../nodesDir3/node_modules/testnode3/index.js | 4 + .../node_modules/testnode3/package.json | 20 ++ 34 files changed, 441 insertions(+), 49 deletions(-) create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/icons/loose1.svg create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json diff --git a/test/unit/@node-red/registry/lib/localfilesystem_spec.js b/test/unit/@node-red/registry/lib/localfilesystem_spec.js index e84761657..3b1bb63f3 100644 --- a/test/unit/@node-red/registry/lib/localfilesystem_spec.js +++ b/test/unit/@node-red/registry/lib/localfilesystem_spec.js @@ -14,26 +14,41 @@ * limitations under the License. **/ -var should = require("should"); -var sinon = require("sinon"); -var path = require("path"); +const should = require("should"); +const sinon = require("sinon"); +const path = require("path"); -var NR_TEST_UTILS = require("nr-test-utils"); +const NR_TEST_UTILS = require("nr-test-utils"); -var localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/localfilesystem"); +const localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/localfilesystem"); -var resourcesDir = path.resolve(path.join(__dirname,"resources","local")); -var userDir = path.resolve(path.join(__dirname,"resources","userDir")); -var moduleDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule")); +const resourcesDir = path.resolve(path.join(__dirname,"resources","local")); +const userDir = path.resolve(path.join(__dirname,"resources","userDir")); -var i18n = NR_TEST_UTILS.require("@node-red/util").i18n; +const nodesDir1 = path.resolve(path.join(__dirname,"resources","nodesDir1")) +const nodesDir2 = path.resolve(path.join(__dirname,"resources","nodesDir2")) +const nodesDir3 =path.resolve(path.join(__dirname,"resources","nodesDir3")) + +const moduleDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule")); + +const i18n = NR_TEST_UTILS.require("@node-red/util").i18n; describe("red/nodes/registry/localfilesystem",function() { + var stubs = []; + function stubPathJoin() { + var _join = path.join; + stubs.push(sinon.stub(path,"join").callsFake(function() { + if (arguments[0] == resourcesDir) { + // This stops the module tree scan from going any higher + // up the tree than resourcesDir. + return arguments[0]; + } + return _join.apply(null,arguments); + })); + } beforeEach(function() { stubs.push(sinon.stub(i18n,"registerMessageCatalog").callsFake(function() { return Promise.resolve(); })); }) - - var stubs = []; afterEach(function() { while(stubs.length) { stubs.pop().restore(); @@ -129,16 +144,76 @@ describe("red/nodes/registry/localfilesystem",function() { checkNodes(nm.nodes,['TestNode5'],['TestNode1']); done(); }); + it("Finds nodes and icons only in nodesDir with files, icons and valid node-red packages",function(done) { + localfilesystem.init({nodesDir:nodesDir1}); + const nodeList = localfilesystem.getNodeFiles(true); + nodeList.should.have.a.property("node-red"); + const nm = nodeList['node-red']; + nm.should.have.a.property('name','node-red'); + nm.should.have.a.property("nodes"); + nm.should.have.a.property("icons"); + checkNodes(nm.nodes,['loose1', 'loose2'], []); + //1 icon in nodesDir1/icons/ - should be found + //2 icons in nodesDir1/loose2/icons/ - should be found + //1 icons in nodesDir1/node-red-node-testnode/icons/ - should be found + //1 icons in nodesDir1/regular_module/icons/ - should NOT be found + //total icon sets 3, total icons 4 + nm.icons.should.have.a.property("length", 3); + nm.icons[0].should.have.a.property("path") + nm.icons[0].should.have.a.property("icons", ['loose1.svg']) + nm.icons[1].should.have.a.property("path") + nm.icons[1].should.have.a.property("icons", ['loose2.svg', 'loose2b.svg']) + nm.icons[2].should.have.a.property("path") + nm.icons[2].should.have.a.property("icons", ['test.svg']) + done(); + }); + it("Should not find node-red node in nodesDir with files, icons and valid node-red packages",function(done) { + // path contains a regular node module and a node-red node module + localfilesystem.init({nodesDir:path.join(nodesDir1)}); + const nodeList = localfilesystem.getNodeFiles(true); + nodeList.should.have.a.property("node-red"); + const nm = nodeList['node-red']; + nm.should.have.a.property('name','node-red'); + nm.should.have.a.property("nodes"); + nm.nodes.should.have.a.property("loose1"); + nm.nodes.should.have.a.property("loose2"); + nm.nodes.should.not.have.a.property("regular_module"); + nm.nodes.should.not.have.a.property("node-red-node-testnode"); + for (let key of Object.keys(nm.nodes)) { + const n = nm.nodes[key]; + n.file.indexOf("regular_module").should.eql(-1, `found icons in a node-red module`) + n.file.indexOf("node-red-node-testnode").should.eql(-1, `found icons in a node-red module`) + } + //1 icon in nodesDir1/icons/ - should be found + //2 icons in nodesDir1/loose2/icons/ - should be found + //1 icons in nodesDir1/node-red-node-testnode/icons/ - should be found + //1 icons in nodesDir1/regular_module/icons/ - should NOT be found + //total icon sets 3, total icons 4 + nm.should.have.a.property("icons"); + nm.icons.should.have.a.property("length", 3); + let iconCount = 0; + for (let index = 0; index < nm.icons.length; index++) { + const iconDir = nm.icons[index]; + iconCount += iconDir.icons.length + iconDir.path.indexOf("node-red-node-testnode").should.eql(-1, `should not find icons in a node-red module`) + } + should(iconCount).eql(4, "Should find only 4 icons") + done(); + }); + it("Should not find node-red node in nodesDir when regular package and valid node-red packages",function(done) { + localfilesystem.init({nodesDir:path.join(nodesDir1,"regular_module")}); + const nodeList = localfilesystem.getNodeFiles(true); + nodeList.should.have.a.property("node-red"); + const nm = nodeList['node-red']; + nm.should.have.a.property('name','node-red'); + nm.should.have.a.property("nodes", {}); + nm.should.have.a.property("icons"); + nm.icons.should.have.a.property("length", 1); //should find 1 icons folder + nm.icons[0].should.have.a.property("icons", [ 'test.svg' ]); //should find 1 icon in regular package + done(); + }); it("Finds nodes module path",function(done) { - var _join = path.join; - stubs.push(sinon.stub(path,"join").callsFake(function() { - if (arguments[0] == resourcesDir) { - // This stops the module tree scan from going any higher - // up the tree than resourcesDir. - return arguments[0]; - } - return _join.apply(null,arguments); - })); + stubPathJoin() localfilesystem.init({coreNodesDir:moduleDir}); var nodeList = localfilesystem.getNodeFiles(); nodeList.should.have.a.property("node-red"); @@ -166,8 +241,6 @@ describe("red/nodes/registry/localfilesystem",function() { i18n.registerMessageCatalog.lastCall.args[1].should.eql(path.resolve(path.join(moduleDir,"locales"))); i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json'); - - done(); }); it.skip("finds locales directory"); @@ -205,15 +278,7 @@ describe("red/nodes/registry/localfilesystem",function() { }); describe("#getModuleFiles",function() { it("gets a nodes module files",function(done) { - var _join = path.join; - stubs.push(sinon.stub(path,"join").callsFake(function() { - if (arguments[0] == resourcesDir) { - // This stops the module tree scan from going any higher - // up the tree than resourcesDir. - return arguments[0]; - } - return _join.apply(null,arguments); - })); + stubPathJoin() localfilesystem.init({coreNodesDir:moduleDir}); var nodeModule = localfilesystem.getModuleFiles('TestNodeModule'); nodeModule.should.have.a.property('TestNodeModule'); @@ -230,16 +295,87 @@ describe("red/nodes/registry/localfilesystem",function() { done(); }); + it("Finds only 1 node-red node in nodesDir amongst legacy nodes and regular nodes",function(done) { + stubPathJoin() + localfilesystem.init({nodesDir:[path.join(nodesDir1,"node-red-node-testnode")]}); + const nodeModule = localfilesystem.getModuleFiles(); + const loaded = Object.keys(nodeModule) + loaded.should.have.a.property("length", 1) + loaded.indexOf('node-red-node-testnode').should.greaterThan(-1, "Should load node-red-node-testnode") + + nodeModule['node-red-node-testnode'].should.have.a.property('name','node-red-node-testnode'); + nodeModule['node-red-node-testnode'].should.have.a.property('version','1.0.0'); + nodeModule['node-red-node-testnode'].should.have.a.property('nodes'); + nodeModule['node-red-node-testnode'].should.have.a.property('path'); + nodeModule['node-red-node-testnode'].should.have.a.property('user', false); + checkNodes(nodeModule['node-red-node-testnode'].nodes,['testnode'],[],'node-red-node-testnode'); + done(); + }); + it("Finds a node-red node in nodesDir with a sub dir containing valid node-red package",function(done) { + stubPathJoin() + localfilesystem.init({nodesDir:[path.join(nodesDir1,"node-red-node-testnode")]}); + const nodeModule = localfilesystem.getModuleFiles(); + const loaded = Object.keys(nodeModule) + nodeModule['node-red-node-testnode'].should.have.a.property('name','node-red-node-testnode'); + nodeModule['node-red-node-testnode'].should.have.a.property('version','1.0.0'); + nodeModule['node-red-node-testnode'].should.have.a.property('nodes'); + nodeModule['node-red-node-testnode'].should.have.a.property('path'); + nodeModule['node-red-node-testnode'].should.have.a.property('user', false); + checkNodes(nodeModule['node-red-node-testnode'].nodes,['testnode'],[],'node-red-node-testnode'); + done(); + }); + it("Finds 2 node-red modules and 1 plugin in nodesDir (in root of dir)",function(done) { + stubPathJoin() + localfilesystem.init({nodesDir:[nodesDir2]}); + const nodeModule = localfilesystem.getModuleFiles(); + const loaded = Object.keys(nodeModule) + loaded.should.have.a.property("length", 3) + loaded.indexOf('@test/testnode').should.greaterThan(-1, "Should load @test/testnode") + loaded.indexOf('testnode2').should.greaterThan(-1, "Should load testnode2") + loaded.indexOf('test-theme2').should.greaterThan(-1, "Should load test-theme2") + + nodeModule['@test/testnode'].should.have.a.property('name','@test/testnode'); + nodeModule['@test/testnode'].should.have.a.property('version','1.0.0'); + nodeModule['@test/testnode'].should.have.a.property('nodes'); + nodeModule['@test/testnode'].should.have.a.property('path'); + nodeModule['@test/testnode'].should.have.a.property('user', false); + + nodeModule['testnode2'].should.have.a.property('name','testnode2'); + nodeModule['testnode2'].should.have.a.property('version','1.0.0'); + nodeModule['testnode2'].should.have.a.property('nodes'); + nodeModule['testnode2'].should.have.a.property('path'); + nodeModule['testnode2'].should.have.a.property('user', false); + + nodeModule['test-theme2'].should.have.a.property('name','test-theme2'); + + nodeModule['test-theme2'].should.have.a.property('version','0.0.1'); + nodeModule['test-theme2'].should.have.a.property('nodes', {}); + nodeModule['test-theme2'].should.have.a.property('path'); + nodeModule['test-theme2'].should.have.a.property('user', false); + nodeModule['test-theme2'].should.have.a.property('plugins'); + nodeModule['test-theme2'].plugins.should.have.a.property('test-theme2'); + nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('name','test-theme2'); + nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('module','test-theme2'); + nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('version', '0.0.1'); + nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('file'); + nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('local', false); + + done(); + }); + it("Finds 2 node-red modules and 1 plugin in nodesDir pointing to a node_modules dir",function(done) { + stubPathJoin() + localfilesystem.init({nodesDir:[path.join(nodesDir3, "node_modules")]}); + const nodeModule = localfilesystem.getModuleFiles(); + const loaded = Object.keys(nodeModule) + loaded.should.have.a.property("length", 3) + + loaded.indexOf('@test/testnode').should.greaterThan(-1, "Should load @test/testnode") + loaded.indexOf('@test/test-theme3').should.greaterThan(-1, "Should load test-theme3") + loaded.indexOf('testnode3').should.greaterThan(-1, "Should load testnode3") + done(); + }); it("throws an error if a node isn't found",function(done) { - var _join = path.join; - stubs.push(sinon.stub(path,"join").callsFake(function() { - if (arguments[0] == resourcesDir) { - // This stops the module tree scan from going any higher - // up the tree than resourcesDir. - return arguments[0]; - } - return _join.apply(null,arguments); - })); + stubPathJoin() localfilesystem.init({coreNodesDir:moduleDir}); /*jshint immed: false */ (function(){ @@ -250,15 +386,7 @@ describe("red/nodes/registry/localfilesystem",function() { it.skip("finds locales directory"); it.skip("finds icon path directory"); it("scans icon files with a module file",function(done) { - var _join = path.join; - stubs.push(sinon.stub(path,"join").callsFake(function() { - if (arguments[0] == resourcesDir) { - // This stops the module tree scan from going any higher - // up the tree than resourcesDir. - return arguments[0]; - } - return _join.apply(null,arguments); - })); + stubPathJoin() localfilesystem.init({ coreNodesDir: moduleDir }); diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/icons/loose1.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/icons/loose1.svg new file mode 100644 index 000000000..927680ee3 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/icons/loose1.svg @@ -0,0 +1 @@ + diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.html b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.html new file mode 100644 index 000000000..8f392056c --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js new file mode 100644 index 000000000..624cfe6d8 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from loose1.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg new file mode 100644 index 000000000..04bebc370 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg @@ -0,0 +1 @@ + diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg new file mode 100644 index 000000000..250348861 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg @@ -0,0 +1 @@ + diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html new file mode 100644 index 000000000..e23e2880a --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js new file mode 100644 index 000000000..e1cde2a82 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from loose2.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg new file mode 100644 index 000000000..04bebc370 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg @@ -0,0 +1 @@ + diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js new file mode 100644 index 000000000..e2e0781d1 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from regular module main.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json new file mode 100644 index 000000000..26d4151fb --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json @@ -0,0 +1,19 @@ +{ + "name": "node-red-node-testnode", + "version": "1.0.0", + "description": "A node-red node that does nothing other than exist", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "node-red" + ], + "node-red": { + "nodes": { + "testnode": "index.js" + } + }, + "author": "@testyMcTersterson", + "license": "MIT" +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg new file mode 100644 index 000000000..04bebc370 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg @@ -0,0 +1 @@ + diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js new file mode 100644 index 000000000..e2e0781d1 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from regular module main.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json new file mode 100644 index 000000000..23cfd7e86 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json @@ -0,0 +1,14 @@ +{ + "name": "regular_node", + "version": "1.0.0", + "description": "A regular node that does nothing other than exist", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "test" + ], + "author": "@testyMcTersterson", + "license": "MIT" +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html new file mode 100644 index 000000000..0e45b3007 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js new file mode 100644 index 000000000..1fe9d89a3 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from @test/testnode index.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json new file mode 100644 index 000000000..a32462631 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json @@ -0,0 +1,20 @@ +{ + "name": "@test/testnode", + "version": "1.0.0", + "description": "A test node that does nothing other than exist", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "node-red", + "test" + ], + "node-red": { + "nodes": { + "testnode": "index.js" + } + }, + "author": "@testyMcTersterson", + "license": "MIT" +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html new file mode 100644 index 000000000..5d9f2b0ec --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js new file mode 100644 index 000000000..0f0eba392 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from testnode2 index.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json new file mode 100644 index 000000000..f9e8aecbe --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json @@ -0,0 +1,20 @@ +{ + "name": "testnode2", + "version": "1.0.0", + "description": "A test node that does nothing other than exist", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "node-red", + "test" + ], + "node-red": { + "nodes": { + "testnode2": "index.js" + } + }, + "author": "@testyMcTersterson", + "license": "MIT" +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js new file mode 100644 index 000000000..fb2e22289 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js @@ -0,0 +1,3 @@ +(function() { + console.log("Hi from test plugin client side") +})() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js new file mode 100644 index 000000000..3202aeb8b --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js @@ -0,0 +1,14 @@ +module.exports = function (RED) { + RED.plugins.registerPlugin('test-theme', { + type: 'node-red-theme', + scripts: [ + 'files/clientside.js' + ], + css: [ + 'files/theme.css', + ], + monacoOptions: { + theme: "vs" + } + }) +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css new file mode 100644 index 000000000..872c93e10 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css @@ -0,0 +1 @@ +:root{--red-ui-primary-background: #f2f3fb;} \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json new file mode 100644 index 000000000..b8608c175 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json @@ -0,0 +1,24 @@ +{ + "name": "test-theme2", + "version": "0.0.1", + "description": "test theme for Node-RED", + + "keywords": [ + "node-red", + "plugin", + "theme" + ], + "author": { + "name": "testy-McTesterson" + }, + "license": "MIT", + "node-red": { + "version": ">=2.2.0", + "plugins": { + "test-theme2": "files/plugin.js" + } + }, + "engines": { + "node": ">=12.x" + } +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html new file mode 100644 index 000000000..0e45b3007 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js new file mode 100644 index 000000000..1fe9d89a3 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from @test/testnode index.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json new file mode 100644 index 000000000..a32462631 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json @@ -0,0 +1,20 @@ +{ + "name": "@test/testnode", + "version": "1.0.0", + "description": "A test node that does nothing other than exist", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "node-red", + "test" + ], + "node-red": { + "nodes": { + "testnode": "index.js" + } + }, + "author": "@testyMcTersterson", + "license": "MIT" +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js new file mode 100644 index 000000000..fb2e22289 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js @@ -0,0 +1,3 @@ +(function() { + console.log("Hi from test plugin client side") +})() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js new file mode 100644 index 000000000..3202aeb8b --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js @@ -0,0 +1,14 @@ +module.exports = function (RED) { + RED.plugins.registerPlugin('test-theme', { + type: 'node-red-theme', + scripts: [ + 'files/clientside.js' + ], + css: [ + 'files/theme.css', + ], + monacoOptions: { + theme: "vs" + } + }) +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css new file mode 100644 index 000000000..872c93e10 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css @@ -0,0 +1 @@ +:root{--red-ui-primary-background: #f2f3fb;} \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json new file mode 100644 index 000000000..56b1bfb6d --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json @@ -0,0 +1,24 @@ +{ + "name": "@test/test-theme3", + "version": "0.0.1", + "description": "test theme for Node-RED", + + "keywords": [ + "node-red", + "plugin", + "theme" + ], + "author": { + "name": "testy-McTesterson" + }, + "license": "MIT", + "node-red": { + "version": ">=2.2.0", + "plugins": { + "test-theme3": "files/plugin.js" + } + }, + "engines": { + "node": ">=12.x" + } +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html new file mode 100644 index 000000000..a4034f340 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js new file mode 100644 index 000000000..855768ad8 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js @@ -0,0 +1,4 @@ + + (function() { + console.log("hello from testnode3 index.js") + })() diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json new file mode 100644 index 000000000..41e9bb8f8 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json @@ -0,0 +1,20 @@ +{ + "name": "testnode3", + "version": "1.0.0", + "description": "A test node that does nothing other than exist", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "node-red", + "test" + ], + "node-red": { + "nodes": { + "testnode3": "index.js" + } + }, + "author": "@testyMcTersterson", + "license": "MIT" +}