UNPKG

fs-rsync

Version:

sync local node-browserfs with remote fs

462 lines (318 loc) 12.3 kB
var assert = chai.assert; var FSRCON = window.FSRCON; var BROWSERFS = window.browserfs; var FSRSYNC = window.FSRSYNC; var browserFs; var connection; var rsync; var protocol = 'http'; var hostname = 'localhost'; var port = 3000; function resetRemoteFs (callback) { var xhr = new XMLHttpRequest(), url = protocol + '://' + hostname + ':' + port + '/resetRemoteFs'; // The last parameter must be set to true to make an asynchronous request xhr.open('get', url, true); // xhr.setRequestHeader('Content-type', 'application/json'); // xhr.setRequestHeader('Accept', 'application/json'); xhr.setRequestHeader('Cache-Control', 'no-cache'); xhr.onload = function () { callback(null); }; xhr.onerror = function () { callback(new Error('ECON')); }; xhr.send(); } function initialize (callback) { var accountId = FSRCON.hash('email@domain.tld'), password = FSRCON.hash('my secret', accountId), connOptions = { protocol: protocol, hostname: hostname, port: port, accountId: accountId }; browserFs = new BROWSERFS(); connection = new FSRCON.Client(connOptions); rsync = new window.FSRSYNC(browserFs, connection); connection.init('init') .then( function () { connection.connect('connect', password) .then( function () { console.log('client connected to server'); resetRemoteFs(callback); }, callback ); }, callback ); } describe('fs-rsync', function () { before(function (done) { initialize(done); }); it('should have loaded module', function () { assert.isFunction(BROWSERFS, 'browserfs'); assert.isObject(FSRCON, 'fs-rcon'); assert.isFunction(FSRSYNC, 'fs-rsync'); }); it('should list remote directory contents and stats', function (done) { assert.isFunction(rsync.remoteList, 'should have a list function'); rsync.remoteList('/', function (err, list) { assert.isNull(err, 'should not have an error'); assert.isObject(list, 'list'); assert.isObject(list.dirA, 'list.dirA'); assert.isTrue(list.dirA.isDirectory); assert.isObject(list.file0, 'list.file0'); assert.isFalse(list.file0.isDirectory); done(); }); }); it('should get stats for a remote file', function (done) { assert.isFunction(rsync.remoteStat); rsync.remoteStat('/', function (err, stats) { assert.isNull(err, 'should not have an error'); assert.isObject(stats, 'stats should be object'); assert.includeMembers(Object.keys(stats), ['size', 'atime', 'mtime', 'ctime', 'birthtime']); done(); }); }); it('convert base64 string to ArrayBuffer', function () { var buffer = FSRSYNC.base64ToArrayBuffer('ZmlsZTAgY29udGVudA=='); assert.instanceOf(buffer, ArrayBuffer); assert.strictEqual(buffer.byteLength, 13); }); it('should load a remote file with small chunks', function (done) { rsync.remoteReadFile( '/file1', {chunkSize: 1024}, function (err, data) { assert.isNull(err, 'should not have an error'); assert.strictEqual(data.byteLength, 3465, 'file content length'); done(); } ); }); describe('synchronizing file systems', function () { it('should sync all files to a local directory from remote fs directory', function (done) { var path = '/'; assert.isFunction(rsync.syncDir); rsync.syncDir(path, function (err, result) { assert.isNull(err, 'should not have an error'); assert.strictEqual(result, path); assert.isTrue(browserFs.existsSync('/file0'), 'file should exist'); assert.isTrue(browserFs.existsSync('/file1'), 'file should exist'); assert.isTrue(browserFs.existsSync('/file2'), 'file should exist'); assert.isTrue(browserFs.statSync('/file2').isFile(), 'file should be a file'); assert.isTrue(browserFs.existsSync('/dirA'), 'directory should exist'); assert.isTrue(browserFs.statSync('/dirA').isDirectory(), 'file should be directory'); done(); }); }); // sync all files to a local directory from remote it('should sync file contents', function (done) { var path = '/'; rsync.syncDir(path, function () { assert.strictEqual( browserFs.readFileSync('/file2', 'utf8'), '½ + ¼ = ¾', 'equal file contents' ); done(); }); }); it('should sync stats', function (done) { var path = '/'; rsync.syncDir(path, function () { var fileNode; fileNode = browserFs.getNode('/file0'); assert.isObject(fileNode.remoteStats, 'file node remote stats'); assert.strictEqual( fileNode.remoteStats.birthtime, fileNode.ctime, 'ctime' ); assert.strictEqual( fileNode.remoteStats.atime, fileNode.atime, 'atime' ); assert.strictEqual( fileNode.remoteStats.mtime, fileNode.mtime, 'mtime' ); fileNode = browserFs.getNode('/dirA'); assert.isObject(fileNode.remoteStats, 'dir node remote stats'); assert.strictEqual( fileNode.remoteStats.birthtime, fileNode.ctime, 'ctime' ); assert.strictEqual( fileNode.remoteStats.atime, fileNode.atime, 'atime' ); assert.strictEqual( fileNode.remoteStats.mtime, fileNode.mtime, 'mtime' ); done(); }); }); it('should sync all new files from local directory to remote fs directory', function (done) { var path = '/', filename, fileNode; assert.isFunction(rsync.syncDir); // create local directory filename = '/local dir ' + (new Date()).getTime(); browserFs.mkdirpSync(filename); fileNode = browserFs.getNode(filename); assert.isUndefined(fileNode.remoteStats); rsync.syncDir(path, function (err) { assert.isNull(err, 'should not have an error'); // check remote dir assert.isObject(fileNode.remoteStats, 'dir remote stats'); // create local file filename += '/local file ' + (new Date()).getTime(); browserFs.writeFileSync(filename, 'local file content'); fileNode = browserFs.getNode(filename); assert.isUndefined(fileNode.remoteStats); path = browserFs.dirname(filename); rsync.syncDir(path, function (err) { assert.isNull(err, 'should not have an error'); // check remote file assert.isObject(fileNode.remoteStats, 'file remote stats'); assert.strictEqual(fileNode.remoteStats.size, 18, 'remote file size'); done(); }); }); }); // sync all new files from local directory to remote it('should delete locally deleted files on remote fs', function (done) { var filename = '/file2', fileNode; assert.isTrue(browserFs.existsSync(filename)); fileNode = browserFs.getNode(filename); assert(fileNode.remoteStats); browserFs.unlinkSync(filename); assert.isFalse(browserFs.existsSync(filename)); rsync.syncDir('/', function (err) { assert.isNull(err, 'should not have an error'); assert.isFalse(browserFs.existsSync(filename)); done(); }); }); it('should delete locally deleted directory on remote fs', function (done) { var filename = '/dirA', fileNode; assert.isTrue(browserFs.existsSync(filename)); fileNode = browserFs.getNode(filename); assert(fileNode.remoteStats); assert.notInclude(rsync.deletedLocalFiles, filename); browserFs.rmrfSync(filename); assert.include(rsync.deletedLocalFiles, filename); assert.isFalse(browserFs.existsSync(filename)); rsync.syncDir('/', function (err) { assert.isNull(err, 'should not have an error'); assert.isFalse(browserFs.existsSync(filename)); assert.notInclude(rsync.deletedLocalFiles, filename); done(); }); }); it('should synchronize recursivly', function (done) { initialize(function () { rsync.syncDir('/', {recursive: true}, function (err) { assert.isNull(err, 'should not have an error'); assert.isTrue(browserFs.existsSync('/dirA/fileA'), 'sync sub dir contents'); done(); }); }); }); it('should sync renamed files', function (done) { assert.isTrue(browserFs.existsSync('/file0'), 'file0 should exist at local fs'); assert.isFalse(browserFs.existsSync('/renamed'), 'renamed should not exist yet at local fs'); browserFs.renameSync('/file0', '/dirA/renamed'); assert.isFalse(browserFs.existsSync('/file0'), 'file0 should not exist now at local fs'); assert.isTrue(browserFs.existsSync('/dirA/renamed'), 'renamed should now exist at local fs'); rsync.syncDir('/', function (err) { assert.isNull(err, 'should not have an error'); assert.isFalse(browserFs.existsSync('/file0'), 'file0 should still not exist at local fs'); rsync.syncDir('/dirA', function (err) { assert.isNull(err, 'should not have an error'); assert.isTrue(browserFs.existsSync('/dirA/renamed'), 'renamed should still exist at local fs'); done(); }); }); }); it('should synchronize a single file', function (done) { var filename = '/file ' + (new Date()).getTime(), fileNode; browserFs.writeFileSync(filename, 'file ' + filename + ' content'); fileNode = browserFs.getNode(filename); assert.isUndefined(fileNode.remoteStats); rsync.syncFile(filename, function (err) { assert.isNull(err, 'should not have an error'); fileNode = browserFs.getNode(filename); assert.isObject(fileNode.remoteStats); done(); }); }); it('should synchronize remote file with unsynced local path', function (done) { initialize(function () { rsync.syncFile('/dirA/fileA', function (err) { assert.isNull(err, 'should not have an error'); assert.isTrue(browserFs.existsSync('/dirA/fileA'), 'sync file without local path'); done(); }); }); }); it('should handle unsynced files that exists on local and remote', function (done) { var filename = '/dirA/fileA'; initialize(function () { // create on local before sync browserFs.mkdirpSync('/dirA'); browserFs.writeFileSync(filename, 'file ' + filename + ' content'); rsync.syncFile(filename, function (err) { assert.instanceOf(err, Error, 'should have an error'); assert.strictEqual(err.message, 'ECONFLICT', 'conflict error message'); done(); }); }); }); it('should ensure remote path when creating file on remote', function (done) { var now = + Date.now(), filenames = [ '/newRootFile' + now, '/dirA/newFileOnExistingPath' + now, '/not' + now + '/existing' + now + '/Path' + now + '/newFile' + now, ]; initialize(function () { FSRSYNC.eachAsync( filenames, function (filename, filenameDone) { // create on local var dirname = browserFs.dirname(filename); if ('/' !== dirname) { browserFs.mkdirpSync(dirname); } browserFs.writeFileSync(filename, 'file ' + filename + ' content'); // remote sync rsync.syncFile(filename, function (err) { filenameDone(err); }); }, function (err) { assert(!err, 'should not have an error'); done(); } ); }); }); }); // describe synchronizing file systems }); // describe fs-rsync