From 39833b0714706d6cb5cf3b12c1868afdae490f45 Mon Sep 17 00:00:00 2001 From: Sergi Mansilla Date: Fri, 3 Jun 2016 16:17:25 +0200 Subject: [PATCH] Switch to a Node.js server for testing, cleanup tests and small fixes --- .eslintrc | 12 + .jshintrc | 57 --- .travis.yml | 4 +- lib/jsftp.js | 205 +++++---- package.json | 1 + test/{test_c9 => fixtures}/testfile.txt | 0 test/fixtures/testfile2.txt | 1 + test/jsftp_test.js | 529 +++++++++++------------- test/server.js | 54 +++ 9 files changed, 431 insertions(+), 432 deletions(-) delete mode 100644 .jshintrc rename test/{test_c9 => fixtures}/testfile.txt (100%) create mode 100644 test/fixtures/testfile2.txt create mode 100644 test/server.js diff --git a/.eslintrc b/.eslintrc index e2d1a4c..2b72bed 100644 --- a/.eslintrc +++ b/.eslintrc @@ -44,7 +44,11 @@ "no-caller": 1, // disallow use of arguments.caller or arguments.callee "no-div-regex": 1, // disallow division operators explicitly at beginning of regular expression "no-else-return": 0, // disallow else after a return in an if +<<<<<<< HEAD "no-labels": 1, // disallow use of labels for anything other then loops and switches +======= + "no-empty-label": 1, // disallow use of labels for anything other then loops and switches +>>>>>>> Switch to a Node.js server for testing, cleanup tests and small fixes "no-eq-null": 0, // disallow comparisons to null without a type-checking operator "no-eval": 1, // disallow use of eval() "no-extend-native": 1, // disallow adding to native types @@ -139,7 +143,11 @@ "quote-props": [1, "as-needed"], // require quotes around object literal property names "semi": 1, // require or disallow use of semicolons instead of ASI "sort-vars": 0, // sort variables within the same declaration block +<<<<<<< HEAD "keyword-spacing": 1, // require a space after certain keywords +======= + "space-after-keywords": 1, // require a space after certain keywords +>>>>>>> Switch to a Node.js server for testing, cleanup tests and small fixes "space-before-blocks": 1, // require a space before blocks "space-before-function-paren": [ // disallow a space before function parenthesis 1, "never" @@ -149,6 +157,10 @@ ], "space-in-parens": 1, // require or disallow spaces inside parentheses "space-infix-ops": 1, // require spaces around operators +<<<<<<< HEAD +======= + "space-return-throw-case": 1, // require a space after return, throw, and case +>>>>>>> Switch to a Node.js server for testing, cleanup tests and small fixes "space-unary-ops": 1, // require a space around word operators such as typeof "max-nested-callbacks": 0, // specify the maximum depth callbacks can be nested "one-var": [1, "never"], // allow just one var statement per function diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 618cb8a..0000000 --- a/.jshintrc +++ /dev/null @@ -1,57 +0,0 @@ -{ - /* - * ENVIRONMENTS - * ================= - */ - - // Define globals exposed by modern browsers. - "browser": true, - - // Define globals exposed by Node.js. - "node": true, - - /* - * ENFORCING OPTIONS - * ================= - */ - - // Force all variable names to use either camelCase style or UPPER_CASE - // with underscores. - "camelcase": true, - - // Prohibit use of == and != in favor of === and !==. - "eqeqeq": true, - - // Enforce tab width of 2 spaces. - "indent": 2, - - // Prohibit use of a variable before it is defined. - "latedef": true, - - // Enforce line length to 80 characters - "maxlen": 80, - - // Require capitalized names for constructor functions. - "newcap": true, - - // Enforce use of single quotation marks for strings. - "quotmark": "single", - - // Enforce placing 'use strict' at the top function scope - "strict": true, - - // Prohibit use of explicitly undeclared variables. - "undef": true, - - // Warn when variables are defined but never used. - "unused": true, - - /* - * RELAXING OPTIONS - * ================= - */ - - // Suppress warnings about == null comparisons. - "eqnull": true -} - diff --git a/.travis.yml b/.travis.yml index 78a6687..16da081 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js node_js: - - "0.10" - "0.12" - - iojs + - "4.4.7" + - "6.2.2" os: - linux - osx diff --git a/lib/jsftp.js b/lib/jsftp.js index fbcf455..d323cc3 100644 --- a/lib/jsftp.js +++ b/lib/jsftp.js @@ -26,7 +26,7 @@ var dbgResponse = require('debug')('jsftp:response'); var FTP_PORT = 21; var TIMEOUT = 10 * 60 * 1000; var IDLE_TIME = 30000; -var NOOP = function () {}; +var NOOP = function() { }; var COMMANDS = [ // Commands without parameters 'abor', 'pwd', 'cdup', 'feat', 'noop', 'quit', 'pasv', 'syst', @@ -39,13 +39,13 @@ var COMMANDS = [ var expectedMarks = { marks: [125, 150], - ignore: 226 + ignore: 226, }; var RE_PASV = /([-\d]+,[-\d]+,[-\d]+,[-\d]+),([-\d]+),([-\d]+)/; var FTP_NEWLINE = /\r\n|\n/; -function getPasvPort (text) { +function getPasvPort(text) { var match = RE_PASV.exec(text); if (!match) { return null; @@ -53,11 +53,11 @@ function getPasvPort (text) { return { host: match[1].replace(/,/g, '.'), - port: (parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255) + port: (parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255), }; } -function runCmd (cmd) { +function runCmd() { var callback = NOOP; var args = [].slice.call(arguments); var completeCmd = args.shift(); @@ -70,16 +70,16 @@ function runCmd (cmd) { this.execute(completeCmd.trim(), callback); } -var Ftp = module.exports = function (cfg) { +var Ftp = module.exports = function(cfg) { this.host = cfg.host || 'localhost'; this.port = cfg.port || FTP_PORT; this.user = cfg.user || 'anonymous'; this.pass = cfg.pass || '@anonymous'; - // True if the server doesn't support the `stat` command. Since listing a // directory or retrieving file properties is quite a common operation, it is // more efficient to avoid the round-trip to the server. - this.useList = false; + this.useList = cfg.useList || false; + this.commandQueue = []; EventEmitter.call(this); @@ -88,8 +88,12 @@ var Ftp = module.exports = function (cfg) { // Generate generic methods from parameter names. they can easily be // overriden if we need special behavior. they accept any parameters given, // it is the responsibility of the user to validate the parameters. - this.raw = function () { return runCmd.apply(self, arguments); }; - COMMANDS.forEach(function (cmd) { self.raw[cmd] = runCmd.bind(self, cmd); }); + this.raw = function() { + return runCmd.apply(self, arguments); + }; + COMMANDS.forEach(function(cmd) { + self.raw[cmd] = runCmd.bind(self, cmd); + }); this.on('data', dbgResponse); @@ -98,15 +102,15 @@ var Ftp = module.exports = function (cfg) { util.inherits(Ftp, EventEmitter); -Ftp.prototype.reemit = function (event) { +Ftp.prototype.reemit = function(event) { var self = this; - return function (data) { + return function(data) { self.emit(event, data); debug('event:' + event, data || {}); }; }; -Ftp.prototype._createSocket = function (port, host, firstAction) { +Ftp.prototype._createSocket = function(port, host, firstAction) { if (this.socket && this.socket.destroy) { this.socket.destroy(); } @@ -125,7 +129,7 @@ Ftp.prototype._createSocket = function (port, host, firstAction) { var self = this; - this.pipeline.on('data', function (data) { + this.pipeline.on('data', function(data) { self.emit('data', data); dbgResponse(data.text); self.parseResponse(data); @@ -133,9 +137,13 @@ Ftp.prototype._createSocket = function (port, host, firstAction) { this.pipeline.on('error', this.reemit('error')); }; -Ftp.prototype.parseResponse = function (response) { - if (this.commandQueue.length === 0) return; - if ([220].indexOf(response.code) > -1) return; +Ftp.prototype.parseResponse = function(response) { + if (this.commandQueue.length === 0) { + return; + } + if ([220].indexOf(response.code) > -1) { + return; + } var next = this.commandQueue[0].callback; if (response.isMark) { @@ -164,8 +172,10 @@ Ftp.prototype.parseResponse = function (response) { * * @param {String} command Command to write in the FTP socket */ -Ftp.prototype.send = function (command) { - if (!command) return; +Ftp.prototype.send = function(command) { + if (!command) { + return; + } dbgCommand(command); this.pipeline.write(command + '\r\n'); @@ -173,7 +183,7 @@ Ftp.prototype.send = function (command) { dbgCommand(command); }; -Ftp.prototype.nextCmd = function () { +Ftp.prototype.nextCmd = function() { if (!this.inProgress && this.commandQueue[0]) { this.send(this.commandQueue[0].action); this.inProgress = true; @@ -193,22 +203,22 @@ Ftp.prototype.nextCmd = function () { * @param {string} action * @param {function} callback */ -Ftp.prototype.execute = function (action, callback) { +Ftp.prototype.execute = function(action, callback) { if (this.socket && this.socket.writable) { return this.runCommand(action, callback || NOOP); } var self = this; this.authenticated = false; - this._createSocket(this.port, this.host, function () { + this._createSocket(this.port, this.host, function() { self.runCommand(action, callback || NOOP); }); }; -Ftp.prototype.runCommand = function (action, callback) { +Ftp.prototype.runCommand = function(action, callback) { var cmd = { action: action, - callback: callback + callback: callback, }; if (this.authenticated || /^(feat|syst|user|pass)/.test(action)) { @@ -218,8 +228,8 @@ Ftp.prototype.runCommand = function (action, callback) { } var self = this; - this.getFeatures(function () { - self.auth(self.user, self.pass, function () { + this.getFeatures(function() { + self.auth(self.user, self.pass, function() { self.commandQueue.push(cmd); self.nextCmd(); }); @@ -234,7 +244,7 @@ Ftp.prototype.runCommand = function (action, callback) { * @param {Object} response Response from the server (contains text and code) * @param {Array} command Contains the command executed and a callback (if any) */ -Ftp.prototype.parse = function (response, command) { +Ftp.prototype.parse = function(response, command) { var err = null; if (response.isError) { err = new Error(response.text || 'Unknown FTP error.'); @@ -252,7 +262,7 @@ Ftp.prototype.parse = function (response, command) { * @param {String} feature Feature to look for * @return {Boolean} Whether the current server has the feature */ -Ftp.prototype.hasFeat = function (feature) { +Ftp.prototype.hasFeat = function(feature) { return !!feature && this.features.indexOf(feature.toLowerCase()) > -1; }; @@ -262,25 +272,29 @@ Ftp.prototype.hasFeat = function (feature) { * @param {String} features Server response for the 'FEAT' command * @return {String[]} Array of feature names */ -Ftp.prototype._parseFeats = function (features) { +Ftp.prototype._parseFeats = function(features) { // Split and ignore header and footer var featureLines = features.split(FTP_NEWLINE).slice(1, -1); return featureLines - .map(function (feat) { return feat.trim().toLowerCase(); }) - .filter(function (feat) { return !!feat; }); + .map(function(feat) { + return feat.trim().toLowerCase(); + }) + .filter(function(feat) { + return !!feat; + }); }; // Below this point all the methods are action helpers for FTP that compose // several actions in one command -Ftp.prototype.getFeatures = function (callback) { +Ftp.prototype.getFeatures = function(callback) { if (this.features) { return callback(null, this.features); } var self = this; - this.raw.feat(function (err, response) { + this.raw.feat(function(err, response) { self.features = err ? [] : self._parseFeats(response.text); - self.raw.syst(function (err, res) { + self.raw.syst(function(err, res) { if (!err && res.code === 215) { self.system = res.text.toLowerCase(); } @@ -297,25 +311,28 @@ Ftp.prototype.getFeatures = function (callback) { * @param {String} pass Password * @param {Function} callback Follow-up function. */ -Ftp.prototype.auth = function (user, pass, callback) { +Ftp.prototype.auth = function(user, pass, callback) { var self = this; if (this.authenticating === true) { return callback(new Error('This client is already authenticating')); } - if (!user) user = 'anonymous'; - if (!pass) pass = '@anonymous'; + if (!user) { + user = 'anonymous'; + } + if (!pass) { + pass = '@anonymous'; + } this.authenticating = true; - self.raw.user(user, function (err, res) { + self.raw.user(user, function(err, res) { if (err || [230, 331, 332].indexOf(res.code) === -1) { self.authenticating = false; callback(err); return; } - - self.raw.pass(pass, function (err, res) { + self.raw.pass(pass, function(err, res) { self.authenticating = false; if (err) { @@ -324,7 +341,7 @@ Ftp.prototype.auth = function (user, pass, callback) { self.authenticated = true; self.user = user; self.pass = pass; - self.raw.type('I', function () { + self.raw.type('I', function() { callback(undefined, res); }); } else if (res.code === 332) { @@ -334,15 +351,17 @@ Ftp.prototype.auth = function (user, pass, callback) { }); }; -Ftp.prototype.setType = function (type, callback) { +Ftp.prototype.setType = function(type, callback) { type = type.toUpperCase(); if (this.type === type) { return callback(); } var self = this; - this.raw.type(type, function (err, data) { - if (!err) self.type = type; + this.raw.type(type, function(err, data) { + if (!err) { + self.type = type; + } callback(err, data); }); @@ -354,7 +373,7 @@ Ftp.prototype.setType = function (type, callback) { * @param {String} path Remote path for the file/folder to retrieve * @param {Function} callback Function to call with errors or results */ -Ftp.prototype.list = function (path, callback) { +Ftp.prototype.list = function(path, callback) { if (arguments.length === 1) { callback = arguments[0]; path = ''; @@ -364,23 +383,29 @@ Ftp.prototype.list = function (path, callback) { var listing = ''; callback = once(callback); - self.getPasvSocket(function (err, socket) { - if (err) return callback(err); + self.getPasvSocket(function(err, socket) { + if (err) { + return callback(err); + } socket.setEncoding('utf8'); - socket.on('data', function (data) { + socket.on('data', function(data) { listing += data; }); self.pasvTimeout(socket, callback); - socket.once('close', function (err) { callback(err, listing); }); + socket.once('close', function(err) { + callback(err, listing); + }); socket.once('error', callback); - function cmdCallback (err, res) { - if (err) return callback(err); + function cmdCallback(err, res) { + if (err) { + return callback(err); + } - var isExpectedMark = expectedMarks.marks.some(function (mark) { + var isExpectedMark = expectedMarks.marks.some(function(mark) { return mark === res.code; }); @@ -397,7 +422,7 @@ Ftp.prototype.list = function (path, callback) { }); }; -Ftp.prototype.emitProgress = function (data) { +Ftp.prototype.emitProgress = function(data) { this.emit('progress', { filename: data.filename, action: data.action, @@ -416,7 +441,7 @@ Ftp.prototype.emitProgress = function (data) { * @param {Function|String} localPath Local path where we create the new file * @param {Function} [callback] Gets called on either success or failure */ -Ftp.prototype.get = function (remotePath, localPath, callback) { +Ftp.prototype.get = function(remotePath, localPath, callback) { var self = this; var finalCallback; @@ -424,7 +449,7 @@ Ftp.prototype.get = function (remotePath, localPath, callback) { finalCallback = once(localPath || NOOP); } else { callback = once(callback || NOOP); - finalCallback = function (err, socket) { + finalCallback = function(err, socket) { if (err) { return callback(err); } @@ -432,7 +457,7 @@ Ftp.prototype.get = function (remotePath, localPath, callback) { var writeStream = fs.createWriteStream(localPath); writeStream.on('error', callback); - socket.on('readable', function () { + socket.on('readable', function() { self.emitProgress({ filename: remotePath, action: 'get', @@ -463,13 +488,15 @@ Ftp.prototype.get = function (remotePath, localPath, callback) { * @param {Function} callback Function to call when finalized, with the socket * as a parameter */ -Ftp.prototype.getGetSocket = function (path, callback) { +Ftp.prototype.getGetSocket = function(path, callback) { var self = this; callback = once(callback); - this.getPasvSocket(function (err, socket) { - if (err) return cmdCallback(err); + this.getPasvSocket(function(err, socket) { + if (err) { + return cmdCallback(err); + } - socket.on('error', function (err) { + socket.on('error', function(err) { if (err.code === 'ECONNREFUSED') { err.msg = 'Probably trying a PASV operation while one is in progress'; } @@ -479,7 +506,7 @@ Ftp.prototype.getGetSocket = function (path, callback) { self.pasvTimeout(socket, cmdCallback); socket.pause(); - function cmdCallback (err, res) { + function cmdCallback(err, res) { if (err) { return callback(err); } @@ -508,11 +535,11 @@ Ftp.prototype.getGetSocket = function (path, callback) { * @param {String} to path for the remote destination. * @param {Function} callback Function to execute on error or success. */ -Ftp.prototype.put = function (from, to, callback) { +Ftp.prototype.put = function(from, to, callback) { var self = this; - function putReadable (from, to, totalSize, callback) { - from.on('readable', function () { + function putReadable(from, to, totalSize, callback) { + from.on('readable', function() { self.emitProgress({ filename: to, action: 'put', @@ -521,7 +548,7 @@ Ftp.prototype.put = function (from, to, callback) { }); }); - self.getPutSocket(to, function (err, socket) { + self.getPutSocket(to, function(err, socket) { if (!err) { from.pipe(socket); } @@ -529,13 +556,13 @@ Ftp.prototype.put = function (from, to, callback) { } if (from instanceof Buffer) { - this.getPutSocket(to, function (err, socket) { + this.getPutSocket(to, function(err, socket) { if (!err) { socket.end(from); } }, callback); } else if (typeof from === 'string') { - fs.stat(from, function (err, stats) { + fs.stat(from, function(err, stats) { if (err && err.code === 'ENOENT') { return callback(new Error("Local file doesn't exist.")); } @@ -555,13 +582,13 @@ Ftp.prototype.put = function (from, to, callback) { } }; -Ftp.prototype.getPutSocket = function (path, callback, doneCallback) { +Ftp.prototype.getPutSocket = function(path, callback, doneCallback) { if (!callback) { throw new Error('A callback argument is required.'); } doneCallback = once(doneCallback || NOOP); - var _callback = once(function (err, _socket) { + var _callback = once(function(err, _socket) { if (err) { callback(err); return doneCallback(err); @@ -570,13 +597,17 @@ Ftp.prototype.getPutSocket = function (path, callback, doneCallback) { }); var self = this; - this.getPasvSocket(function (err, socket) { - if (err) return _callback(err); + this.getPasvSocket(function(err, socket) { + if (err) { + return _callback(err); + } socket.on('close', doneCallback); socket.on('error', doneCallback); - var putCallback = once(function putCallback (err, res) { - if (err) return _callback(err); + var putCallback = once(function putCallback(err, res) { + if (err) { + return _callback(err); + } // Mark 150 indicates that the 'STOR' socket is ready to receive data. // Anything else is not relevant. @@ -594,9 +625,9 @@ Ftp.prototype.getPutSocket = function (path, callback, doneCallback) { }); }; -Ftp.prototype.pasvTimeout = function (socket, callback) { +Ftp.prototype.pasvTimeout = function(socket, callback) { var self = this; - socket.once('timeout', function () { + socket.once('timeout', function() { debug('PASV socket timeout'); self.emit('timeout'); socket.end(); @@ -604,11 +635,11 @@ Ftp.prototype.pasvTimeout = function (socket, callback) { }); }; -Ftp.prototype.getPasvSocket = function (callback) { +Ftp.prototype.getPasvSocket = function(callback) { var self = this; callback = once(callback || NOOP); - this.execute('pasv', function (err, res) { + this.execute('pasv', function(err, res) { if (err) { return callback(err); } @@ -620,7 +651,7 @@ Ftp.prototype.getPasvSocket = function (callback) { var socket = self._pasvSocket = Net.createConnection(options); socket.setTimeout(self.timeout || TIMEOUT); - socket.once('close', function () { + socket.once('close', function() { self._pasvSocket = undefined; }); @@ -655,18 +686,18 @@ Ftp.prototype.getPasvSocket = function (callback) { * @param {Function} callback Function to call with the proper data when * the listing is finished. */ -Ftp.prototype.ls = function (filePath, callback) { - function entriesToList (err, entries) { +Ftp.prototype.ls = function(filePath, callback) { + function entriesToList(err, entries) { if (err) { return callback(err); } - ListingParser.parseFtpEntries(entries.text || entries, function (err, files) { + ListingParser.parseFtpEntries(entries.text || entries, function(err, files) { if (err) { return callback(err); } - files.forEach(function (file) { + files.forEach(function(file) { // Normalize UTF8 doing canonical decomposition, followed by // canonical Composition file.name = unorm.nfc(file.name); @@ -679,7 +710,7 @@ Ftp.prototype.ls = function (filePath, callback) { this.list(filePath, entriesToList); } else { var self = this; - this.raw.stat(filePath, function (err, data) { + this.raw.stat(filePath, function(err, data) { // We might be connected to a server that doesn't support the // 'STAT' command, which is set as default. We use 'LIST' instead, // and we set the variable `useList` to true, to avoid extra round @@ -699,9 +730,9 @@ Ftp.prototype.ls = function (filePath, callback) { } }; -Ftp.prototype.rename = function (from, to, callback) { +Ftp.prototype.rename = function(from, to, callback) { var self = this; - this.raw.rnfr(from, function (err) { + this.raw.rnfr(from, function(err) { if (err) { return callback(err); } @@ -709,7 +740,7 @@ Ftp.prototype.rename = function (from, to, callback) { }); }; -Ftp.prototype.keepAlive = function (wait) { +Ftp.prototype.keepAlive = function(wait) { var self = this; if (this._keepAliveInterval) { clearInterval(this._keepAliveInterval); @@ -718,7 +749,7 @@ Ftp.prototype.keepAlive = function (wait) { this._keepAliveInterval = setInterval(self.raw.noop, wait || IDLE_TIME); }; -Ftp.prototype.destroy = function () { +Ftp.prototype.destroy = function() { if (this._keepAliveInterval) { clearInterval(this._keepAliveInterval); } diff --git a/package.json b/package.json index 0bc5edf..b3fbf0a 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "devDependencies": { "concat-stream": "^1.5.0", "ftp-test-server": "0.0.2", + "ftpd": "^0.2.15", "istanbul": "^0.3.22", "mocha": "^1.21.4", "mocha-istanbul": "0.2.0", diff --git a/test/test_c9/testfile.txt b/test/fixtures/testfile.txt similarity index 100% rename from test/test_c9/testfile.txt rename to test/fixtures/testfile.txt diff --git a/test/fixtures/testfile2.txt b/test/fixtures/testfile2.txt new file mode 100644 index 0000000..d606037 --- /dev/null +++ b/test/fixtures/testfile2.txt @@ -0,0 +1 @@ +test2 \ No newline at end of file diff --git a/test/jsftp_test.js b/test/jsftp_test.js index ad5f274..368973a 100755 --- a/test/jsftp_test.js +++ b/test/jsftp_test.js @@ -6,76 +6,59 @@ */ /*global it describe beforeEach afterEach */ -"use strict"; - -var assert = require("assert"); -var Fs = require("fs"); -var exec = require('child_process').spawn; -var Ftp = require("../"); -var Path = require("path"); -var sinon = require("sinon"); -var EventEmitter = require("events").EventEmitter; -var ftpServer = require("ftp-test-server"); -var rimraf = require("rimraf"); +'use strict'; + +var assert = require('assert'); +var Fs = require('fs'); +var Ftp = require('../'); +var Path = require('path'); +var sinon = require('sinon'); +var EventEmitter = require('events').EventEmitter; +var rimraf = require('rimraf'); var concat = require('concat-stream'); +var unorm = require('unorm'); -var dbgServer = require('debug')('jsftp:test:server'); +var ftpServer = require('./server'); // Write down your system credentials. This test suite will use OSX internal // FTP server. If you want to test against a remote server, simply change the // `host` and `port` properties as well. -var FTPCredentials = { - host: "localhost", - user: "user", - port: 3334, - pass: "12345" +var options = { + user: 'user', + pass: '12345', + host: process.env.IP || '127.0.0.1', + port: process.env.PORT || 7002, + useList: true, + cwd: '/', + root: Path.join(process.cwd(), 'test'), + tls: null }; -function getRemotePath(path) { - return Path.join('test', 'test_c9', path); -} -function getLocalPath(path) { - return Path.join(process.cwd(), 'test', 'test_c9', path); +function getLocalFixturesPath(path) { + return Path.join(process.cwd(), 'test', 'fixtures', path); } -var CWD = process.cwd() + "/test"; -var remoteCWD = "test/test_c9"; -exec('mkdir', [__dirname + "/" + remoteCWD]); -describe("jsftp test suite", function() { - process.on('uncaughtException', function(err) { - console.log('Caught exception: ' + err); - server.stop(); - }); +function getRemoteFixturesPath(path) { + return Path.join('/', 'fixtures', path || ''); +} - var ftp, server; +var remoteCWD = '/fixtures'; +describe('jsftp test suite', function() { + var ftp; before(function(done) { - if (FTPCredentials.host === "localhost") { - server = new ftpServer(); - server.init(FTPCredentials); - - server.server.stdout.on('data', function(data) { - dbgServer(data.toString()); - }); - - server.server.stderr.on('data', function(data) { - dbgServer(data.toString()); - }); - - server.on('error', function(data) { - dbgServer(data.toString()); - }); - } + var _server = ftpServer.makeServer(options); + _server.listen(options.port); setTimeout(done, 1000); }); beforeEach(function(done) { - rimraf(getLocalPath(''), function() { - Fs.mkdirSync(getLocalPath('')); - Fs.writeFileSync(getLocalPath('testfile.txt'), 'test'); - Fs.writeFileSync(getLocalPath('testfile2.txt'), 'test2'); + rimraf(getLocalFixturesPath(''), function() { + Fs.mkdirSync(getLocalFixturesPath('')); + Fs.writeFileSync(getLocalFixturesPath('testfile.txt'), 'test'); + Fs.writeFileSync(getLocalFixturesPath('testfile2.txt'), 'test2'); - ftp = new Ftp(FTPCredentials); + ftp = new Ftp(options); ftp.once('connect', done); }); }); @@ -90,26 +73,37 @@ describe("jsftp test suite", function() { }, 50); }); - after(function() { server.stop(); }); + after(function() { }); + + it('test invalid password', function(next) { + ftp.auth( + options.user, + options.pass + '_invalid', + function(err, data) { + assert.equal(err.code, 530); + assert.equal(data, null); + next(); + }); + }); - it("test initialize bad host", function(next) { + it('test initialize bad host', function(next) { var ftp2 = new Ftp({ - host: "badhost", - user: "user", + host: 'badhost', + user: 'user', port: 21, - pass: "12345" + pass: '12345' }); - ftp2.on("error", function(err) { + ftp2.on('error', function(err) { assert.equal(err.code, 'ENOTFOUND'); next(); }); }); - it("test initialize", function(next) { - assert.equal(ftp.host, FTPCredentials.host); - assert.equal(ftp.port, FTPCredentials.port); - assert.equal(ftp.user, FTPCredentials.user); + it('test initialize', function(next) { + assert.equal(ftp.host, options.host); + assert.equal(ftp.port, options.port); + assert.equal(ftp.user, options.user); assert.ok(ftp instanceof EventEmitter); assert.equal(ftp.commandQueue.length, 0); @@ -117,19 +111,19 @@ describe("jsftp test suite", function() { next(); }); - it("test parseResponse with mark", function(next) { + it('test parseResponse with mark', function(next) { var cb = sinon.spy(); cb.expectsMark = { marks: [150] }; var data = { code: 150, - text: "150 File status okay; about to open data connection.", + text: '150 File status okay; about to open data connection.', isMark: true }; ftp.commandQueue = [ - { action:"retr fakefile.txt", callback: cb } + { action:'retr fakefile.txt', callback: cb } ]; ftp.parse = sinon.spy(); @@ -139,16 +133,16 @@ describe("jsftp test suite", function() { next(); }); - it("test parseResponse with no mark", function(next) { + it('test parseResponse with no mark', function(next) { var cb = sinon.spy(); var data = { code: 150, - text: "150 File status okay; about to open data connection.", + text: '150 File status okay; about to open data connection.', isMark: true }; ftp.commandQueue = [ - { action: "retr fakefile.txt", callback: cb } + { action: 'retr fakefile.txt', callback: cb } ]; ftp.parse = sinon.spy(); @@ -157,18 +151,18 @@ describe("jsftp test suite", function() { next(); }); - it("test send function", function(next) { + it('test send function', function(next) { ftp.pipeline = { write: sinon.spy() }; ftp.send(); - ftp.send("list /"); + ftp.send('list /'); assert.equal(ftp.pipeline.write.callCount, 1); - assert(ftp.pipeline.write.calledWithExactly("list /\r\n")); + assert(ftp.pipeline.write.calledWithExactly('list /\r\n')); next(); }); - it("test parseResponse with ignore code", function(next) { + it('test parseResponse with ignore code', function(next) { var cb = sinon.spy(); cb.expectsMark = { marks: [150], @@ -176,18 +170,18 @@ describe("jsftp test suite", function() { }; var data1 = { code: 150, - text: "150 File status okay; about to open data connection.", + text: '150 File status okay; about to open data connection.', isMark: true }; var data2 = { code: 226, - text: "226 Transfer complete.", + text: '226 Transfer complete.', isMark: false }; ftp.commandQueue = [ - { action: "retr fakefile.txt", callback: cb }, - { action: "list /", callback: function() {} } + { action: 'retr fakefile.txt', callback: cb }, + { action: 'list /', callback: function() {} } ]; ftp.parse = sinon.spy(); ftp.ignoreCmdCode = 150; @@ -200,27 +194,16 @@ describe("jsftp test suite", function() { next(); }); - // this will fail, can't figure out why - xit("test invalid password", function(next) { - ftp.auth( - FTPCredentials.user, - FTPCredentials.pass + '_invalid', - function(err, data) { - assert.equal(err.code, 530); - assert.equal(data, null); - next(); - }); - }); - - it("test getFeatures", function(next) { + it('test getFeatures', function(next) { ftp.getFeatures(function(err, feats) { + assert.ok(!err); assert.ok(Array.isArray(feats)); assert.ok(Array.isArray(ftp.features)); assert.ok(ftp.system.length > 0); var feat = ftp.features[0]; assert.ok(ftp.hasFeat(feat)); - assert.equal(false, ftp.hasFeat("madeup-feat")); + assert.equal(false, ftp.hasFeat('madeup-feat')); assert.equal(false, ftp.hasFeat()); assert.equal(false, ftp.hasFeat(null)); assert.equal(false, ftp.hasFeat('')); @@ -229,45 +212,45 @@ describe("jsftp test suite", function() { }); }); - it("test print working directory", function(next) { + it('test print working directory', function(next) { ftp.raw.pwd(function(err, res) { assert(!err, err); var code = parseInt(res.code, 10); - assert.ok(code === 257, "PWD command was not successful: " + res.text); + assert.ok(code === 257, 'PWD command was not successful: ' + res.text); next(); }); }); - it("test switch CWD", function(next) { + it('test switch CWD', function(next) { ftp.raw.cwd(remoteCWD, function(err, res) { assert.ok(!err, err); var code = parseInt(res.code, 10); - assert.ok(code === 200 || code === 250, "CWD command was not successful"); + assert.ok(code === 200 || code === 250, 'CWD command was not successful'); ftp.raw.pwd(function(err, res) { assert.ok(!err, err); var code = parseInt(res.code, 10); - assert.ok(code === 257, "PWD command was not successful"); - assert.ok(res.text.indexOf(remoteCWD), "Unexpected CWD"); + assert.ok(code === 257, 'PWD command was not successful'); + assert.ok(res.text.indexOf(remoteCWD), 'Unexpected CWD'); next(); }); }); }); - it("test switch to unexistent CWD", function(next) { - ftp.raw.cwd("/unexistentDir/", function(err, res) { + it('test switch to unexistent CWD', function(next) { + ftp.raw.cwd('/unexistentDir/', function(err, res) { var code = parseInt(res.code, 10); - assert.ok( !! err); - assert.equal(code, 550, "A (wrong) CWD command was successful. It should have failed"); + assert.ok(!!err); + assert.equal(code, 550, 'A (wrong) CWD command was successful. It should have failed'); next(); }); }); - it("test switch to unexistent CWD contains special string", function (next) { + it('test switch to unexistent CWD contains special string', function (next) { ftp.raw.cwd('/unexistentDir/user', function (err, res) { var code = parseInt(res.code, 10); assert.equal(code, 550); @@ -275,7 +258,7 @@ describe("jsftp test suite", function() { }); }); - it("test passive listing of current directory", function(next) { + it('test passive listing of current directory', function(next) { ftp.list(remoteCWD, function(err, res) { assert.ok(!err, err); assert.ok(res.length > 0); @@ -283,18 +266,20 @@ describe("jsftp test suite", function() { }); }); - it("test passive listing of nonexisting directory", function(next) { - ftp.list('does-not-exist/', function(err, res) { + it('test passive listing of nonexisting directory', function(next) { + ftp.list('does-not-exist/', function(err) { + assert(err); assert.equal(typeof err, 'object'); assert.ok(err.code === 450 || err.code === 550); next(); }); }); - it("test ftp node stat", function(next) { + it('test ftp node stat', function(next) { ftp.raw.pwd(function(err, res) { + assert.ok(!err); var parent = new RegExp('.*"(.*)".*').exec(res.text)[1]; - var path = Path.resolve(parent + "/" + remoteCWD); + var path = Path.resolve(parent + '/' + remoteCWD); ftp.raw.stat(path, function(err, res) { assert.ok(!err, res); assert.ok(res); @@ -305,8 +290,8 @@ describe("jsftp test suite", function() { }); }); - it("test create and delete a directory", function(next) { - var newDir = remoteCWD + "/ftp_test_dir"; + it('test create and delete a directory', function(next) { + var newDir = remoteCWD + '/ftp_test_dir'; ftp.raw.mkd(newDir, function(err, res) { assert.ok(!err); assert.equal(res.code, 257); @@ -318,8 +303,8 @@ describe("jsftp test suite", function() { }); }); - it("test create and delete a directory containing a space", function(next) { - var newDir = remoteCWD + "/ftp test dür"; + it('test create and delete a directory containing a space', function(next) { + var newDir = remoteCWD + '/ftp test dür'; ftp.raw.mkd(newDir, function(err, res) { assert.ok(!err); assert.equal(res.code, 257); @@ -331,118 +316,110 @@ describe("jsftp test suite", function() { }); }); - it("test create and delete a file", function(next) { - var filePath = getRemotePath("file_ftp_test.txt"); - Fs.readFile(__filename, "binary", function(err, data) { - var buffer = new Buffer(data, "binary"); + it('test create and delete a file', function(next) { + var filePath = getRemoteFixturesPath('file_ftp_test.txt'); + Fs.readFile(__filename, 'binary', function(err, data) { + assert.ok(!err); + var buffer = new Buffer(data, 'binary'); ftp.put(buffer, filePath, function(hadError) { assert.ok(!hadError); - ftp.ls(filePath, function(err, res) { - assert.ok(!err); - assert.equal(buffer.length, Fs.statSync(CWD + "/jsftp_test.js").size); + assert.equal(buffer.length, + Fs.statSync(Path.join(process.cwd(), 'test/jsftp_test.js')).size); - ftp.raw.dele(filePath, function(err, data) { - assert.ok(!err); - - next(); - }); + ftp.raw.dele(filePath, function(err, data) { + assert.ok(!err); + next(); }); }); }); }); - it("test save a remote copy of a local file", function(next) { + it('test save a remote copy of a local file', function(next) { this.timeout(10000); - var filePath = getRemotePath("file_ftp_test.txt"); + var filePath = getRemoteFixturesPath('file_ftp_test.txt'); var onProgress = sinon.spy(); ftp.on('progress', onProgress); ftp.put(__filename, filePath, function(err, res) { assert.ok(!err, err); + assert(onProgress.called); - ftp.ls(filePath, function(err, res) { - assert.ok(!err); - assert(onProgress.called); - var data = onProgress.args[0][0]; - assert.equal(data.filename, filePath); - assert.equal(data.action, 'put'); - assert.ok(typeof data.transferred, 'number'); + var data = onProgress.args[0][0]; + assert.equal(data.filename, filePath); + assert.equal(data.action, 'put'); + assert.ok(typeof data.transferred, 'number'); - ftp.raw.dele(filePath, function(err, data) { - assert.ok(!err); - next(); - }); + ftp.raw.dele(filePath, function(err, data) { + assert.ok(!err); + next(); }); }); }); - it("test passing a dir instead of file path to put should callback with error", function (next) { - var localUploadPath = "."; - var remoteFileName = "directory_file_upload_should_fail.txt"; + it('test passing a dir instead of file path to put should callback with error', function(next) { + var localUploadPath = '.'; + var remoteFileName = 'directory_file_upload_should_fail.txt'; - ftp.put(localUploadPath, remoteFileName, function(hadError) { - assert.ok(hadError); - next(); + ftp.put(localUploadPath, remoteFileName, function(hadError) { + assert.ok(hadError); + next(); }); }); - it("test streaming put", function(next) { + it('test streaming put', function(next) { + var readStream = Fs.createReadStream(__filename); - var remoteFileName = "file_ftp_test.txt"; - var filePath = getRemotePath(remoteFileName); + var remoteFileName = 'file_ftp_test.txt'; + var filePath = getRemoteFixturesPath(remoteFileName); ftp.put(readStream, filePath, function(hadError) { assert.ok(!hadError); - ftp.ls(filePath, function(err, res) { - assert.ok(!err); - assert.equal(res[0].size, Fs.statSync(CWD + "/jsftp_test.js").size); + var uploadedFileSize = Fs.statSync(getLocalFixturesPath(remoteFileName)).size; + var originalFileSize = Fs.statSync(__filename).size; + assert.equal(uploadedFileSize, originalFileSize); - ftp.raw.dele(filePath, function(err, data) { - assert.ok(!err); - - next(); - }); + ftp.raw.dele(filePath, function(err, data) { + assert.ok(!err); + next(); }); }); }); - it("test rename a file", function(next) { - var from = getRemotePath("file_ftp_test.txt"); - var to = getRemotePath("file_ftp_test_renamed.txt"); - Fs.readFile(__filename, "binary", function(err, data) { + it('test rename a file', function(next) { + var from = getRemoteFixturesPath('file_ftp_test.txt'); + var to = getRemoteFixturesPath('file_ftp_test_renamed.txt'); + Fs.readFile(__filename, 'binary', function(err, data) { assert.ok(!err, err); - var buffer = new Buffer(data, "binary"); + var buffer = new Buffer(data, 'binary'); ftp.put(buffer, from, function(err, res) { assert.ok(!err, err); ftp.rename(from, to, function(err, res) { - ftp.ls(to, function(err, res) { - assert.ok(!err); + assert.ok(!err); - assert.equal(buffer.length, Fs.statSync(__filename).size); + assert.equal(buffer.length, Fs.statSync(__filename).size); - ftp.raw.dele(to, function(err, data) { - assert.ok(!err); - next(); - }); + ftp.raw.dele(to, function(err, data) { + assert.ok(!err); + next(); }); }); }); }); }); - it("test get a file", function(next) { - var localPath = CWD + '/test_c9/testfile.txt'; - var remotePath = remoteCWD + "/testfile.txt"; - var realContents = Fs.readFileSync(localPath, "utf8"); - var str = ""; + it('test get a file', function(next) { + var localPath = getLocalFixturesPath('testfile.txt'); + var remotePath = getRemoteFixturesPath('testfile.txt'); + var realContents = Fs.readFileSync(localPath, 'utf8'); + var str = ''; ftp.get(remotePath, function(err, socket) { assert.ok(!err, err); assert.ok(arguments.length === 2); - socket.on("data", function(d) { + socket.on('data', function(d) { str += d; - }) - socket.on("close", function(hadErr) { + }); + socket.on('close', function(hadErr) { assert.equal(realContents, str); next(); }); @@ -450,15 +427,16 @@ describe("jsftp test suite", function() { }); }); - it("test get a file and save it locally", function(next) { - var localPath = getLocalPath("testfile.txt"); - var remotePath = getRemotePath("testfile.txt"); - var destination = localPath + ".copy"; + it('test get a file and save it locally', function(next) { + var localPath = getLocalFixturesPath('testfile.txt'); + var remotePath = getRemoteFixturesPath('testfile.txt'); + var destination = localPath + '.copy'; var onProgress = sinon.spy(); ftp.on('progress', onProgress); Fs.unlink(destination, function() { - Fs.readFile(localPath, "utf8", function(err, realContents) { + Fs.readFile(localPath, 'utf8', function(err, realContents) { + assert(!err); ftp.get(remotePath, destination, function(err) { assert.ok(!err, err); assert.ok(arguments.length < 2, arguments.length); @@ -466,7 +444,8 @@ describe("jsftp test suite", function() { assert.equal(data.filename, remotePath); assert.equal(data.action, 'get'); assert.ok(typeof data.transferred, 'number'); - Fs.readFile(destination, "utf8", function(err, data) { + Fs.readFile(destination, 'utf8', function(err, data) { + assert.ok(!err); assert.strictEqual(data, realContents); next(); }); @@ -475,11 +454,11 @@ describe("jsftp test suite", function() { }); }); - it("test get a big file stream", function(next) { - var remotePath = getRemotePath("bigfile.test"); - var localPath = getLocalPath("bigfile.test"); - var data = (new Array(1 * 1024 * 1024)).join("x"); - var buffer = new Buffer(data, "binary"); + it('test get a big file stream', function(next) { + var remotePath = getRemoteFixturesPath('bigfile.test'); + var localPath = getLocalFixturesPath('bigfile.test'); + var data = (new Array(1 * 1024 * 1024)).join('x'); + var buffer = new Buffer(data, 'binary'); Fs.writeFileSync(localPath, buffer); @@ -505,9 +484,9 @@ describe("jsftp test suite", function() { }); }); - it("test put a big file stream", function(next) { - var remotePath = getRemotePath("bigfile.test"); - var data = (new Array(1 * 1024 * 1024)).join("x"); + it('test put a big file stream', function(next) { + var remotePath = getRemoteFixturesPath('bigfile.test'); + var data = (new Array(1 * 1024 * 1024)).join('x'); ftp.getPutSocket(remotePath, function(err, socket) { assert.ok(!err, err); @@ -526,23 +505,22 @@ describe("jsftp test suite", function() { }); }); - it("test put a big file stream fail", function(next) { - var remotePath = getRemotePath("/nonexisting/path/to/file.txt"); + it('test put a big file stream fail', function(next) { + var remotePath = getRemoteFixturesPath('/nonexisting/path/to/file.txt'); ftp.getPutSocket(remotePath, function(err, socket, res) { - assert.ok( !! err, err); - assert.equal(err.code, 550, err); + assert.ok(!!err, err); }, function(err, res) { - assert.ok( !! err); + assert.ok(!!err); next(); }); }); - it("test get fileList array", function(next) { - var file1 = "testfile.txt"; + it('test get fileList array', function(next) { + var file1 = 'testfile.txt'; - ftp.raw.cwd(getRemotePath(''), function() { - ftp.ls(".", function(err, res) { + ftp.raw.cwd(getRemoteFixturesPath(''), function() { + ftp.ls('.', function(err, res) { assert.ok(!err, err); assert.ok(Array.isArray(res)); @@ -558,22 +536,26 @@ describe("jsftp test suite", function() { }); }); - it("test reconnect", function(next) { + it('test reconnect', function(next) { this.timeout(10000); ftp.raw.pwd(function(err, res) { - if (err) throw err; + if (err) { + throw err; + } ftp.socket.destroy(); ftp.raw.quit(function(err, res) { - if (err) throw err; + if (err) { + throw err; + } next(); }); }); }); - it("test attach event handlers: connect", function(_next) { + it('test attach event handlers: connect', function(_next) { var clientOnConnect = function() { - client.auth(FTPCredentials.user, FTPCredentials.pass, next); + client.auth(options.user, options.pass, next); }; var next = function(err) { @@ -583,30 +565,31 @@ describe("jsftp test suite", function() { }; var client = new Ftp({ - host: "localhost", - user: "user", - port: 3334, - pass: "12345" + host: options.host, + port: options.port, }); - client.on("connect", clientOnConnect); + client.on('connect', clientOnConnect); }); - it("test PASV streaming: Copy file using piping", function(next) { - var filePath = getRemotePath("testfile.txt"); - var originalData = Fs.readFileSync(getLocalPath("testfile.txt")); + it.skip('test PASV streaming: Copy file using piping', function(next) { + var filePath = getRemoteFixturesPath('testfile.txt'); + var originalData = Fs.readFileSync(getLocalFixturesPath('testfile.txt')); ftp.getGetSocket(filePath, function(err, readable) { assert(!err, err); assert.ok(readable); - readable.on("error", error); + readable.on('error', error); function error(err) { assert.ok(!err, err); - if (readable.destroy) readable.destroy(); + if (readable.destroy) { + readable.destroy(); + } + next(); } - var remoteCopy = filePath + ".bak"; + var remoteCopy = filePath + '.bak'; ftp.getPutSocket(remoteCopy, function(err, socket) { assert.ok(!err, err); readable.pipe(socket); @@ -616,14 +599,15 @@ describe("jsftp test suite", function() { function(hadError) { assert.ok(!hadError); - var str = ""; + var str = ''; ftp.getGetSocket(remoteCopy, function(err, socket) { assert.ok(!err, err); - socket.on("data", function(d) { + + socket.on('data', function(d) { str += d; }); - socket.on("close", function(hadErr) { - assert.equal(originalData.toString("utf8"), str); + socket.on('close', function(hadErr) { + assert.equal(originalData.toString('utf8'), str); next(); }); socket.resume(); @@ -632,10 +616,10 @@ describe("jsftp test suite", function() { }); }); - it("Test that streaming GET (RETR) retrieves a file properly", function(next) { - var path = getLocalPath("testfile.txt"); + it('Test that streaming GET (RETR) retrieves a file properly', function(next) { + var path = getLocalFixturesPath('testfile.txt'); var originalData = Fs.readFileSync(path); - ftp.getGetSocket(getRemotePath("testfile.txt"), function(err, readable) { + ftp.getGetSocket(getRemoteFixturesPath('testfile.txt'), function(err, readable) { assert.ok(!err); var concatStream = concat(function(buffer) { assert.ok(!err); @@ -651,28 +635,29 @@ describe("jsftp test suite", function() { }); }); - it("Test that streaming GET (RETR) fails when a file is not present", function(next) { - ftp.getGetSocket("unexisting/file/path", function(err, readable) { + it('Test that streaming GET (RETR) fails when a file is not present', function(next) { + ftp.getGetSocket('unexisting/file/path', function(err, readable) { assert.ok(err); assert.equal(550, err.code); next(); }); }); - it("Test that streaming PUT (STOR) stores a file properly", function(next) { - var path = getLocalPath("testfile.txt"); - var originalData = Fs.createReadStream(getLocalPath("testfile.txt")); + it('Test that streaming PUT (STOR) stores a file properly', function(next) { + var path = getLocalFixturesPath('testfile.txt'); + var originalData = Fs.createReadStream(getLocalFixturesPath('testfile.txt')); originalData.pause(); - ftp.getPutSocket(getRemotePath("testfile.txt.bak"), function(err, socket) { + ftp.getPutSocket(getRemoteFixturesPath('testfile.txt.bak'), function(err, socket) { assert.ok(!err); originalData.pipe(socket); originalData.resume(); var concatStream = concat(function(buffer) { assert.ok(!err); - Fs.readFile(path, "utf8", function(err, original) { - assert.equal(buffer.toString("utf8"), original); + Fs.readFile(path, 'utf8', function(err, original) { + assert.ok(!err); + assert.equal(buffer.toString('utf8'), original); next(); }); }); @@ -685,64 +670,43 @@ describe("jsftp test suite", function() { }); }); - it("Test that streaming PUT (STOR) fails when a file is not present", function(next) { - ftp.getPutSocket("unexisting/file/path", function(err, socket) { + it('Test that streaming PUT (STOR) fails when a file is not present', function(next) { + ftp.getPutSocket('unexisting/file/path', function(err, socket) { assert.ok(err); next(); }); }); - it("Test that onConnect is called", function(next) { - var ftp2 = new Ftp(FTPCredentials); - ftp2.on("connect", function() { + it('Test that onConnect is called', function(next) { + var ftp2 = new Ftp(options); + ftp2.on('connect', function() { next(); }); }); - it("Test for correct data on ls 1", function(next) { - var paths = ['test/test_c9/testfile.txt', 'work/test/main.css']; - ftp.auth(FTPCredentials.user, FTPCredentials.pass, function(err, data) { - if (err) return console.log(err); - - var processed = 0; - ftp.ls(paths[0], function showFile(err, res) { - assert.ok(!err); - assert.strictEqual(res[0].name, 'testfile.txt'); - processed += 1; - if (processed === 2) next(); - }); - - ftp.ls(paths[1], function showFile(err, res1) { - assert.ok( !! err); - processed += 1; - if (processed === 2) next(); - }); - }); - }); - - it("Test raw method with PWD", function(next) { + it('Test raw method with PWD', function(next) { ftp.raw('pwd', function(err, res) { assert(!err, err); var code = parseInt(res.code, 10); - assert.ok(code === 257, "Raw PWD command was not successful: " + res.text); + assert.ok(code === 257, 'Raw PWD command was not successful: ' + res.text); next(); }); }); - it("Test raw method with HELP", function(next) { - ftp.raw('help', function(err, res) { + it('Test raw method with NOOP', function(next) { + ftp.raw('noop', function(err, res) { assert(!err, err); var code = parseInt(res.code, 10); - assert.ok(code === 214, "Raw HELP command was not successful: " + res.text); + assert.ok(code === 200, 'Raw HELP command was not successful: ' + res.text); next(); }); }); - it("Test keep-alive with NOOP", function(next) { + it('Test keep-alive with NOOP', function(next) { this.timeout(10000); ftp.keepAlive(); ftp.keepAlive(1000); @@ -752,35 +716,33 @@ describe("jsftp test suite", function() { }, 5000); }); - it.skip("Test handling error on simultaneous PASV requests {#90}", function(next) { - var file1 = remoteCWD + "/testfile.txt"; - var file2 = remoteCWD + "/testfile2.txt"; + it('Test handling error on simultaneous PASV requests {#90}', function(next) { + var file1 = getRemoteFixturesPath('testfile.txt'); + var file2 = getRemoteFixturesPath('testfile2.txt'); var counter = 0; var args = []; function onDone() { counter += 1; if (counter === 2) { - assert.ok(args.some(function(arg) { return arg instanceof Error; })); + assert.ok(args.some(function(arg) { + return arg instanceof Error; + })); next(); } } - ftp.raw.pwd(function(err) { - assert.ok(!err); - - ftp.get(file1, function() { - args.push(arguments[0]); - onDone(); - }); - ftp.get(file2, function() { - args.push(arguments[0]); - onDone(); - }); + ftp.get(file1, function() { + args.push(arguments[0]); + onDone(); + }); + ftp.get(file2, function() { + args.push(arguments[0]); + onDone(); }); }); - it("test set binary type", function(next) { + it('test set binary type', function(next) { ftp.setType('I', function(err, res) { assert.ok(!err); assert.equal(ftp.type, 'I'); @@ -799,22 +761,17 @@ describe("jsftp test suite", function() { }); }); - it('test listing a folder containing special UTF characters', function(next) { - var dirName = '_éàèùâêûô_'; + it.skip('test listing a folder containing special UTF characters', function(next) { + var dirName = unorm.nfc('_éàèùâêûô_'); var newDir = Path.join(remoteCWD, dirName); ftp.raw.mkd(newDir, function(err, res) { assert.ok(!err); assert.equal(res.code, 257); - ftp.ls(remoteCWD, function(err, res) { - assert.ok(!err); - assert.ok(res.some(function(el) { - return el.name.indexOf(dirName) > -1; - })); - ftp.raw.rmd(newDir, function(err, res) { - assert.ok(!err); - next(); - }); - }); + var list = Fs.readdirSync(Path.join(__dirname, 'fixtures')); + assert.ok(list.some(function(dir) { + return unorm.nfc(dir.trim()) === dirName; + })); + next(); }); }); }); diff --git a/test/server.js b/test/server.js new file mode 100644 index 0000000..27a8301 --- /dev/null +++ b/test/server.js @@ -0,0 +1,54 @@ +var ftpd = require('ftpd'); + +var _user = 'user'; +var _pass = '12345'; + +function makeServer(options) { + var server = new ftpd.FtpServer(options.host, { + getInitialCwd: function() { + return options.cwd || '/'; + }, + getRoot: function() { + return options.root || process.cwd(); + }, + pasvPortRangeStart: 1025, + pasvPortRangeEnd: 1050, + tlsOptions: options.tls, + allowUnauthorizedTls: false, + useWriteFile: false, + useReadFile: false, + uploadMaxSlurpSize: 7000, // N/A unless 'useWriteFile' is true. + }); + + server.on('error', function(error) { + console.log('FTP Server error:', error); + }); + + server.on('client:connected', function(connection) { + var username = null; + console.log('client connected: ' + connection.remoteAddress); + connection.on('command:user', function(user, success, failure) { + if (_user === user) { + username = user; + success(); + } else { + failure(); + } + }); + + connection.on('command:pass', function(pass, success, failure) { + if (_pass === pass) { + success(username); + } else { + failure(); + } + }); + }); + + server.debugging = 4; + return server; +} + +module.exports = { + makeServer: makeServer +};