1 | process.env.NODE_TLS_REJECT_UNAUTHORIZED=0
|
2 | import Promise from 'bluebird'
|
3 | import oada from '../src/index'
|
4 | const pretty = require('prettyjson');
|
5 | const _ = require('lodash');
|
6 | const {expect} = require('chai');
|
7 | const {token, domain} = require('./config.js');
|
8 | const {tree, putResource, getConnections} = require('./utils.js');
|
9 |
|
10 | var connections;
|
11 | var expects = {};
|
12 |
|
13 | async function setupWatch(connOne, tre, payload) {
|
14 |
|
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 |
|
22 | var getOne = await connOne.get({
|
23 | path: '/bookmarks/test',
|
24 | tree: tre || tree,
|
25 | watch: {
|
26 | payload: payload || {someExtra: 'payload'},
|
27 | |
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | }
|
35 | })
|
36 | expect(getOne.status).to.equal(200);
|
37 | return {putOne, getOne}
|
38 | }
|
39 |
|
40 | describe(`~~~~~~~~~~~WATCH~~~~~~~~~~~~~~`, function() {
|
41 | var connOne;
|
42 | var connTwo;
|
43 | before(`Create connection types`, async function() {
|
44 | connections = await getConnections({domain, token})
|
45 |
|
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 |
|
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 |
|
65 | var getTwo = await connOne.get({
|
66 | path: '/bookmarks/test',
|
67 | tree,
|
68 | })
|
69 |
|
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 |
|
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 |
|
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 |
|
111 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
337 | await Promise.map(testConnections, async function(conn, i) {
|
338 | await conn.resetCache();
|
339 | })
|
340 |
|
341 | })
|
342 | |
343 |
|
344 |
|
345 |
|
346 |
|
347 |
|
348 |
|
349 |
|
350 |
|
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 |
|
388 |
|
389 |
|
390 | it('Now clean up', async function() {
|
391 | await connOne.resetCache();
|
392 | await connOne.delete({path:'/bookmarks/test', tree})
|
393 | })
|
394 | })
|