feature(package) add dropbox support

This commit is contained in:
coderaiser 2018-10-29 20:17:18 +02:00
parent ef116a9a53
commit 0908837392
14 changed files with 366 additions and 229 deletions

View file

@ -33,6 +33,7 @@
"com",
"dev",
"deepword",
"dropbox",
"dword",
"edward",
"favicon",

113
HELP.md
View file

@ -107,6 +107,8 @@ Cloud Commander supports command line parameters:
| `--import-token` | authorization token used to connect to export server
| `--import-url` | url of an import server
| `--import-listen` | enable listen on config updates from import server
| `--dropbox` | enable dropbox integration
| `--dropbox-token` | set dropbox token
| `--log` | enable logging
| `--no-show-config` | do not show config values
| `--no-server` | do not start server
@ -132,8 +134,10 @@ Cloud Commander supports command line parameters:
| `--no-export` | disable export config through a server
| `--no-import` | disable import of config
| `--no-import-listen` | disable listen on config updates from import server
| `--no-log` | disable logging
| `--no-show-file-name` | do not show file name in view and edit
| `--no-dropbox` | disable dropbox integration
| `--no-dropbox-token` | unset dropbox token
| `--no-log` | disable logging
If no parameters given Cloud Commander reads information from `~/.cloudcmd.json` and use
port from it (`8000` default). if port variables `PORT` isn't exist.
@ -374,49 +378,51 @@ Here is description of options:
```js
{
"name" : "", /* set tab name in web browser */
"auth" : false, /* enable http authentication */
"username" : "root", /* username for authentication */
   "password"         : "toor",   /* password hash for authentication */
"algo" : "sha512WithRSAEncryption", /* cryptographic algorithm */
"editor" : "edward", /* default, could be "dword" or "edward" */
"packer" : "tar", /* default, could be "tar" or "zip" */
"diff" : true, /* when save - send patch, not whole file */
"zip" : true, /* zip text before send / unzip before save */
"buffer" : true, /* buffer for copying files */
"dirStorage" : true, /* store directory listing */
"online" : false, /* do not load js files from cdn */
"open" : true, /* open web browser when server started */
"oneFilePanel" : false, /* show one file panel */
"keysPanel" : true, /* show classic panel with buttons of keys */
"port" : 8000, /* http port */
"ip" : null, /* ip or null(default) */
"root" : "/", /* root directory */
"prefix" : "", /* url prefix */
"prefixSocket" : "", /* prefix for socket connection */
"progress" : true, /* show progress of file operations */
"confirmCopy" : true, /* confirm copy */
"confirmMove" : true, /* confirm move */
"showConfig" : false, /* show config at startap */
"showFileName" : false /* do not show file name in view and edit */
"contact" : true, /* enable contact */
"configDialog" : true, /* enable config dialog */
"configAuth" : true, /* enable auth change in config dialog */
"console" : true, /* enable console */
"syncConsolePath" : false /* do not sync console path */
"terminal" : false, /* disable terminal */
"terminalPath" : '', /* path of a terminal */
"terminalCommand" : '', /* set command to run in terminal */
"terminalAutoRestart" : true, /* restart command on exit */
"vim" : false, /* disable vim hot keys */
"columns" : "name-size-date-owner-mode", /* set visible columns */
"export" : false, /* enable export of config through a server */
"exportToken" : "root", /* token used by export server */
"import" : false, /* enable import of config */
"import-url" : "http://localhost:8000", /* url of an export server */
"importToken" : "root", /* token used to connect to export server */
"importListen" : false, /* listen on config updates */
"log" : true /* logging */
"name" : "", // set tab name in web browser
"auth" : false, // enable http authentication
"username" : "root", // username for authentication
   "password"         : "toor",   // password hash for authentication
"algo" : "sha512WithRSAEncryption", // cryptographic algorithm
"editor" : "edward", // default, could be "dword" or "edward"
"packer" : "tar", // default, could be "tar" or "zip"
"diff" : true, // when save - send patch, not whole file
"zip" : true, // zip text before send / unzip before save
"buffer" : true, // buffer for copying files
"dirStorage" : true, // store directory listing
"online" : false, // do not load js files from cdn
"open" : true, // open web browser when server started
"oneFilePanel" : false, // show one file panel
"keysPanel" : true, // show classic panel with buttons of keys
"port" : 8000, // http port
"ip" : null, // ip or null(default)
"root" : "/", // root directory
"prefix" : "", // url prefix
"prefixSocket" : "", // prefix for socket connection
"progress" : true, // show progress of file operations
"confirmCopy" : true, // confirm copy
"confirmMove" : true, // confirm move
"showConfig" : false, // show config at startup
"showFileName" : false // do not show file name in view and edit
"contact" : true, // enable contact
"configDialog" : true, // enable config dialog
"configAuth" : true, // enable auth change in config dialog
"console" : true, // enable console
"syncConsolePath" : false // do not sync console path
"terminal" : false, // disable terminal
"terminalPath" : '', // path of a terminal
"terminalCommand" : '', // set command to run in terminal
"terminalAutoRestart" : true, // restart command on exit
"vim" : false, // disable vim hot keys
"columns" : "name-size-date-owner-mode", // set visible columns
"export" : false, // enable export of config through a server
"exportToken" : "root", // token used by export server
"import" : false, // enable import of config
"import-url" : "http://localhost:8000", // url of an export server
"importToken" : "root", // token used to connect to export server
"importListen" : false, // listen on config updates
"dropbox" : false, // disable dropbox integration
"dropboxToken" : "", // unset dropbox token
"log" : true // logging
}
```
@ -785,6 +791,25 @@ When you create this file run:
docker-compose up
```
# Dropbox
Dropbox support integrated into Cloud Commander and you can switch from local file system to a dropbox account.
All you need to do is set `--dropbox` option and [generate dropbox token](https://blogs.dropbox.com/developers/2014/05/generate-an-access-token-for-your-own-account/) for you account.
This can look like this:
```sh
cloudcmd --dropbox --dropbox-token your-dropbox-token
```
Using `dropbox` remember that there is no remote support of a `console` and `terminal. Progress of file operation also not supported. There is only basic support, but you can do next things with `files` and `directories`:
- create
- remove
- rename/move
- view
- edit
Get involved
---------------

View file

@ -43,6 +43,7 @@ const args = require('minimist')(argv.slice(2), {
'import-url',
'import-token',
'export-token',
'dropbox-token',
],
boolean: [
'auth',
@ -71,6 +72,7 @@ const args = require('minimist')(argv.slice(2), {
'import',
'import-listen',
'log',
'dropbox',
],
default: {
server : true,
@ -112,6 +114,9 @@ const args = require('minimist')(argv.slice(2), {
'keys-panel': env.bool('keys_panel') || config('keysPanel'),
'import-token': env('import_token') || config('importToken'),
'export-token': env('export_token') || config('exportToken'),
'dropbox': config('dropbox'),
'dropbox-token': config('dropboxToken'),
},
alias: {
v: 'version',
@ -177,6 +182,9 @@ function main() {
config('importListen', args['import-listen']);
config('importUrl', args['import-url']);
config('dropbox', args['dropbox']);
config('dropboxToken', args['dropbox-token'] || '');
readConfig(args.config);
const options = {

View file

@ -143,7 +143,7 @@ function CloudCmdProto(DOM) {
};
CloudCmd.prefix = prefix;
CloudCmd.prefixURL = prefix + apiURL;
CloudCmd.prefixURL = `${prefix}${apiURL}`;
CloudCmd.prefixSocket = config.prefixSocket;
CloudCmd.config = (key) => config[key];

View file

@ -13,7 +13,6 @@ const uploadFiles = require('../dom/upload-files');
const {
FS,
apiURL,
} = require('../../common/cloudfunc');
const NBSP_REG = RegExp(String.fromCharCode(160), 'g');
@ -303,6 +302,7 @@ function onTouch(event) {
* in Chrome (HTML5)
*/
function onDragStart(event) {
const {prefixURL} = CloudCmd;
const element = getLIElement(event.target);
const isDir = Info.isDir;
let link = DOM.getCurrentLink(element);
@ -313,7 +313,7 @@ function onDragStart(event) {
name += EXT;
link = document.createElement('a');
link.textContent = name;
link.href = apiURL + '/pack' + Info.path + EXT;
link.href = prefixURL + '/pack' + Info.path + EXT;
}
event.dataTransfer.setData('DownloadURL',

View file

@ -61,14 +61,14 @@ const noFilesCheck = () => {
return is;
};
module.exports.init = promisify((callback) => {
showLoad();
exec.series([
DOM.loadSocket,
(callback) => {
if (!config('progress'))
if (!config('progress') || config('dropbox'))
return callback();
load(initOperations(CloudCmd.prefix, callback));

View file

@ -41,6 +41,8 @@
"importToken": "root",
"importUrl": "http://localhost:8000",
"importListen": false,
"log": true
"log": true,
"dropbox": false,
"dropboxToken": ""
}

View file

@ -38,6 +38,8 @@
"--import-url ": "url of an export server",
"--import-token ": "authorization token used to connect to export server",
"--import-listen ": "enable listen on config updates from import server",
"--dropbox ": "enable dropbox integration",
"--dropbox-token ": "set dropbox token",
"--log ": "enable logging",
"--no-show-config ": "do not show config values",
"--no-server ": "do not start server",
@ -63,6 +65,8 @@
"--no-export ": "disable export config through a server",
"--no-import ": "disable import of config",
"--no-import-listen ": "disable listen on config updates from import server",
"--no-log ": "disable logging",
"--no-show-file-name ": "do not show file name in view and edit"
"--no-show-file-name ": "do not show file name in view and edit",
"--no-dropbox ": "disable dropbox integration",
"--no-dropbox-token ": "unset dropbox token",
"--no-log ": "disable logging"
}

View file

@ -62,6 +62,8 @@ programs in browser from any computer, mobile or tablet device.
--import-url url of an import server
--import-token authorization token used to connect to export server
--import-listen enable listen on config updates from import server
--dropbox enable dropbox integration
--dropbox-token set dropbox token
--log enable logging
--no-show-config do not show config values
--no-server do not start server
@ -88,8 +90,10 @@ programs in browser from any computer, mobile or tablet device.
--no-import disable import of config
--no-import-url url of an import server
--no-import-listen disable listen on config updates from import server
--no-log disable logging
--no-show-file-name do not show file name in view and edit modes
--no-dropbox disable dropbox integration
--no-dropbox-token unset dropbox token
--no-log disable logging
.SH RESOURCES AND DOCUMENTATION

View file

@ -110,6 +110,7 @@
},
"subdomain": "cloudcmd",
"dependencies": {
"@cloudcmd/dropbox": "^4.0.1",
"@cloudcmd/fileop": "^2.0.0",
"@cloudcmd/move-files": "^2.0.1",
"@cloudcmd/read-files-sync": "^2.0.0",
@ -120,9 +121,9 @@
"criton": "^2.0.0",
"currify": "^3.0.0",
"deepmerge": "^2.0.0",
"deepword": "^5.0.0",
"dword": "^9.0.0",
"edward": "^9.0.0",
"deepword": "^5.1.0",
"dword": "^9.1.0",
"edward": "^9.1.0",
"execon": "^1.2.0",
"express": "^4.13.0",
"files-io": "^3.0.0",
@ -147,6 +148,7 @@
"pullout": "^2.0.0",
"rendy": "^2.0.0",
"restafary": "^5.0.0",
"restbox": "^1.0.1",
"shortdate": "^1.2.0",
"socket.io": "^2.0.3",
"socket.io-client": "^2.1.1",

View file

@ -23,6 +23,7 @@ const currify = require('currify');
const apart = require('apart');
const ponse = require('ponse');
const restafary = require('restafary');
const restbox = require('restbox');
const konsole = require('console-io');
const edward = require('edward');
const dword = require('dword');
@ -164,6 +165,9 @@ function cloudcmd(prefix, plugins, modules) {
const dir = DIR_ROOT;
const ponseStatic = ponse.static(dir, {cache});
const dropbox = config('dropbox');
const dropboxToken = config('dropboxToken');
const funcs = clean([
config('console') && konsole({
@ -177,25 +181,29 @@ function cloudcmd(prefix, plugins, modules) {
online,
diff,
zip,
dropbox,
dropboxToken,
}),
dword({
online,
diff,
zip,
dropbox,
dropboxToken,
}),
deepword({
online,
diff,
zip,
dropbox,
dropboxToken,
}),
fileop({
}),
fileop(),
nomine({
}),
nomine(),
setUrl,
setSW,
@ -205,6 +213,12 @@ function cloudcmd(prefix, plugins, modules) {
modules && modulas(modules),
config('dropbox') && restbox({
prefix: cloudfunc.apiURL,
root,
token: dropboxToken,
}),
restafary({
prefix: cloudfunc.apiURL + '/fs',
root

View file

@ -35,10 +35,20 @@ const sendIndex = (params, data) => {
const {FS} = CloudFunc;
const Columns = require('./columns');
const Template = require('./template');
const Columns = require(`${DIR_SERVER}/columns`);
const Template = require(`${DIR_SERVER}/template`);
const read = promisify(flop.read);
const getReadDir = () => {
if (!config('dropbox'))
return promisify(flop.read);
const tokenize = (fn, a) => (b) => fn(a, b);
const {readDir} = require('@cloudcmd/dropbox');
return tokenize(readDir, config('dropboxToken'));
};
const read = getReadDir();
const realpath = promisify(fs.realpath);
/**
@ -55,6 +65,8 @@ module.exports = currify((options, request, response, next) => {
.catch(next);
});
module.exports._getReadDir = getReadDir;
async function route(options, request, response) {
const name = ponse.getPathName(request);
const gzip = true;

View file

@ -3,48 +3,37 @@
const path = require('path');
const fs = require('fs');
const test = require('tape');
const {promisify} = require('util');
const pullout = require('pullout');
const request = require('request');
const tryToCatch = require('try-to-catch');
const tryToTape = require('try-to-tape');
const test = tryToTape(require('tape'));
const mockRequire = require('mock-require');
const {reRequire} = mockRequire;
const clear = require('clear-module');
const rootDir = path.join(__dirname, '../..');
const fixtureDir = path.join(__dirname, '..', 'test', 'fixture');
const routePath = './route';
const cloudcmdPath = './cloudcmd';
const beforePath = path.join(__dirname, '../test/before');
const {connect} = require(beforePath);
const warp = (fn, ...a) => (...b) => fn(...b, ...a);
const _pullout = promisify(pullout);
const get = promisify((url, fn) => {
fn(null, request(url));
});
const getStr = (url) => {
return get(url)
.then(warp(_pullout, 'string'))
.catch(console.error);
};
const cloudcmd = require(cloudcmdPath);
const serveOnce = require('serve-once');
const {request} = serveOnce(cloudcmd);
test('cloudcmd: route: buttons: no console', async (t) => {
const config = {
console: false
console: false,
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.ok(/icon-console none/.test(result), 'should hide console');
const {body} = await request.get('/', {
options,
});
t.ok(/icon-console none/.test(body), 'should hide console');
t.end();
await done();
});
test('cloudcmd: route: buttons: console', async (t) => {
@ -52,13 +41,16 @@ test('cloudcmd: route: buttons: console', async (t) => {
console: true,
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.notOk(/icon-console none/.test(result), 'should not hide console');
const {body} = await request.get('/', {
options,
});
t.notOk(/icon-console none/.test(body), 'should not hide console');
t.end();
await done();
});
test('cloudcmd: route: buttons: no config', async (t) => {
@ -66,13 +58,16 @@ test('cloudcmd: route: buttons: no config', async (t) => {
configDialog: false
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.ok(/icon-config none/.test(result), 'should hide config');
const {body} = await request.get('/', {
options,
});
t.ok(/icon-config none/.test(body), 'should hide config');
t.end();
await done();
});
test('cloudcmd: route: buttons: no contact', async (t) => {
@ -80,13 +75,16 @@ test('cloudcmd: route: buttons: no contact', async (t) => {
contact: false
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.ok(/icon-contact none/.test(result), 'should hide contact');
const {body} = await request.get('/', {
options,
});
t.ok(/icon-contact none/.test(body), 'should hide contact');
t.end();
await done();
});
test('cloudcmd: route: buttons: one file panel: move', async (t) => {
@ -94,13 +92,16 @@ test('cloudcmd: route: buttons: one file panel: move', async (t) => {
oneFilePanel: true
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.ok(/icon-move none/.test(result), 'should hide move button');
const {body} = await request.get('/', {
options,
});
t.ok(/icon-move none/.test(body), 'should hide move button');
t.end();
await done();
});
test('cloudcmd: route: buttons: no one file panel: move', async (t) => {
@ -108,13 +109,16 @@ test('cloudcmd: route: buttons: no one file panel: move', async (t) => {
oneFilePanel: false
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.notOk(/icon-move none/.test(result), 'should not hide move button');
const {body} = await request.get('/', {
options,
});
t.notOk(/icon-move none/.test(body), 'should not hide move button');
t.end();
await done();
});
test('cloudcmd: route: buttons: one file panel: move', async (t) => {
@ -122,13 +126,16 @@ test('cloudcmd: route: buttons: one file panel: move', async (t) => {
oneFilePanel: true
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.ok(/icon-copy none/.test(result), 'should hide copy button');
const {body} = await request.get('/', {
options,
});
t.ok(/icon-copy none/.test(body), 'should hide copy button');
t.end();
await done();
});
test('cloudcmd: route: keys panel: hide', async (t) => {
@ -136,13 +143,16 @@ test('cloudcmd: route: keys panel: hide', async (t) => {
keysPanel: false
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.ok(/keyspanel hidden/.test(result), 'should hide keyspanel');
const {body} = await request.get('/', {
options,
});
t.ok(/keyspanel hidden/.test(body), 'should hide keyspanel');
t.end();
await done();
});
test('cloudcmd: route: keys panel', async (t) => {
@ -150,13 +160,16 @@ test('cloudcmd: route: keys panel', async (t) => {
keysPanel: true
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
};
t.notOk(/keyspanel hidden/.test(result), 'should show keyspanel');
const {body} = await request.get('/', {
options,
});
t.notOk(/keyspanel hidden/.test(body), 'should show keyspanel');
t.end();
await done();
});
test('cloudcmd: route: file: fs', async (t) => {
@ -165,13 +178,16 @@ test('cloudcmd: route: file: fs', async (t) => {
root,
};
const {port, done} = await connect({config});
const empty = await getStr(`http://localhost:${port}/fs`);
const options = {
config,
};
t.equal(empty, '', 'should equal');
const {body} = await request.get('/', {
options,
});
t.equal(body, '', 'should equal');
t.end();
await done();
});
test('cloudcmd: route: symlink', async (t) => {
@ -183,16 +199,22 @@ test('cloudcmd: route: symlink', async (t) => {
root,
};
const options = {
config,
};
fs.symlinkSync(emptyDir, symlink);
const {port, done} = await connect({config});
const data = await getStr(`http://localhost:${port}/fs/symlink-dir`);
const {body} = await request.get('/fs/symlink-dir', {
options,
});
t.ok(data.length, 'should return html document');
fs.unlinkSync(symlink);
t.end();
await done();
console.log(body);
t.ok(body.length, 'should return html document');
t.end();
});
test('cloudcmd: route: not found', async (t) => {
@ -201,13 +223,16 @@ test('cloudcmd: route: not found', async (t) => {
root,
};
const {port, done} = await connect({config});
const data = await getStr(`http://localhost:${port}/fs/file-not-found`);
const options = {
config,
};
t.ok(~data.indexOf('ENOENT: no such file or directory'), 'should return error');
const {body} = await request.get('/fs/file-not-found', {
options,
});
t.ok(~body.indexOf('ENOENT: no such file or directory'), 'should return error');
t.end();
await done();
});
test('cloudcmd: route: realpath: error', async (t) => {
@ -223,19 +248,22 @@ test('cloudcmd: route: realpath: error', async (t) => {
root: fixtureDir,
};
reRequire('./route');
reRequire('./cloudcmd');
const options = {
config,
};
const {connect} = reRequire(beforePath);
const {port, done} = await connect({config});
const data = await getStr(`http://localhost:${port}/fs/empty-file`);
reRequire(routePath);
const cloudcmd = reRequire(cloudcmdPath);
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/fs/empty-file', {
options,
});
fs.realpath = realpath;
t.ok(/^ENOENT/.test(data), 'should return error');
t.ok(/^ENOENT/.test(body), 'should return error');
t.end();
await done();
});
test('cloudcmd: route: sendIndex: encode', async (t) => {
@ -255,17 +283,14 @@ test('cloudcmd: route: sendIndex: encode', async (t) => {
});
reRequire(routePath);
reRequire(cloudcmdPath);
const cloudcmd = reRequire(cloudcmdPath);
const {connect} = reRequire(beforePath);
const {port, done} = await connect();
const data = await getStr(`http://localhost:${port}`);
t.ok(data.includes(nameEncoded), 'should encode name');
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/');
mockRequire.stop('flop');
await done();
t.ok(body.includes(nameEncoded), 'should encode name');
t.end();
});
@ -284,22 +309,15 @@ test('cloudcmd: route: sendIndex: encode: not encoded', async (t) => {
read
});
clear(routePath);
clear(cloudcmdPath);
clear(beforePath);
reRequire(routePath);
const cloudcmd = reRequire(cloudcmdPath);
const {connect} = require(beforePath);
const {port, done} = await connect();
const data = await getStr(`http://localhost:${port}`);
t.notOk(data.includes(name), 'should not put not encoded name');
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/');
mockRequire.stop('flop');
clear(routePath);
clear(cloudcmdPath);
clear(beforePath);
await done();
t.notOk(body.includes(name), 'should not put not encoded name');
t.end();
});
@ -318,23 +336,15 @@ test('cloudcmd: route: sendIndex: ddos: render', async (t) => {
read
});
clear(routePath);
clear(cloudcmdPath);
clear(beforePath);
reRequire(routePath);
const cloudcmd = reRequire(cloudcmdPath);
const {connect} = require(beforePath);
const {port, done} = await connect();
await getStr(`http://localhost:${port}`);
t.pass('should not hang up');
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/');
mockRequire.stop('flo');
clear(routePath);
clear(cloudcmdPath);
clear(beforePath);
await done();
t.pass('should not hang up');
t.end();
});
@ -343,12 +353,34 @@ test('cloudcmd: route: buttons: no terminal', async (t) => {
terminal: false
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
}
t.ok(/icon-terminal none/.test(result), 'should hide terminal');
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/', {
options
});
await done();
t.ok(/icon-terminal none/.test(body), 'should hide terminal');
t.end();
});
test('cloudcmd: route: no termianl: /fs', async (t) => {
const config = {
terminal: false
};
const options = {
config,
}
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/fs', {
options,
});
t.ok(/icon-terminal none/.test(body), 'should hide terminal');
t.end();
});
@ -358,12 +390,54 @@ test('cloudcmd: route: buttons: terminal', async (t) => {
terminalPath: 'gritty',
};
const {port, done} = await connect({config});
const result = await getStr(`http://localhost:${port}`);
const options = {
config,
}
t.notOk(/icon-terminal none/.test(result), 'should enable terminal');
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/', {
options
});
await done();
t.notOk(/icon-terminal none/.test(body), 'should enable terminal');
t.end();
});
test('cloudcmd: route: buttons: contact', async (t) => {
const config = {
contact: true,
};
const options = {
config,
}
const {request} = serveOnce(cloudcmd);
const {body} = await request.get('/', {
options
});
t.notOk(/icon-contact none/.test(body), 'should enable terminal');
t.end();
});
test('cloudcmd: route: dropbox', async (t) => {
const config = require('./config');
const dropbox = config('dropbox');
const dropboxToken = config('dropboxToken');
config('dropbox', true);
config('dropboxToken', '');
const {_getReadDir} = reRequire(routePath);
const readdir = _getReadDir();
const [e] = await tryToCatch(readdir, '/root');
config('dropbox', dropbox);
config('dropboxToken', dropboxToken);
t.ok(/token/.test(e.message), 'should contain word token in message');
t.end();
});

View file

@ -1,47 +1,39 @@
'use strict';
const test = require('tape');
const mock = require('mock-require');
const diff = require('sinon-called-with-diff');
const sinon = diff(require('sinon'));
const stub = require('mock-require');
const clean = require('clear-module');
const mockRequire = require('mock-require');
const {reRequire} = mockRequire;
const configPath = '../../server/config';
const terminalPath = '../../server/terminal';
test('cloudcmd: terminal: disabled', (t) => {
clean(terminalPath);
stub(configPath, () => {
mockRequire(configPath, () => {
return false;
});
const terminal = require('../../server/terminal');
const terminal = reRequire('../../server/terminal');
const fn = terminal();
mockRequire.stop(configPath);
t.notOk(fn(), 'should return noop');
clean(configPath);
require(configPath);
t.end();
});
test('cloudcmd: terminal: disabled: listen', (t) => {
clean(terminalPath);
stub(configPath, () => false);
const terminal = require(terminalPath);
mockRequire(configPath, () => false);
const terminal = reRequire(terminalPath);
const fn = terminal().listen();
mockRequire.stop(configPath);
reRequire(terminalPath);
t.notOk(fn, 'should return noop');
clean(configPath);
require(configPath);
t.end();
});
@ -49,13 +41,15 @@ test('cloudcmd: terminal: enabled', (t) => {
const term = sinon.stub();
const arg = 'hello';
clean(terminalPath);
stub(configPath, () => '/terminal');
stub('/terminal', term);
mockRequire(configPath, () => '/terminal');
mockRequire(terminalPath, term);
const terminal = require(terminalPath);
terminal(arg);
mockRequire.stop(configPath);
mockRequire.stop(terminalPath);
t.ok(term.calledWith(arg), 'should call terminal');
t.end();
});
@ -64,44 +58,41 @@ test('cloudcmd: terminal: enabled: no string', (t) => {
const {log:originalLog} = console;
const log = sinon.stub();
clean(terminalPath);
stub(configPath, () => 'hello');
mockRequire(configPath, () => 'hello');
console.log = log;
const terminal = require(terminalPath);
const terminal = reRequire(terminalPath);
terminal();
console.log = originalLog;
mockRequire.stop(configPath);
reRequire(terminalPath);
const msg = 'cloudcmd --terminal: Cannot find module \'hello\'';
t.ok(log.calledWith(msg), 'should call exit');
t.end();
});
test('cloudcmd: terminal: no arg', (t) => {
const gritty = {};
mock('gritty', gritty);
clean(terminalPath);
stub(configPath, (a) => {
mockRequire('gritty', gritty);
mockRequire(configPath, (a) => {
if (a === 'terminal')
return true;
return 'gritty';
});
const terminal = require(terminalPath);
const terminal = reRequire(terminalPath);
const result = terminal();
mockRequire.stop('gritty');
mockRequire.stop(configPath);
reRequire(terminalPath);
t.equal(result, gritty, 'should equal');
mock.stop('gritty');
clean(configPath);
require(configPath);
t.end();
});