UNPKG

21.7 kBJavaScriptView Raw
1// Copyright (c) 2016 Kinvey Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4// in compliance with the License. You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software distributed under the License
9// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10// or implied. See the License for the specific language governing permissions and limitations under
11// the License.
12
13const supertest = require('supertest');
14const runner = require('../../lib/receiver');
15const should = require('should');
16const bigBody = require('../scripts/bigBody.json'); // 8.90 KB JSON
17
18const TEST_URL = 'http://localhost:7777';
19const SERVICE_OBJECT_ROUTE = '/serviceObject';
20const HEALTHCHECK_ROUTE = '/healthcheck/';
21const LOGIC_ROUTE = '/_flexFunctions/testHandler';
22const DISCOVERY_ROUTE = '/_command/discover';
23const AUTH_ROUTE = '/_auth/someAuthHandler';
24
25describe('http receiver', () => {
26 function startReceiver(taskReceivedCallback, callback, options) {
27 if (!taskReceivedCallback) {
28 taskReceivedCallback = () => {};
29 }
30
31 if (!options) {
32 options = { type: 'http', port: '7777', requestBodyLimit: 10240 /* 10 KB */ };
33 }
34
35 runner.start(options, taskReceivedCallback, () => {
36 setTimeout(callback, 20);
37 });
38 }
39
40 function stopReceiver() {
41 runner.stop();
42 }
43 afterEach((done) => {
44 stopReceiver();
45 done();
46 });
47
48 it('should do a healthcheck', (done) => {
49 startReceiver(null, () => {
50 //noinspection JSCheckFunctionSignatures
51 supertest(TEST_URL)
52 .get(HEALTHCHECK_ROUTE)
53 .end((err, res) => {
54 if (err) {
55 throw (err);
56 }
57 //noinspection JSUnresolvedVariable
58 res.body.healthy.should.be.true();
59 done();
60 });
61 });
62 });
63
64 it('should invoke taskReceivedCallback on receiving a task', (done) => {
65 function taskReceivedCallback(receivedTask, callback) {
66 receivedTask.should.be.an.Object();
67 receivedTask.taskType.should.eql('data');
68 receivedTask.request.serviceObjectName.should.eql('serviceObject');
69 receivedTask.request.method.should.eql('GET');
70 receivedTask.response.statusCode = 200;
71 receivedTask.response.body = {};
72 receivedTask.response.continue = false;
73
74 callback(null, receivedTask);
75 }
76
77 startReceiver(taskReceivedCallback, () => {
78 //noinspection JSCheckFunctionSignatures
79 supertest(TEST_URL)
80 .get(SERVICE_OBJECT_ROUTE)
81 .expect(200)
82 .end(done);
83 });
84 });
85
86 it('should accept appMetadata header', (done) => {
87 function taskReceivedCallback(receivedTask, callback) {
88 receivedTask.should.be.an.Object();
89 should.exist(receivedTask.appMetadata);
90 receivedTask.appMetadata.should.not.be.empty();
91 receivedTask.appMetadata.foo.should.eql('bar');
92 receivedTask.response.statusCode = 200;
93 receivedTask.response.body = {};
94 receivedTask.response.continue = false;
95 callback(null, receivedTask);
96 }
97
98 startReceiver(taskReceivedCallback, () => {
99 //noinspection JSCheckFunctionSignatures
100 supertest(TEST_URL)
101 .get(SERVICE_OBJECT_ROUTE)
102 .set('X-Kinvey-App-Metadata', JSON.stringify({ foo: 'bar' }))
103 .expect(200)
104 .end(done);
105 });
106 });
107
108 it('should contain appMetadata object even if appMetadata isn\'t passed', (done) => {
109 function taskReceivedCallback(receivedTask, callback) {
110 receivedTask.should.be.an.Object();
111 should.exist(receivedTask.appMetadata);
112 receivedTask.appMetadata.should.be.empty();
113 receivedTask.response.statusCode = 200;
114 receivedTask.response.body = {};
115 receivedTask.response.continue = false;
116 callback(null, receivedTask);
117 }
118
119 startReceiver(taskReceivedCallback, () => {
120 //noinspection JSCheckFunctionSignatures
121 supertest(TEST_URL)
122 .get(SERVICE_OBJECT_ROUTE)
123 .expect(200)
124 .end(done);
125 });
126 });
127
128 it('should accept original request headers header', (done) => {
129 function taskReceivedCallback(receivedTask, callback) {
130 receivedTask.should.be.an.Object();
131 should.exist(receivedTask.request.headers);
132 receivedTask.request.headers.should.not.be.empty();
133 receivedTask.request.headers.foo.should.eql('bar');
134 receivedTask.response.statusCode = 200;
135 receivedTask.response.body = {};
136 receivedTask.response.continue = false;
137 callback(null, receivedTask);
138 }
139
140 startReceiver(taskReceivedCallback, () => {
141 //noinspection JSCheckFunctionSignatures
142 supertest(TEST_URL)
143 .get(SERVICE_OBJECT_ROUTE)
144 .set('X-Kinvey-Original-Request-Headers', JSON.stringify({ foo: 'bar' }))
145 .expect(200)
146 .end(done);
147 });
148 });
149
150 it('should contain request headers object even if request headers aren\'t passed', (done) => {
151 function taskReceivedCallback(receivedTask, callback) {
152 receivedTask.should.be.an.Object();
153 should.exist(receivedTask.request.headers);
154 receivedTask.request.headers.should.be.empty();
155 receivedTask.response.statusCode = 200;
156 receivedTask.response.body = {};
157 receivedTask.response.continue = false;
158 callback(null, receivedTask);
159 }
160
161 startReceiver(taskReceivedCallback, () => {
162 //noinspection JSCheckFunctionSignatures
163 supertest(TEST_URL)
164 .get(SERVICE_OBJECT_ROUTE)
165 .expect(200)
166 .end(done);
167 });
168 });
169
170 it('should populate the environmentId', (done) => {
171 function taskReceivedCallback(receivedTask, callback) {
172 receivedTask.should.be.an.Object();
173 should.exist(receivedTask.request.headers);
174 receivedTask.appId.should.eql('abcd');
175 receivedTask.response.statusCode = 200;
176 receivedTask.response.body = {};
177 receivedTask.response.continue = false;
178 callback(null, receivedTask);
179 }
180
181 startReceiver(taskReceivedCallback, () => {
182 //noinspection JSCheckFunctionSignatures
183 supertest(TEST_URL)
184 .get(SERVICE_OBJECT_ROUTE)
185 .set('X-Kinvey-Environment-Id', 'abcd')
186 .expect(200)
187 .end(done);
188 });
189 });
190
191 it('should populate the environmentId', (done) => {
192 function taskReceivedCallback(receivedTask, callback) {
193 receivedTask.should.be.an.Object();
194 should.exist(receivedTask.appId);
195 receivedTask.appId.should.eql('abcd');
196 receivedTask.response.statusCode = 200;
197 receivedTask.response.body = {};
198 receivedTask.response.continue = false;
199 callback(null, receivedTask);
200 }
201
202 startReceiver(taskReceivedCallback, () => {
203 //noinspection JSCheckFunctionSignatures
204 supertest(TEST_URL)
205 .get(SERVICE_OBJECT_ROUTE)
206 .set('X-Kinvey-Environment-Id', 'abcd')
207 .expect(200)
208 .end(done);
209 });
210 });
211
212 it('should pass a blank environmentId if not passed', (done) => {
213 function taskReceivedCallback(receivedTask, callback) {
214 receivedTask.should.be.an.Object();
215 should.exist(receivedTask.appId);
216 receivedTask.appId.should.eql('');
217 receivedTask.response.statusCode = 200;
218 receivedTask.response.body = {};
219 receivedTask.response.continue = false;
220 callback(null, receivedTask);
221 }
222
223 startReceiver(taskReceivedCallback, () => {
224 //noinspection JSCheckFunctionSignatures
225 supertest(TEST_URL)
226 .get(SERVICE_OBJECT_ROUTE)
227 .expect(200)
228 .end(done);
229 });
230 });
231
232 it('should populate the authKey', (done) => {
233 function taskReceivedCallback(receivedTask, callback) {
234 receivedTask.should.be.an.Object();
235 should.exist(receivedTask.authKey);
236 receivedTask.authKey.should.eql('abcd');
237 receivedTask.response.statusCode = 200;
238 receivedTask.response.body = {};
239 receivedTask.response.continue = false;
240 callback(null, receivedTask);
241 }
242
243 startReceiver(taskReceivedCallback, () => {
244 //noinspection JSCheckFunctionSignatures
245 supertest(TEST_URL)
246 .get(SERVICE_OBJECT_ROUTE)
247 .set('X-Auth-Key', 'abcd')
248 .expect(200)
249 .end(done);
250 });
251 });
252
253 it('should not include the authKey property if it\'s not sent', (done) => {
254 function taskReceivedCallback(receivedTask, callback) {
255 receivedTask.should.be.an.Object();
256 should.not.exist(receivedTask.authKey);
257 receivedTask.response.statusCode = 200;
258 receivedTask.response.body = {};
259 receivedTask.response.continue = false;
260 callback(null, receivedTask);
261 }
262
263 startReceiver(taskReceivedCallback, () => {
264 //noinspection JSCheckFunctionSignatures
265 supertest(TEST_URL)
266 .get(SERVICE_OBJECT_ROUTE)
267 .expect(200)
268 .end(done);
269 });
270 });
271
272 it('should populate the requestId', (done) => {
273 function taskReceivedCallback(receivedTask, callback) {
274 receivedTask.should.be.an.Object();
275 should.exist(receivedTask.requestId);
276 receivedTask.requestId.should.eql('abcd');
277 receivedTask.response.statusCode = 200;
278 receivedTask.response.body = {};
279 receivedTask.response.continue = false;
280 callback(null, receivedTask);
281 }
282
283 startReceiver(taskReceivedCallback, () => {
284 //noinspection JSCheckFunctionSignatures
285 supertest(TEST_URL)
286 .get(SERVICE_OBJECT_ROUTE)
287 .set('X-Kinvey-Request-Id', 'abcd')
288 .expect(200)
289 .end(done);
290 });
291 });
292
293 it('should set the requestId to an empty string if not present', (done) => {
294 function taskReceivedCallback(receivedTask, callback) {
295 receivedTask.should.be.an.Object();
296 should.exist(receivedTask.requestId);
297 receivedTask.requestId.should.eql('');
298 receivedTask.response.statusCode = 200;
299 receivedTask.response.body = {};
300 receivedTask.response.continue = false;
301 callback(null, receivedTask);
302 }
303
304 startReceiver(taskReceivedCallback, () => {
305 //noinspection JSCheckFunctionSignatures
306 supertest(TEST_URL)
307 .get(SERVICE_OBJECT_ROUTE)
308 .expect(200)
309 .end(done);
310 });
311 });
312
313 it('should populate the username', (done) => {
314 function taskReceivedCallback(receivedTask, callback) {
315 receivedTask.should.be.an.Object();
316 should.exist(receivedTask.request.username);
317 receivedTask.request.username.should.eql('abcd');
318 receivedTask.response.statusCode = 200;
319 receivedTask.response.body = {};
320 receivedTask.response.continue = false;
321 callback(null, receivedTask);
322 }
323
324 startReceiver(taskReceivedCallback, () => {
325 //noinspection JSCheckFunctionSignatures
326 supertest(TEST_URL)
327 .get(SERVICE_OBJECT_ROUTE)
328 .set('X-Kinvey-Username', 'abcd')
329 .expect(200)
330 .end(done);
331 });
332 });
333
334 it('should populate the response if sent as headers', (done) => {
335 function taskReceivedCallback(receivedTask, callback) {
336 receivedTask.should.be.an.Object();
337 should.exist(receivedTask.request.username);
338 receivedTask.response.status.should.eql('202');
339 receivedTask.response.body.should.eql(JSON.stringify({ foo: 'bar' }));
340 receivedTask.response.headers.should.eql(JSON.stringify({ someheader: 'somevalue' }));
341 receivedTask.response.body = {};
342 receivedTask.response.continue = false;
343 callback(null, receivedTask);
344 }
345
346 startReceiver(taskReceivedCallback, () => {
347 //noinspection JSCheckFunctionSignatures
348 supertest(TEST_URL)
349 .get(SERVICE_OBJECT_ROUTE)
350 .set('X-Kinvey-Response-Status', 202)
351 .set('X-Kinvey-Response-Body', JSON.stringify({ foo: 'bar' }))
352 .set('X-Kinvey-Response-Headers', JSON.stringify({ someheader: 'somevalue' }))
353 .expect(200)
354 .end(done);
355 });
356 });
357
358 it('should set the username to an empty string if not present', (done) => {
359 function taskReceivedCallback(receivedTask, callback) {
360 receivedTask.should.be.an.Object();
361 should.exist(receivedTask.request.username);
362 receivedTask.request.username.should.eql('');
363 receivedTask.response.statusCode = 200;
364 receivedTask.response.body = {};
365 receivedTask.response.continue = false;
366 callback(null, receivedTask);
367 }
368
369 startReceiver(taskReceivedCallback, () => {
370 //noinspection JSCheckFunctionSignatures
371 supertest(TEST_URL)
372 .get(SERVICE_OBJECT_ROUTE)
373 .expect(200)
374 .end(done);
375 });
376 });
377
378 it('should populate the tempObjectStore', (done) => {
379 function taskReceivedCallback(receivedTask, callback) {
380 receivedTask.should.be.an.Object();
381 should.exist(receivedTask.request.tempObjectStore);
382 receivedTask.request.tempObjectStore.foo.should.eql('bar');
383 receivedTask.response.statusCode = 200;
384 receivedTask.response.body = {};
385 receivedTask.response.continue = false;
386 callback(null, receivedTask);
387 }
388
389 startReceiver(taskReceivedCallback, () => {
390 //noinspection JSCheckFunctionSignatures
391 supertest(TEST_URL)
392 .post(LOGIC_ROUTE)
393 .send({ tempObjectStore: { foo: 'bar' }, body: {} })
394 .expect(200)
395 .end(done);
396 });
397 });
398
399 it('should populate the userId', (done) => {
400 function taskReceivedCallback(receivedTask, callback) {
401 receivedTask.should.be.an.Object();
402 should.exist(receivedTask.request.userId);
403 receivedTask.request.userId.should.eql('abcd');
404 receivedTask.response.statusCode = 200;
405 receivedTask.response.body = {};
406 receivedTask.response.continue = false;
407 callback(null, receivedTask);
408 }
409
410 startReceiver(taskReceivedCallback, () => {
411 //noinspection JSCheckFunctionSignatures
412 supertest(TEST_URL)
413 .get(SERVICE_OBJECT_ROUTE)
414 .set('X-Kinvey-User-Id', 'abcd')
415 .expect(200)
416 .end(done);
417 });
418 });
419
420 it('should set the userId to an empty string if not present', (done) => {
421 function taskReceivedCallback(receivedTask, callback) {
422 receivedTask.should.be.an.Object();
423 should.exist(receivedTask.request.userId);
424 receivedTask.request.userId.should.eql('');
425 receivedTask.response.statusCode = 200;
426 receivedTask.response.body = {};
427 receivedTask.response.continue = false;
428 callback(null, receivedTask);
429 }
430
431 startReceiver(taskReceivedCallback, () => {
432 //noinspection JSCheckFunctionSignatures
433 supertest(TEST_URL)
434 .get(SERVICE_OBJECT_ROUTE)
435 .expect(200)
436 .end(done);
437 });
438 });
439
440 it('should send a response', (done) => {
441 function taskReceivedCallback(receivedTask, callback) {
442 receivedTask.should.be.an.Object();
443 receivedTask.taskType.should.eql('data');
444 receivedTask.request.serviceObjectName.should.eql('serviceObject');
445 receivedTask.request.method.should.eql('GET');
446 receivedTask.response.statusCode = 200;
447 receivedTask.response.body = { foo: 'bar' };
448 receivedTask.response.continue = false;
449
450 callback(null, receivedTask);
451 }
452
453 startReceiver(taskReceivedCallback, () => {
454 //noinspection JSCheckFunctionSignatures
455 supertest(TEST_URL)
456 .get(SERVICE_OBJECT_ROUTE)
457 .expect(200)
458 .end((err, res) => {
459 res.body.foo.should.eql('bar');
460 res.statusCode.should.eql(200);
461 done();
462 });
463 });
464 });
465
466 it('should send a functions message', (done) => {
467 function taskReceivedCallback(receivedTask, callback) {
468 receivedTask.should.be.an.Object();
469 receivedTask.taskType.should.eql('functions');
470 receivedTask.taskName.should.eql('testHandler');
471 receivedTask.hookType.should.eql('customEndpoint');
472 receivedTask.request.objectName.should.eql('testObject');
473 receivedTask.request.method.should.eql('POST');
474 receivedTask.request.entityId.should.eql(5);
475 receivedTask.response.statusCode = 200;
476 receivedTask.response.body = { foo: 'bar' };
477 receivedTask.response.continue = false;
478
479 callback(null, receivedTask);
480 }
481
482 startReceiver(taskReceivedCallback, () => {
483 //noinspection JSCheckFunctionSignatures
484 supertest(TEST_URL)
485 .post(LOGIC_ROUTE)
486 .send({ objectName: 'testObject', entityId: 5 })
487 .expect(200)
488 .end((err, res) => {
489 res.body.response.body.foo.should.eql('bar');
490 res.body.response.statusCode.should.eql(200);
491 res.statusCode.should.eql(200);
492 done();
493 });
494 });
495 });
496
497 it('should populate the response', (done) => {
498 function taskReceivedCallback(receivedTask, callback) {
499 receivedTask.should.be.an.Object();
500 receivedTask.response.status.should.eql(202);
501 receivedTask.response.body = { foo: 'bar' };
502 receivedTask.response.headers.should.eql({ someheader: 'somevalue' });
503 receivedTask.response.continue = false;
504
505 callback(null, receivedTask);
506 }
507
508 startReceiver(taskReceivedCallback, () => {
509 //noinspection JSCheckFunctionSignatures
510 supertest(TEST_URL)
511 .post(LOGIC_ROUTE)
512 .send({ objectName: 'testObject', entityId: 5, response: {
513 status: 202,
514 body: { foo: 'bar' },
515 headers: { someheader: 'somevalue' }
516 }
517 })
518 .end(done);
519 });
520 });
521
522 it('should send a functions message with a big json body', (done) => {
523 function taskReceivedCallback(receivedTask, callback) {
524 receivedTask.should.be.an.Object();
525 receivedTask.taskType.should.eql('functions');
526 receivedTask.taskName.should.eql('testHandler');
527 receivedTask.hookType.should.eql('customEndpoint');
528 receivedTask.request.objectName.should.eql('testObject');
529 receivedTask.request.method.should.eql('POST');
530 receivedTask.request.entityId.should.eql(5);
531 receivedTask.response.statusCode = 200;
532 receivedTask.response.body = { foo: 'bar' };
533 receivedTask.response.continue = false;
534
535 callback(null, receivedTask);
536 }
537
538 startReceiver(taskReceivedCallback, () => {
539 //noinspection JSCheckFunctionSignatures
540 supertest(TEST_URL)
541 .post(LOGIC_ROUTE)
542 .send(bigBody)
543 .expect(200)
544 .end((err, res) => {
545 res.body.response.body.foo.should.eql('bar');
546 res.body.response.statusCode.should.eql(200);
547 res.statusCode.should.eql(200);
548 done();
549 });
550 });
551 });
552
553 it('should send a discover message', (done) => {
554 function taskReceivedCallback(receivedTask, callback) {
555 receivedTask.should.be.an.Object();
556 receivedTask.taskType.should.eql('serviceDiscovery');
557
558 receivedTask.discoveryObjects = {
559 data: {
560 foo: 'bar'
561 },
562 functions: {
563 bar: 'foo'
564 }
565 };
566
567 callback(null, receivedTask);
568 }
569
570 startReceiver(taskReceivedCallback, () => {
571 //noinspection JSCheckFunctionSignatures
572 supertest(TEST_URL)
573 .post(DISCOVERY_ROUTE)
574 .expect(200)
575 .end((err, res) => {
576 res.statusCode.should.eql(200);
577 res.body.data.foo.should.eql('bar');
578 res.body.functions.bar.should.eql('foo');
579 done();
580 });
581 });
582 });
583
584 it('should send an auth task', (done) => {
585 function taskReceivedCallback(receivedTask, callback) {
586 receivedTask.should.be.an.Object();
587 receivedTask.taskType.should.eql('auth');
588 receivedTask.taskName.should.eql('someAuthHandler');
589 should.exist(receivedTask.request.body.username);
590 should.exist(receivedTask.request.body.password);
591 should.exist(receivedTask.request.body.options);
592
593 receivedTask.response = {
594 body: {
595 authenticated: true,
596 token: 'qwerty1234'
597 }
598 };
599
600 callback(null, receivedTask);
601 }
602
603 startReceiver(taskReceivedCallback, () => {
604 //noinspection JSCheckFunctionSignatures
605 supertest(TEST_URL)
606 .post(AUTH_ROUTE)
607 .send({ username: 'foo', password: 'bar', options: {} })
608 .expect(200)
609 .end((err, res) => {
610 res.statusCode.should.eql(200);
611 res.body.authenticated.should.be.true();
612 res.body.token.should.eql('qwerty1234');
613 done();
614 });
615 });
616 });
617
618 // some bugs only show up the second time a task is run
619 it('should run multiple tasks', (done) => {
620 function taskReceivedCallback(receivedTask, callback) {
621 receivedTask.should.be.an.Object();
622 receivedTask.taskType.should.eql('data');
623 receivedTask.request.serviceObjectName.should.eql('serviceObject');
624 receivedTask.request.method.should.eql('GET');
625 receivedTask.response.statusCode = 200;
626 receivedTask.response.body = { foo: 'bar' };
627 receivedTask.response.continue = false;
628
629 callback(null, receivedTask);
630 }
631
632 startReceiver(taskReceivedCallback, () => {
633 let counter = 2;
634 //noinspection JSCheckFunctionSignatures
635 supertest(TEST_URL)
636 .get(SERVICE_OBJECT_ROUTE)
637 .expect(200)
638 .end((err, res) => {
639 res.body.foo.should.eql('bar');
640 res.statusCode.should.eql(200);
641 counter -= 1;
642 });
643 //noinspection JSCheckFunctionSignatures
644 supertest(TEST_URL)
645 .get(SERVICE_OBJECT_ROUTE)
646 .expect(200)
647 .end((err, res) => {
648 res.body.foo.should.eql('bar');
649 res.statusCode.should.eql(200);
650 counter -= 1;
651 });
652
653 setTimeout(() => {
654 counter.should.eql(0);
655 done();
656 }, 250);
657 });
658 });
659});