mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	First pass of projects test coverage
This commit is contained in:
		| @@ -968,6 +968,7 @@ function init(_settings, _runtime) { | ||||
|     runtime = _runtime; | ||||
|     log = runtime.log; | ||||
|     projectsDir = fspath.join(settings.userDir,"projects"); | ||||
|     authCache.init(); | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
| @@ -17,6 +17,9 @@ | ||||
| var authCache = {} | ||||
|  | ||||
| module.exports = { | ||||
|     init: function() { | ||||
|         authCache = {}; | ||||
|     }, | ||||
|     clear: function(project,remote, user) { | ||||
|         if (user && remote && authCache[project] && authCache[project][remote]) { | ||||
|             delete authCache[project][remote][user]; | ||||
|   | ||||
| @@ -36,7 +36,7 @@ function getListenPath() { | ||||
|  | ||||
| var ResponseServer = function(auth) { | ||||
|     return new Promise(function(resolve, reject) { | ||||
|         server = net.createServer(function(connection) { | ||||
|         var server = net.createServer(function(connection) { | ||||
|             connection.setEncoding('utf8'); | ||||
|             var parts = []; | ||||
|             connection.on('data', function(data) { | ||||
| @@ -81,7 +81,7 @@ var ResponseServer = function(auth) { | ||||
|  | ||||
| var ResponseSSHServer = function(auth) { | ||||
|     return new Promise(function(resolve, reject) { | ||||
|         server = net.createServer(function(connection) { | ||||
|         var server = net.createServer(function(connection) { | ||||
|             connection.setEncoding('utf8'); | ||||
|             var parts = []; | ||||
|             connection.on('data', function(data) { | ||||
| @@ -93,6 +93,7 @@ var ResponseSSHServer = function(auth) { | ||||
|                     console.log("LINE:",line); | ||||
|                     parts = []; | ||||
|                     if (line==='The') { | ||||
|                         // TODO: document these exchanges! | ||||
|                         connection.end('yes'); | ||||
|                         // server.close(); | ||||
|                     } else if (line === 'Enter') { | ||||
|   | ||||
| @@ -0,0 +1,19 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| describe("storage/localfilesystem/projects/Project", function() { | ||||
|     it.skip("NEEDS TESTS WRITING",function() {}); | ||||
| }) | ||||
| @@ -0,0 +1,68 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
|  | ||||
| var should = require("should"); | ||||
| var defaultFileSet = require("../../../../../../red/runtime/storage/localfilesystem/projects/defaultFileSet"); | ||||
|  | ||||
| describe('storage/localfilesystem/projects/defaultFileSet', function() { | ||||
|     it('generates package.json for a project', function() { | ||||
|         var generated = defaultFileSet["package.json"]({ | ||||
|             name: "A TEST NAME", | ||||
|             summary: "A TEST SUMMARY", | ||||
|             files: { | ||||
|                 flow: "MY FLOW FILE", | ||||
|                 credentials: "MY CREDENTIALS FILE" | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         var parsed = JSON.parse(generated); | ||||
|         parsed.should.have.property('name',"A TEST NAME"); | ||||
|         parsed.should.have.property('description',"A TEST SUMMARY"); | ||||
|         parsed.should.have.property('node-red'); | ||||
|         parsed['node-red'].should.have.property('settings'); | ||||
|         parsed['node-red'].settings.should.have.property('flowFile',"MY FLOW FILE"); | ||||
|         parsed['node-red'].settings.should.have.property('credentialsFile',"MY CREDENTIALS FILE"); | ||||
|     }); | ||||
|  | ||||
|     it('generates README.md for a project', function() { | ||||
|         var generated = defaultFileSet["README.md"]({ | ||||
|             name: "A TEST NAME", | ||||
|             summary: "A TEST SUMMARY" | ||||
|         }); | ||||
|         generated.should.match(/A TEST NAME/); | ||||
|         generated.should.match(/A TEST SUMMARY/); | ||||
|     }); | ||||
|     it('generates settings.json for a project', function() { | ||||
|         var generated = defaultFileSet["settings.json"]({ | ||||
|             name: "A TEST NAME", | ||||
|             summary: "A TEST SUMMARY" | ||||
|         }); | ||||
|         generated.length.should.be.greaterThan(0); | ||||
|     }); | ||||
|     it('generates .gitignore for a project', function() { | ||||
|         var generated = defaultFileSet[".gitignore"]({ | ||||
|             name: "A TEST NAME", | ||||
|             summary: "A TEST SUMMARY" | ||||
|         }); | ||||
|         generated.length.should.be.greaterThan(0); | ||||
|     }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| }); | ||||
| @@ -0,0 +1,83 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var should = require("should"); | ||||
| var sinon = require("sinon"); | ||||
|  | ||||
| var authCache = require("../../../../../../../red/runtime/storage/localfilesystem/projects/git/authCache") | ||||
|  | ||||
| describe("localfilesystem/projects/git/authCache", function() { | ||||
|  | ||||
|     beforeEach(function() { | ||||
|         authCache.init(); | ||||
|     }); | ||||
|     afterEach(function() { | ||||
|         authCache.init(); | ||||
|     }); | ||||
|  | ||||
|     it('sets/clears auth details for a given project/remote/user', function() { | ||||
|         should.not.exist(authCache.get("project","remote1","user1")); | ||||
|         should.not.exist(authCache.get("project","remote1","user2")); | ||||
|  | ||||
|         authCache.set("project","remote1","user1",{foo1:"bar1"}); | ||||
|         authCache.set("project","remote1","user2",{foo2:"bar2"}); | ||||
|  | ||||
|         var result = authCache.get("project","remote1","user1"); | ||||
|         result.should.have.property("foo1","bar1"); | ||||
|  | ||||
|         result = authCache.get("project","remote1","user2"); | ||||
|         result.should.have.property("foo2","bar2"); | ||||
|  | ||||
|         authCache.clear("project","remote1","user1"); | ||||
|         should.not.exist(authCache.get("project","remote1","user1")); | ||||
|         should.exist(authCache.get("project","remote1","user2")); | ||||
|  | ||||
|     }); | ||||
|  | ||||
|  | ||||
|     it('clears auth details for all users on a given project/remote', function() { | ||||
|  | ||||
|         authCache.set("project","remote1","user1",{foo1:"bar1"}); | ||||
|         authCache.set("project","remote1","user2",{foo2:"bar2"}); | ||||
|         authCache.set("project","remote2","user1",{foo3:"bar3"}); | ||||
|  | ||||
|         should.exist(authCache.get("project","remote1","user1")); | ||||
|         should.exist(authCache.get("project","remote1","user2")); | ||||
|         should.exist(authCache.get("project","remote2","user1")); | ||||
|  | ||||
|         authCache.clear("project","remote1"); | ||||
|         should.not.exist(authCache.get("project","remote1","user1")); | ||||
|         should.not.exist(authCache.get("project","remote1","user2")); | ||||
|         should.exist(authCache.get("project","remote2","user1")); | ||||
|     }); | ||||
|  | ||||
|     it('clears auth details for all remotes/users on a given project', function() { | ||||
|  | ||||
|         authCache.set("project1","remote1","user1",{foo1:"bar1"}); | ||||
|         authCache.set("project1","remote1","user2",{foo2:"bar2"}); | ||||
|         authCache.set("project2","remote2","user1",{foo3:"bar3"}); | ||||
|  | ||||
|         should.exist(authCache.get("project1","remote1","user1")); | ||||
|         should.exist(authCache.get("project1","remote1","user2")); | ||||
|         should.exist(authCache.get("project2","remote2","user1")); | ||||
|  | ||||
|         authCache.clear("project2"); | ||||
|         should.exist(authCache.get("project1","remote1","user1")); | ||||
|         should.exist(authCache.get("project1","remote1","user2")); | ||||
|         should.not.exist(authCache.get("project2","remote2","user1")); | ||||
|     }); | ||||
|  | ||||
| }); | ||||
| @@ -0,0 +1,73 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var net = require("net"); | ||||
| var path = require("path"); | ||||
| var os = require("os"); | ||||
| var should = require("should"); | ||||
| var sinon = require("sinon"); | ||||
| var child_process = require("child_process"); | ||||
| var fs = require("fs-extra"); | ||||
|  | ||||
| var authServer = require("../../../../../../../red/runtime/storage/localfilesystem/projects/git/authServer"); | ||||
|  | ||||
|  | ||||
| var sendPrompt = function(localPath, prompt) { | ||||
|     return new Promise(function(resolve,reject) { | ||||
|         var response; | ||||
|         var socket = net.connect(localPath, function() { | ||||
|             socket.on('data', function(data) { response = data; socket.end() }); | ||||
|             socket.on('end', function() { | ||||
|                 resolve(response); | ||||
|             }); | ||||
|             socket.on('error',reject); | ||||
|             socket.write(prompt+"\n", 'utf8'); | ||||
|         }); | ||||
|         socket.setEncoding('utf8'); | ||||
|     }); | ||||
| } | ||||
|  | ||||
|  | ||||
| describe("localfilesystem/projects/git/authServer", function() { | ||||
|     it("listens for user/pass prompts and returns provided auth", function(done) { | ||||
|         authServer.ResponseServer({username: "TEST_USER", password: "TEST_PASS"}).then(function(rs) { | ||||
|             sendPrompt(rs.path,"Username").then(function(response) { | ||||
|                 response.should.eql("TEST_USER"); | ||||
|                 return sendPrompt(rs.path,"Password"); | ||||
|             }).then(function(response) { | ||||
|                 response.should.eql("TEST_PASS"); | ||||
|             }).then(done).catch(function(err) { | ||||
|                 done(err); | ||||
|             }) | ||||
|  | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|     it("listens for ssh prompts and returns provided auth", function(done) { | ||||
|         authServer.ResponseSSHServer({passphrase: "TEST_PASSPHRASE"}).then(function(rs) { | ||||
|             sendPrompt(rs.path,"The").then(function(response) { | ||||
|                 // TODO: | ||||
|                 response.should.eql("yes"); | ||||
|                 return sendPrompt(rs.path,"Enter"); | ||||
|             }).then(function(response) { | ||||
|                 response.should.eql("TEST_PASSPHRASE"); | ||||
|             }).then(done).catch(function(err) { | ||||
|                 done(err); | ||||
|             }) | ||||
|  | ||||
|         }) | ||||
|     }) | ||||
| }); | ||||
| @@ -0,0 +1,80 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var net = require("net"); | ||||
| var path = require("path"); | ||||
| var os = require("os"); | ||||
| var should = require("should"); | ||||
| var sinon = require("sinon"); | ||||
| var child_process = require("child_process"); | ||||
| var fs = require("fs-extra"); | ||||
|  | ||||
| var authWriter = "../../../../../../../red/runtime/storage/localfilesystem/projects/git/authWriter"; | ||||
|  | ||||
| function getListenPath() { | ||||
|     var seed = (0x100000+Math.random()*0x999999).toString(16); | ||||
|     var fn = 'node-red-git-askpass-'+seed+'-sock'; | ||||
|     var listenPath; | ||||
|     if (process.platform === 'win32') { | ||||
|         listenPath = '\\\\.\\pipe\\'+getListenPath; | ||||
|     } else { | ||||
|         listenPath = path.join(process.env['XDG_RUNTIME_DIR'] || os.tmpdir(), fn); | ||||
|     } | ||||
|     // console.log(listenPath); | ||||
|     return listenPath; | ||||
| } | ||||
|  | ||||
|  | ||||
| describe("localfilesystem/projects/git/authWriter", function() { | ||||
|     it("connects to port and sends passphrase", function(done) { | ||||
|         var receivedData = ""; | ||||
|         var server = net.createServer(function(connection) { | ||||
|             connection.setEncoding('utf8'); | ||||
|             connection.on('data', function(data) { | ||||
|                 receivedData += data; | ||||
|                 var m = data.indexOf("\n"); | ||||
|                 if (m !== -1) { | ||||
|                     connection.end(); | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         var listenPath = getListenPath(); | ||||
|  | ||||
|         server.listen(listenPath, function(ready) { | ||||
|             child_process.exec(process.execPath+' "'+authWriter+'" "'+listenPath+'" TEST_PHRASE_FOO',{cwd:__dirname}, (error,stdout,stderr) => { | ||||
|                 server.close(); | ||||
|                 try { | ||||
|                     receivedData.should.eql("TEST_PHRASE_FOO\n"); | ||||
|                     done(); | ||||
|                 } catch(err) { | ||||
|                     done(err); | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|         server.on('close', function() { | ||||
|             // console.log("Closing response server"); | ||||
|             fs.removeSync(listenPath); | ||||
|         }); | ||||
|         server.on('error',function(err) { | ||||
|             console.log("ResponseServer unexpectedError:",err.toString()); | ||||
|             server.close(); | ||||
|             done(err); | ||||
|         }); | ||||
|  | ||||
|  | ||||
|     }) | ||||
| }); | ||||
| @@ -0,0 +1,19 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| describe("storage/localfilesystem/projects/git/index", function() { | ||||
|     it.skip("NEEDS TESTS WRITING",function() {}); | ||||
| }) | ||||
|   | ||||
| @@ -0,0 +1,19 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| describe("storage/localfilesystem/projects/index", function() { | ||||
|     it.skip("NEEDS TESTS WRITING",function() {}); | ||||
| }) | ||||
|   | ||||
							
								
								
									
										129
									
								
								test/red/runtime/storage/localfilesystem/projects/ssh_spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								test/red/runtime/storage/localfilesystem/projects/ssh_spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var should = require("should"); | ||||
| var sinon = require("sinon"); | ||||
| var child_process = require('child_process'); | ||||
| var EventEmitter = require("events"); | ||||
|  | ||||
| var ssh = require("../../../../../../red/runtime/storage/localfilesystem/projects/ssh") | ||||
|  | ||||
| describe("localfilesystem/projects/ssh", function() { | ||||
|  | ||||
|     afterEach(function() { | ||||
|         child_process.spawn.restore(); | ||||
|     }) | ||||
|  | ||||
|     it("invokes sshkeygen", function(done) { | ||||
|         var command; | ||||
|         var args; | ||||
|         var opts; | ||||
|         sinon.stub(child_process,"spawn", function(_command,_args,_opts) { | ||||
|             _command = command; | ||||
|             _args = args; | ||||
|             _opts = opts; | ||||
|  | ||||
|             var e = new EventEmitter(); | ||||
|             e.stdout = new EventEmitter(); | ||||
|             e.stderr = new EventEmitter(); | ||||
|             setTimeout(function() { | ||||
|                 e.stdout.emit("data","result"); | ||||
|                 e.emit("close",0); | ||||
|             },50) | ||||
|             return e; | ||||
|         }); | ||||
|  | ||||
|         ssh.generateKey({ | ||||
|             size: 123, | ||||
|             location: 'location', | ||||
|             comment: 'comment', | ||||
|             password: 'password' | ||||
|         }).then(function(output) { | ||||
|             output.should.equal("result"); | ||||
|             done(); | ||||
|         }).catch(function(err) { | ||||
|             done(err); | ||||
|         }) | ||||
|     }) | ||||
|  | ||||
|     it("reports passphrase too short", function(done) { | ||||
|         var command; | ||||
|         var args; | ||||
|         var opts; | ||||
|         sinon.stub(child_process,"spawn", function(_command,_args,_opts) { | ||||
|             _command = command; | ||||
|             _args = args; | ||||
|             _opts = opts; | ||||
|  | ||||
|             var e = new EventEmitter(); | ||||
|             e.stdout = new EventEmitter(); | ||||
|             e.stderr = new EventEmitter(); | ||||
|             setTimeout(function() { | ||||
|                 e.stdout.emit("data","result"); | ||||
|                 e.stderr.emit("data","passphrase is too short"); | ||||
|                 e.emit("close",1); | ||||
|             },5) | ||||
|             return e; | ||||
|         }); | ||||
|  | ||||
|         ssh.generateKey({ | ||||
|             size: 123, | ||||
|             location: 'location', | ||||
|             comment: 'comment', | ||||
|             password: 'password' | ||||
|         }).then(function(output) { | ||||
|             done(new Error("Error not thrown")); | ||||
|         }).catch(function(err) { | ||||
|             err.should.have.property("code","key_passphrase_too_short"); | ||||
|             done(); | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|     it("reports key length too short", function(done) { | ||||
|         var command; | ||||
|         var args; | ||||
|         var opts; | ||||
|         sinon.stub(child_process,"spawn", function(_command,_args,_opts) { | ||||
|             _command = command; | ||||
|             _args = args; | ||||
|             _opts = opts; | ||||
|  | ||||
|             var e = new EventEmitter(); | ||||
|             e.stdout = new EventEmitter(); | ||||
|             e.stderr = new EventEmitter(); | ||||
|             setTimeout(function() { | ||||
|                 e.stdout.emit("data","result"); | ||||
|                 e.stderr.emit("data","Key must at least be 1024 bits"); | ||||
|                 e.emit("close",1); | ||||
|             },50) | ||||
|             return e; | ||||
|         }); | ||||
|  | ||||
|         ssh.generateKey({ | ||||
|             size: 123, | ||||
|             location: 'location', | ||||
|             comment: 'comment', | ||||
|             password: 'password' | ||||
|         }).then(function(output) { | ||||
|             done(new Error("Error not thrown")); | ||||
|         }).catch(function(err) { | ||||
|             err.should.have.property("code","key_length_too_short"); | ||||
|             done(); | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|  | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user