UNPKG

16.6 kBJavaScriptView Raw
1process.env.NODE_TLS_REJECT_UNAUTHORIZED=0
2import Promise from 'bluebird'
3import oada from '../src/index'
4const pretty = require('prettyjson');
5const _ = require('lodash');
6const {expect} = require('chai');
7const {token, domain} = require('./config.js');
8const {tree, putResource, getConnections} = require('./utils.js');
9
10var connections;
11var expects = {};
12
13async function setupWatch(connOne, tre, payload) {
14 // create the endpoint to watch before watching
15 var putOne = await connOne.put({
16 path: '/bookmarks/test',
17 data: {},
18 tree: tre || tree,
19 })
20 expect(putOne.status).to.equal(204);
21 //watch the endpoint
22 var getOne = await connOne.get({
23 path: '/bookmarks/test',
24 tree: tre || tree,
25 watch: {
26 payload: payload || {someExtra: 'payload'},
27 /*
28 func: (pay) => {
29 console.log(pay.response.headers['x-request-id'])
30 expects[pay.response.headers['x-request-id']].forEach((exp) => {
31 exp()
32 })
33 }*/
34 }
35 })
36 expect(getOne.status).to.equal(200);
37 return {putOne, getOne}
38}
39
40describe(`~~~~~~~~~~~WATCH~~~~~~~~~~~~~~`, function() {
41 var connOne;
42 var connTwo;
43 before(`Create connection types`, async function() {
44 connections = await getConnections({domain, token})
45// connections = Object.values(connections)
46 connOne = connections['cYesWYes'];
47 connTwo = connections['cNoWYes'];
48 })
49
50 it(`Watches should automatically update the cache when a single resource is created (single connection)`, async function() {
51 this.timeout(8000);
52 await connOne.delete({path:'/bookmarks/test', tree})
53 await connOne.resetCache();
54 var result = await setupWatch(connOne);
55 expect(result.getOne.status).to.equal(200)
56 // Execute a deep PUT below the watched resource
57 var putTwo = await connTwo.put({
58 path: '/bookmarks/test/aaa',
59 tree,
60 data: { testAAA: 123 },
61 })
62 expect(putTwo.status).to.equal(204)
63 await Promise.delay(1000)
64 // Retreive the data to determine that its been cached
65 var getTwo = await connOne.get({
66 path: '/bookmarks/test',
67 tree,
68 })
69 // Compare the rev of the parent at /bookmarks/test
70 var getOneRev = parseInt(result.getOne.headers['x-oada-rev'].split('-')[0]);
71 var getTwoRev = parseInt(getTwo.headers['x-oada-rev'].split('-')[0]);
72
73 expect(getOneRev < getTwoRev).to.equal(true)
74 expect(getTwo.data.aaa).to.include.keys(['_id','_rev', 'testAAA'])
75 })
76
77 it(`Watches should automatically update the cache when a deep endpoint creates many resources (single connection)`, async function() {
78 this.timeout(8000);
79 await connOne.delete({path:'/bookmarks/test', tree})
80 await connOne.resetCache();
81 var result = await setupWatch(connOne);
82 // Execute a deep PUT below the watched resource
83 var putTwo = await connOne.put({
84 path: '/bookmarks/test/aaa/bbb/index-one/ccc/index-two/ddd/index-three/eee',
85 tree,
86 data: { testAAA: 123 },
87 })
88 expect(putTwo.status).to.equal(204)
89 // Retreive the data to determine that its been cached
90 var getTwo = await connOne.get({
91 path: '/bookmarks/test',
92 tree,
93 })
94 var getOneRev = parseInt(result.getOne.headers['x-oada-rev'].split('-')[0]);
95 var getTwoRev = parseInt(getTwo.headers['x-oada-rev'].split('-')[0]);
96 expect(getOneRev < getTwoRev).to.equal(true)
97
98 var getThree = await connOne.get({
99 path: '/bookmarks/test',
100 tree,
101 })
102 expect(getThree.data.aaa.bbb['index-one'].ccc['index-two'].ddd['index-three'].eee).to.include.keys(['_id','_rev', 'testAAA'])
103 })
104
105 it(`Should receive the watch changes from several concurrent PUTs to the server via another connection.`, async function() {
106 this.timeout(20000);
107 await connOne.delete({path:'/bookmarks/test', tree})
108 await connOne.resetCache();
109
110 // If we do not include the _rev on the deepest resource endpoint, we won't receive
111 // the change notifications on our watch.
112 var newTree = _.cloneDeep(tree)
113 newTree.bookmarks.test.aaa.bbb['index-one']['*']['index-two']['*']['index-three']['*']._rev = '0-0';
114 var result = await setupWatch(connOne, newTree);
115 var putOne = connTwo.put({
116 path: '/bookmarks/test/aaa/bbb/index-one/ccc/index-two/ddd/index-three/eee',
117 tree: newTree,
118 data: {testOne: 123},
119 })
120 var putTwo = connTwo.put({
121 path: '/bookmarks/test/aaa/bbb/index-one/ccc/index-two/fff/index-three/eee',
122 tree: newTree,
123 data: {testTwo: 123},
124 })
125 var putThree = connTwo.put({
126 path: '/bookmarks/test/aaa/bbb/index-one/ggg/index-two/ddd/index-three/eee',
127 tree: newTree,
128 data: {testThree: 123},
129 })
130 var putFour = connTwo.put({
131 path: '/bookmarks/test/aaa/bbb/index-one/ccc/index-two/ddd/index-three/eee',
132 tree: newTree,
133 data: {testFour: 123},
134 })
135 var join = await Promise.join(putOne,putTwo,putThree, putFour, async function(putOne,putTwo,putThree,putFour) {
136 // Now give the watch time to push changes down to the cache
137 await Promise.delay(8000);
138 var response = await connOne.get({
139 path: '/bookmarks/test',
140 tree: newTree
141 })
142
143 var putOneRev = parseInt(putOne.headers['x-oada-rev'].split('-')[0]);
144 var putTwoRev = parseInt(putTwo.headers['x-oada-rev'].split('-')[0]);
145 var putThreeRev = parseInt(putThree.headers['x-oada-rev'].split('-')[0]);
146 var putFourRev = parseInt(putFour.headers['x-oada-rev'].split('-')[0]);
147 var maxRev = Math.max(putOneRev, putTwoRev, putThreeRev, putFourRev);
148 var minRev = Math.min(putOneRev, putTwoRev, putThreeRev, putFourRev);
149
150 var getOneRev = parseInt(result.getOne.headers['x-oada-rev'].split('-')[0]);
151 var getTwoRev = parseInt(response.headers['x-oada-rev'].split('-')[0]);
152 var responsePutTwo = parseInt(response.data.aaa.bbb['index-one'].ccc['index-two'].fff['index-three'].eee._rev.split('-')[0]);
153 var responsePutThree = parseInt(response.data.aaa.bbb['index-one'].ggg['index-two'].ddd['index-three'].eee._rev.split('-')[0]);
154 var responseDERev = parseInt(response.data.aaa.bbb['index-one'].ccc['index-two'].ddd['index-three'].eee._rev.split('-')[0]);
155 var maxDERev = Math.max(putOneRev, putFourRev);
156
157 expect(putTwoRev).to.equal(responsePutTwo)
158 expect(putThreeRev).to.equal(responsePutThree)
159 expect(responseDERev).to.equal(maxDERev)
160 expect(getTwoRev).to.equal(parseInt(response.data._rev.split('-')[0]));
161
162 expect(getOneRev < getTwoRev).to.equal(true)
163 expect(getOneRev < maxRev).to.equal(true)
164 expect(getOneRev < minRev).to.equal(true)
165
166 expect(putOne.status).to.equal(204)
167 expect(putTwo.status).to.equal(204)
168 expect(putThree.status).to.equal(204)
169 expect(response.status).to.equal(200)
170 expect(response.status).to.equal(200)
171 expect(response.headers).to.include.keys(['content-location', 'x-oada-rev'])
172 expect(response.data).to.include.keys(['_id', '_rev', '_type', 'aaa'])
173 expect(response.data.aaa).to.include.keys(['_id', '_rev', 'bbb', '_type'])
174 expect(response.data.aaa.bbb).to.include.keys(['_id', '_rev', 'index-one', '_type'])
175 expect(response.data.aaa.bbb['index-one']).to.include.keys(['ccc', 'ggg'])
176 expect(response.data.aaa.bbb['index-one'].ccc).to.include.keys(['_id', '_rev', '_type', 'index-two'])
177 expect(response.data.aaa.bbb['index-one'].ggg).to.include.keys(['_id', '_rev', '_type', 'index-two'])
178 expect(response.data.aaa.bbb['index-one'].ccc['index-two']).to.include.keys(['ddd', 'fff'])
179 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].ddd).to.include.keys(['_id', '_rev', '_type', 'index-three'])
180 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].fff).to.include.keys(['_id', '_rev', '_type', 'index-three'])
181 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].ddd['index-three'].eee).to.include.keys(['_id', '_rev', '_type', 'testOne', 'testFour'])
182 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].fff['index-three'].eee).to.include.keys(['_id', '_rev', '_type', 'testTwo'])
183 expect(response.data.aaa.bbb['index-one'].ggg['index-two']).to.include.keys(['ddd'])
184 expect(response.data.aaa.bbb['index-one'].ggg['index-two'].ddd).to.include.keys(['_id', '_rev', '_type', 'index-three'])
185 expect(response.data.aaa.bbb['index-one'].ggg['index-two'].ddd['index-three'].eee).to.include.keys(['_id', '_rev', '_type', 'testThree'])
186 expect(response.cached).to.equal(true)
187 })
188 })
189
190 it(`Should send a change feed when "offline" changes are made before a watch is set. This change feed should bring the cache up to date.`, async function() {
191 this.timeout(15000);
192 await connOne.delete({path:'/bookmarks/test', tree})
193 await connOne.resetCache();
194
195 var newTree = _.cloneDeep(tree)
196 newTree.bookmarks.test.aaa.bbb['index-one']['*']['index-two']['*']['index-three']['*']._rev = '0-0';
197 // First, get the resource into the cache
198 var putOne = await connOne.put({
199 path: '/bookmarks/test/aaa/bbb/index-one/ccc/index-two/ddd/index-three/eee',
200 tree: newTree,
201 data: {testOne: 123},
202 })
203 var putOneRev = parseInt(putOne.headers['x-oada-rev'].split('-')[0]);
204 //Next, create several changes over a second connection
205 var putTwo = connTwo.put({
206 path: '/bookmarks/test/aaa/bbb/index-one/ccc/index-two/fff/index-three/eee',
207 tree: newTree,
208 data: {testTwo: 123},
209 })
210 var putThree = connTwo.put({
211 path: '/bookmarks/test/aaa/bbb/index-one/ggg/index-two/ddd/index-three/eee',
212 tree: newTree,
213 data: {testThree: 123},
214 })
215 var putFour = connTwo.put({
216 path: '/bookmarks/test/aaa/bbb/index-one/ccc/index-two/ddd/index-three/eee',
217 tree: newTree,
218 data: {testFour: 123},
219 })
220 var join = await Promise.join(putOne,putTwo,putThree, putFour, async function(putOne,putTwo,putThree,putFour) {
221
222 // Now, after putting a bunch of documents, setup the watch. And wait for the changes to roll in.
223 var result = await setupWatch(connOne, newTree);
224 await Promise.delay(10000)
225 var response = await connOne.get({
226 path: '/bookmarks/test',
227 tree: newTree
228 })
229
230 var putOneRev = parseInt(putOne.headers['x-oada-rev'].split('-')[0]);
231 var putTwoRev = parseInt(putTwo.headers['x-oada-rev'].split('-')[0]);
232 var putThreeRev = parseInt(putThree.headers['x-oada-rev'].split('-')[0]);
233 var putFourRev = parseInt(putFour.headers['x-oada-rev'].split('-')[0]);
234 var maxRev = Math.max(putOneRev, putTwoRev, putThreeRev, putFourRev);
235 var minRev = Math.min(putOneRev, putTwoRev, putThreeRev, putFourRev);
236
237 var getOneRev = parseInt(result.getOne.headers['x-oada-rev'].split('-')[0]);
238 var getTwoRev = parseInt(response.headers['x-oada-rev'].split('-')[0]);
239 var responsePutTwo = parseInt(response.data.aaa.bbb['index-one'].ccc['index-two'].fff['index-three'].eee._rev.split('-')[0]);
240 var responsePutThree = parseInt(response.data.aaa.bbb['index-one'].ggg['index-two'].ddd['index-three'].eee._rev.split('-')[0]);
241 var responsePutFour = parseInt(response.data.aaa.bbb['index-one'].ccc['index-two'].ddd['index-three'].eee._rev.split('-')[0]);
242 var responseDERev = parseInt(response.data.aaa.bbb['index-one'].ccc['index-two'].ddd['index-three'].eee._rev.split('-')[0]);
243 var maxDERev = Math.max(putOneRev, putFourRev);
244
245 expect(putTwoRev).to.equal(responsePutTwo)
246 expect(putThreeRev).to.equal(responsePutThree)
247 expect(responseDERev).to.equal(maxDERev)
248 expect(getTwoRev).to.equal(parseInt(response.data._rev.split('-')[0]));
249
250 expect(getOneRev).to.equal(getTwoRev)
251 expect(getOneRev > maxRev).to.equal(true)
252 expect(getOneRev > minRev).to.equal(true)
253
254 expect(putOne.status).to.equal(204)
255 expect(putTwo.status).to.equal(204)
256 expect(putThree.status).to.equal(204)
257 expect(response.status).to.equal(200)
258 expect(response.status).to.equal(200)
259 expect(response.headers).to.include.keys(['content-location', 'x-oada-rev'])
260 expect(response.data).to.include.keys(['_id', '_rev', '_type', 'aaa'])
261 expect(response.data.aaa).to.include.keys(['_id', '_rev', 'bbb', '_type'])
262 expect(response.data.aaa.bbb).to.include.keys(['_id', '_rev', 'index-one', '_type'])
263 expect(response.data.aaa.bbb['index-one']).to.include.keys(['ccc', 'ggg'])
264 expect(response.data.aaa.bbb['index-one'].ccc).to.include.keys(['_id', '_rev', '_type', 'index-two'])
265 expect(response.data.aaa.bbb['index-one'].ggg).to.include.keys(['_id', '_rev', '_type', 'index-two'])
266 expect(response.data.aaa.bbb['index-one'].ccc['index-two']).to.include.keys(['ddd', 'fff'])
267 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].ddd).to.include.keys(['_id', '_rev', '_type', 'index-three'])
268 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].fff).to.include.keys(['_id', '_rev', '_type', 'index-three'])
269 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].ddd['index-three'].eee).to.include.keys(['_id', '_rev', '_type', 'testOne', 'testFour'])
270 expect(response.data.aaa.bbb['index-one'].ccc['index-two'].fff['index-three'].eee).to.include.keys(['_id', '_rev', '_type', 'testTwo'])
271 expect(response.data.aaa.bbb['index-one'].ggg['index-two']).to.include.keys(['ddd'])
272 expect(response.data.aaa.bbb['index-one'].ggg['index-two'].ddd).to.include.keys(['_id', '_rev', '_type', 'index-three'])
273 expect(response.data.aaa.bbb['index-one'].ggg['index-two'].ddd['index-three'].eee).to.include.keys(['_id', '_rev', '_type', 'testThree'])
274 expect(response.cached).to.equal(true)
275 })
276 await connOne.delete({path:'/bookmarks/test', tree})
277 await connOne.resetCache();
278 })
279
280 it(`Should receive watches from 10 independent connections`, async function() {
281 this.timeout(20000);
282 var newTree = _.cloneDeep(tree)
283 newTree.bookmarks.test.aaa.bbb['index-one']['*']['index-two']['*']['index-three']['*']._rev = '0-0';
284
285 var connection = await oada.connect({
286 domain,
287 token,
288 })
289
290 await connection.put({
291 path: '/bookmarks/test',
292 data: {sometest: i},
293 type: 'application/json'
294 })
295
296 var response = await connection.get({
297 path: '/bookmarks/test',
298 watch: {
299 payload: {someExtra: 'payload'},
300 }
301 })
302 expect(response.status).to.equal(200)
303
304 // Create 10 connections
305 var testConnections = [];
306 for (var i = 0; i < 10; i++) {
307 testConnections.push(await oada.connect({
308 domain,
309 token,
310 cache: {name: 'connection'+i.toString()}
311 }))
312 }
313
314 await Promise.map(testConnections, async function(conn, i) {
315 for (var j = 0; j < 25; j++) {
316 conn.put({
317 path: '/bookmarks/test/conn'+i,
318 type: 'application/json',
319 data: { [`put${j}`]: `value${j}`},
320 })
321 }
322 })
323
324 await Promise.delay(15000);
325
326 var getOne = await connection.get({
327 path: '/bookmarks/test',
328 })
329 expect(getOne.cached).to.equal(true)
330 for (var i = 0; i < 10; i++) {
331 for (var k = 0; k < 25; k++) {
332 expect(getOne.data['conn'+i]).to.include.key('put'+k)
333 }
334 }
335
336 // Now wipe out all of the caches
337 await Promise.map(testConnections, async function(conn, i) {
338 await conn.resetCache();
339 })
340
341 })
342 /*
343 it(`Should "autofix" a broken cache state and shouldn't 404 on recursiveGet`, async function() {
344 this.timeout(15000);
345 await connOne.delete({path:'/bookmarks/test', tree})
346 await connOne.resetCache();
347 var newTree = _.cloneDeep(tree)
348 newTree.bookmarks.test.aaa.bbb['index-one']['*']['index-two']['*']['index-three']['*']._rev = '0-0';
349
350 // 1. Put some deep stuff
351 console.log('putting')
352 var putOne = await connOne.put({
353 path: '/bookmarks/test/aaa/bbb/index-one/ccc',
354 data: {sometest: 'foo'},
355 tree,
356 })
357 var getOne = await connOne.get({
358 path: '/bookmarks/test',
359 tree
360 })
361 getOne = await connOne.get({
362 path: '/bookmarks/test',
363 tree
364 })
365 expect(getOne.cached).to.equal(true);
366 console.log('!!!!!!!!!!!deleting!!!!!!!!!!!!!!!!!')
367 // 2. Delete that deep stuff without affecting connOne's cache
368 var deleteOne = await connTwo.delete({
369 path: '/bookmarks/test/aaa/bbb/index-one/ccc',
370 type: 'application/json',
371 })
372 console.log('watching')
373 // 3. Set a watch on bookmarks/test; we don't want the recursive get to 404
374 // We want the offline changes to fix the cache
375 var response = await connOne.get({
376 path: '/bookmarks/test',
377 tree,
378 watch: {
379 payload: {someExtra: 'payload'},
380 }
381 })
382 expect(response.status).to.equal(200)
383 console.log(pretty.render(response.data));
384 expect(response.data).to.include.keys(['_id', '_rev', '_type', 'aaa'])
385 expect(response.data.aaa).to.include.keys(['_id', '_rev', 'bbb', '_type'])
386 expect(response.data.aaa.bbb).to.include.keys(['_id', '_rev', 'index-one', '_type'])
387 expect(response.data.aaa.bbb['index-one']).to.include.keys(['ccc'])
388 expect(response.data.aaa.bbb['index-one'].ccc).to.include.keys(['_id', '_rev', '_type', 'sometest'])
389 })*/
390 it('Now clean up', async function() {
391 await connOne.resetCache();
392 await connOne.delete({path:'/bookmarks/test', tree})
393 })
394})