oc-backbone-webdavSpec.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /**
  2. * ownCloud
  3. *
  4. * @author Vincent Petry
  5. * @copyright 2014 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('Backbone Webdav extension', function() {
  23. var davClientRequestStub;
  24. var davClientPropPatchStub;
  25. var davClientPropFindStub;
  26. var deferredRequest;
  27. beforeEach(function() {
  28. deferredRequest = $.Deferred();
  29. davClientRequestStub = sinon.stub(dav.Client.prototype, 'request');
  30. davClientPropPatchStub = sinon.stub(dav.Client.prototype, 'propPatch');
  31. davClientPropFindStub = sinon.stub(dav.Client.prototype, 'propFind');
  32. davClientRequestStub.returns(deferredRequest.promise());
  33. davClientPropPatchStub.returns(deferredRequest.promise());
  34. davClientPropFindStub.returns(deferredRequest.promise());
  35. });
  36. afterEach(function() {
  37. davClientRequestStub.restore();
  38. davClientPropPatchStub.restore();
  39. davClientPropFindStub.restore();
  40. });
  41. describe('collections', function() {
  42. var TestModel;
  43. var TestCollection;
  44. beforeEach(function() {
  45. TestModel = OC.Backbone.Model.extend({
  46. sync: OC.Backbone.davSync,
  47. davProperties: {
  48. 'firstName': '{http://owncloud.org/ns}first-name',
  49. 'lastName': '{http://owncloud.org/ns}last-name',
  50. 'age': '{http://owncloud.org/ns}age',
  51. 'married': '{http://owncloud.org/ns}married'
  52. },
  53. parse: function(data) {
  54. return {
  55. id: data.id,
  56. firstName: data.firstName,
  57. lastName: data.lastName,
  58. age: parseInt(data.age, 10),
  59. married: data.married === 'true' || data.married === true
  60. };
  61. }
  62. });
  63. TestCollection = OC.Backbone.Collection.extend({
  64. sync: OC.Backbone.davSync,
  65. model: TestModel,
  66. url: 'http://example.com/owncloud/remote.php/test/'
  67. });
  68. });
  69. it('makes a POST request to create model into collection', function() {
  70. var collection = new TestCollection();
  71. var model = collection.create({
  72. firstName: 'Hello',
  73. lastName: 'World'
  74. });
  75. expect(davClientRequestStub.calledOnce).toEqual(true);
  76. expect(davClientRequestStub.getCall(0).args[0])
  77. .toEqual('POST');
  78. expect(davClientRequestStub.getCall(0).args[1])
  79. .toEqual('http://example.com/owncloud/remote.php/test/');
  80. expect(davClientRequestStub.getCall(0).args[2]['Content-Type'])
  81. .toEqual('application/json');
  82. expect(davClientRequestStub.getCall(0).args[2]['X-Requested-With'])
  83. .toEqual('XMLHttpRequest');
  84. expect(davClientRequestStub.getCall(0).args[3])
  85. .toEqual(JSON.stringify({
  86. 'firstName': 'Hello',
  87. 'lastName': 'World'
  88. }));
  89. var responseHeaderStub = sinon.stub()
  90. .withArgs('Content-Location')
  91. .returns('http://example.com/owncloud/remote.php/test/123');
  92. deferredRequest.resolve({
  93. status: 201,
  94. body: '',
  95. xhr: {
  96. getResponseHeader: responseHeaderStub
  97. }
  98. });
  99. expect(model.id).toEqual('123');
  100. });
  101. it('uses PROPFIND to retrieve collection', function() {
  102. var successStub = sinon.stub();
  103. var errorStub = sinon.stub();
  104. var collection = new TestCollection();
  105. collection.fetch({
  106. success: successStub,
  107. error: errorStub
  108. });
  109. expect(davClientPropFindStub.calledOnce).toEqual(true);
  110. expect(davClientPropFindStub.getCall(0).args[0])
  111. .toEqual('http://example.com/owncloud/remote.php/test/');
  112. expect(davClientPropFindStub.getCall(0).args[1])
  113. .toEqual([
  114. '{http://owncloud.org/ns}first-name',
  115. '{http://owncloud.org/ns}last-name',
  116. '{http://owncloud.org/ns}age',
  117. '{http://owncloud.org/ns}married'
  118. ]);
  119. expect(davClientPropFindStub.getCall(0).args[2])
  120. .toEqual(1);
  121. expect(davClientPropFindStub.getCall(0).args[3]['X-Requested-With'])
  122. .toEqual('XMLHttpRequest');
  123. deferredRequest.resolve({
  124. status: 207,
  125. body: [
  126. // root element
  127. {
  128. href: 'http://example.org/owncloud/remote.php/test/',
  129. propStat: []
  130. },
  131. // first model
  132. {
  133. href: 'http://example.org/owncloud/remote.php/test/123',
  134. propStat: [{
  135. status: 'HTTP/1.1 200 OK',
  136. properties: {
  137. '{http://owncloud.org/ns}first-name': 'Hello',
  138. '{http://owncloud.org/ns}last-name': 'World'
  139. }
  140. }]
  141. },
  142. // second model
  143. {
  144. href: 'http://example.org/owncloud/remote.php/test/456',
  145. propStat: [{
  146. status: 'HTTP/1.1 200 OK',
  147. properties: {
  148. '{http://owncloud.org/ns}first-name': 'Test',
  149. '{http://owncloud.org/ns}last-name': 'Person'
  150. }
  151. }]
  152. }
  153. ]
  154. });
  155. expect(collection.length).toEqual(2);
  156. var model = collection.get('123');
  157. expect(model.id).toEqual('123');
  158. expect(model.get('firstName')).toEqual('Hello');
  159. expect(model.get('lastName')).toEqual('World');
  160. model = collection.get('456');
  161. expect(model.id).toEqual('456');
  162. expect(model.get('firstName')).toEqual('Test');
  163. expect(model.get('lastName')).toEqual('Person');
  164. expect(successStub.calledOnce).toEqual(true);
  165. expect(errorStub.notCalled).toEqual(true);
  166. });
  167. function testMethodError(doCall) {
  168. var successStub = sinon.stub();
  169. var errorStub = sinon.stub();
  170. doCall(successStub, errorStub);
  171. deferredRequest.resolve({
  172. status: 404,
  173. body: ''
  174. });
  175. expect(successStub.notCalled).toEqual(true);
  176. expect(errorStub.calledOnce).toEqual(true);
  177. }
  178. it('calls error handler if error status in PROPFIND response', function() {
  179. testMethodError(function(success, error) {
  180. var collection = new TestCollection();
  181. collection.fetch({
  182. success: success,
  183. error: error
  184. });
  185. });
  186. });
  187. it('calls error handler if error status in POST response', function() {
  188. testMethodError(function(success, error) {
  189. var collection = new TestCollection();
  190. collection.create({
  191. firstName: 'Hello',
  192. lastName: 'World'
  193. }, {
  194. success: success,
  195. error: error
  196. });
  197. });
  198. });
  199. });
  200. describe('models', function() {
  201. var TestModel;
  202. beforeEach(function() {
  203. TestModel = OC.Backbone.Model.extend({
  204. sync: OC.Backbone.davSync,
  205. davProperties: {
  206. 'firstName': '{http://owncloud.org/ns}first-name',
  207. 'lastName': '{http://owncloud.org/ns}last-name',
  208. 'age': '{http://owncloud.org/ns}age', // int
  209. 'married': '{http://owncloud.org/ns}married', // bool
  210. },
  211. url: function() {
  212. return 'http://example.com/owncloud/remote.php/test/' + this.id;
  213. },
  214. parse: function(data) {
  215. return {
  216. id: data.id,
  217. firstName: data.firstName,
  218. lastName: data.lastName,
  219. age: parseInt(data.age, 10),
  220. married: data.married === 'true' || data.married === true
  221. };
  222. }
  223. });
  224. });
  225. it('makes a PROPPATCH request to update model', function() {
  226. var model = new TestModel({
  227. id: '123',
  228. firstName: 'Hello',
  229. lastName: 'World',
  230. age: 32,
  231. married: false
  232. });
  233. model.save({
  234. firstName: 'Hey',
  235. age: 33,
  236. married: true
  237. });
  238. expect(davClientPropPatchStub.calledOnce).toEqual(true);
  239. expect(davClientPropPatchStub.getCall(0).args[0])
  240. .toEqual('http://example.com/owncloud/remote.php/test/123');
  241. expect(davClientPropPatchStub.getCall(0).args[1])
  242. .toEqual({
  243. '{http://owncloud.org/ns}first-name': 'Hey',
  244. '{http://owncloud.org/ns}age': '33',
  245. '{http://owncloud.org/ns}married': 'true'
  246. });
  247. expect(davClientPropPatchStub.getCall(0).args[2]['X-Requested-With'])
  248. .toEqual('XMLHttpRequest');
  249. deferredRequest.resolve({
  250. status: 201,
  251. body: ''
  252. });
  253. expect(model.id).toEqual('123');
  254. expect(model.get('firstName')).toEqual('Hey');
  255. expect(model.get('age')).toEqual(33);
  256. expect(model.get('married')).toEqual(true);
  257. });
  258. it('uses PROPFIND to fetch single model', function() {
  259. var model = new TestModel({
  260. id: '123'
  261. });
  262. model.fetch();
  263. expect(davClientPropFindStub.calledOnce).toEqual(true);
  264. expect(davClientPropFindStub.getCall(0).args[0])
  265. .toEqual('http://example.com/owncloud/remote.php/test/123');
  266. expect(davClientPropFindStub.getCall(0).args[1])
  267. .toEqual([
  268. '{http://owncloud.org/ns}first-name',
  269. '{http://owncloud.org/ns}last-name',
  270. '{http://owncloud.org/ns}age',
  271. '{http://owncloud.org/ns}married'
  272. ]);
  273. expect(davClientPropFindStub.getCall(0).args[2])
  274. .toEqual(0);
  275. expect(davClientPropFindStub.getCall(0).args[3]['X-Requested-With'])
  276. .toEqual('XMLHttpRequest');
  277. deferredRequest.resolve({
  278. status: 207,
  279. body: {
  280. href: 'http://example.org/owncloud/remote.php/test/123',
  281. propStat: [{
  282. status: 'HTTP/1.1 200 OK',
  283. properties: {
  284. '{http://owncloud.org/ns}first-name': 'Hello',
  285. '{http://owncloud.org/ns}last-name': 'World',
  286. '{http://owncloud.org/ns}age': '35',
  287. '{http://owncloud.org/ns}married': 'true'
  288. }
  289. }]
  290. }
  291. });
  292. expect(model.id).toEqual('123');
  293. expect(model.get('firstName')).toEqual('Hello');
  294. expect(model.get('lastName')).toEqual('World');
  295. expect(model.get('age')).toEqual(35);
  296. expect(model.get('married')).toEqual(true);
  297. });
  298. it('makes a DELETE request to destroy model', function() {
  299. var model = new TestModel({
  300. id: '123',
  301. firstName: 'Hello',
  302. lastName: 'World'
  303. });
  304. model.destroy();
  305. expect(davClientRequestStub.calledOnce).toEqual(true);
  306. expect(davClientRequestStub.getCall(0).args[0])
  307. .toEqual('DELETE');
  308. expect(davClientRequestStub.getCall(0).args[1])
  309. .toEqual('http://example.com/owncloud/remote.php/test/123');
  310. expect(davClientRequestStub.getCall(0).args[2]['X-Requested-With'])
  311. .toEqual('XMLHttpRequest');
  312. expect(davClientRequestStub.getCall(0).args[3])
  313. .toBeFalsy();
  314. deferredRequest.resolve({
  315. status: 200,
  316. body: ''
  317. });
  318. });
  319. function testMethodError(doCall) {
  320. var successStub = sinon.stub();
  321. var errorStub = sinon.stub();
  322. doCall(successStub, errorStub);
  323. deferredRequest.resolve({
  324. status: 404,
  325. body: ''
  326. });
  327. expect(successStub.notCalled).toEqual(true);
  328. expect(errorStub.calledOnce).toEqual(true);
  329. }
  330. it('calls error handler if error status in PROPFIND response', function() {
  331. testMethodError(function(success, error) {
  332. var model = new TestModel();
  333. model.fetch({
  334. success: success,
  335. error: error
  336. });
  337. });
  338. });
  339. it('calls error handler if error status in PROPPATCH response', function() {
  340. testMethodError(function(success, error) {
  341. var model = new TestModel();
  342. model.save({
  343. firstName: 'Hey'
  344. }, {
  345. success: success,
  346. error: error
  347. });
  348. });
  349. });
  350. });
  351. });