Commit 3e002090 authored by Romain Courteaud's avatar Romain Courteaud

[DropboxStorage] Switch to Dropbox API v2.

Root parameter is removed, as it must be now configured on dropbox website itself.

Thanks to Sven Franck <sven.franck@nexedi.com> for his original work on this topic.
parent 18cf665b
...@@ -7,27 +7,18 @@ ...@@ -7,27 +7,18 @@
* JIO Dropbox Storage. Type = "dropbox". * JIO Dropbox Storage. Type = "dropbox".
* Dropbox "database" storage. * Dropbox "database" storage.
*/ */
/*global Blob, jIO, RSVP, UriTemplate*/ /*global Blob, jIO, RSVP*/
/*jslint nomen: true*/ /*jslint nomen: true*/
(function (jIO, RSVP, Blob, UriTemplate) { (function (jIO, RSVP, Blob, JSON) {
"use strict"; "use strict";
var UPLOAD_URL = "https://content.dropboxapi.com/1/files_put/" + var GET_URL = "https://content.dropboxapi.com/2/files/download",
"{+root}{+id}{+name}{?access_token}", UPLOAD_URL = "https://content.dropboxapi.com/2/files/upload",
upload_template = UriTemplate.parse(UPLOAD_URL), REMOVE_URL = "https://api.dropboxapi.com/2/files/delete_v2",
CREATE_DIR_URL = "https://api.dropboxapi.com/1/fileops/create_folder" + CREATE_DIR_URL = "https://api.dropboxapi.com/2/files/create_folder_v2",
"{?access_token,root,path}", METADATA_URL = "https://api.dropboxapi.com/2/files/get_metadata",
create_dir_template = UriTemplate.parse(CREATE_DIR_URL), LIST_FOLDER_URL = "https://api.dropboxapi.com/2/files/list_folder",
REMOVE_URL = "https://api.dropboxapi.com/1/fileops/delete/" + LIST_MORE_URL = "https://api.dropboxapi.com/2/files/list_folder/continue";
"{?access_token,root,path}",
remote_template = UriTemplate.parse(REMOVE_URL),
GET_URL = "https://content.dropboxapi.com/1/files" +
"{/root,id}{+name}{?access_token}",
get_template = UriTemplate.parse(GET_URL),
//LIST_URL = 'https://api.dropboxapi.com/1/metadata/sandbox/';
METADATA_URL = "https://api.dropboxapi.com/1/metadata" +
"{/root}{+id}{?access_token}",
metadata_template = UriTemplate.parse(METADATA_URL);
function restrictDocumentId(id) { function restrictDocumentId(id) {
if (id.indexOf("/") !== 0) { if (id.indexOf("/") !== 0) {
...@@ -38,7 +29,7 @@ ...@@ -38,7 +29,7 @@
throw new jIO.util.jIOError("id " + id + " is forbidden (no end /)", throw new jIO.util.jIOError("id " + id + " is forbidden (no end /)",
400); 400);
} }
return id; return id.slice(0, -1);
} }
function restrictAttachmentId(id) { function restrictAttachmentId(id) {
...@@ -48,6 +39,66 @@ ...@@ -48,6 +39,66 @@
} }
} }
function recursiveAllAttachments(result, token, id, cursor) {
var data,
url;
if (cursor === undefined) {
data = {
"path": id,
"recursive": false,
"include_media_info": false,
"include_deleted": false,
"include_has_explicit_shared_members": false,
"include_mounted_folders": true
};
url = LIST_FOLDER_URL;
} else {
data = {"cursor": cursor};
url = LIST_MORE_URL;
}
return new RSVP.Queue()
.push(function () {
return jIO.util.ajax({
type: "POST",
url: url,
headers: {
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
},
data: JSON.stringify(data)
});
})
.push(function (evt) {
var obj = JSON.parse(evt.target.response || evt.target.responseText),
i;
for (i = 0; i < obj.entries.length; i += 1) {
if (obj.entries[i][".tag"] === "file") {
result[obj.entries[i].name] = {};
}
}
if (obj.has_more) {
return recursiveAllAttachments(result, token, id, obj.cursor);
}
return result;
}, function (error) {
if (error.target !== undefined && error.target.status === 409) {
var err_content = JSON.parse(error.target.response ||
error.target.responseText);
if ((err_content.error['.tag'] === 'path') &&
(err_content.error.path['.tag'] === 'not_folder')) {
throw new jIO.util.jIOError("Not a directory: " + id + "/",
404);
}
if ((err_content.error['.tag'] === 'path') &&
(err_content.error.path['.tag'] === 'not_found')) {
throw new jIO.util.jIOError("Cannot find document: " + id + "/",
404);
}
}
throw error;
});
}
/** /**
* The JIO Dropbox Storage extension * The JIO Dropbox Storage extension
* *
...@@ -59,12 +110,7 @@ ...@@ -59,12 +110,7 @@
throw new TypeError("Access Token' must be a string " + throw new TypeError("Access Token' must be a string " +
"which contains more than one character."); "which contains more than one character.");
} }
if (typeof spec.root !== 'string' || !spec.root ||
(spec.root !== "dropbox" && spec.root !== "sandbox")) {
throw new TypeError("root must be 'dropbox' or 'sandbox'");
}
this._access_token = spec.access_token; this._access_token = spec.access_token;
this._root = spec.root;
} }
DropboxStorage.prototype.put = function (id, param) { DropboxStorage.prototype.put = function (id, param) {
...@@ -79,18 +125,24 @@ ...@@ -79,18 +125,24 @@
.push(function () { .push(function () {
return jIO.util.ajax({ return jIO.util.ajax({
type: "POST", type: "POST",
url: create_dir_template.expand({ url: CREATE_DIR_URL,
access_token: that._access_token, headers: {
root: that._root, "Authorization": "Bearer " + that._access_token,
path: id "Content-Type": "application/json"
}) },
data: JSON.stringify({"path": id, "autorename": false})
}); });
}) })
.push(undefined, function (err) { .push(undefined, function (err) {
if ((err.target !== undefined) && if ((err.target !== undefined) &&
(err.target.status === 405)) { (err.target.status === 409)) {
// Directory already exists, no need to fail var err_content = JSON.parse(err.target.response ||
return; err.target.responseText);
if ((err_content.error['.tag'] === 'path') &&
(err_content.error.path['.tag'] === 'conflict')) {
// Directory already exists, no need to fail
return;
}
} }
throw err; throw err;
}); });
...@@ -100,11 +152,12 @@ ...@@ -100,11 +152,12 @@
id = restrictDocumentId(id); id = restrictDocumentId(id);
return jIO.util.ajax({ return jIO.util.ajax({
type: "POST", type: "POST",
url: remote_template.expand({ url: REMOVE_URL,
access_token: this._access_token, headers: {
root: this._root, "Authorization": "Bearer " + this._access_token,
path: id "Content-Type": "application/json"
}) },
data: JSON.stringify({"path": id})
}); });
}; };
...@@ -119,64 +172,39 @@ ...@@ -119,64 +172,39 @@
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return jIO.util.ajax({ return jIO.util.ajax({
type: "GET", type: "POST",
url: metadata_template.expand({ url: METADATA_URL,
access_token: that._access_token, headers: {
root: that._root, "Authorization": "Bearer " + that._access_token,
id: id "Content-Type": "application/json"
}) },
data: JSON.stringify({"path": id})
}); });
}) })
.push(function (evt) { .push(function (evt) {
var obj = JSON.parse(evt.target.response || var obj = JSON.parse(evt.target.response ||
evt.target.responseText); evt.target.responseText);
if (obj.is_dir) { if (obj[".tag"] === "folder") {
return {}; return {};
} }
throw new jIO.util.jIOError("Not a directory: " + id, 404); throw new jIO.util.jIOError("Not a directory: " + id + "/", 404);
}, function (error) { }, function (error) {
if (error.target !== undefined && error.target.status === 404) { if (error.target !== undefined && error.target.status === 409) {
throw new jIO.util.jIOError("Cannot find document: " + id, 404); var err_content = JSON.parse(error.target.response ||
error.target.responseText);
if ((err_content.error['.tag'] === 'path') &&
(err_content.error.path['.tag'] === 'not_found')) {
throw new jIO.util.jIOError("Cannot find document: " + id + "/",
404);
}
} }
throw error; throw error;
}); });
}; };
DropboxStorage.prototype.allAttachments = function (id) { DropboxStorage.prototype.allAttachments = function (id) {
var that = this;
id = restrictDocumentId(id); id = restrictDocumentId(id);
return recursiveAllAttachments({}, this._access_token, id);
return new RSVP.Queue()
.push(function () {
return jIO.util.ajax({
type: "GET",
url: metadata_template.expand({
access_token: that._access_token,
root: that._root,
id: id
})
});
})
.push(function (evt) {
var obj = JSON.parse(evt.target.response || evt.target.responseText),
i,
result = {};
if (!obj.is_dir) {
throw new jIO.util.jIOError("Not a directory: " + id, 404);
}
for (i = 0; i < obj.contents.length; i += 1) {
if (!obj.contents[i].is_dir) {
result[obj.contents[i].path.split("/").pop()] = {};
}
}
return result;
}, function (error) {
if (error.target !== undefined && error.target.status === 404) {
throw new jIO.util.jIOError("Cannot find document: " + id, 404);
}
throw error;
});
}; };
//currently, putAttachment will fail with files larger than 150MB, //currently, putAttachment will fail with files larger than 150MB,
...@@ -191,20 +219,24 @@ ...@@ -191,20 +219,24 @@
restrictAttachmentId(name); restrictAttachmentId(name);
return jIO.util.ajax({ return jIO.util.ajax({
type: "PUT", type: "POST",
url: upload_template.expand({ url: UPLOAD_URL,
root: this._root, headers: {
id: id, "Authorization": "Bearer " + this._access_token,
name: name, "Content-Type": "application/octet-stream",
access_token: this._access_token "Dropbox-API-Arg": JSON.stringify({
}), "path": id + "/" + name,
dataType: blob.type, "mode": "overwrite",
"autorename": false,
"mute": false
})
},
data: blob data: blob
}); });
}; };
DropboxStorage.prototype.getAttachment = function (id, name) { DropboxStorage.prototype.getAttachment = function (id, name) {
var that = this; var context = this;
id = restrictDocumentId(id); id = restrictDocumentId(id);
restrictAttachmentId(name); restrictAttachmentId(name);
...@@ -212,26 +244,48 @@ ...@@ -212,26 +244,48 @@
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return jIO.util.ajax({ return jIO.util.ajax({
type: "GET", url: GET_URL,
type: "POST",
dataType: "blob", dataType: "blob",
url: get_template.expand({ headers: {
root: that._root, "Authorization": "Bearer " + context._access_token,
id: id, "Dropbox-API-Arg": JSON.stringify({"path": id + "/" + name})
name: name, }
access_token: that._access_token
})
}); });
}) })
.push(function (evt) { .push(function (evt) {
if (evt.target.response instanceof Blob) {
return evt.target.response;
}
return new Blob( return new Blob(
[evt.target.response || evt.target.responseText], [evt.target.responseText],
{"type": evt.target.getResponseHeader('Content-Type') || {"type": evt.target.getResponseHeader('Content-Type') ||
"application/octet-stream"} "application/octet-stream"}
); );
}, function (error) { }, function (error) {
if (error.target !== undefined && error.target.status === 404) { if (error.target !== undefined && error.target.status === 409) {
throw new jIO.util.jIOError("Cannot find attachment: " + if (!(error.target.response instanceof Blob)) {
id + ", " + name, 404); var err_content = JSON.parse(error.target.responseText);
if ((err_content.error['.tag'] === 'path') &&
(err_content.error.path['.tag'] === 'not_found')) {
throw new jIO.util.jIOError("Cannot find attachment: " +
id + "/, " + name, 404);
}
throw error;
}
return new RSVP.Queue()
.push(function () {
return jIO.util.readBlobAsText(error.target.response);
})
.push(function (evt) {
var err_content = JSON.parse(evt.target.result);
if ((err_content.error['.tag'] === 'path') &&
(err_content.error.path['.tag'] === 'not_found')) {
throw new jIO.util.jIOError("Cannot find attachment: " +
id + "/, " + name, 404);
}
throw error;
});
} }
throw error; throw error;
}); });
...@@ -248,16 +302,22 @@ ...@@ -248,16 +302,22 @@
.push(function () { .push(function () {
return jIO.util.ajax({ return jIO.util.ajax({
type: "POST", type: "POST",
url: remote_template.expand({ url: REMOVE_URL,
access_token: that._access_token, headers: {
root: that._root, "Authorization": "Bearer " + that._access_token,
path: id + name "Content-Type": "application/json"
}) },
data: JSON.stringify({"path": id + "/" + name})
}); });
}).push(undefined, function (error) { }).push(undefined, function (error) {
if (error.target !== undefined && error.target.status === 404) { if (error.target !== undefined && error.target.status === 409) {
throw new jIO.util.jIOError("Cannot find attachment: " + var err_content = JSON.parse(error.target.response ||
id + ", " + name, 404); error.target.responseText);
if ((err_content.error['.tag'] === 'path_lookup') &&
(err_content.error.path_lookup['.tag'] === 'not_found')) {
throw new jIO.util.jIOError("Cannot find attachment: " +
id + "/, " + name, 404);
}
} }
throw error; throw error;
}); });
...@@ -265,4 +325,4 @@ ...@@ -265,4 +325,4 @@
jIO.addStorage('dropbox', DropboxStorage); jIO.addStorage('dropbox', DropboxStorage);
}(jIO, RSVP, Blob, UriTemplate)); }(jIO, RSVP, Blob, JSON));
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
deepEqual = QUnit.deepEqual, deepEqual = QUnit.deepEqual,
equal = QUnit.equal, equal = QUnit.equal,
module = QUnit.module, module = QUnit.module,
throws = QUnit.throws,
token = "sample_token"; token = "sample_token";
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -21,31 +20,10 @@ ...@@ -21,31 +20,10 @@
test("create storage", function () { test("create storage", function () {
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "sandbox"
}); });
equal(jio.__type, "dropbox"); equal(jio.__type, "dropbox");
deepEqual(jio.__storage._access_token, token); deepEqual(jio.__storage._access_token, token);
deepEqual(jio.__storage._root, "sandbox");
});
test("reject invalid root", function () {
throws(
function () {
jIO.createJIO({
type: "dropbox",
access_token: token,
root : "foobar"
});
},
function (error) {
ok(error instanceof TypeError);
equal(error.message,
"root must be 'dropbox' or 'sandbox'");
return true;
}
);
}); });
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -60,8 +38,7 @@ ...@@ -60,8 +38,7 @@
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "dropbox"
}); });
}, },
teardown: function () { teardown: function () {
...@@ -71,8 +48,7 @@ ...@@ -71,8 +48,7 @@
}); });
test("put document", function () { test("put document", function () {
var url = "https://api.dropboxapi.com/1/fileops/create_folder?access_token=" var url = "https://api.dropboxapi.com/2/files/create_folder_v2",
+ token + "&root=dropbox&path=%2Fput1%2F",
server = this.server; server = this.server;
this.server.respondWith("POST", url, [201, { this.server.respondWith("POST", url, [201, {
"Content-Type": "text/xml" "Content-Type": "text/xml"
...@@ -87,10 +63,14 @@ ...@@ -87,10 +63,14 @@
equal(server.requests[0].method, "POST"); equal(server.requests[0].method, "POST");
equal(server.requests[0].url, url); equal(server.requests[0].url, url);
equal(server.requests[0].status, 201); equal(server.requests[0].status, 201);
equal(server.requests[0].requestBody, undefined); deepEqual(JSON.parse(server.requests[0].requestBody), {
"path": "/put1",
"autorename": false
});
equal(server.requests[0].responseText, ""); equal(server.requests[0].responseText, "");
deepEqual(server.requests[0].requestHeaders, { deepEqual(server.requests[0].requestHeaders, {
"Content-Type": "text/plain;charset=utf-8" "Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
}); });
}) })
.fail(function (error) { .fail(function (error) {
...@@ -101,18 +81,53 @@ ...@@ -101,18 +81,53 @@
}); });
}); });
test("don't throw error when putting existing directory", function () { test("put sub document", function () {
var url = "https://api.dropboxapi.com/1/fileops/create_folder?access_token=" var url = "https://api.dropboxapi.com/2/files/create_folder_v2",
+ token + "&root=dropbox&path=%2Fexisting%2F",
server = this.server; server = this.server;
this.server.respondWith("POST", url, [405, { this.server.respondWith("POST", url, [201, {
"Content-Type": "text/xml" "Content-Type": "text/xml"
}, "POST" + url + "(Forbidden)"]); }, ""]);
stop();
expect(7);
this.jio.put("/put1/put2/", {})
.then(function () {
equal(server.requests.length, 1);
equal(server.requests[0].method, "POST");
equal(server.requests[0].url, url);
equal(server.requests[0].status, 201);
deepEqual(JSON.parse(server.requests[0].requestBody), {
"path": "/put1/put2",
"autorename": false
});
equal(server.requests[0].responseText, "");
deepEqual(server.requests[0].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
});
})
.fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
test("don't throw error when putting existing directory", function () {
var url = "https://api.dropboxapi.com/2/files/create_folder_v2",
server = this.server;
this.server.respondWith("POST", url, [409, {
"Content-Type": "application/json"
}, JSON.stringify(
{error: {'.tag': 'path', 'path': {'.tag': 'conflict'}}}
)]);
stop(); stop();
expect(1); expect(1);
this.jio.put("/existing/", {}) this.jio.put("/existing/", {})
.then(function () { .then(function () {
equal(server.requests[0].status, 405); equal(server.requests[0].status, 409);
}) })
.fail(function (error) { .fail(function (error) {
ok(false, error); ok(false, error);
...@@ -188,8 +203,7 @@ ...@@ -188,8 +203,7 @@
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "dropbox"
}); });
}, },
teardown: function () { teardown: function () {
...@@ -197,9 +211,9 @@ ...@@ -197,9 +211,9 @@
delete this.server; delete this.server;
} }
}); });
test("remove document", function () { test("remove document", function () {
var url_delete = "https://api.dropboxapi.com/1/fileops/delete/?" + var url_delete = "https://api.dropboxapi.com/2/files/delete_v2",
"access_token=" + token + "&root=dropbox&path=%2Fremove1%2F",
server = this.server; server = this.server;
this.server.respondWith("POST", url_delete, [204, { this.server.respondWith("POST", url_delete, [204, {
"Content-Type": "text/xml" "Content-Type": "text/xml"
...@@ -213,10 +227,13 @@ ...@@ -213,10 +227,13 @@
equal(server.requests[0].method, "POST"); equal(server.requests[0].method, "POST");
equal(server.requests[0].url, url_delete); equal(server.requests[0].url, url_delete);
equal(server.requests[0].status, 204); equal(server.requests[0].status, 204);
equal(server.requests[0].requestBody, undefined); deepEqual(JSON.parse(server.requests[0].requestBody), {
equal(server.requests[0].responseText, ''); "path": "/remove1"
});
equal(server.requests[0].responseText, "");
deepEqual(server.requests[0].requestHeaders, { deepEqual(server.requests[0].requestHeaders, {
"Content-Type": "text/plain;charset=utf-8" "Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
}); });
}) })
.fail(function (error) { .fail(function (error) {
...@@ -275,8 +292,7 @@ ...@@ -275,8 +292,7 @@
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "dropbox"
}); });
}, },
teardown: function () { teardown: function () {
...@@ -322,6 +338,13 @@ ...@@ -322,6 +338,13 @@
}); });
test("get inexistent document", function () { test("get inexistent document", function () {
var url = "https://api.dropboxapi.com/2/files/get_metadata";
this.server.respondWith("POST", url, [409, {
"Content-Type": "application/json"
}, JSON.stringify(
{error: {'.tag': 'path', 'path': {'.tag': 'not_found'}}}
)]);
stop(); stop();
expect(3); expect(3);
...@@ -340,18 +363,25 @@ ...@@ -340,18 +363,25 @@
}); });
test("get directory", function () { test("get directory", function () {
var url = "https://api.dropboxapi.com/1/metadata/dropbox" + var url = "https://api.dropboxapi.com/2/files/get_metadata",
"/id1/?access_token=" + token; server = this.server;
this.server.respondWith("GET", url, [200, { this.server.respondWith("POST", url, [200, {
"Content-Type": "text/xml" "Content-Type": "application/json"
}, '{"is_dir": true, "contents": []}' }, '{".tag": "folder"}'
]); ]);
stop(); stop();
expect(1); expect(3);
this.jio.get("/id1/") this.jio.get("/id1/")
.then(function (result) { .then(function (result) {
deepEqual(result, {}, "Check document"); deepEqual(result, {}, "Check document");
deepEqual(JSON.parse(server.requests[0].requestBody), {
"path": "/id1"
});
deepEqual(server.requests[0].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
});
}) })
.fail(function (error) { .fail(function (error) {
ok(false, error); ok(false, error);
...@@ -362,11 +392,10 @@ ...@@ -362,11 +392,10 @@
}); });
test("get file", function () { test("get file", function () {
var url = "https://api.dropboxapi.com/1/metadata/dropbox" + var url = "https://api.dropboxapi.com/2/files/get_metadata";
"/id1/?access_token=" + token; this.server.respondWith("POST", url, [200, {
this.server.respondWith("GET", url, [200, { "Content-Type": "application/json"
"Content-Type": "text/xml" }, '{".tag": "file"}'
}, '{"is_dir": false, "contents": []}'
]); ]);
stop(); stop();
expect(3); expect(3);
...@@ -397,8 +426,7 @@ ...@@ -397,8 +426,7 @@
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "dropbox"
}); });
}, },
teardown: function () { teardown: function () {
...@@ -444,12 +472,14 @@ ...@@ -444,12 +472,14 @@
}); });
test("get file", function () { test("get file", function () {
var url = "https://api.dropboxapi.com/1/metadata/dropbox" + var url = "https://api.dropboxapi.com/2/files/list_folder";
"/id1/?access_token=" + token;
this.server.respondWith("GET", url, [200, { this.server.respondWith("POST", url, [409, {
"Content-Type": "text/xml" "Content-Type": "application/json"
}, '{"is_dir": false, "contents": []}' }, JSON.stringify(
]); {error: {'.tag': 'path', 'path': {'.tag': 'not_folder'}}}
)]);
stop(); stop();
expect(3); expect(3);
...@@ -468,6 +498,14 @@ ...@@ -468,6 +498,14 @@
}); });
test("get inexistent document", function () { test("get inexistent document", function () {
var url = "https://api.dropboxapi.com/2/files/list_folder";
this.server.respondWith("POST", url, [409, {
"Content-Type": "application/json"
}, JSON.stringify(
{error: {'.tag': 'path', 'path': {'.tag': 'not_found'}}}
)]);
stop(); stop();
expect(3); expect(3);
...@@ -486,18 +524,30 @@ ...@@ -486,18 +524,30 @@
}); });
test("get document without attachment", function () { test("get document without attachment", function () {
var url = "https://api.dropboxapi.com/1/metadata/dropbox" + var url = "https://api.dropboxapi.com/2/files/list_folder",
"/id1/?access_token=" + token; server = this.server;
this.server.respondWith("GET", url, [200, { this.server.respondWith("POST", url, [200, {
"Content-Type": "text/xml" "Content-Type": "application/json"
}, '{"is_dir": true, "contents": []}' }, '{"entries": [], "has_more": false}'
]); ]);
stop(); stop();
expect(1); expect(3);
this.jio.allAttachments("/id1/") this.jio.allAttachments("/id1/")
.then(function (result) { .then(function (result) {
deepEqual(result, {}, "Check document"); deepEqual(result, {}, "Check document");
deepEqual(JSON.parse(server.requests[0].requestBody), {
"include_deleted": false,
"include_has_explicit_shared_members": false,
"include_media_info": false,
"include_mounted_folders": true,
"path": "/id1",
"recursive": false
});
deepEqual(server.requests[0].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
});
}) })
.fail(function (error) { .fail(function (error) {
ok(false, error); ok(false, error);
...@@ -508,28 +558,26 @@ ...@@ -508,28 +558,26 @@
}); });
test("get document with attachment", function () { test("get document with attachment", function () {
var url = "https://api.dropboxapi.com/1/metadata/dropbox" + var url = "https://api.dropboxapi.com/2/files/list_folder",
"/id1/?access_token=" + token; server = this.server;
this.server.respondWith("GET", url, [200, { this.server.respondWith("POST", url, [200, {
"Content-Type": "text/xml" "Content-Type": "application/json"
}, '{"is_dir": true, "path": "/id1", ' + }, JSON.stringify({
'"contents": ' + "entries": [{
'[{"rev": "143bb45509", ' + ".tag": "file",
'"thumb_exists": false, ' + "name": "attachment1"
'"path": "/id1/attachment1", ' + }, {
'"is_dir": false, "bytes": 151}, ' + ".tag": "file",
'{"rev": "153bb45509", ' + "name": "attachment2"
'"thumb_exists": false, ' + }, {
'"path": "/id1/attachment2", ' + ".tag": "folder",
'"is_dir": false, "bytes": 11}, ' + "name": "fold1"
'{"rev": "173bb45509", ' + }],
'"thumb_exists": false, ' + "has_more": false
'"path": "/id1/fold1", ' + })]);
'"is_dir": true, "bytes": 0}], ' +
'"icon": "folder"}'
]);
stop(); stop();
expect(1); expect(3);
this.jio.allAttachments("/id1/") this.jio.allAttachments("/id1/")
.then(function (result) { .then(function (result) {
...@@ -537,6 +585,92 @@ ...@@ -537,6 +585,92 @@
attachment1: {}, attachment1: {},
attachment2: {} attachment2: {}
}, "Check document"); }, "Check document");
deepEqual(JSON.parse(server.requests[0].requestBody), {
"include_deleted": false,
"include_has_explicit_shared_members": false,
"include_media_info": false,
"include_mounted_folders": true,
"path": "/id1",
"recursive": false
});
deepEqual(server.requests[0].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
});
})
.fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
test("get document with attachment and pagination", function () {
var url = "https://api.dropboxapi.com/2/files/list_folder",
paginate_url = "https://api.dropboxapi.com/2/files/list_folder/continue",
server = this.server,
cursor = "foocursor";
this.server.respondWith("POST", url, [200, {
"Content-Type": "application/json"
}, JSON.stringify({
"entries": [{
".tag": "file",
"name": "attachment1"
}, {
".tag": "folder",
"name": "fold1"
}],
"has_more": true,
"cursor": cursor
})]);
this.server.respondWith("POST", paginate_url, [200, {
"Content-Type": "application/json"
}, JSON.stringify({
"entries": [{
".tag": "file",
"name": "attachment2"
}, {
".tag": "folder",
"name": "fold2"
}],
"has_more": false
})]);
stop();
expect(7);
this.jio.allAttachments("/id1/")
.then(function (result) {
deepEqual(result, {
attachment1: {},
attachment2: {}
}, "Check document");
deepEqual(server.requests[0].url, url);
deepEqual(JSON.parse(server.requests[0].requestBody), {
"include_deleted": false,
"include_has_explicit_shared_members": false,
"include_media_info": false,
"include_mounted_folders": true,
"path": "/id1",
"recursive": false
});
deepEqual(server.requests[0].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
});
deepEqual(server.requests[1].url, paginate_url);
deepEqual(JSON.parse(server.requests[1].requestBody), {
"cursor": cursor
});
deepEqual(server.requests[1].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
});
}) })
.fail(function (error) { .fail(function (error) {
ok(false, error); ok(false, error);
...@@ -558,8 +692,7 @@ ...@@ -558,8 +692,7 @@
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "dropbox"
}); });
}, },
teardown: function () { teardown: function () {
...@@ -635,13 +768,11 @@ ...@@ -635,13 +768,11 @@
}); });
test("putAttachment document", function () { test("putAttachment document", function () {
var blob = new Blob(["foo"]), var blob = new Blob(["foo"], {"type": "xapplication/foo"}),
url_put_att = "https://content.dropboxapi.com/1/files_put/dropbox" url_put_att = "https://content.dropboxapi.com/2/files/upload",
+ "/putAttachment1/"
+ "attachment1?access_token=" + token,
server = this.server; server = this.server;
this.server.respondWith("PUT", url_put_att, [204, { this.server.respondWith("POST", url_put_att, [204, {
"Content-Type": "text/xml" "Content-Type": "text/xml"
}, ""]); }, ""]);
...@@ -656,12 +787,16 @@ ...@@ -656,12 +787,16 @@
.then(function () { .then(function () {
equal(server.requests.length, 1); equal(server.requests.length, 1);
equal(server.requests[0].method, "PUT"); equal(server.requests[0].method, "POST");
equal(server.requests[0].url, url_put_att); equal(server.requests[0].url, url_put_att);
equal(server.requests[0].status, 204); equal(server.requests[0].status, 204);
equal(server.requests[0].responseText, ""); equal(server.requests[0].responseText, "");
deepEqual(server.requests[0].requestHeaders, { deepEqual(server.requests[0].requestHeaders, {
"Content-Type": "text/plain;charset=utf-8" "Authorization": "Bearer sample_token",
"Content-Type": "application/octet-stream;charset=utf-8",
"Dropbox-API-Arg": '{"path":"/putAttachment1/attachment1",' +
'"mode":"overwrite",' +
'"autorename":false,"mute":false}'
}); });
equal(server.requests[0].requestBody, blob); equal(server.requests[0].requestBody, blob);
}) })
...@@ -685,8 +820,7 @@ ...@@ -685,8 +820,7 @@
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "dropbox"
}); });
}, },
teardown: function () { teardown: function () {
...@@ -759,9 +893,7 @@ ...@@ -759,9 +893,7 @@
}); });
test("removeAttachment document", function () { test("removeAttachment document", function () {
var url_delete = "https://api.dropboxapi.com/1/fileops/delete/" + var url_delete = "https://api.dropboxapi.com/2/files/delete_v2",
"?access_token=" + token + "&root=dropbox" +
"&path=%2FremoveAttachment1%2Fattachment1",
server = this.server; server = this.server;
this.server.respondWith("POST", url_delete, [204, { this.server.respondWith("POST", url_delete, [204, {
...@@ -781,10 +913,13 @@ ...@@ -781,10 +913,13 @@
equal(server.requests[0].method, "POST"); equal(server.requests[0].method, "POST");
equal(server.requests[0].url, url_delete); equal(server.requests[0].url, url_delete);
equal(server.requests[0].status, 204); equal(server.requests[0].status, 204);
equal(server.requests[0].requestBody, undefined); deepEqual(JSON.parse(server.requests[0].requestBody), {
"path": "/removeAttachment1/attachment1"
});
equal(server.requests[0].responseText, ""); equal(server.requests[0].responseText, "");
deepEqual(server.requests[0].requestHeaders, { deepEqual(server.requests[0].requestHeaders, {
"Content-Type": "text/plain;charset=utf-8" "Authorization": "Bearer sample_token",
"Content-Type": "application/json;charset=utf-8"
}); });
}) })
.fail(function (error) { .fail(function (error) {
...@@ -796,6 +931,13 @@ ...@@ -796,6 +931,13 @@
}); });
test("remove inexistent attachment", function () { test("remove inexistent attachment", function () {
var url_delete = "https://api.dropboxapi.com/2/files/delete_v2";
this.server.respondWith("POST", url_delete, [409, {
"Content-Type": "application/json"
}, JSON.stringify(
{error: {'.tag': 'path_lookup', 'path_lookup': {'.tag': 'not_found'}}}
)]);
stop(); stop();
expect(3); expect(3);
...@@ -829,8 +971,7 @@ ...@@ -829,8 +971,7 @@
this.jio = jIO.createJIO({ this.jio = jIO.createJIO({
type: "dropbox", type: "dropbox",
access_token: token, access_token: token
root : "dropbox"
}); });
}, },
teardown: function () { teardown: function () {
...@@ -903,15 +1044,14 @@ ...@@ -903,15 +1044,14 @@
}); });
test("getAttachment document", function () { test("getAttachment document", function () {
var url = "https://content.dropboxapi.com/1/files/dropbox/" + var url = "https://content.dropboxapi.com/2/files/download",
"%2FgetAttachment1%2Fattachment1?access_token=" + token,
server = this.server; server = this.server;
this.server.respondWith("GET", url, [200, { this.server.respondWith("POST", url, [200, {
"Content-Type": "text/plain" "Content-Type": "text/xplain"
}, "foo\nbaré"]); }, "foo\nbaré"]);
stop(); stop();
expect(9); expect(10);
this.jio.getAttachment( this.jio.getAttachment(
"/getAttachment1/", "/getAttachment1/",
...@@ -919,14 +1059,19 @@ ...@@ -919,14 +1059,19 @@
) )
.then(function (result) { .then(function (result) {
equal(server.requests.length, 1); equal(server.requests.length, 1);
equal(server.requests[0].method, "GET"); equal(server.requests[0].method, "POST");
equal(server.requests[0].url, url); equal(server.requests[0].url, url);
equal(server.requests[0].status, 200); equal(server.requests[0].status, 200);
equal(server.requests[0].requestBody, undefined); equal(server.requests[0].requestBody, undefined);
equal(server.requests[0].responseText, "foo\nbaré"); equal(server.requests[0].responseText, "foo\nbaré");
deepEqual(server.requests[0].requestHeaders, {
"Authorization": "Bearer sample_token",
"Content-Type": "text/plain;charset=utf-8",
"Dropbox-API-Arg": '{"path":"/getAttachment1/attachment1"}'
});
ok(result instanceof Blob, "Data is Blob"); ok(result instanceof Blob, "Data is Blob");
deepEqual(result.type, "text/plain", "Check mimetype"); deepEqual(result.type, "text/xplain", "Check mimetype");
return jIO.util.readBlobAsText(result); return jIO.util.readBlobAsText(result);
}) })
.then(function (result) { .then(function (result) {
...@@ -942,6 +1087,14 @@ ...@@ -942,6 +1087,14 @@
}); });
test("get inexistent attachment", function () { test("get inexistent attachment", function () {
var url = "https://content.dropboxapi.com/2/files/download";
this.server.respondWith("POST", url, [409, {
"Content-Type": "application/json"
}, JSON.stringify(
{error: {'.tag': 'path', 'path': {'.tag': 'not_found'}}}
)]);
stop(); stop();
expect(3); expect(3);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment