clientSpec.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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. 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. } catch (e) {
  414. thrown = true;
  415. }
  416. expect(thrown).toEqual(true);
  417. });
  418. });
  419. describe('file info', function() {
  420. var responseXml = dav.Client.prototype.parseMultiStatus(
  421. '<?xml version="1.0" encoding="utf-8"?>' +
  422. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  423. makeResponseBlock(
  424. '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/',
  425. {
  426. 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
  427. 'd:getetag': '"56cfcabd79abb"',
  428. 'd:resourcetype': '<d:collection/>',
  429. 'oc:id': '00000011oc2d13a6a068',
  430. 'oc:fileid': '11',
  431. 'oc:permissions': 'RDNVCK',
  432. 'oc:size': '120'
  433. },
  434. [
  435. 'd:getcontenttype',
  436. 'd:getcontentlength'
  437. ]
  438. ) +
  439. '</d:multistatus>'
  440. );
  441. it('sends PROPFIND with zero depth to get single file info', function() {
  442. client.getFileInfo('path/to space/文件夹');
  443. expect(requestStub.calledOnce).toEqual(true);
  444. expect(requestStub.lastCall.args[0]).toEqual('PROPFIND');
  445. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  446. expect(requestStub.lastCall.args[2].Depth).toEqual(0);
  447. var props = getRequestedProperties(requestStub.lastCall.args[3]);
  448. expect(props).toContain('{DAV:}getlastmodified');
  449. expect(props).toContain('{DAV:}getcontentlength');
  450. expect(props).toContain('{DAV:}getcontenttype');
  451. expect(props).toContain('{DAV:}getetag');
  452. expect(props).toContain('{DAV:}resourcetype');
  453. expect(props).toContain('{http://owncloud.org/ns}fileid');
  454. expect(props).toContain('{http://owncloud.org/ns}size');
  455. expect(props).toContain('{http://owncloud.org/ns}permissions');
  456. });
  457. it('parses the result into a FileInfo', function() {
  458. var promise = client.getFileInfo('path/to space/文件夹');
  459. expect(requestStub.calledOnce).toEqual(true);
  460. requestDeferred.resolve({
  461. status: 207,
  462. body: responseXml
  463. });
  464. promise.then(function(status, response) {
  465. expect(status).toEqual(207);
  466. expect(_.isArray(response)).toEqual(false);
  467. var info = response;
  468. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  469. expect(info.id).toEqual(11);
  470. expect(info.path).toEqual('/path/to space');
  471. expect(info.name).toEqual('文件夹');
  472. expect(info.permissions).toEqual(31);
  473. expect(info.size).toEqual(120);
  474. expect(info.mtime).toEqual(1436522405000);
  475. expect(info.mimetype).toEqual('httpd/unix-directory');
  476. expect(info.etag).toEqual('56cfcabd79abb');
  477. });
  478. });
  479. it('properly parses entry inside root', function() {
  480. var responseXml = dav.Client.prototype.parseMultiStatus(
  481. '<?xml version="1.0" encoding="utf-8"?>' +
  482. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  483. makeResponseBlock(
  484. '/owncloud/remote.php/webdav/in%20root',
  485. {
  486. 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
  487. 'd:getetag': '"56cfcabd79abb"',
  488. 'd:resourcetype': '<d:collection/>',
  489. 'oc:id': '00000011oc2d13a6a068',
  490. 'oc:fileid': '11',
  491. 'oc:permissions': 'RDNVCK',
  492. 'oc:size': '120'
  493. },
  494. [
  495. 'd:getcontenttype',
  496. 'd:getcontentlength'
  497. ]
  498. ) +
  499. '</d:multistatus>'
  500. );
  501. var promise = client.getFileInfo('in root');
  502. expect(requestStub.calledOnce).toEqual(true);
  503. requestDeferred.resolve({
  504. status: 207,
  505. body: responseXml
  506. });
  507. promise.then(function(status, response) {
  508. expect(status).toEqual(207);
  509. expect(_.isArray(response)).toEqual(false);
  510. var info = response;
  511. expect(info instanceof OC.Files.FileInfo).toEqual(true);
  512. expect(info.id).toEqual(11);
  513. expect(info.path).toEqual('/');
  514. expect(info.name).toEqual('in root');
  515. expect(info.permissions).toEqual(31);
  516. expect(info.size).toEqual(120);
  517. expect(info.mtime).toEqual(1436522405000);
  518. expect(info.mimetype).toEqual('httpd/unix-directory');
  519. expect(info.etag).toEqual('56cfcabd79abb');
  520. });
  521. });
  522. it('rejects promise when an error occurred', function() {
  523. var promise = client.getFileInfo('path/to space/文件夹');
  524. respondAndCheckError(promise, 404);
  525. });
  526. it('throws exception if arguments are missing', function() {
  527. // TODO
  528. });
  529. });
  530. describe('permissions', function() {
  531. function getFileInfoWithPermission(webdavPerm, isFile) {
  532. var props = {
  533. 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT',
  534. 'd:getetag': '"559fcabd79a38"',
  535. 'd:getcontentlength': 250,
  536. 'oc:id': '00000051oc2d13a6a068',
  537. 'oc:fileid': '51',
  538. 'oc:permissions': webdavPerm,
  539. };
  540. if (isFile) {
  541. props['d:getcontenttype'] = 'text/plain';
  542. } else {
  543. props['d:resourcetype'] = '<d:collection/>';
  544. }
  545. var def = new $.Deferred();
  546. requestStub.reset();
  547. requestStub.returns(def);
  548. var responseXml = dav.Client.prototype.parseMultiStatus(
  549. '<?xml version="1.0" encoding="utf-8"?>' +
  550. '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
  551. makeResponseBlock(
  552. '/owncloud/remote.php/webdav/file.txt',
  553. props
  554. ) +
  555. '</d:multistatus>'
  556. );
  557. var promise = client.getFileInfo('file.txt');
  558. expect(requestStub.calledOnce).toEqual(true);
  559. def.resolve({
  560. status: 207,
  561. body: responseXml
  562. });
  563. return promise;
  564. }
  565. function testPermission(permission, isFile, expectedPermissions) {
  566. var promise = getFileInfoWithPermission(permission, isFile);
  567. promise.then(function(result) {
  568. expect(result.permissions).toEqual(expectedPermissions);
  569. });
  570. }
  571. function testMountType(permission, isFile, expectedMountType) {
  572. var promise = getFileInfoWithPermission(permission, isFile);
  573. promise.then(function(result) {
  574. expect(result.mountType).toEqual(expectedMountType);
  575. });
  576. }
  577. it('properly parses file permissions', function() {
  578. // permission, isFile, expectedPermissions
  579. var testCases = [
  580. ['', true, OC.PERMISSION_READ],
  581. ['C', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE],
  582. ['K', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE],
  583. ['W', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
  584. ['D', true, OC.PERMISSION_READ | OC.PERMISSION_DELETE],
  585. ['R', true, OC.PERMISSION_READ | OC.PERMISSION_SHARE],
  586. ['CKWDR', true, OC.PERMISSION_ALL]
  587. ];
  588. _.each(testCases, function(testCase) {
  589. return testPermission.apply(testCase);
  590. });
  591. });
  592. it('properly parses folder permissions', function() {
  593. var testCases = [
  594. ['', false, OC.PERMISSION_READ],
  595. ['C', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
  596. ['K', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
  597. ['W', false, OC.PERMISSION_READ | OC.PERMISSION_UPDATE],
  598. ['D', false, OC.PERMISSION_READ | OC.PERMISSION_DELETE],
  599. ['R', false, OC.PERMISSION_READ | OC.PERMISSION_SHARE],
  600. ['CKWDR', false, OC.PERMISSION_ALL]
  601. ];
  602. _.each(testCases, function(testCase) {
  603. return testPermission.apply(testCase);
  604. });
  605. });
  606. it('properly parses mount types', function() {
  607. var testCases = [
  608. ['CKWDR', false, null],
  609. ['M', false, 'external'],
  610. ['S', false, 'shared'],
  611. ['SM', false, 'shared']
  612. ];
  613. _.each(testCases, function(testCase) {
  614. return testMountType.apply(testCase);
  615. });
  616. });
  617. });
  618. describe('get file contents', function() {
  619. it('returns file contents', function() {
  620. var promise = client.getFileContents('path/to space/文件夹/One.txt');
  621. expect(requestStub.calledOnce).toEqual(true);
  622. expect(requestStub.lastCall.args[0]).toEqual('GET');
  623. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
  624. requestDeferred.resolve({
  625. status: 200,
  626. body: 'some contents'
  627. });
  628. promise.then(function(status, response) {
  629. expect(status).toEqual(200);
  630. expect(response).toEqual('some contents');
  631. });
  632. });
  633. it('rejects promise when an error occurred', function() {
  634. var promise = client.getFileContents('path/to space/文件夹/One.txt');
  635. respondAndCheckError(promise, 409);
  636. });
  637. it('throws exception if arguments are missing', function() {
  638. // TODO
  639. });
  640. });
  641. describe('put file contents', function() {
  642. it('sends PUT with file contents', function() {
  643. var promise = client.putFileContents(
  644. 'path/to space/文件夹/One.txt',
  645. 'some contents'
  646. );
  647. expect(requestStub.calledOnce).toEqual(true);
  648. expect(requestStub.lastCall.args[0]).toEqual('PUT');
  649. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
  650. expect(requestStub.lastCall.args[2]['If-None-Match']).toEqual('*');
  651. expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/plain;charset=utf-8');
  652. expect(requestStub.lastCall.args[3]).toEqual('some contents');
  653. respondAndCheckStatus(promise, 201);
  654. });
  655. it('sends PUT with file contents with headers matching options', function() {
  656. var promise = client.putFileContents(
  657. 'path/to space/文件夹/One.txt',
  658. 'some contents',
  659. {
  660. overwrite: false,
  661. contentType: 'text/markdown'
  662. }
  663. );
  664. expect(requestStub.calledOnce).toEqual(true);
  665. expect(requestStub.lastCall.args[0]).toEqual('PUT');
  666. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
  667. expect(requestStub.lastCall.args[2]['If-None-Match']).not.toBeDefined();
  668. expect(requestStub.lastCall.args[2]['Content-Type']).toEqual('text/markdown');
  669. expect(requestStub.lastCall.args[3]).toEqual('some contents');
  670. respondAndCheckStatus(promise, 201);
  671. });
  672. it('rejects promise when an error occurred', function() {
  673. var promise = client.putFileContents(
  674. 'path/to space/文件夹/One.txt',
  675. 'some contents'
  676. );
  677. respondAndCheckError(promise, 409);
  678. });
  679. it('throws exception if arguments are missing', function() {
  680. // TODO
  681. });
  682. });
  683. describe('create directory', function() {
  684. it('sends MKCOL with specified path', function() {
  685. var promise = client.createDirectory('path/to space/文件夹/new dir');
  686. expect(requestStub.calledOnce).toEqual(true);
  687. expect(requestStub.lastCall.args[0]).toEqual('MKCOL');
  688. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir');
  689. respondAndCheckStatus(promise, 201);
  690. });
  691. it('rejects promise when an error occurred', function() {
  692. var promise = client.createDirectory('path/to space/文件夹/new dir');
  693. respondAndCheckError(promise, 404);
  694. });
  695. it('throws exception if arguments are missing', function() {
  696. // TODO
  697. });
  698. });
  699. describe('deletion', function() {
  700. it('sends DELETE with specified path', function() {
  701. var promise = client.remove('path/to space/文件夹');
  702. expect(requestStub.calledOnce).toEqual(true);
  703. expect(requestStub.lastCall.args[0]).toEqual('DELETE');
  704. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  705. respondAndCheckStatus(promise, 201);
  706. });
  707. it('rejects promise when an error occurred', function() {
  708. var promise = client.remove('path/to space/文件夹');
  709. respondAndCheckError(promise, 404);
  710. });
  711. it('throws exception if arguments are missing', function() {
  712. // TODO
  713. });
  714. });
  715. describe('move', function() {
  716. it('sends MOVE with specified paths with fail on overwrite by default', function() {
  717. var promise = client.move(
  718. 'path/to space/文件夹',
  719. 'path/to space/anotherdir/文件夹'
  720. );
  721. expect(requestStub.calledOnce).toEqual(true);
  722. expect(requestStub.lastCall.args[0]).toEqual('MOVE');
  723. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  724. expect(requestStub.lastCall.args[2].Destination)
  725. .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
  726. expect(requestStub.lastCall.args[2].Overwrite)
  727. .toEqual('F');
  728. respondAndCheckStatus(promise, 201);
  729. });
  730. it('sends MOVE with silent overwrite mode when specified', function() {
  731. var promise = client.move(
  732. 'path/to space/文件夹',
  733. 'path/to space/anotherdir/文件夹',
  734. {allowOverwrite: true}
  735. );
  736. expect(requestStub.calledOnce).toEqual(true);
  737. expect(requestStub.lastCall.args[0]).toEqual('MOVE');
  738. expect(requestStub.lastCall.args[1]).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
  739. expect(requestStub.lastCall.args[2].Destination)
  740. .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
  741. expect(requestStub.lastCall.args[2].Overwrite)
  742. .not.toBeDefined();
  743. respondAndCheckStatus(promise, 201);
  744. });
  745. it('rejects promise when an error occurred', function() {
  746. var promise = client.move(
  747. 'path/to space/文件夹',
  748. 'path/to space/anotherdir/文件夹',
  749. {allowOverwrite: true}
  750. );
  751. respondAndCheckError(promise, 404);
  752. });
  753. it('throws exception if arguments are missing', function() {
  754. // TODO
  755. });
  756. });
  757. });