clientSpec.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /**
  2. * ownCloud
  3. *
  4. * @author Vincent Petry
  5. * @copyright 2015 Vincent Petry <pvince81@owncloud.com>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  9. * License as published by the Free Software Foundation; either
  10. * version 3 of the License, or any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public
  18. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. /* global dav */
  22. describe('OC.Files.Client tests', function() {
  23. var Client = OC.Files.Client;
  24. var baseUrl;
  25. var client;
  26. var requestStub;
  27. var requestDeferred;
  28. beforeEach(function() {
  29. requestDeferred = new $.Deferred();
  30. requestStub = sinon.stub(dav.Client.prototype, 'request').returns(requestDeferred.promise());
  31. baseUrl = 'https://testhost/owncloud/remote.php/webdav/';
  32. client = new Client({
  33. host: 'testhost',
  34. root: '/owncloud/remote.php/webdav',
  35. useHTTPS: true
  36. });
  37. });
  38. afterEach(function() {
  39. client = null;
  40. requestStub.restore();
  41. });
  42. /**
  43. * Send an status response and check that the given
  44. * promise gets its success handler called with the error
  45. * status code
  46. *
  47. * @param {Promise} promise promise
  48. * @param {int} status status to test
  49. */
  50. function respondAndCheckStatus(promise, status) {
  51. var successHandler = sinon.stub();
  52. var failHandler = sinon.stub();
  53. promise.done(successHandler);
  54. promise.fail(failHandler);
  55. requestDeferred.resolve({
  56. status: status,
  57. body: ''
  58. });
  59. promise.then(function() {
  60. expect(successHandler.calledOnce).toEqual(true);
  61. expect(successHandler.getCall(0).args[0]).toEqual(status);
  62. expect(failHandler.notCalled).toEqual(true);
  63. });
  64. return promise;
  65. }
  66. /**
  67. * Send an error response and check that the given
  68. * promise gets its fail handler called with the error
  69. * status code
  70. *
  71. * @param {Promise} promise promise object
  72. * @param {int} status error status to test
  73. */
  74. function respondAndCheckError(promise, status) {
  75. var successHandler = sinon.stub();
  76. var failHandler = sinon.stub();
  77. promise.done(successHandler);
  78. promise.fail(failHandler);
  79. requestDeferred.resolve({
  80. status: status,
  81. body: ''
  82. });
  83. promise.then(function() {
  84. expect(failHandler.calledOnce).toEqual(true);
  85. expect(failHandler.calledWith(status)).toEqual(true);
  86. expect(successHandler.notCalled).toEqual(true);
  87. });
  88. return promise;
  89. }
  90. /**
  91. * Returns a list of request properties parsed from the given request body.
  92. *
  93. * @param {string} requestBody request XML
  94. *
  95. * @return {Array.<String>} array of request properties in the format
  96. * "{NS:}propname"
  97. */
  98. function getRequestedProperties(requestBody) {
  99. var doc = (new window.DOMParser()).parseFromString(
  100. requestBody,
  101. 'application/xml'
  102. );
  103. var propRoots = doc.getElementsByTagNameNS('DAV:', 'prop');
  104. var propsList = propRoots.item(0).childNodes;
  105. return _.map(propsList, function(propNode) {
  106. return '{' + propNode.namespaceURI + '}' + propNode.localName;
  107. });
  108. }
  109. function makePropBlock(props) {
  110. var s = '<d:prop>\n';
  111. _.each(props, function(value, key) {
  112. s += '<' + key + '>' + value + '</' + key + '>\n';
  113. });
  114. return s + '</d:prop>\n';
  115. }
  116. function makeResponseBlock(href, props, failedProps) {
  117. var s = '<d:response>\n';
  118. s += '<d:href>' + href + '</d:href>\n';
  119. s += '<d:propstat>\n';
  120. s += makePropBlock(props);
  121. s += '<d:status>HTTP/1.1 200 OK</d:status>';
  122. s += '</d:propstat>\n';
  123. if (failedProps) {
  124. s += '<d:propstat>\n';
  125. _.each(failedProps, function(prop) {
  126. s += '<' + prop + '/>\n';
  127. });
  128. s += '<d:status>HTTP/1.1 404 Not Found</d:status>\n';
  129. s += '</d:propstat>\n';
  130. }
  131. return s + '</d:response>\n';
  132. }
  133. describe('file listing', function() {
  134. // TODO: switch this to the already parsed structure
  135. var folderContentsXml = dav.Client.prototype.parseMultiStatus(
  136. '<?xml version="1.0" encoding="utf-8"?>' +
  137. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  138. makeResponseBlock(
  139. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/',
  140. {
  141. 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
  142. 'd:getetag': '"56cfcabd79abb"',
  143. 'd:resourcetype': '<d:collection/>',
  144. 'oc:id': '00000011oc2d13a6a068',
  145. 'oc:fileid': '11',
  146. 'oc:permissions': 'RDNVCK',
  147. 'oc:size': '120'
  148. },
  149. [
  150. 'd:getcontenttype',
  151. 'd:getcontentlength'
  152. ]
  153. ) +
  154. makeResponseBlock(
  155. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt',
  156. {
  157. 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT',
  158. 'd:getetag': '"559fcabd79a38"',
  159. 'd:getcontenttype': 'text/plain',
  160. 'd:getcontentlength': 250,
  161. 'd:resourcetype': '',
  162. 'oc:id': '00000051oc2d13a6a068',
  163. 'oc:fileid': '51',
  164. 'oc:permissions': 'RDNVW'
  165. },
  166. [
  167. 'oc:size',
  168. ]
  169. ) +
  170. makeResponseBlock(
  171. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/sub',
  172. {
  173. 'd:getlastmodified': 'Fri, 10 Jul 2015 14:00:00 GMT',
  174. 'd:getetag': '"66cfcabd79abb"',
  175. 'd:resourcetype': '<d:collection/>',
  176. 'oc:id': '00000015oc2d13a6a068',
  177. 'oc:fileid': '15',
  178. 'oc:permissions': 'RDNVCK',
  179. 'oc:size': '100'
  180. },
  181. [
  182. 'd:getcontenttype',
  183. 'd:getcontentlength'
  184. ]
  185. ) +
  186. '</d:multistatus>'
  187. );
  188. it('sends PROPFIND with explicit properties to get file list', function() {
  189. client.getFolderContents('path/to space/文件夹');
  190. expect(requestStub.calledOnce).toEqual(true);
  191. expect(requestStub.lastCall.args[0]).toEqual('PROPFIND');
  192. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  193. expect(requestStub.lastCall.args[2].Depth).toEqual(1);
  194. var props = getRequestedProperties(requestStub.lastCall.args[3]);
  195. expect(props).toContain('{DAV:}getlastmodified');
  196. expect(props).toContain('{DAV:}getcontentlength');
  197. expect(props).toContain('{DAV:}getcontenttype');
  198. expect(props).toContain('{DAV:}getetag');
  199. expect(props).toContain('{DAV:}resourcetype');
  200. expect(props).toContain('{http://owncloud.org/ns}fileid');
  201. expect(props).toContain('{http://owncloud.org/ns}size');
  202. expect(props).toContain('{http://owncloud.org/ns}permissions');
  203. });
  204. it('sends PROPFIND to base url when empty path given', function() {
  205. client.getFolderContents('');
  206. expect(requestStub.calledOnce).toEqual(true);
  207. expect(requestStub.lastCall.args[1]).toEqual(baseUrl);
  208. });
  209. it('sends PROPFIND to base url when root path given', function() {
  210. client.getFolderContents('/');
  211. expect(requestStub.calledOnce).toEqual(true);
  212. expect(requestStub.lastCall.args[1]).toEqual(baseUrl);
  213. });
  214. it('parses the result list into a FileInfo array', function() {
  215. var promise = client.getFolderContents('path/to space/文件夹');
  216. expect(requestStub.calledOnce).toEqual(true);
  217. requestDeferred.resolve({
  218. status: 207,
  219. body: folderContentsXml
  220. });
  221. promise.then(function(status, response) {
  222. expect(status).toEqual(207);
  223. expect(_.isArray(response)).toEqual(true);
  224. expect(response.length).toEqual(2);
  225. // file entry
  226. var info = response[0];
  227. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  228. expect(info.id).toEqual(51);
  229. expect(info.path).toEqual('/path/to space/文件夹');
  230. expect(info.name).toEqual('One.txt');
  231. expect(info.permissions).toEqual(27);
  232. expect(info.size).toEqual(250);
  233. expect(info.mtime).toEqual(1436535485000);
  234. expect(info.mimetype).toEqual('text/plain');
  235. expect(info.etag).toEqual('559fcabd79a38');
  236. // sub entry
  237. info = response[1];
  238. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  239. expect(info.id).toEqual(15);
  240. expect(info.path).toEqual('/path/to space/文件夹');
  241. expect(info.name).toEqual('sub');
  242. expect(info.permissions).toEqual(31);
  243. expect(info.size).toEqual(100);
  244. expect(info.mtime).toEqual(1436536800000);
  245. expect(info.mimetype).toEqual('httpd/unix-directory');
  246. expect(info.etag).toEqual('66cfcabd79abb');
  247. });
  248. });
  249. it('returns parent node in result if specified', function() {
  250. var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true});
  251. expect(requestStub.calledOnce).toEqual(true);
  252. requestDeferred.resolve({
  253. status: 207,
  254. body: folderContentsXml
  255. });
  256. promise.then(function(status, response) {
  257. expect(status).toEqual(207);
  258. expect(_.isArray(response)).toEqual(true);
  259. expect(response.length).toEqual(3);
  260. // root entry
  261. var info = response[0];
  262. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  263. expect(info.id).toEqual(11);
  264. expect(info.path).toEqual('/path/to space');
  265. expect(info.name).toEqual('文件夹');
  266. expect(info.permissions).toEqual(31);
  267. expect(info.size).toEqual(120);
  268. expect(info.mtime).toEqual(1436522405000);
  269. expect(info.mimetype).toEqual('httpd/unix-directory');
  270. expect(info.etag).toEqual('56cfcabd79abb');
  271. // the two other entries follow
  272. expect(response[1].id).toEqual(51);
  273. expect(response[2].id).toEqual(15);
  274. });
  275. });
  276. it('rejects promise when an error occurred', function() {
  277. var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true});
  278. respondAndCheckError(promise, 404);
  279. });
  280. it('throws exception if arguments are missing', function() {
  281. // TODO
  282. });
  283. });
  284. describe('file filtering', function() {
  285. // TODO: switch this to the already parsed structure
  286. var folderContentsXml = dav.Client.prototype.parseMultiStatus(
  287. '<?xml version="1.0" encoding="utf-8"?>' +
  288. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  289. makeResponseBlock(
  290. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/',
  291. {
  292. 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
  293. 'd:getetag': '"56cfcabd79abb"',
  294. 'd:resourcetype': '<d:collection/>',
  295. 'oc:id': '00000011oc2d13a6a068',
  296. 'oc:fileid': '11',
  297. 'oc:permissions': 'RDNVCK',
  298. 'oc:size': '120'
  299. },
  300. [
  301. 'd:getcontenttype',
  302. 'd:getcontentlength'
  303. ]
  304. ) +
  305. makeResponseBlock(
  306. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt',
  307. {
  308. 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT',
  309. 'd:getetag': '"559fcabd79a38"',
  310. 'd:getcontenttype': 'text/plain',
  311. 'd:getcontentlength': 250,
  312. 'd:resourcetype': '',
  313. 'oc:id': '00000051oc2d13a6a068',
  314. 'oc:fileid': '51',
  315. 'oc:permissions': 'RDNVW'
  316. },
  317. [
  318. 'oc:size',
  319. ]
  320. ) +
  321. makeResponseBlock(
  322. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/sub',
  323. {
  324. 'd:getlastmodified': 'Fri, 10 Jul 2015 14:00:00 GMT',
  325. 'd:getetag': '"66cfcabd79abb"',
  326. 'd:resourcetype': '<d:collection/>',
  327. 'oc:id': '00000015oc2d13a6a068',
  328. 'oc:fileid': '15',
  329. 'oc:permissions': 'RDNVCK',
  330. 'oc:size': '100'
  331. },
  332. [
  333. 'd:getcontenttype',
  334. 'd:getcontentlength'
  335. ]
  336. ) +
  337. '</d:multistatus>'
  338. );
  339. it('sends REPORT with filter information', function() {
  340. client.getFilteredFiles({
  341. systemTagIds: ['123', '456']
  342. });
  343. expect(requestStub.calledOnce).toEqual(true);
  344. expect(requestStub.lastCall.args[0]).toEqual('REPORT');
  345. expect(requestStub.lastCall.args[1]).toEqual(baseUrl);
  346. var body = requestStub.lastCall.args[3];
  347. var doc = (new window.DOMParser()).parseFromString(
  348. body,
  349. 'application/xml'
  350. );
  351. var ns = 'http://owncloud.org/ns';
  352. expect(doc.documentElement.localName).toEqual('filter-files');
  353. expect(doc.documentElement.namespaceURI).toEqual(ns);
  354. var filterRoots = doc.getElementsByTagNameNS(ns, 'filter-rules');
  355. var rulesList = filterRoots[0] = doc.getElementsByTagNameNS(ns, 'systemtag');
  356. expect(rulesList.length).toEqual(2);
  357. expect(rulesList[0].localName).toEqual('systemtag');
  358. expect(rulesList[0].namespaceURI).toEqual(ns);
  359. expect(rulesList[0].textContent).toEqual('123');
  360. expect(rulesList[1].localName).toEqual('systemtag');
  361. expect(rulesList[1].namespaceURI).toEqual(ns);
  362. expect(rulesList[1].textContent).toEqual('456');
  363. });
  364. it('sends REPORT with explicit properties to filter file list', function() {
  365. client.getFilteredFiles({
  366. systemTagIds: ['123', '456']
  367. });
  368. expect(requestStub.calledOnce).toEqual(true);
  369. expect(requestStub.lastCall.args[0]).toEqual('REPORT');
  370. expect(requestStub.lastCall.args[1]).toEqual(baseUrl);
  371. var props = getRequestedProperties(requestStub.lastCall.args[3]);
  372. expect(props).toContain('{DAV:}getlastmodified');
  373. expect(props).toContain('{DAV:}getcontentlength');
  374. expect(props).toContain('{DAV:}getcontenttype');
  375. expect(props).toContain('{DAV:}getetag');
  376. expect(props).toContain('{DAV:}resourcetype');
  377. expect(props).toContain('{http://owncloud.org/ns}fileid');
  378. expect(props).toContain('{http://owncloud.org/ns}size');
  379. expect(props).toContain('{http://owncloud.org/ns}permissions');
  380. });
  381. it('parses the result list into a FileInfo array', function() {
  382. var promise = client.getFilteredFiles({
  383. systemTagIds: ['123', '456']
  384. });
  385. expect(requestStub.calledOnce).toEqual(true);
  386. requestDeferred.resolve({
  387. status: 207,
  388. body: folderContentsXml
  389. });
  390. promise.then(function(status, response) {
  391. expect(status).toEqual(207);
  392. expect(_.isArray(response)).toEqual(true);
  393. // returns all entries
  394. expect(response.length).toEqual(3);
  395. // file entry
  396. var info = response[0];
  397. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  398. expect(info.id).toEqual(11);
  399. // file entry
  400. var info = response[1];
  401. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  402. expect(info.id).toEqual(51);
  403. // sub entry
  404. info = response[2];
  405. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  406. expect(info.id).toEqual(15);
  407. });
  408. });
  409. it('throws exception if arguments are missing', function() {
  410. var thrown = null;
  411. try {
  412. client.getFilteredFiles({
  413. systemTagIds: []
  414. });
  415. } catch (e) {
  416. thrown = true;
  417. }
  418. expect(thrown).toEqual(true);
  419. });
  420. });
  421. describe('file info', function() {
  422. var responseXml = dav.Client.prototype.parseMultiStatus(
  423. '<?xml version="1.0" encoding="utf-8"?>' +
  424. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  425. makeResponseBlock(
  426. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/',
  427. {
  428. 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
  429. 'd:getetag': '"56cfcabd79abb"',
  430. 'd:resourcetype': '<d:collection/>',
  431. 'oc:id': '00000011oc2d13a6a068',
  432. 'oc:fileid': '11',
  433. 'oc:permissions': 'RDNVCK',
  434. 'oc:size': '120'
  435. },
  436. [
  437. 'd:getcontenttype',
  438. 'd:getcontentlength'
  439. ]
  440. ) +
  441. '</d:multistatus>'
  442. );
  443. it('sends PROPFIND with zero depth to get single file info', function() {
  444. client.getFileInfo('path/to space/文件夹');
  445. expect(requestStub.calledOnce).toEqual(true);
  446. expect(requestStub.lastCall.args[0]).toEqual('PROPFIND');
  447. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  448. expect(requestStub.lastCall.args[2].Depth).toEqual(0);
  449. var props = getRequestedProperties(requestStub.lastCall.args[3]);
  450. expect(props).toContain('{DAV:}getlastmodified');
  451. expect(props).toContain('{DAV:}getcontentlength');
  452. expect(props).toContain('{DAV:}getcontenttype');
  453. expect(props).toContain('{DAV:}getetag');
  454. expect(props).toContain('{DAV:}resourcetype');
  455. expect(props).toContain('{http://owncloud.org/ns}fileid');
  456. expect(props).toContain('{http://owncloud.org/ns}size');
  457. expect(props).toContain('{http://owncloud.org/ns}permissions');
  458. });
  459. it('parses the result into a FileInfo', function() {
  460. var promise = client.getFileInfo('path/to space/文件夹');
  461. expect(requestStub.calledOnce).toEqual(true);
  462. requestDeferred.resolve({
  463. status: 207,
  464. body: responseXml
  465. });
  466. promise.then(function(status, response) {
  467. expect(status).toEqual(207);
  468. expect(_.isArray(response)).toEqual(false);
  469. var info = response;
  470. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  471. expect(info.id).toEqual(11);
  472. expect(info.path).toEqual('/path/to space');
  473. expect(info.name).toEqual('文件夹');
  474. expect(info.permissions).toEqual(31);
  475. expect(info.size).toEqual(120);
  476. expect(info.mtime).toEqual(1436522405000);
  477. expect(info.mimetype).toEqual('httpd/unix-directory');
  478. expect(info.etag).toEqual('56cfcabd79abb');
  479. });
  480. });
  481. it('properly parses entry inside root', function() {
  482. var responseXml = dav.Client.prototype.parseMultiStatus(
  483. '<?xml version="1.0" encoding="utf-8"?>' +
  484. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  485. makeResponseBlock(
  486. '/owncloud/remote.php/webdav/in%20root',
  487. {
  488. 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
  489. 'd:getetag': '"56cfcabd79abb"',
  490. 'd:resourcetype': '<d:collection/>',
  491. 'oc:id': '00000011oc2d13a6a068',
  492. 'oc:fileid': '11',
  493. 'oc:permissions': 'RDNVCK',
  494. 'oc:size': '120'
  495. },
  496. [
  497. 'd:getcontenttype',
  498. 'd:getcontentlength'
  499. ]
  500. ) +
  501. '</d:multistatus>'
  502. );
  503. var promise = client.getFileInfo('in root');
  504. expect(requestStub.calledOnce).toEqual(true);
  505. requestDeferred.resolve({
  506. status: 207,
  507. body: responseXml
  508. });
  509. promise.then(function(status, response) {
  510. expect(status).toEqual(207);
  511. expect(_.isArray(response)).toEqual(false);
  512. var info = response;
  513. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  514. expect(info.id).toEqual(11);
  515. expect(info.path).toEqual('/');
  516. expect(info.name).toEqual('in root');
  517. expect(info.permissions).toEqual(31);
  518. expect(info.size).toEqual(120);
  519. expect(info.mtime).toEqual(1436522405000);
  520. expect(info.mimetype).toEqual('httpd/unix-directory');
  521. expect(info.etag).toEqual('56cfcabd79abb');
  522. });
  523. });
  524. it('rejects promise when an error occurred', function() {
  525. var promise = client.getFileInfo('path/to space/文件夹');
  526. respondAndCheckError(promise, 404);
  527. });
  528. it('throws exception if arguments are missing', function() {
  529. // TODO
  530. });
  531. });
  532. describe('permissions', function() {
  533. function getFileInfoWithPermission(webdavPerm, isFile) {
  534. var props = {
  535. 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT',
  536. 'd:getetag': '"559fcabd79a38"',
  537. 'd:getcontentlength': 250,
  538. 'oc:id': '00000051oc2d13a6a068',
  539. 'oc:fileid': '51',
  540. 'oc:permissions': webdavPerm,
  541. };
  542. if (isFile) {
  543. props['d:getcontenttype'] = 'text/plain';
  544. } else {
  545. props['d:resourcetype'] = '<d:collection/>';
  546. }
  547. var def = new $.Deferred();
  548. requestStub.reset();
  549. requestStub.returns(def);
  550. var responseXml = dav.Client.prototype.parseMultiStatus(
  551. '<?xml version="1.0" encoding="utf-8"?>' +
  552. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  553. makeResponseBlock(
  554. '/owncloud/remote.php/webdav/file.txt',
  555. props
  556. ) +
  557. '</d:multistatus>'
  558. );
  559. var promise = client.getFileInfo('file.txt');
  560. expect(requestStub.calledOnce).toEqual(true);
  561. def.resolve({
  562. status: 207,
  563. body: responseXml
  564. });
  565. return promise;
  566. }
  567. function testPermission(permission, isFile, expectedPermissions) {
  568. var promise = getFileInfoWithPermission(permission, isFile);
  569. promise.then(function(result) {
  570. expect(result.permissions).toEqual(expectedPermissions);
  571. });
  572. }
  573. function testMountType(permission, isFile, expectedMountType) {
  574. var promise = getFileInfoWithPermission(permission, isFile);
  575. promise.then(function(result) {
  576. expect(result.mountType).toEqual(expectedMountType);
  577. });
  578. }
  579. it('properly parses file permissions', function() {
  580. // permission, isFile, expectedPermissions
  581. var testCases = [
  582. ['', true, OC.PERMISSION_READ],
  583. ['C', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE],
  584. ['K', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE],
  585. ['W', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
  586. ['D', true, OC.PERMISSION_READ | OC.PERMISSION_DELETE],
  587. ['R', true, OC.PERMISSION_READ | OC.PERMISSION_SHARE],
  588. ['CKWDR', true, OC.PERMISSION_ALL]
  589. ];
  590. _.each(testCases, function(testCase) {
  591. return testPermission.apply(testCase);
  592. });
  593. });
  594. it('properly parses folder permissions', function() {
  595. var testCases = [
  596. ['', false, OC.PERMISSION_READ],
  597. ['C', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
  598. ['K', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
  599. ['W', false, OC.PERMISSION_READ | OC.PERMISSION_UPDATE],
  600. ['D', false, OC.PERMISSION_READ | OC.PERMISSION_DELETE],
  601. ['R', false, OC.PERMISSION_READ | OC.PERMISSION_SHARE],
  602. ['CKWDR', false, OC.PERMISSION_ALL]
  603. ];
  604. _.each(testCases, function(testCase) {
  605. return testPermission.apply(testCase);
  606. });
  607. });
  608. it('properly parses mount types', function() {
  609. var testCases = [
  610. ['CKWDR', false, null],
  611. ['M', false, 'external'],
  612. ['S', false, 'shared'],
  613. ['SM', false, 'shared']
  614. ];
  615. _.each(testCases, function(testCase) {
  616. return testMountType.apply(testCase);
  617. });
  618. });
  619. });
  620. describe('get file contents', function() {
  621. it('returns file contents', function() {
  622. var promise = client.getFileContents('path/to space/文件夹/One.txt');
  623. expect(requestStub.calledOnce).toEqual(true);
  624. expect(requestStub.lastCall.args[0]).toEqual('GET');
  625. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
  626. requestDeferred.resolve({
  627. status: 200,
  628. body: 'some contents'
  629. });
  630. promise.then(function(status, response) {
  631. expect(status).toEqual(200);
  632. expect(response).toEqual('some contents');
  633. });
  634. });
  635. it('rejects promise when an error occurred', function() {
  636. var promise = client.getFileContents('path/to space/文件夹/One.txt');
  637. respondAndCheckError(promise, 409);
  638. });
  639. it('throws exception if arguments are missing', function() {
  640. // TODO
  641. });
  642. });
  643. describe('put file contents', function() {
  644. it('sends PUT with file contents', function() {
  645. var promise = client.putFileContents(
  646. 'path/to space/文件夹/One.txt',
  647. 'some contents'
  648. );
  649. expect(requestStub.calledOnce).toEqual(true);
  650. expect(requestStub.lastCall.args[0]).toEqual('PUT');
  651. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
  652. expect(requestStub.lastCall.args[2]['If-None-Match']).toEqual('*');
  653. expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/plain;charset=utf-8');
  654. expect(requestStub.lastCall.args[3]).toEqual('some contents');
  655. respondAndCheckStatus(promise, 201);
  656. });
  657. it('sends PUT with file contents with headers matching options', function() {
  658. var promise = client.putFileContents(
  659. 'path/to space/文件夹/One.txt',
  660. 'some contents',
  661. {
  662. overwrite: false,
  663. contentType: 'text/markdown'
  664. }
  665. );
  666. expect(requestStub.calledOnce).toEqual(true);
  667. expect(requestStub.lastCall.args[0]).toEqual('PUT');
  668. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
  669. expect(requestStub.lastCall.args[2]['If-None-Match']).not.toBeDefined();
  670. expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/markdown');
  671. expect(requestStub.lastCall.args[3]).toEqual('some contents');
  672. respondAndCheckStatus(promise, 201);
  673. });
  674. it('rejects promise when an error occurred', function() {
  675. var promise = client.putFileContents(
  676. 'path/to space/文件夹/One.txt',
  677. 'some contents'
  678. );
  679. respondAndCheckError(promise, 409);
  680. });
  681. it('throws exception if arguments are missing', function() {
  682. // TODO
  683. });
  684. });
  685. describe('create directory', function() {
  686. it('sends MKCOL with specified path', function() {
  687. var promise = client.createDirectory('path/to space/文件夹/new dir');
  688. expect(requestStub.calledOnce).toEqual(true);
  689. expect(requestStub.lastCall.args[0]).toEqual('MKCOL');
  690. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir');
  691. respondAndCheckStatus(promise, 201);
  692. });
  693. it('rejects promise when an error occurred', function() {
  694. var promise = client.createDirectory('path/to space/文件夹/new dir');
  695. respondAndCheckError(promise, 404);
  696. });
  697. it('throws exception if arguments are missing', function() {
  698. // TODO
  699. });
  700. });
  701. describe('deletion', function() {
  702. it('sends DELETE with specified path', function() {
  703. var promise = client.remove('path/to space/文件夹');
  704. expect(requestStub.calledOnce).toEqual(true);
  705. expect(requestStub.lastCall.args[0]).toEqual('DELETE');
  706. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  707. respondAndCheckStatus(promise, 201);
  708. });
  709. it('rejects promise when an error occurred', function() {
  710. var promise = client.remove('path/to space/文件夹');
  711. respondAndCheckError(promise, 404);
  712. });
  713. it('throws exception if arguments are missing', function() {
  714. // TODO
  715. });
  716. });
  717. describe('move', function() {
  718. it('sends MOVE with specified paths with fail on overwrite by default', function() {
  719. var promise = client.move(
  720. 'path/to space/文件夹',
  721. 'path/to space/anotherdir/文件夹'
  722. );
  723. expect(requestStub.calledOnce).toEqual(true);
  724. expect(requestStub.lastCall.args[0]).toEqual('MOVE');
  725. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  726. expect(requestStub.lastCall.args[2].Destination)
  727. .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
  728. expect(requestStub.lastCall.args[2].Overwrite)
  729. .toEqual('F');
  730. respondAndCheckStatus(promise, 201);
  731. });
  732. it('sends MOVE with silent overwrite mode when specified', function() {
  733. var promise = client.move(
  734. 'path/to space/文件夹',
  735. 'path/to space/anotherdir/文件夹',
  736. {allowOverwrite: true}
  737. );
  738. expect(requestStub.calledOnce).toEqual(true);
  739. expect(requestStub.lastCall.args[0]).toEqual('MOVE');
  740. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  741. expect(requestStub.lastCall.args[2].Destination)
  742. .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
  743. expect(requestStub.lastCall.args[2].Overwrite)
  744. .not.toBeDefined();
  745. respondAndCheckStatus(promise, 201);
  746. });
  747. it('rejects promise when an error occurred', function() {
  748. var promise = client.move(
  749. 'path/to space/文件夹',
  750. 'path/to space/anotherdir/文件夹',
  751. {allowOverwrite: true}
  752. );
  753. respondAndCheckError(promise, 404);
  754. });
  755. it('throws exception if arguments are missing', function() {
  756. // TODO
  757. });
  758. });
  759. });