1 | process.env.NODE_TLS_REJECT_UNAUTHORIZED=0
|
2 | const Promise = require('bluebird');
|
3 | const oada = require('../build/index')
|
4 | const _ = require('lodash');
|
5 | var chai = require('chai');
|
6 | var chaiAsPromised = require("chai-as-promised");
|
7 | chai.use(chaiAsPromised);
|
8 | var expect = chai.expect;
|
9 | const {token, domain} = require('./config.js');
|
10 | const {tree, putResource, getConnections} = require('./utils.js');
|
11 |
|
12 | var connections;
|
13 | var resources = [];
|
14 |
|
15 | describe(`------------DELETE-----------------`, async function() {
|
16 | before(`Create connection types`, async function() {
|
17 | connections = await getConnections({
|
18 | domain,
|
19 | token
|
20 | })
|
21 | connections = Object.values(connections)
|
22 | })
|
23 |
|
24 | for (let i = 0; i < 4; i++) {
|
25 | describe(`Testing connection ${i+1}`, async function() {
|
26 |
|
27 | it(`Should error when neither 'url' nor 'path' are supplied`, async function() {
|
28 | console.log(`Cache: ${connections[i].cache ? true : false}; Websocket: ${connections[i].websocket ? true : false}`)
|
29 | await connections[i].resetCache()
|
30 | await connections[i].delete({path:'/bookmarks/test', tree})
|
31 | await putResource({'something': 'b'}, '/bookmarks/test')
|
32 |
|
33 | return expect(
|
34 | connections[i].delete({
|
35 | type: 'application/json'
|
36 | })
|
37 | ).to.be.rejectedWith(Error, 'Either path or url must be specified.')
|
38 | })
|
39 |
|
40 | it(`Shouldn't error when the 'Content-Type' header can be derived from the 'type' key`, async function() {
|
41 | await connections[i].resetCache()
|
42 | await connections[i].delete({path:'/bookmarks/test', tree})
|
43 | await putResource({'something': 'b'}, '/bookmarks/test')
|
44 | var response = await connections[i].delete({
|
45 | path: '/bookmarks/test',
|
46 | type: 'application/json'
|
47 | })
|
48 | expect(response.status).to.equal(204)
|
49 | })
|
50 |
|
51 | it(`Shouldn't error when 'Content-Type' header is specified.`, async function() {
|
52 | await connections[i].resetCache()
|
53 | await connections[i].delete({path:'/bookmarks/test', tree})
|
54 | await putResource({'something': 'b'}, '/bookmarks/test')
|
55 | var response = await connections[i].delete({
|
56 | path: '/bookmarks/test',
|
57 | headers: {'content-type': 'application/json'}
|
58 | })
|
59 | expect(response.status).to.equal(204)
|
60 | })
|
61 |
|
62 | it(`Should error when _type cannot be derived from the above tested sources`, async function() {
|
63 | await connections[i].resetCache()
|
64 | await connections[i].delete({path:'/bookmarks/test', tree})
|
65 | await putResource({'something': 'b'}, '/bookmarks/test')
|
66 | return expect(
|
67 | connections[i].delete({
|
68 | path: '/bookmarks/test',
|
69 | })
|
70 | ).to.be.rejectedWith(Error, `content-type header must be specified.`)
|
71 | })
|
72 |
|
73 | it(`Should produce a 403 error when using a content-type header for which your token does not have access to read/write`, async function() {
|
74 | this.timeout(4000);
|
75 | await connections[i].resetCache()
|
76 | await connections[i].delete({path:'/bookmarks/test', tree})
|
77 | await putResource({'something': 'b'}, '/bookmarks/test')
|
78 | return expect(
|
79 | connections[i].delete({
|
80 | path: '/bookmarks/test',
|
81 | headers: {'content-type': 'application/vnd.oada.foobar.1+json'},
|
82 | })
|
83 | ).to.be.rejectedWith(Error, `Request failed with status code 403`)
|
84 | })
|
85 |
|
86 | it(`Should allow us to delete only a resource and leave the link alone`, async function() {
|
87 | this.timeout(4000);
|
88 | await connections[i].resetCache()
|
89 | await connections[i].delete({path:'/bookmarks/test', tree})
|
90 | var result = await putResource({'something': 'b'}, '/bookmarks/test')
|
91 | var deleteResponse = await connections[i].delete({
|
92 | path: result.resource.headers['content-location'],
|
93 | headers: {'content-type': 'application/json'}
|
94 | })
|
95 | expect(deleteResponse.status).to.equal(204);
|
96 | var response = await connections[i].get({
|
97 | path: '/bookmarks/test'
|
98 | })
|
99 | expect(response.status).to.equal(200);
|
100 | expect(response.data).to.include.keys(['_id', '_rev'])
|
101 | expect(response.data).to.not.include.keys(['_meta', '_type', 'something'])
|
102 | })
|
103 |
|
104 | it(`Should allow us to delete only a link and leave the resource alone`, async function() {
|
105 | this.timeout(4000);
|
106 | await connections[i].resetCache()
|
107 | await connections[i].delete({path:'/bookmarks/test', tree})
|
108 | var result = await putResource({'something': 'b'}, '/bookmarks/test')
|
109 | var deleteResponse = await connections[i].delete({
|
110 | path: '/bookmarks/test',
|
111 | headers: {'content-type': 'application/json'}
|
112 | })
|
113 | expect(deleteResponse.status).to.equal(204);
|
114 | var response = await connections[i].get({
|
115 | path: result.resource.headers['content-location'],
|
116 | })
|
117 | expect(response.status).to.equal(200);
|
118 | })
|
119 |
|
120 | it(`Should handle a two deletes in series`, async function() {
|
121 | this.timeout(4000);
|
122 | await connections[i].resetCache()
|
123 | await connections[i].delete({path:'/bookmarks/test', tree})
|
124 | var result = await putResource({'something': 'b'}, '/bookmarks/test')
|
125 | var deleteOne = await connections[i].delete({
|
126 | path: '/bookmarks/test',
|
127 | headers: {'content-type': 'application/json'}
|
128 | })
|
129 | expect(deleteOne.status).to.equal(204)
|
130 | var deleteTwo = await connections[i].delete({
|
131 | path: '/bookmarks/test',
|
132 | headers: {'content-type': 'application/json'}
|
133 | })
|
134 | expect(deleteTwo.status).to.equal(204)
|
135 | })
|
136 |
|
137 | it(`Should handle concurrent deletes, ultimately deleting the target endpoint as intended`, async function() {
|
138 | this.timeout(4000);
|
139 | await connections[i].resetCache()
|
140 | await connections[i].delete({path:'/bookmarks/test', tree})
|
141 | var result = await putResource({'something': 'b'}, '/bookmarks/test')
|
142 | var deleteOne = connections[i].delete({
|
143 | path: '/bookmarks/test',
|
144 | headers: {'content-type': 'application/json'}
|
145 | })
|
146 | var deleteTwo = connections[i].delete({
|
147 | path: '/bookmarks/test',
|
148 | headers: {'content-type': 'application/json'}
|
149 | })
|
150 | var deleteThree = connections[i].delete({
|
151 | path: '/bookmarks/test',
|
152 | headers: {'content-type': 'application/json'}
|
153 | })
|
154 | await Promise.join(deleteOne, deleteTwo, deleteThree, async function(deleteOne, deleteTwo, deleteThree) {
|
155 | expect(deleteOne.status).to.equal(204)
|
156 | expect(deleteTwo.status).to.equal(204)
|
157 | expect(deleteThree.status).to.equal(204)
|
158 | return expect(connections[i].get({
|
159 | path: '/bookmarks/test',
|
160 | })).to.be.rejectedWith(Error, 'Request failed with status code 404');
|
161 | })
|
162 | })
|
163 |
|
164 | it(`Should produce a 412 if the 'If-Match' precondition fails`, async function() {
|
165 | this.timeout(4000);
|
166 | await connections[i].resetCache();
|
167 | await connections[i].delete({path:'/bookmarks/test', tree})
|
168 | var result = await putResource({foo: 'bar'}, '/bookmarks/test');
|
169 | return expect(connections[i].delete({
|
170 | path: '/bookmarks/test',
|
171 | headers: {
|
172 | 'If-Match': '2-foobar',
|
173 | 'content-type': 'application/json'
|
174 | }
|
175 | })).to.be.rejectedWith(Error, 'Request failed with status code 412')
|
176 | })
|
177 |
|
178 | it(`Should succeed in deleting a link if a valid 'If-Match' header which matches the current resource's _rev is supplied`, async function() {
|
179 | var result = await putResource({something: 'else'}, '/bookmarks/test');
|
180 | var response = await connections[i].delete({
|
181 | path: '/bookmarks/test',
|
182 | headers: {
|
183 | 'if-match': result.link.headers['x-oada-rev'],
|
184 | 'content-type': 'application/json'
|
185 | }
|
186 | })
|
187 | expect(response.status).to.equal(204)
|
188 | })
|
189 |
|
190 | it(`Should succeed in deleting a resource if a valid 'If-Match' header which matches the current resource's _rev is supplied`, async function() {
|
191 | var result = await putResource({foo: 'bar'}, '/bookmarks/test');
|
192 | var response = await connections[i].delete({
|
193 | path: result.resource.headers['content-location'],
|
194 | headers: {
|
195 | 'if-match': result.resource.headers['x-oada-rev'],
|
196 | 'content-type': 'application/json'
|
197 | }
|
198 | })
|
199 | expect(response.status).to.equal(204)
|
200 | })
|
201 |
|
202 | it(`Should delete an entire tree of links and resources when the 'tree' option is supplied`, async function() {
|
203 | var test = await putResource({foo: 'bar'}, '/bookmarks/test');
|
204 | var aaa = await putResource({foo: 'bar'}, '/bookmarks/test/aaa');
|
205 | var bbb = await putResource({foo: 'bar'}, '/bookmarks/test/aaa/bbb');
|
206 | var ccc = await putResource({foo: 'bar'}, '/bookmarks/test/aaa/bbb/index-one/ccc');
|
207 | var response = await connections[i].delete({
|
208 | path: '/bookmarks/test',
|
209 | tree
|
210 | })
|
211 | expect(response.status).to.equal(204)
|
212 | return Promise.each([
|
213 | test.resource.headers['content-location'],
|
214 | aaa.link.headers['content-location'],
|
215 | aaa.resource.headers['content-location'],
|
216 | bbb.link.headers['content-location'],
|
217 | bbb.resource.headers['content-location'],
|
218 | ccc.link.headers['content-location'],
|
219 | ccc.resource.headers['content-location'],
|
220 | ], (path) => {
|
221 | if (/^\/resources/.test(path)) {
|
222 | return expect(connections[i].get({path})).to.be.rejectedWith(Error, 'Request failed with status code 403');
|
223 | } else {
|
224 | return expect(connections[i].get({path})).to.be.rejectedWith(Error, 'Request failedf with status code 404');
|
225 | }
|
226 | })
|
227 | })
|
228 |
|
229 | it(`Should gracefully handle a sequence of PUT, DELETE, PUT executed in series`, async function() {
|
230 | var putOne = await connections[i].put({
|
231 | path: '/bookmarks/test/aaa',
|
232 | tree,
|
233 | data: {putOne: 'putOne'}
|
234 | })
|
235 | expect(putOne.status).to.equal(204)
|
236 |
|
237 | var putTwo = await connections[i].put({
|
238 | path: '/bookmarks/test/aaa/bbb',
|
239 | tree,
|
240 | data: {putTwo: 'putTwo'}
|
241 | })
|
242 | expect(putTwo.status).to.equal(204)
|
243 |
|
244 | var deleteOne = await connections[i].delete({
|
245 | path: '/bookmarks/test',
|
246 | tree,
|
247 | })
|
248 | expect(deleteOne.status).to.equal(204)
|
249 |
|
250 | var putThree = await connections[i].put({
|
251 | path: '/bookmarks/test/aaa/bbb/index-one/ccc',
|
252 | tree,
|
253 | data: {putThree: 'putThree'}
|
254 | })
|
255 | expect(putThree.status).to.equal(204)
|
256 |
|
257 | var getOne = await connections[i].get({
|
258 | path: '/bookmarks/test',
|
259 | tree
|
260 | })
|
261 | expect(getOne.status).to.equal(200)
|
262 | expect(getOne.data.aaa).to.not.include.key('putOne')
|
263 | expect(getOne.data.aaa.bbb).to.not.include.key('putTwo')
|
264 | expect(getOne.data.aaa.bbb['index-one'].ccc).to.include.key('putThree')
|
265 | })
|
266 |
|
267 | it(`Should gracefully handle a concurrent sequence of PUT, DELETE, PUT`, async function() {
|
268 | var putOne = connections[i].put({
|
269 | path: '/bookmarks/test/aaa',
|
270 | tree,
|
271 | data: {putOne: 'putOne'}
|
272 | })
|
273 | var putTwo = connections[i].put({
|
274 | path: '/bookmarks/test/aaa/bbb',
|
275 | tree,
|
276 | data: {putTwo: 'putTwo'}
|
277 | })
|
278 | var deleteOne = connections[i].delete({
|
279 | path: '/bookmarks/test/aaa/bbb/index-one/ccc',
|
280 | tree,
|
281 | })
|
282 | var putThree = connections[i].put({
|
283 | path: '/bookmarks/test/aaa/bbb/index-one/ccc',
|
284 | tree,
|
285 | data: {putThree: 'putThree'}
|
286 | })
|
287 | var result = Promise.join(
|
288 | putOne,
|
289 | putTwo,
|
290 | deleteOne,
|
291 | putThree,
|
292 | async function(putOne,putTwo,deleteOne,putThree) {
|
293 | expect(putOne.status).to.equal(204)
|
294 | expect(putTwo.status).to.equal(204)
|
295 | expect(deleteOne.status).to.equal(204)
|
296 | expect(putThree.status).to.equal(204)
|
297 | }
|
298 | )
|
299 | })
|
300 |
|
301 | it('Now clean up', async function() {
|
302 | await connections[i].resetCache();
|
303 | await connections[i].delete({path:'/bookmarks/test', tree})
|
304 | })
|
305 | })
|
306 | }
|
307 | })
|