Skip to content

Commit

Permalink
Adds UT on Dropbox
Browse files Browse the repository at this point in the history
* Fixes error handling
* Uses /create_folder_v2
* Retrieve account when providing only the token
* Fixes batch upload (Closes ##114)
  • Loading branch information
JbIPS committed Nov 21, 2017
1 parent b4abca7 commit e53f66c
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 44 deletions.
70 changes: 53 additions & 17 deletions lib/unifile-dropbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function callAPI(session, path, data, subdomain = 'api', isJson = true, headers
encoding: null
};

if(Object.keys(data).length !== 0) reqOptions.body = data;
if(data && Object.keys(data).length !== 0) reqOptions.body = data;

if(headers) {
for(const header in headers) {
Expand All @@ -50,8 +50,23 @@ function callAPI(session, path, data, subdomain = 'api', isJson = true, headers
if(err) {
reject(err);
} else if(res.statusCode >= 400) {
return reject(new Error((isJson ? body : JSON.parse(body)).error_summary));
} else resolve(body);
let errorMessage = null;
// In case of users/get_current_account, Dropbox return a String with the error
// Since isJson = true, it gets parsed by request
if(Buffer.isBuffer(body)) {
errorMessage = body.toString();
} else {
errorMessage = (isJson ? body : JSON.parse(body)).error_summary;
}
const code = (() => {
switch (res.statusCode) {
case 403: return UnifileError.EACCES;
case 404: return UnifileError.ENOENT;
default: return UnifileError.EIO;
}
})();
return reject(new UnifileError(code, errorMessage));
} else resolve(body);
});
});
}
Expand Down Expand Up @@ -159,15 +174,30 @@ class DropboxConnector {

setAccessToken(session, token) {
session.token = token;
const accountFields = [
'account_id',
'name',
'email'
];
const filterAccountInfos = (account) => {
return Object.keys(account).reduce((memo, key) => {
if(accountFields.includes(key)) memo[key] = account[key];
return memo;
}, {});
};
let accountPromised = null;
if(session.account && 'id' in session.account) {
return callAPI(session, '/users/get_account', {
accountPromised = callAPI(session, '/users/get_account', {
account_id: session.account.id
})
.then((account) => {
session.account = account;
return token;
});
} else return Promise.resolve(token);
} else {
accountPromised = callAPI(session, '/users/get_current_account');
}
return accountPromised.then((account) => {
session.account = filterAccountInfos(account);
return token;
})
.catch((err) => Promise.reject(new UnifileError(UnifileError.EACCES, 'Bad credentials')));
}

clearAccessToken(session) {
Expand Down Expand Up @@ -258,7 +288,7 @@ class DropboxConnector {

mkdir(session, path) {
if(!path) return Promise.reject(new UnifileError(UnifileError.EINVAL, 'Cannot create dir with an empty name.'));
return callAPI(session, '/files/create_folder', {
return callAPI(session, '/files/create_folder_v2', {
path: makePathAbsolute(path)
});
}
Expand Down Expand Up @@ -394,7 +424,7 @@ class DropboxConnector {
},
commit: {
path: makePathAbsolute(action.path),
mode: {'.tag': this.writeMode}
mode: this.writeMode
}
};
});
Expand All @@ -420,14 +450,20 @@ class DropboxConnector {
case 'rename':
closeBatchs(action.name.toLowerCase());
if(!action.destination)
return Promise.reject('Rename action must have a `destination` field');
return Promise.reject(new BatchError(
UnifileError.EINVAL,
'Rename actions should have a destination'));
moveEntries.push({
from_path: makePathAbsolute(action.path),
to_path: makePathAbsolute(action.destination)
});
break;
case 'writefile':
closeBatchs(action.name.toLowerCase());
if(!action.content)
return Promise.reject(new BatchError(
UnifileError.EINVAL,
'Write actions should have a content'));
uploadEntries.push(action);
break;
case 'mkdir':
Expand All @@ -436,11 +472,11 @@ class DropboxConnector {
return this.mkdir(session, action.path);
})
.catch((err) => err.name !== 'BatchError',
(err) => {
throw new BatchError(
UnifileError.EINVAL,
`Could not complete action ${action.name}: ${err.message}`);
});
(err) => {
throw new BatchError(
UnifileError.EINVAL,
`Could not complete action ${action.name}: ${err.message}`);
});
break;
default:
console.warn(`Unsupported batch action: ${action.name}`);
Expand Down
5 changes: 2 additions & 3 deletions lib/unifile-github.js
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ class GitHubConnector {
`Could not complete action ${actionName}: Cannot create file here.`));
case 'rename':
if(!action.destination)
return new Promise.reject(new BatchError(
return Promise.reject(new BatchError(
UnifileError.EINVAL,
'Rename actions should have a destination'));
actionsChain = actionsChain.then(() => this.rename(session, action.path, action.destination))
Expand Down Expand Up @@ -907,8 +907,7 @@ class GitHubConnector {
default: return UnifileError.EIO;
}
})();
const error = new UnifileError(code, JSON.parse(body).message);
return reject(error);
return reject(new UnifileError(code, JSON.parse(body).message));
}
try {
const result = res.statusCode !== 204 ? JSON.parse(body) : null;
Expand Down
34 changes: 10 additions & 24 deletions test/unifile-dropbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@ const dropboxDefaultInfos = {
};

function isEnvValid() {
return process.env.DROPBOX_SECRET && process.env.DROPBOX_TOKEN;
return process.env.DROPBOX_SECRET && process.env.DROPBOX_TOKEN && process.env.DROPBOX_ACCOUNT;
}

function checkSession(session) {
expect(session.token).to.exist;
expect(session.account).to.exist;
expect(session.account).to.have.all.keys('display_name', 'login', 'num_repos');
expect(session.account).to.have.all.keys('account_id', 'email', 'name');
}

describe('DropboxConnector', function() {
describe.only('DropboxConnector', function() {

const session = {};
const session = {
account: {id: process.env.DROPBOX_ACCOUNT}
};
const defaultConfig = {
clientId: 'b4e46028bf36d871f68d',
clientSecret: 'a',
Expand Down Expand Up @@ -133,7 +135,7 @@ describe('DropboxConnector', function() {
expect(infos.description).to.equal(dropboxDefaultInfos.description);
expect(infos.isLoggedIn).to.be.true;
expect(infos.isOAuth).to.be.true;
expect(infos.username).to.equal('Jean-Baptiste Richardet');
expect(infos.username).to.equal('Jean-Baptiste RICHARDET');
}
});
});
Expand Down Expand Up @@ -169,12 +171,6 @@ describe('DropboxConnector', function() {
connector = new DropboxConnector(defaultConfig);
});

it('rejects the promise if the token is nor OAuth nor Basic', function() {
const token = 'baaaad';
const session = {};
return connector.setAccessToken(session, token).should.be.rejectedWith('Invalid token');
});

it('rejects the promise if the token credentials are wrong', function() {
const token = 'Basic baaaad';
const session = {};
Expand Down Expand Up @@ -892,29 +888,19 @@ describe('DropboxConnector', function() {
.should.be.rejectedWith('Cannot execute batch action without a path');
});

it.only('rejects the promise if one repo/branch action failed', function() {
it('rejects the promise if one repo/branch action failed', function() {
return connector.batch(session, [{name: 'mkdir', path: 'authouou/outeum'}])
.should.be.rejectedWith('Could not complete action');
});

it('rejects the promise if a rename action on repo/branch does not have a destination', function() {
it('rejects the promise if a rename action does not have a destination', function() {
return connector.batch(session, [{name: 'rename', path: 'tmp'}])
.should.be.rejectedWith('Rename actions should have a destination');
});

it('rejects the promise if a rename action does not have a destination', function() {
return connector.batch(session, [{name: 'rename', path: 'tmp/test/a'}])
.should.be.rejectedWith('Could not modify tree');
});

it('rejects the promise if a writefile action does not have content', function() {
return connector.batch(session, [{name: 'writefile', path: 'tmp/test/a'}])
.should.be.rejectedWith('Could not modify tree');
});

it('rejects the promise if a writefile is programmed on a repo/branch', function() {
return connector.batch(session, [{name: 'writefile', path: 'tmp/test', content: 'aaaa'}])
.should.be.rejectedWith('Cannot create file here');
.should.be.rejectedWith('Write actions should have a content');
});

it('executes action in order', function() {
Expand Down

0 comments on commit e53f66c

Please sign in to comment.