orator 5.0.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -81
- package/docs/.nojekyll +0 -0
- package/docs/README.md +142 -0
- package/docs/_sidebar.md +21 -0
- package/docs/architecture.md +92 -0
- package/docs/configuration.md +94 -0
- package/docs/cover.md +11 -0
- package/docs/getting-started.md +133 -0
- package/docs/http-proxy.md +45 -0
- package/docs/index.html +39 -0
- package/docs/ipc-server.md +123 -0
- package/docs/lifecycle-hooks.md +95 -0
- package/docs/restify-server.md +82 -0
- package/docs/service-servers.md +87 -0
- package/docs/static-files.md +75 -0
- package/package.json +6 -7
- package/source/Orator.js +40 -74
- package/test/Orator_complex_routes_tests.js +949 -0
- package/test/Orator_static_serving_tests.js +1355 -0
- package/test/static_content/about.html +1 -0
- package/test/static_content/data.json +1 -0
- package/test/static_content/index.html +1 -0
- package/test/static_content/style.css +1 -0
- package/test/static_content/subsite/index.html +1 -0
|
@@ -0,0 +1,949 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for Orator complex routes and static file serving
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
*
|
|
6
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const libOrator = require('../source/Orator.js');
|
|
10
|
+
|
|
11
|
+
const Chai = require("chai");
|
|
12
|
+
const Expect = Chai.expect;
|
|
13
|
+
const Assert = Chai.assert;
|
|
14
|
+
|
|
15
|
+
const libFable = require('fable');
|
|
16
|
+
const libPath = require('path');
|
|
17
|
+
|
|
18
|
+
const defaultFableSettings = (
|
|
19
|
+
{
|
|
20
|
+
Product:'Orator-ComplexRouteTests',
|
|
21
|
+
ProductVersion: '0.0.0',
|
|
22
|
+
APIServerPort: 0
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
suite
|
|
26
|
+
(
|
|
27
|
+
'Orator',
|
|
28
|
+
() =>
|
|
29
|
+
{
|
|
30
|
+
suite
|
|
31
|
+
(
|
|
32
|
+
'Multiple HTTP Verbs',
|
|
33
|
+
() =>
|
|
34
|
+
{
|
|
35
|
+
test
|
|
36
|
+
(
|
|
37
|
+
'ipc should be able to handle POST routes',
|
|
38
|
+
(fDone) =>
|
|
39
|
+
{
|
|
40
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
41
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
42
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
43
|
+
tmpOrator.startService();
|
|
44
|
+
|
|
45
|
+
tmpOrator.serviceServer.post
|
|
46
|
+
(
|
|
47
|
+
'/api/item',
|
|
48
|
+
(pRequest, pResponse, fNext) =>
|
|
49
|
+
{
|
|
50
|
+
pResponse.send({Created: true, Method: 'POST'});
|
|
51
|
+
return fNext();
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
tmpOrator.invoke('POST', '/api/item', {Name: 'TestItem'},
|
|
56
|
+
(pError, pResponseData) =>
|
|
57
|
+
{
|
|
58
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
59
|
+
Expect(tmpResponseObject).to.have.a.property('Created');
|
|
60
|
+
Expect(tmpResponseObject.Created).to.equal(true);
|
|
61
|
+
Expect(tmpResponseObject.Method).to.equal('POST');
|
|
62
|
+
tmpOrator.log.info(`POST /api/item responded with [${pResponseData}]`);
|
|
63
|
+
return fDone();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
test
|
|
69
|
+
(
|
|
70
|
+
'ipc should be able to handle PUT routes',
|
|
71
|
+
(fDone) =>
|
|
72
|
+
{
|
|
73
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
74
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
75
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
76
|
+
tmpOrator.startService();
|
|
77
|
+
|
|
78
|
+
tmpOrator.serviceServer.put
|
|
79
|
+
(
|
|
80
|
+
'/api/item/:id',
|
|
81
|
+
(pRequest, pResponse, fNext) =>
|
|
82
|
+
{
|
|
83
|
+
pResponse.send({Updated: true, ID: pRequest.params.id, Method: 'PUT'});
|
|
84
|
+
return fNext();
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
tmpOrator.invoke('PUT', '/api/item/42', {Name: 'UpdatedItem'},
|
|
89
|
+
(pError, pResponseData) =>
|
|
90
|
+
{
|
|
91
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
92
|
+
Expect(tmpResponseObject).to.have.a.property('Updated');
|
|
93
|
+
Expect(tmpResponseObject.Updated).to.equal(true);
|
|
94
|
+
Expect(tmpResponseObject.ID).to.equal('42');
|
|
95
|
+
Expect(tmpResponseObject.Method).to.equal('PUT');
|
|
96
|
+
tmpOrator.log.info(`PUT /api/item/42 responded with [${pResponseData}]`);
|
|
97
|
+
return fDone();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
test
|
|
103
|
+
(
|
|
104
|
+
'ipc should be able to handle DELETE routes',
|
|
105
|
+
(fDone) =>
|
|
106
|
+
{
|
|
107
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
108
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
109
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
110
|
+
tmpOrator.startService();
|
|
111
|
+
|
|
112
|
+
tmpOrator.serviceServer.del
|
|
113
|
+
(
|
|
114
|
+
'/api/item/:id',
|
|
115
|
+
(pRequest, pResponse, fNext) =>
|
|
116
|
+
{
|
|
117
|
+
pResponse.send({Deleted: true, ID: pRequest.params.id, Method: 'DELETE'});
|
|
118
|
+
return fNext();
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
tmpOrator.invoke('DELETE', '/api/item/99', null,
|
|
123
|
+
(pError, pResponseData) =>
|
|
124
|
+
{
|
|
125
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
126
|
+
Expect(tmpResponseObject).to.have.a.property('Deleted');
|
|
127
|
+
Expect(tmpResponseObject.Deleted).to.equal(true);
|
|
128
|
+
Expect(tmpResponseObject.ID).to.equal('99');
|
|
129
|
+
Expect(tmpResponseObject.Method).to.equal('DELETE');
|
|
130
|
+
tmpOrator.log.info(`DELETE /api/item/99 responded with [${pResponseData}]`);
|
|
131
|
+
return fDone();
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
test
|
|
137
|
+
(
|
|
138
|
+
'ipc should be able to handle PATCH routes',
|
|
139
|
+
(fDone) =>
|
|
140
|
+
{
|
|
141
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
142
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
143
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
144
|
+
tmpOrator.startService();
|
|
145
|
+
|
|
146
|
+
tmpOrator.serviceServer.patch
|
|
147
|
+
(
|
|
148
|
+
'/api/item/:id',
|
|
149
|
+
(pRequest, pResponse, fNext) =>
|
|
150
|
+
{
|
|
151
|
+
pResponse.send({Patched: true, ID: pRequest.params.id, Method: 'PATCH'});
|
|
152
|
+
return fNext();
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
tmpOrator.invoke('PATCH', '/api/item/7', null,
|
|
157
|
+
(pError, pResponseData) =>
|
|
158
|
+
{
|
|
159
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
160
|
+
Expect(tmpResponseObject).to.have.a.property('Patched');
|
|
161
|
+
Expect(tmpResponseObject.Patched).to.equal(true);
|
|
162
|
+
Expect(tmpResponseObject.ID).to.equal('7');
|
|
163
|
+
Expect(tmpResponseObject.Method).to.equal('PATCH');
|
|
164
|
+
tmpOrator.log.info(`PATCH /api/item/7 responded with [${pResponseData}]`);
|
|
165
|
+
return fDone();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
test
|
|
171
|
+
(
|
|
172
|
+
'ipc should be able to register and invoke all verb types in the same service',
|
|
173
|
+
(fDone) =>
|
|
174
|
+
{
|
|
175
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
176
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
177
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
178
|
+
tmpOrator.startService();
|
|
179
|
+
|
|
180
|
+
// Register multiple verbs on the same path pattern
|
|
181
|
+
tmpOrator.serviceServer.get('/api/resource/:id',
|
|
182
|
+
(pRequest, pResponse, fNext) =>
|
|
183
|
+
{
|
|
184
|
+
pResponse.send({Action: 'read', ID: pRequest.params.id});
|
|
185
|
+
return fNext();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
tmpOrator.serviceServer.post('/api/resource',
|
|
189
|
+
(pRequest, pResponse, fNext) =>
|
|
190
|
+
{
|
|
191
|
+
pResponse.send({Action: 'create'});
|
|
192
|
+
return fNext();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
tmpOrator.serviceServer.put('/api/resource/:id',
|
|
196
|
+
(pRequest, pResponse, fNext) =>
|
|
197
|
+
{
|
|
198
|
+
pResponse.send({Action: 'update', ID: pRequest.params.id});
|
|
199
|
+
return fNext();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
tmpOrator.serviceServer.del('/api/resource/:id',
|
|
203
|
+
(pRequest, pResponse, fNext) =>
|
|
204
|
+
{
|
|
205
|
+
pResponse.send({Action: 'delete', ID: pRequest.params.id});
|
|
206
|
+
return fNext();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
tmpFable.Utility.waterfall([
|
|
210
|
+
(fStageComplete) =>
|
|
211
|
+
{
|
|
212
|
+
tmpOrator.invoke('GET', '/api/resource/10', null,
|
|
213
|
+
(pError, pResponseData) =>
|
|
214
|
+
{
|
|
215
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
216
|
+
Expect(tmpResponseObject.Action).to.equal('read');
|
|
217
|
+
Expect(tmpResponseObject.ID).to.equal('10');
|
|
218
|
+
return fStageComplete();
|
|
219
|
+
});
|
|
220
|
+
},
|
|
221
|
+
(fStageComplete) =>
|
|
222
|
+
{
|
|
223
|
+
tmpOrator.invoke('POST', '/api/resource', {Name: 'New'},
|
|
224
|
+
(pError, pResponseData) =>
|
|
225
|
+
{
|
|
226
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
227
|
+
Expect(tmpResponseObject.Action).to.equal('create');
|
|
228
|
+
return fStageComplete();
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
(fStageComplete) =>
|
|
232
|
+
{
|
|
233
|
+
tmpOrator.invoke('PUT', '/api/resource/10', {Name: 'Updated'},
|
|
234
|
+
(pError, pResponseData) =>
|
|
235
|
+
{
|
|
236
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
237
|
+
Expect(tmpResponseObject.Action).to.equal('update');
|
|
238
|
+
Expect(tmpResponseObject.ID).to.equal('10');
|
|
239
|
+
return fStageComplete();
|
|
240
|
+
});
|
|
241
|
+
},
|
|
242
|
+
(fStageComplete) =>
|
|
243
|
+
{
|
|
244
|
+
tmpOrator.invoke('DELETE', '/api/resource/10', null,
|
|
245
|
+
(pError, pResponseData) =>
|
|
246
|
+
{
|
|
247
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
248
|
+
Expect(tmpResponseObject.Action).to.equal('delete');
|
|
249
|
+
Expect(tmpResponseObject.ID).to.equal('10');
|
|
250
|
+
return fStageComplete();
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
(pError) =>
|
|
255
|
+
{
|
|
256
|
+
tmpOrator.log.info('All CRUD operations completed successfully via IPC');
|
|
257
|
+
return fDone();
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
suite
|
|
265
|
+
(
|
|
266
|
+
'Complex Route Patterns',
|
|
267
|
+
() =>
|
|
268
|
+
{
|
|
269
|
+
test
|
|
270
|
+
(
|
|
271
|
+
'ipc should be able to handle multiple URL parameters',
|
|
272
|
+
(fDone) =>
|
|
273
|
+
{
|
|
274
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
275
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
276
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
277
|
+
tmpOrator.startService();
|
|
278
|
+
|
|
279
|
+
tmpOrator.serviceServer.get
|
|
280
|
+
(
|
|
281
|
+
'/api/:entity/:id/child/:childId',
|
|
282
|
+
(pRequest, pResponse, fNext) =>
|
|
283
|
+
{
|
|
284
|
+
pResponse.send(
|
|
285
|
+
{
|
|
286
|
+
Entity: pRequest.params.entity,
|
|
287
|
+
ID: pRequest.params.id,
|
|
288
|
+
ChildID: pRequest.params.childId
|
|
289
|
+
});
|
|
290
|
+
return fNext();
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
tmpOrator.invoke('GET', '/api/Author/5/child/12', null,
|
|
295
|
+
(pError, pResponseData) =>
|
|
296
|
+
{
|
|
297
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
298
|
+
Expect(tmpResponseObject.Entity).to.equal('Author');
|
|
299
|
+
Expect(tmpResponseObject.ID).to.equal('5');
|
|
300
|
+
Expect(tmpResponseObject.ChildID).to.equal('12');
|
|
301
|
+
tmpOrator.log.info(`Nested route responded with entity [${tmpResponseObject.Entity}] id [${tmpResponseObject.ID}] child [${tmpResponseObject.ChildID}]`);
|
|
302
|
+
return fDone();
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
test
|
|
308
|
+
(
|
|
309
|
+
'ipc should be able to handle routes that return string responses',
|
|
310
|
+
(fDone) =>
|
|
311
|
+
{
|
|
312
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
313
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
314
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
315
|
+
tmpOrator.startService();
|
|
316
|
+
|
|
317
|
+
tmpOrator.serviceServer.get
|
|
318
|
+
(
|
|
319
|
+
'/api/version',
|
|
320
|
+
(pRequest, pResponse, fNext) =>
|
|
321
|
+
{
|
|
322
|
+
pResponse.send('1.0.0');
|
|
323
|
+
return fNext();
|
|
324
|
+
}
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
tmpOrator.invoke('GET', '/api/version', null,
|
|
328
|
+
(pError, pResponseData) =>
|
|
329
|
+
{
|
|
330
|
+
Expect(pResponseData).to.equal('1.0.0');
|
|
331
|
+
tmpOrator.log.info(`String endpoint responded with [${pResponseData}]`);
|
|
332
|
+
return fDone();
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
test
|
|
338
|
+
(
|
|
339
|
+
'ipc should handle chained route handlers sequentially',
|
|
340
|
+
(fDone) =>
|
|
341
|
+
{
|
|
342
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
343
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
344
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
345
|
+
tmpOrator.startService();
|
|
346
|
+
|
|
347
|
+
// Register a route with multiple handler functions chained together
|
|
348
|
+
tmpOrator.serviceServer.get
|
|
349
|
+
(
|
|
350
|
+
'/api/chained/:value',
|
|
351
|
+
// First handler: decorate the request
|
|
352
|
+
(pRequest, pResponse, fNext) =>
|
|
353
|
+
{
|
|
354
|
+
pRequest.Decorated = true;
|
|
355
|
+
pRequest.ProcessingSteps = ['step1'];
|
|
356
|
+
return fNext();
|
|
357
|
+
},
|
|
358
|
+
// Second handler: add more decoration
|
|
359
|
+
(pRequest, pResponse, fNext) =>
|
|
360
|
+
{
|
|
361
|
+
pRequest.ProcessingSteps.push('step2');
|
|
362
|
+
return fNext();
|
|
363
|
+
},
|
|
364
|
+
// Third handler: send the response
|
|
365
|
+
(pRequest, pResponse, fNext) =>
|
|
366
|
+
{
|
|
367
|
+
pResponse.send(
|
|
368
|
+
{
|
|
369
|
+
Value: pRequest.params.value,
|
|
370
|
+
Decorated: pRequest.Decorated,
|
|
371
|
+
Steps: pRequest.ProcessingSteps
|
|
372
|
+
});
|
|
373
|
+
return fNext();
|
|
374
|
+
}
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
tmpOrator.invoke('GET', '/api/chained/TestValue', null,
|
|
378
|
+
(pError, pResponseData) =>
|
|
379
|
+
{
|
|
380
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
381
|
+
Expect(tmpResponseObject.Value).to.equal('TestValue');
|
|
382
|
+
Expect(tmpResponseObject.Decorated).to.equal(true);
|
|
383
|
+
Expect(tmpResponseObject.Steps).to.be.an('array');
|
|
384
|
+
Expect(tmpResponseObject.Steps).to.have.lengthOf(2);
|
|
385
|
+
Expect(tmpResponseObject.Steps[0]).to.equal('step1');
|
|
386
|
+
Expect(tmpResponseObject.Steps[1]).to.equal('step2');
|
|
387
|
+
tmpOrator.log.info(`Chained handler responded after ${tmpResponseObject.Steps.length} processing steps`);
|
|
388
|
+
return fDone();
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
test
|
|
394
|
+
(
|
|
395
|
+
'ipc should handle post-behavior functions after route handlers',
|
|
396
|
+
(fDone) =>
|
|
397
|
+
{
|
|
398
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
399
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
400
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
401
|
+
tmpOrator.startService();
|
|
402
|
+
|
|
403
|
+
let tmpPostBehaviorExecuted = false;
|
|
404
|
+
|
|
405
|
+
// Add a post-behavior function
|
|
406
|
+
tmpOrator.serviceServer.addPostBehaviorFunction(
|
|
407
|
+
(pRequest, pResponse, fNext) =>
|
|
408
|
+
{
|
|
409
|
+
tmpPostBehaviorExecuted = true;
|
|
410
|
+
return fNext();
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
tmpOrator.serviceServer.get
|
|
414
|
+
(
|
|
415
|
+
'/api/postbehavior',
|
|
416
|
+
(pRequest, pResponse, fNext) =>
|
|
417
|
+
{
|
|
418
|
+
pResponse.send({Message: 'Handled'});
|
|
419
|
+
return fNext();
|
|
420
|
+
}
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
tmpOrator.invoke('GET', '/api/postbehavior', null,
|
|
424
|
+
(pError, pResponseData) =>
|
|
425
|
+
{
|
|
426
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
427
|
+
Expect(tmpResponseObject.Message).to.equal('Handled');
|
|
428
|
+
Expect(tmpPostBehaviorExecuted).to.equal(true, 'Post-behavior function should have executed');
|
|
429
|
+
tmpOrator.log.info(`Post-behavior test completed, postBehaviorExecuted: ${tmpPostBehaviorExecuted}`);
|
|
430
|
+
return fDone();
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
suite
|
|
438
|
+
(
|
|
439
|
+
'Service Lifecycle',
|
|
440
|
+
() =>
|
|
441
|
+
{
|
|
442
|
+
test
|
|
443
|
+
(
|
|
444
|
+
'orator should be able to stop and report inactive status',
|
|
445
|
+
(fDone) =>
|
|
446
|
+
{
|
|
447
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
448
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
449
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
450
|
+
tmpOrator.startService(
|
|
451
|
+
() =>
|
|
452
|
+
{
|
|
453
|
+
Expect(tmpOrator.serviceServer.Active).to.equal(true);
|
|
454
|
+
tmpOrator.stopService(
|
|
455
|
+
() =>
|
|
456
|
+
{
|
|
457
|
+
Expect(tmpOrator.serviceServer.Active).to.equal(false);
|
|
458
|
+
tmpOrator.log.info('Service started and stopped successfully');
|
|
459
|
+
return fDone();
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
test
|
|
466
|
+
(
|
|
467
|
+
'orator should warn when stopping a service that has not been initialized',
|
|
468
|
+
(fDone) =>
|
|
469
|
+
{
|
|
470
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
471
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
472
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
473
|
+
// Try to stop without starting
|
|
474
|
+
tmpOrator.stopService(
|
|
475
|
+
(pError) =>
|
|
476
|
+
{
|
|
477
|
+
Expect(pError).to.be.a('string');
|
|
478
|
+
tmpOrator.log.info(`Stop-before-init warning: ${pError}`);
|
|
479
|
+
return fDone();
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
test
|
|
485
|
+
(
|
|
486
|
+
'orator should use ServicePort from options and fall back to defaults',
|
|
487
|
+
(fDone) =>
|
|
488
|
+
{
|
|
489
|
+
// ServicePort passed directly in options should be used
|
|
490
|
+
let tmpFable = new libFable(
|
|
491
|
+
{
|
|
492
|
+
Product:'Orator-PortTest',
|
|
493
|
+
ProductVersion: '0.0.0'
|
|
494
|
+
});
|
|
495
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
496
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {ServicePort: 9999});
|
|
497
|
+
Expect(tmpOrator.options.ServicePort).to.equal(9999);
|
|
498
|
+
|
|
499
|
+
// Test the legacy APIServerPort migration from fable settings
|
|
500
|
+
let tmpFableLegacy = new libFable(
|
|
501
|
+
{
|
|
502
|
+
Product:'Orator-LegacyPortTest',
|
|
503
|
+
ProductVersion: '0.0.0',
|
|
504
|
+
APIServerPort: 7777
|
|
505
|
+
});
|
|
506
|
+
tmpFableLegacy.serviceManager.addServiceType('Orator', libOrator);
|
|
507
|
+
let tmpOratorLegacy = tmpFableLegacy.serviceManager.instantiateServiceProvider('Orator', {});
|
|
508
|
+
Expect(tmpOratorLegacy.options.ServicePort).to.equal(7777);
|
|
509
|
+
|
|
510
|
+
// Test the default port when nothing is configured
|
|
511
|
+
let tmpFableDefault = new libFable(
|
|
512
|
+
{
|
|
513
|
+
Product:'Orator-DefaultPortTest',
|
|
514
|
+
ProductVersion: '0.0.0'
|
|
515
|
+
});
|
|
516
|
+
tmpFableDefault.serviceManager.addServiceType('Orator', libOrator);
|
|
517
|
+
let tmpOratorDefault = tmpFableDefault.serviceManager.instantiateServiceProvider('Orator', {});
|
|
518
|
+
Expect(tmpOratorDefault.options.ServicePort).to.equal(8080);
|
|
519
|
+
|
|
520
|
+
tmpOrator.log.info('Port configuration tests passed');
|
|
521
|
+
return fDone();
|
|
522
|
+
}
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
test
|
|
526
|
+
(
|
|
527
|
+
'orator should provide a legacy webServer property',
|
|
528
|
+
(fDone) =>
|
|
529
|
+
{
|
|
530
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
531
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
532
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
533
|
+
tmpOrator.initialize(
|
|
534
|
+
() =>
|
|
535
|
+
{
|
|
536
|
+
Expect(tmpOrator.webServer).to.be.an('object');
|
|
537
|
+
Expect(tmpOrator.webServer).to.equal(tmpOrator.serviceServer);
|
|
538
|
+
Expect(tmpOrator.webServer.ServiceServerType).to.equal('IPC');
|
|
539
|
+
tmpOrator.log.info('Legacy webServer alias verified');
|
|
540
|
+
return fDone();
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
test
|
|
546
|
+
(
|
|
547
|
+
'orator legacy startWebServer and stopWebServer should work',
|
|
548
|
+
(fDone) =>
|
|
549
|
+
{
|
|
550
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
551
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
552
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
553
|
+
tmpOrator.startWebServer(
|
|
554
|
+
() =>
|
|
555
|
+
{
|
|
556
|
+
Expect(tmpOrator.serviceServer.Active).to.equal(true);
|
|
557
|
+
tmpOrator.stopWebServer(
|
|
558
|
+
() =>
|
|
559
|
+
{
|
|
560
|
+
Expect(tmpOrator.serviceServer.Active).to.equal(false);
|
|
561
|
+
tmpOrator.log.info('Legacy start/stop methods verified');
|
|
562
|
+
return fDone();
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
suite
|
|
571
|
+
(
|
|
572
|
+
'Static File Serving',
|
|
573
|
+
() =>
|
|
574
|
+
{
|
|
575
|
+
test
|
|
576
|
+
(
|
|
577
|
+
'addStaticRoute should return false when no file path is provided',
|
|
578
|
+
(fDone) =>
|
|
579
|
+
{
|
|
580
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
581
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
582
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
583
|
+
tmpOrator.initialize(
|
|
584
|
+
() =>
|
|
585
|
+
{
|
|
586
|
+
let tmpResult = tmpOrator.addStaticRoute();
|
|
587
|
+
Expect(tmpResult).to.equal(false);
|
|
588
|
+
tmpOrator.log.info('addStaticRoute correctly rejected missing file path');
|
|
589
|
+
return fDone();
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
test
|
|
595
|
+
(
|
|
596
|
+
'addStaticRoute should return true with a valid file path',
|
|
597
|
+
(fDone) =>
|
|
598
|
+
{
|
|
599
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
600
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
601
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
602
|
+
tmpOrator.initialize(
|
|
603
|
+
() =>
|
|
604
|
+
{
|
|
605
|
+
let tmpStaticPath = libPath.normalize(__dirname + '/static_content/');
|
|
606
|
+
let tmpResult = tmpOrator.addStaticRoute(tmpStaticPath);
|
|
607
|
+
Expect(tmpResult).to.equal(true);
|
|
608
|
+
tmpOrator.log.info(`addStaticRoute mapped [${tmpStaticPath}] successfully`);
|
|
609
|
+
return fDone();
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
test
|
|
615
|
+
(
|
|
616
|
+
'addStaticRoute should accept all optional parameters',
|
|
617
|
+
(fDone) =>
|
|
618
|
+
{
|
|
619
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
620
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
621
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
622
|
+
tmpOrator.initialize(
|
|
623
|
+
() =>
|
|
624
|
+
{
|
|
625
|
+
let tmpStaticPath = libPath.normalize(__dirname + '/static_content/');
|
|
626
|
+
let tmpResult = tmpOrator.addStaticRoute(tmpStaticPath, 'about.html', '/content/*', '/content/', {maxAge: '1d'});
|
|
627
|
+
Expect(tmpResult).to.equal(true);
|
|
628
|
+
tmpOrator.log.info('addStaticRoute accepted all optional parameters');
|
|
629
|
+
return fDone();
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
);
|
|
633
|
+
|
|
634
|
+
test
|
|
635
|
+
(
|
|
636
|
+
'addStaticRoute should reject non-string file paths',
|
|
637
|
+
(fDone) =>
|
|
638
|
+
{
|
|
639
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
640
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
641
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
642
|
+
tmpOrator.initialize(
|
|
643
|
+
() =>
|
|
644
|
+
{
|
|
645
|
+
Expect(tmpOrator.addStaticRoute(42)).to.equal(false);
|
|
646
|
+
Expect(tmpOrator.addStaticRoute(null)).to.equal(false);
|
|
647
|
+
Expect(tmpOrator.addStaticRoute({})).to.equal(false);
|
|
648
|
+
Expect(tmpOrator.addStaticRoute(true)).to.equal(false);
|
|
649
|
+
tmpOrator.log.info('addStaticRoute rejected all non-string file paths');
|
|
650
|
+
return fDone();
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
);
|
|
656
|
+
|
|
657
|
+
suite
|
|
658
|
+
(
|
|
659
|
+
'Route Validation',
|
|
660
|
+
() =>
|
|
661
|
+
{
|
|
662
|
+
test
|
|
663
|
+
(
|
|
664
|
+
'service server should reject non-string route parameters',
|
|
665
|
+
(fDone) =>
|
|
666
|
+
{
|
|
667
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
668
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
669
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
670
|
+
tmpOrator.initialize(
|
|
671
|
+
() =>
|
|
672
|
+
{
|
|
673
|
+
Expect(tmpOrator.serviceServer.get(42)).to.equal(false);
|
|
674
|
+
Expect(tmpOrator.serviceServer.post(null)).to.equal(false);
|
|
675
|
+
Expect(tmpOrator.serviceServer.put(undefined)).to.equal(false);
|
|
676
|
+
Expect(tmpOrator.serviceServer.del({})).to.equal(false);
|
|
677
|
+
Expect(tmpOrator.serviceServer.patch([])).to.equal(false);
|
|
678
|
+
Expect(tmpOrator.serviceServer.opts(true)).to.equal(false);
|
|
679
|
+
tmpOrator.log.info('All verb methods correctly rejected non-string routes');
|
|
680
|
+
return fDone();
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
test
|
|
686
|
+
(
|
|
687
|
+
'service server use should reject non-function handlers',
|
|
688
|
+
(fDone) =>
|
|
689
|
+
{
|
|
690
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
691
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
692
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
693
|
+
tmpOrator.initialize(
|
|
694
|
+
() =>
|
|
695
|
+
{
|
|
696
|
+
Expect(tmpOrator.serviceServer.use('not a function')).to.equal(false);
|
|
697
|
+
Expect(tmpOrator.serviceServer.use(42)).to.equal(false);
|
|
698
|
+
Expect(tmpOrator.serviceServer.use(null)).to.equal(false);
|
|
699
|
+
tmpOrator.log.info('use() correctly rejected non-function handlers');
|
|
700
|
+
return fDone();
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
suite
|
|
708
|
+
(
|
|
709
|
+
'Middleware and Complex Behavior Pipeline',
|
|
710
|
+
() =>
|
|
711
|
+
{
|
|
712
|
+
test
|
|
713
|
+
(
|
|
714
|
+
'multiple pre-behavior functions should execute in order',
|
|
715
|
+
(fDone) =>
|
|
716
|
+
{
|
|
717
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
718
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
719
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
720
|
+
tmpOrator.startService();
|
|
721
|
+
|
|
722
|
+
// Add three pre-behavior functions that build up an array
|
|
723
|
+
tmpOrator.serviceServer.use(
|
|
724
|
+
(pRequest, pResponse, fNext) =>
|
|
725
|
+
{
|
|
726
|
+
pRequest.Pipeline = ['first'];
|
|
727
|
+
return fNext();
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
tmpOrator.serviceServer.use(
|
|
731
|
+
(pRequest, pResponse, fNext) =>
|
|
732
|
+
{
|
|
733
|
+
pRequest.Pipeline.push('second');
|
|
734
|
+
return fNext();
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
tmpOrator.serviceServer.use(
|
|
738
|
+
(pRequest, pResponse, fNext) =>
|
|
739
|
+
{
|
|
740
|
+
pRequest.Pipeline.push('third');
|
|
741
|
+
return fNext();
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
tmpOrator.serviceServer.get
|
|
745
|
+
(
|
|
746
|
+
'/api/pipeline',
|
|
747
|
+
(pRequest, pResponse, fNext) =>
|
|
748
|
+
{
|
|
749
|
+
pResponse.send({Pipeline: pRequest.Pipeline});
|
|
750
|
+
return fNext();
|
|
751
|
+
}
|
|
752
|
+
);
|
|
753
|
+
|
|
754
|
+
tmpOrator.invoke('GET', '/api/pipeline', null,
|
|
755
|
+
(pError, pResponseData) =>
|
|
756
|
+
{
|
|
757
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
758
|
+
Expect(tmpResponseObject.Pipeline).to.be.an('array');
|
|
759
|
+
Expect(tmpResponseObject.Pipeline).to.have.lengthOf(3);
|
|
760
|
+
Expect(tmpResponseObject.Pipeline[0]).to.equal('first');
|
|
761
|
+
Expect(tmpResponseObject.Pipeline[1]).to.equal('second');
|
|
762
|
+
Expect(tmpResponseObject.Pipeline[2]).to.equal('third');
|
|
763
|
+
tmpOrator.log.info(`Pipeline executed in order: ${tmpResponseObject.Pipeline.join(' -> ')}`);
|
|
764
|
+
return fDone();
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
);
|
|
768
|
+
|
|
769
|
+
test
|
|
770
|
+
(
|
|
771
|
+
'pre-behavior and post-behavior functions should bracket the route handler',
|
|
772
|
+
(fDone) =>
|
|
773
|
+
{
|
|
774
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
775
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
776
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
777
|
+
tmpOrator.startService();
|
|
778
|
+
|
|
779
|
+
let tmpExecutionOrder = [];
|
|
780
|
+
|
|
781
|
+
tmpOrator.serviceServer.use(
|
|
782
|
+
(pRequest, pResponse, fNext) =>
|
|
783
|
+
{
|
|
784
|
+
tmpExecutionOrder.push('pre');
|
|
785
|
+
return fNext();
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
tmpOrator.serviceServer.addPostBehaviorFunction(
|
|
789
|
+
(pRequest, pResponse, fNext) =>
|
|
790
|
+
{
|
|
791
|
+
tmpExecutionOrder.push('post');
|
|
792
|
+
return fNext();
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
tmpOrator.serviceServer.get
|
|
796
|
+
(
|
|
797
|
+
'/api/bracket',
|
|
798
|
+
(pRequest, pResponse, fNext) =>
|
|
799
|
+
{
|
|
800
|
+
tmpExecutionOrder.push('handler');
|
|
801
|
+
pResponse.send({Order: 'captured'});
|
|
802
|
+
return fNext();
|
|
803
|
+
}
|
|
804
|
+
);
|
|
805
|
+
|
|
806
|
+
tmpOrator.invoke('GET', '/api/bracket', null,
|
|
807
|
+
(pError, pResponseData) =>
|
|
808
|
+
{
|
|
809
|
+
Expect(tmpExecutionOrder).to.have.lengthOf(3);
|
|
810
|
+
Expect(tmpExecutionOrder[0]).to.equal('pre');
|
|
811
|
+
Expect(tmpExecutionOrder[1]).to.equal('handler');
|
|
812
|
+
Expect(tmpExecutionOrder[2]).to.equal('post');
|
|
813
|
+
tmpOrator.log.info(`Execution order: ${tmpExecutionOrder.join(' -> ')}`);
|
|
814
|
+
return fDone();
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
);
|
|
818
|
+
|
|
819
|
+
test
|
|
820
|
+
(
|
|
821
|
+
'middleware should share request state across separate invoke calls',
|
|
822
|
+
(fDone) =>
|
|
823
|
+
{
|
|
824
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
825
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
826
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
827
|
+
tmpOrator.startService();
|
|
828
|
+
|
|
829
|
+
let tmpRequestCount = 0;
|
|
830
|
+
|
|
831
|
+
// Middleware that counts requests
|
|
832
|
+
tmpOrator.serviceServer.use(
|
|
833
|
+
(pRequest, pResponse, fNext) =>
|
|
834
|
+
{
|
|
835
|
+
tmpRequestCount++;
|
|
836
|
+
pRequest.RequestNumber = tmpRequestCount;
|
|
837
|
+
return fNext();
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
tmpOrator.serviceServer.get
|
|
841
|
+
(
|
|
842
|
+
'/api/counted',
|
|
843
|
+
(pRequest, pResponse, fNext) =>
|
|
844
|
+
{
|
|
845
|
+
pResponse.send({RequestNumber: pRequest.RequestNumber});
|
|
846
|
+
return fNext();
|
|
847
|
+
}
|
|
848
|
+
);
|
|
849
|
+
|
|
850
|
+
tmpFable.Utility.waterfall([
|
|
851
|
+
(fStageComplete) =>
|
|
852
|
+
{
|
|
853
|
+
tmpOrator.invoke('GET', '/api/counted', null,
|
|
854
|
+
(pError, pResponseData) =>
|
|
855
|
+
{
|
|
856
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
857
|
+
Expect(tmpResponseObject.RequestNumber).to.equal(1);
|
|
858
|
+
return fStageComplete();
|
|
859
|
+
});
|
|
860
|
+
},
|
|
861
|
+
(fStageComplete) =>
|
|
862
|
+
{
|
|
863
|
+
tmpOrator.invoke('GET', '/api/counted', null,
|
|
864
|
+
(pError, pResponseData) =>
|
|
865
|
+
{
|
|
866
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
867
|
+
Expect(tmpResponseObject.RequestNumber).to.equal(2);
|
|
868
|
+
return fStageComplete();
|
|
869
|
+
});
|
|
870
|
+
},
|
|
871
|
+
(fStageComplete) =>
|
|
872
|
+
{
|
|
873
|
+
tmpOrator.invoke('GET', '/api/counted', null,
|
|
874
|
+
(pError, pResponseData) =>
|
|
875
|
+
{
|
|
876
|
+
let tmpResponseObject = JSON.parse(pResponseData);
|
|
877
|
+
Expect(tmpResponseObject.RequestNumber).to.equal(3);
|
|
878
|
+
return fStageComplete();
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
],
|
|
882
|
+
(pError) =>
|
|
883
|
+
{
|
|
884
|
+
Expect(tmpRequestCount).to.equal(3);
|
|
885
|
+
tmpOrator.log.info(`Request counter middleware tracked ${tmpRequestCount} invocations`);
|
|
886
|
+
return fDone();
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
);
|
|
892
|
+
|
|
893
|
+
suite
|
|
894
|
+
(
|
|
895
|
+
'IPC Server Properties',
|
|
896
|
+
() =>
|
|
897
|
+
{
|
|
898
|
+
test
|
|
899
|
+
(
|
|
900
|
+
'ipc service server should have correct properties',
|
|
901
|
+
(fDone) =>
|
|
902
|
+
{
|
|
903
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
904
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
905
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
906
|
+
tmpOrator.initialize(
|
|
907
|
+
() =>
|
|
908
|
+
{
|
|
909
|
+
Expect(tmpOrator.serviceServer.ServiceServerType).to.equal('IPC');
|
|
910
|
+
Expect(tmpOrator.serviceServer.URL).to.equal('IPC');
|
|
911
|
+
Expect(tmpOrator.serviceServer.Port).to.equal(0);
|
|
912
|
+
Expect(tmpOrator.serviceServer.Active).to.equal(false);
|
|
913
|
+
Expect(tmpOrator.serviceServer.Name).to.equal('Orator-ComplexRouteTests');
|
|
914
|
+
tmpOrator.log.info('IPC service server properties verified');
|
|
915
|
+
return fDone();
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
);
|
|
919
|
+
|
|
920
|
+
test
|
|
921
|
+
(
|
|
922
|
+
'ipc bodyParser should return a passthrough function',
|
|
923
|
+
(fDone) =>
|
|
924
|
+
{
|
|
925
|
+
let tmpFable = new libFable(defaultFableSettings);
|
|
926
|
+
tmpFable.serviceManager.addServiceType('Orator', libOrator);
|
|
927
|
+
let tmpOrator = tmpFable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
928
|
+
tmpOrator.initialize(
|
|
929
|
+
() =>
|
|
930
|
+
{
|
|
931
|
+
let tmpBodyParser = tmpOrator.serviceServer.bodyParser();
|
|
932
|
+
Expect(tmpBodyParser).to.be.a('function');
|
|
933
|
+
// The IPC body parser should be a no-op passthrough
|
|
934
|
+
let tmpNextCalled = false;
|
|
935
|
+
tmpBodyParser({}, {},
|
|
936
|
+
() =>
|
|
937
|
+
{
|
|
938
|
+
tmpNextCalled = true;
|
|
939
|
+
});
|
|
940
|
+
Expect(tmpNextCalled).to.equal(true);
|
|
941
|
+
tmpOrator.log.info('IPC bodyParser is a passthrough function');
|
|
942
|
+
return fDone();
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
);
|