iotagent-node-lib 4.5.0 → 4.6.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.
Files changed (84) hide show
  1. package/README.md +67 -272
  2. package/doc/README.md +1 -1
  3. package/doc/admin.md +3 -15
  4. package/doc/api.md +469 -134
  5. package/doc/deprecated.md +4 -0
  6. package/doc/devel/architecture.md +5 -135
  7. package/doc/devel/development.md +224 -12
  8. package/doc/getting-started.md +114 -53
  9. package/doc/roadmap.md +5 -5
  10. package/docker/Mosquitto/Dockerfile +2 -2
  11. package/docker/Mosquitto/README.md +14 -11
  12. package/lib/constants.js +3 -0
  13. package/lib/fiware-iotagent-lib.js +12 -15
  14. package/lib/jexlTranformsMap.js +3 -1
  15. package/lib/model/dbConn.js +1 -4
  16. package/lib/services/common/alarmManagement.js +3 -0
  17. package/lib/services/groups/groupService.js +1 -1
  18. package/lib/services/ngsi/entities-NGSI-LD.js +320 -570
  19. package/lib/services/ngsi/entities-NGSI-v2.js +36 -1
  20. package/lib/services/ngsi/ngsiService.js +3 -1
  21. package/lib/services/northBound/deviceGroupAdministrationServer.js +42 -6
  22. package/lib/services/northBound/deviceProvisioningServer.js +0 -1
  23. package/lib/services/northBound/northboundServer.js +2 -0
  24. package/lib/services/stats/statsRegistry.js +128 -101
  25. package/lib/templates/createDevice.json +0 -24
  26. package/lib/templates/createDeviceLax.json +0 -23
  27. package/lib/templates/deviceGroup.json +1 -25
  28. package/lib/templates/updateDevice.json +0 -24
  29. package/lib/templates/updateDeviceLax.json +0 -23
  30. package/package.json +2 -2
  31. package/scripts/legacy_expression_tool/README.md +0 -1
  32. package/test/functional/README.md +22 -17
  33. package/test/functional/functional-tests-runner.js +9 -4
  34. package/test/functional/functional-tests.js +4 -4
  35. package/test/functional/testCases.js +245 -4
  36. package/test/unit/examples/deviceProvisioningRequests/provisionFullDevice.json +1 -13
  37. package/test/unit/examples/groupProvisioningRequests/multipleConfigGroupsCreation.json +44 -0
  38. package/test/unit/examples/groupProvisioningRequests/provisionDuplicateConfigGroup.json +35 -0
  39. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroup.json +36 -0
  40. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroupAlternate.json +36 -0
  41. package/test/unit/general/deviceService-test.js +102 -0
  42. package/test/unit/general/statistics-service_test.js +1 -74
  43. package/test/unit/mongodb/mongodb-configGroup-registry-test.js +452 -0
  44. package/test/unit/mongodb/mongodb-connectionoptions-test.js +2 -3
  45. package/test/unit/mongodb/mongodb-group-registry-test.js +34 -33
  46. package/test/unit/mongodb/mongodb-service-registry-test.js +477 -0
  47. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin1a.json +4 -4
  48. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin2.json +22 -22
  49. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin29.json +4 -4
  50. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin32.json +14 -15
  51. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin1.json +23 -23
  52. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin15.json +0 -5
  53. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin4.json +11 -16
  54. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin5.json +23 -28
  55. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin6.json +8 -13
  56. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin7.json +0 -5
  57. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin8.json +24 -29
  58. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin2.json +12 -17
  59. package/test/unit/ngsi-ld/examples/contextRequests/updateContextStaticLinkedAttributes.json +12 -10
  60. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +0 -102
  61. package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +4 -5
  62. package/test/unit/ngsi-ld/provisioning/listProvisionedDevices-test.js +0 -4
  63. package/test/unit/ngsiv2/general/deviceService-test.js +94 -1
  64. package/test/unit/ngsiv2/general/iotam-autoregistration-test.js +195 -0
  65. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +259 -0
  66. package/test/unit/ngsiv2/provisioning/device-provisioning-configGroup-api_test.js +1189 -0
  67. package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +0 -4
  68. package/test/unit/statsRegistry/openmetrics-test.js +167 -0
  69. package/lib/templates/queryContext.json +0 -25
  70. package/test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json +0 -35
  71. package/test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json +0 -17
  72. package/test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json +0 -31
  73. package/test/unit/general/statistics-persistence_test.js +0 -121
  74. package/test/unit/ngsi-ld/examples/contextRequests/createBidirectionalDevice.json +0 -17
  75. package/test/unit/ngsi-ld/examples/contextRequests/updateContextProcessTimestamp.json +0 -12
  76. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  77. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithDatasetId.json +0 -21
  78. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -17
  79. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -23
  80. package/test/unit/ngsi-ld/plugins/timestamp-processing-plugin_test.js +0 -132
  81. package/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json +0 -8
  82. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  83. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -19
  84. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -24
@@ -156,6 +156,34 @@ const groupCreation = {
156
156
  'fiware-servicepath': '/testingPath'
157
157
  }
158
158
  };
159
+ const configGroupCreation = {
160
+ url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/groups',
161
+ method: 'POST',
162
+ json: {
163
+ groups: [
164
+ {
165
+ resource: '',
166
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
167
+ entity_type: 'TheLightType',
168
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
169
+ cbHost: 'http://192.168.1.1:1026',
170
+ commands: [],
171
+ lazy: [],
172
+ attributes: [
173
+ {
174
+ name: 'status',
175
+ type: 'Boolean'
176
+ }
177
+ ],
178
+ static_attributes: []
179
+ }
180
+ ]
181
+ },
182
+ headers: {
183
+ 'fiware-service': 'testservice',
184
+ 'fiware-servicepath': '/testingPath'
185
+ }
186
+ };
159
187
  const deviceCreation = {
160
188
  url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices',
161
189
  method: 'POST',
@@ -182,7 +210,7 @@ describe('NGSI-v2 - Device Service: utils', function () {
182
210
  nock.cleanAll();
183
211
  async.series([iotAgentLib.clearAll, iotAgentLib.deactivate], done);
184
212
  });
185
-
213
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
186
214
  describe('When an existing device tries to be retrieved with retrieveOrCreate()', function () {
187
215
  beforeEach(function (done) {
188
216
  // This mock does not check the payload since the aim of the test is not to verify
@@ -212,7 +240,39 @@ describe('NGSI-v2 - Device Service: utils', function () {
212
240
  });
213
241
  });
214
242
  });
243
+ describe('When an existing device tries to be retrieved with retrieveOrCreate()', function () {
244
+ beforeEach(function (done) {
245
+ // This mock does not check the payload since the aim of the test is not to verify
246
+ // device provisioning functionality. Appropriate verification is done in tests under
247
+ // provisioning folder
248
+ contextBrokerMock = nock('http://192.168.1.1:1026')
249
+ .matchHeader('fiware-service', 'testservice')
250
+ .matchHeader('fiware-servicepath', '/testingPath')
251
+ .post('/v2/entities?options=upsert')
252
+ .reply(204);
253
+
254
+ async.series(
255
+ [
256
+ utils.request.bind(utils.request, configGroupCreation),
257
+ utils.request.bind(utils.request, deviceCreation)
258
+ ],
259
+ function (error, results) {
260
+ done();
261
+ }
262
+ );
263
+ });
264
+
265
+ it('should return the existing device', function (done) {
266
+ iotAgentLib.retrieveDevice('Light1', '801230BJKL23Y9090DSFL123HJK09H324HV8732', function (error, device) {
267
+ should.not.exist(error);
268
+ should.exist(device);
215
269
 
270
+ device.id.should.equal('Light1');
271
+ done();
272
+ });
273
+ });
274
+ });
275
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
216
276
  describe('When an unexisting device tries to be retrieved for an existing APIKey', function () {
217
277
  beforeEach(function (done) {
218
278
  // This mock does not check the payload since the aim of the test is not to verify
@@ -246,6 +306,39 @@ describe('NGSI-v2 - Device Service: utils', function () {
246
306
  });
247
307
  });
248
308
 
309
+ describe('When an unexisting device tries to be retrieved for an existing APIKey', function () {
310
+ beforeEach(function (done) {
311
+ // This mock does not check the payload since the aim of the test is not to verify
312
+ // device provisioning functionality. Appropriate verification is done in tests under
313
+ // provisioning folder
314
+ contextBrokerMock = nock('http://192.168.1.1:1026')
315
+ .matchHeader('fiware-service', 'testservice')
316
+ .matchHeader('fiware-servicepath', '/testingPath')
317
+ .post('/v2/entities?options=upsert')
318
+ .reply(204);
319
+
320
+ async.series([utils.request.bind(utils.request, configGroupCreation)], function (error, results) {
321
+ done();
322
+ });
323
+ });
324
+
325
+ it('should register the device and return it', function (done) {
326
+ iotAgentLib.retrieveDevice(
327
+ 'UNEXISTENT_DEV',
328
+ '801230BJKL23Y9090DSFL123HJK09H324HV8732',
329
+ function (error, device) {
330
+ should.not.exist(error);
331
+ should.exist(device);
332
+
333
+ device.id.should.equal('UNEXISTENT_DEV');
334
+ should.exist(device.protocol);
335
+ device.protocol.should.equal('MQTT_UL');
336
+ done();
337
+ }
338
+ );
339
+ });
340
+ });
341
+
249
342
  describe('When an unexisting device tries to be retrieved for an unexisting APIKey', function () {
250
343
  it('should raise an error', function (done) {
251
344
  iotAgentLib.retrieveDevice(
@@ -134,6 +134,43 @@ const optionsCreation = {
134
134
  'fiware-servicepath': 'theSubService'
135
135
  }
136
136
  };
137
+ const configGroupCreation = {
138
+ url: 'http://localhost:4041/iot/groups',
139
+ method: 'POST',
140
+ json: {
141
+ groups: [
142
+ {
143
+ resource: '/deviceTest',
144
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
145
+ entity_type: 'SensorMachine',
146
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
147
+ cbHost: 'http://unexistentHost:1026',
148
+ commands: [
149
+ {
150
+ name: 'wheel1',
151
+ type: 'Wheel'
152
+ }
153
+ ],
154
+ lazy: [
155
+ {
156
+ name: 'luminescence',
157
+ type: 'Lumens'
158
+ }
159
+ ],
160
+ attributes: [
161
+ {
162
+ name: 'status',
163
+ type: 'Boolean'
164
+ }
165
+ ]
166
+ }
167
+ ]
168
+ },
169
+ headers: {
170
+ 'fiware-service': 'theservice',
171
+ 'fiware-servicepath': 'theSubService'
172
+ }
173
+ };
137
174
  const optionsCreationStatic = {
138
175
  url: 'http://localhost:4041/iot/services',
139
176
  method: 'POST',
@@ -172,6 +209,44 @@ const optionsCreationStatic = {
172
209
  'fiware-servicepath': 'theSubService'
173
210
  }
174
211
  };
212
+ const configGroupCreationStatic = {
213
+ url: 'http://localhost:4041/iot/groups',
214
+ method: 'POST',
215
+ json: {
216
+ groups: [
217
+ {
218
+ resource: '/deviceTest',
219
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
220
+ entity_type: 'SensorMachine',
221
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
222
+ cbHost: 'http://unexistentHost:1026',
223
+ commands: [
224
+ {
225
+ name: 'wheel1',
226
+ type: 'Wheel'
227
+ }
228
+ ],
229
+ static_attributes: [
230
+ {
231
+ name: 'position',
232
+ type: 'location',
233
+ values: '123,12'
234
+ }
235
+ ],
236
+ attributes: [
237
+ {
238
+ name: 'status',
239
+ type: 'Boolean'
240
+ }
241
+ ]
242
+ }
243
+ ]
244
+ },
245
+ headers: {
246
+ 'fiware-service': 'theservice',
247
+ 'fiware-servicepath': 'theSubService'
248
+ }
249
+ };
175
250
  const optionsDelete = {
176
251
  url: 'http://localhost:4041/iot/services',
177
252
  method: 'DELETE',
@@ -185,6 +260,19 @@ const optionsDelete = {
185
260
  apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
186
261
  }
187
262
  };
263
+ const configGroupDelete = {
264
+ url: 'http://localhost:4041/iot/groups',
265
+ method: 'DELETE',
266
+ json: {},
267
+ headers: {
268
+ 'fiware-service': 'theservice',
269
+ 'fiware-servicepath': 'theSubService'
270
+ },
271
+ qs: {
272
+ resource: '/deviceTest',
273
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
274
+ }
275
+ };
188
276
  let iotamMock;
189
277
 
190
278
  describe('NGSI-v2 - IoT Manager autoregistration', function () {
@@ -263,6 +351,7 @@ describe('NGSI-v2 - IoT Manager autoregistration', function () {
263
351
  });
264
352
  });
265
353
 
354
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
266
355
  describe('When a new service is created in the IoT Agent', function () {
267
356
  beforeEach(function (done) {
268
357
  nock.cleanAll();
@@ -298,6 +387,42 @@ describe('NGSI-v2 - IoT Manager autoregistration', function () {
298
387
  });
299
388
  });
300
389
 
390
+ describe('When a new configGroup is created in the IoT Agent', function () {
391
+ beforeEach(function (done) {
392
+ nock.cleanAll();
393
+
394
+ iotamMock = nock('http://mockediotam.com:9876')
395
+ .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json'))
396
+ .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json'));
397
+
398
+ iotamMock
399
+ .post(
400
+ '/protocols',
401
+ utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')
402
+ )
403
+ .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json'));
404
+
405
+ iotAgentLib.activate(iotAgentConfig, function (error) {
406
+ done();
407
+ });
408
+ });
409
+
410
+ afterEach(function (done) {
411
+ groupRegistryMemory.clear(function () {
412
+ iotAgentLib.deactivate(done);
413
+ });
414
+ });
415
+
416
+ it('should update the registration in the IoT Manager', function (done) {
417
+ request(configGroupCreation, function (error, result, body) {
418
+ should.not.exist(error);
419
+ iotamMock.done();
420
+ done();
421
+ });
422
+ });
423
+ });
424
+
425
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
301
426
  describe('When a service is removed from the IoT Agent', function () {
302
427
  beforeEach(function (done) {
303
428
  nock.cleanAll();
@@ -333,6 +458,42 @@ describe('NGSI-v2 - IoT Manager autoregistration', function () {
333
458
  });
334
459
  });
335
460
 
461
+ describe('When a configGroup is removed from the IoT Agent', function () {
462
+ beforeEach(function (done) {
463
+ nock.cleanAll();
464
+
465
+ iotamMock = nock('http://mockediotam.com:9876')
466
+ .post(
467
+ '/protocols',
468
+ utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')
469
+ )
470
+ .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json'));
471
+
472
+ iotamMock
473
+ .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json'))
474
+ .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json'));
475
+
476
+ groupRegistryMemory.create(groupCreation, function () {
477
+ iotAgentLib.activate(iotAgentConfig, done);
478
+ });
479
+ });
480
+
481
+ afterEach(function (done) {
482
+ groupRegistryMemory.clear(function () {
483
+ iotAgentLib.deactivate(done);
484
+ });
485
+ });
486
+
487
+ it('should update the registration in the IoT Manager', function (done) {
488
+ request(configGroupDelete, function (error, result, body) {
489
+ should.not.exist(error);
490
+ iotamMock.done();
491
+ done();
492
+ });
493
+ });
494
+ });
495
+
496
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
336
497
  describe('When a new service with static attributes is created in the IoT Agent', function () {
337
498
  beforeEach(function (done) {
338
499
  nock.cleanAll();
@@ -367,4 +528,38 @@ describe('NGSI-v2 - IoT Manager autoregistration', function () {
367
528
  });
368
529
  });
369
530
  });
531
+ describe('When a new configGroup with static attributes is created in the IoT Agent', function () {
532
+ beforeEach(function (done) {
533
+ nock.cleanAll();
534
+
535
+ iotamMock = nock('http://mockediotam.com:9876')
536
+ .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json'))
537
+ .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json'));
538
+
539
+ iotamMock
540
+ .post(
541
+ '/protocols',
542
+ utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithStaticGroups.json')
543
+ )
544
+ .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json'));
545
+
546
+ iotAgentLib.activate(iotAgentConfig, function (error) {
547
+ done();
548
+ });
549
+ });
550
+
551
+ afterEach(function (done) {
552
+ groupRegistryMemory.clear(function () {
553
+ iotAgentLib.deactivate(done);
554
+ });
555
+ });
556
+
557
+ it('should update the registration in the IoT Manager', function (done) {
558
+ request(configGroupCreationStatic, function (error, result, body) {
559
+ should.not.exist(error);
560
+ iotamMock.done();
561
+ done();
562
+ });
563
+ });
564
+ });
370
565
  });
@@ -23,6 +23,8 @@
23
23
 
24
24
  /* eslint-disable no-unused-vars */
25
25
 
26
+ // #FIXME1649: parallel tests in device-provisioning-configGroup-api_test.js.
27
+
26
28
  const iotAgentLib = require('../../../../lib/fiware-iotagent-lib');
27
29
  const _ = require('underscore');
28
30
  const async = require('async');
@@ -118,6 +120,19 @@ const optionsDelete = {
118
120
  apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
119
121
  }
120
122
  };
123
+ const optionsDeleteGroup = {
124
+ url: 'http://localhost:4041/iot/services',
125
+ method: 'DELETE',
126
+ json: {},
127
+ headers: {
128
+ 'fiware-service': 'Testservice',
129
+ 'fiware-servicepath': '/testingPath'
130
+ },
131
+ qs: {
132
+ resource: '/deviceTest',
133
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
134
+ }
135
+ };
121
136
  const optionsDeleteDevice = {
122
137
  url: 'http://localhost:4041/iot/services',
123
138
  method: 'DELETE',
@@ -175,6 +190,49 @@ const optionsUpdate = {
175
190
  apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
176
191
  }
177
192
  };
193
+ const optionsUpdateGroup = {
194
+ url: 'http://localhost:4041/iot/services',
195
+ method: 'PUT',
196
+ json: {
197
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
198
+ cbHost: 'http://anotherUnexistentHost:1026',
199
+ transport: 'MQTT',
200
+ endpoint: 'http://yourendpoint.com',
201
+ commands: [
202
+ {
203
+ name: 'wheel1',
204
+ type: 'Wheel'
205
+ }
206
+ ],
207
+ lazy: [
208
+ {
209
+ name: 'luminescence',
210
+ type: 'Lumens'
211
+ }
212
+ ],
213
+ attributes: [
214
+ {
215
+ name: 'status',
216
+ type: 'Boolean'
217
+ }
218
+ ],
219
+ static_attributes: [
220
+ {
221
+ name: 'identifier',
222
+ type: 'UUID',
223
+ value: 'WERTYUIOP234567890'
224
+ }
225
+ ]
226
+ },
227
+ headers: {
228
+ 'fiware-service': 'Testservice',
229
+ 'fiware-servicepath': '/testingPath'
230
+ },
231
+ qs: {
232
+ resource: '/deviceTest',
233
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
234
+ }
235
+ };
178
236
  const optionsList = {
179
237
  url: 'http://localhost:4041/iot/services',
180
238
  method: 'GET',
@@ -194,6 +252,20 @@ const optionsGet = {
194
252
  }
195
253
  };
196
254
 
255
+ // Add new options using the literal groups instead of services
256
+ const configGroupTerm = 'groups';
257
+
258
+ const newOptionsCreation = JSON.parse(JSON.stringify(optionsCreation));
259
+ newOptionsCreation.url = newOptionsCreation.url.replace('services', configGroupTerm);
260
+ newOptionsCreation.json[configGroupTerm] = newOptionsCreation.json.services;
261
+ delete newOptionsCreation.json.services;
262
+
263
+ const newOptionsList = JSON.parse(JSON.stringify(optionsList));
264
+ newOptionsList.url = newOptionsList.url.replace('services', configGroupTerm);
265
+
266
+ const newOptionsGet = JSON.parse(JSON.stringify(optionsGet));
267
+ newOptionsGet.url = newOptionsGet.url.replace('services', configGroupTerm);
268
+
197
269
  describe('NGSI-v2 - Device Group Configuration API', function () {
198
270
  beforeEach(function (done) {
199
271
  iotAgentLib.activate(iotAgentConfig, function () {
@@ -411,6 +483,33 @@ describe('NGSI-v2 - Device Group Configuration API', function () {
411
483
  });
412
484
  });
413
485
  });
486
+ describe('When a device group removal request arrives with service-header in uppercase', function () {
487
+ beforeEach(function (done) {
488
+ request(optionsCreation, done);
489
+ });
490
+
491
+ it('should return a 204 OK', function (done) {
492
+ request(optionsDeleteGroup, function (error, response, body) {
493
+ should.not.exist(error);
494
+ response.statusCode.should.equal(204);
495
+ done();
496
+ });
497
+ });
498
+ it('should remove it from the database', function (done) {
499
+ request(optionsDeleteGroup, function (error, response, body) {
500
+ request(optionsList, function (error, response, body) {
501
+ body.count.should.equal(0);
502
+ done();
503
+ });
504
+ });
505
+ });
506
+ it('should remove it from the configuration', function (done) {
507
+ request(optionsDeleteGroup, function (error, response, body) {
508
+ should.not.exist(iotAgentConfig.types.SensorMachine);
509
+ done();
510
+ });
511
+ });
512
+ });
414
513
  describe('When a device group removal request arrives with device=true option', function () {
415
514
  let contextBrokerMock;
416
515
 
@@ -704,6 +803,83 @@ describe('NGSI-v2 - Device Group Configuration API', function () {
704
803
  });
705
804
  });
706
805
 
806
+ describe('When a device group update request arrives with service-header in uppercase', function () {
807
+ beforeEach(function (done) {
808
+ const optionsCreation1 = _.clone(optionsCreation);
809
+ const optionsCreation2 = _.clone(optionsCreation);
810
+ const optionsCreation3 = _.clone(optionsCreation);
811
+
812
+ optionsCreation1.json = { services: [] };
813
+ optionsCreation3.json = { services: [] };
814
+
815
+ optionsCreation1.json.services[0] = _.clone(optionsCreation.json.services[0]);
816
+ optionsCreation3.json.services[0] = _.clone(optionsCreation.json.services[0]);
817
+
818
+ optionsCreation1.json.services[0].apikey = 'qwertyuiop';
819
+ optionsCreation3.json.services[0].apikey = 'lkjhgfds';
820
+
821
+ async.series(
822
+ [
823
+ async.apply(request, optionsCreation1),
824
+ async.apply(request, optionsCreation2),
825
+ async.apply(request, optionsCreation3)
826
+ ],
827
+ done
828
+ );
829
+ });
830
+
831
+ it('should return a 204 OK', function (done) {
832
+ request(optionsUpdateGroup, function (error, response, body) {
833
+ should.not.exist(error);
834
+ response.statusCode.should.equal(204);
835
+ done();
836
+ });
837
+ });
838
+ it('should update the appropriate values in the database', function (done) {
839
+ request(optionsUpdateGroup, function (error, response, body) {
840
+ request(optionsList, function (error, response, body) {
841
+ let found = false;
842
+ body.count.should.equal(3);
843
+
844
+ for (let i = 0; i < body.services.length; i++) {
845
+ if (
846
+ body.services[i].apikey === '801230BJKL23Y9090DSFL123HJK09H324HV8732' &&
847
+ body.services[i].resource === '/deviceTest'
848
+ ) {
849
+ body.services[i].cbHost.should.equal('http://anotherUnexistentHost:1026');
850
+ body.services[i].static_attributes.length.should.equal(1);
851
+ found = true;
852
+ }
853
+ }
854
+
855
+ found.should.equal(true);
856
+ done();
857
+ });
858
+ });
859
+ });
860
+ it('should call the configuration creation handler', function (done) {
861
+ let handlerCalled = false;
862
+
863
+ iotAgentLib.setConfigurationHandler(function (newConfiguration, callback) {
864
+ should.exist(newConfiguration);
865
+ should.exist(callback);
866
+ newConfiguration.cbHost.should.equal('http://anotherUnexistentHost:1026');
867
+ newConfiguration.trust.should.equal('8970A9078A803H3BL98PINEQRW8342HBAMS');
868
+ newConfiguration.service.should.equal('Testservice');
869
+ newConfiguration.subservice.should.equal('/testingPath');
870
+ newConfiguration.resource.should.equal('/deviceTest');
871
+ newConfiguration.apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732');
872
+ handlerCalled = true;
873
+ callback();
874
+ });
875
+
876
+ request(optionsUpdateGroup, function (error, response, body) {
877
+ handlerCalled.should.equal(true);
878
+ done();
879
+ });
880
+ });
881
+ });
882
+
707
883
  describe('When a device group update request arrives declaring a different service', function () {
708
884
  beforeEach(function (done) {
709
885
  optionsUpdate.headers['fiware-service'] = 'UnexistentService';
@@ -996,4 +1172,87 @@ describe('NGSI-v2 - Device Group Configuration API', function () {
996
1172
  });
997
1173
  });
998
1174
  });
1175
+
1176
+ describe('When a new device group creation request arrives with the NEW API endpoint ', function () {
1177
+ it('should return a 200 OK', function (done) {
1178
+ request(newOptionsCreation, function (error, response, body) {
1179
+ should.not.exist(error);
1180
+ response.statusCode.should.equal(201);
1181
+ done();
1182
+ });
1183
+ });
1184
+ it('should be recovered using the OLD API endpoint', function (done) {
1185
+ request(newOptionsCreation, function (error, response, body) {
1186
+ request(optionsList, function (error, response, body) {
1187
+ body.count.should.equal(1);
1188
+ body.services[0].apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732');
1189
+ body.services[0].transport.should.equal('HTTP');
1190
+ body.services[0].endpoint.should.equal('http://myendpoint.com');
1191
+
1192
+ body.count.should.equal(1);
1193
+ should.exist(body.services[0].attributes);
1194
+ body.services[0].attributes.length.should.equal(1);
1195
+ body.services[0].attributes[0].name.should.equal('status');
1196
+
1197
+ should.exist(body.services[0].lazy);
1198
+ body.services[0].lazy.length.should.equal(1);
1199
+ body.services[0].lazy[0].name.should.equal('luminescence');
1200
+
1201
+ should.exist(body.services[0].commands);
1202
+ body.services[0].commands.length.should.equal(1);
1203
+ body.services[0].commands[0].name.should.equal('wheel1');
1204
+
1205
+ should.exist(body.services[0].static_attributes);
1206
+ body.services[0].static_attributes.length.should.equal(1);
1207
+ body.services[0].static_attributes[0].name.should.equal('bootstrapServer');
1208
+
1209
+ body.count.should.equal(1);
1210
+ body.services[0].service.should.equal('testservice');
1211
+ body.services[0].subservice.should.equal('/testingPath');
1212
+ done();
1213
+ });
1214
+ });
1215
+ });
1216
+ });
1217
+ describe('When a new device group creation request arrives with the NEW OLD endpoint ', function () {
1218
+ it('should return a 200 OK', function (done) {
1219
+ request(optionsCreation, function (error, response, body) {
1220
+ should.not.exist(error);
1221
+ response.statusCode.should.equal(201);
1222
+ done();
1223
+ });
1224
+ });
1225
+ it('should be recovered using the NEW API endpoint', function (done) {
1226
+ request(optionsCreation, function (error, response, body) {
1227
+ request(newOptionsList, function (error, response, body) {
1228
+ body.count.should.equal(1);
1229
+ body[configGroupTerm][0].apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732');
1230
+ body[configGroupTerm][0].transport.should.equal('HTTP');
1231
+ body[configGroupTerm][0].endpoint.should.equal('http://myendpoint.com');
1232
+
1233
+ body.count.should.equal(1);
1234
+ should.exist(body[configGroupTerm][0].attributes);
1235
+ body[configGroupTerm][0].attributes.length.should.equal(1);
1236
+ body[configGroupTerm][0].attributes[0].name.should.equal('status');
1237
+
1238
+ should.exist(body[configGroupTerm][0].lazy);
1239
+ body[configGroupTerm][0].lazy.length.should.equal(1);
1240
+ body[configGroupTerm][0].lazy[0].name.should.equal('luminescence');
1241
+
1242
+ should.exist(body[configGroupTerm][0].commands);
1243
+ body[configGroupTerm][0].commands.length.should.equal(1);
1244
+ body[configGroupTerm][0].commands[0].name.should.equal('wheel1');
1245
+
1246
+ should.exist(body[configGroupTerm][0].static_attributes);
1247
+ body[configGroupTerm][0].static_attributes.length.should.equal(1);
1248
+ body[configGroupTerm][0].static_attributes[0].name.should.equal('bootstrapServer');
1249
+
1250
+ body.count.should.equal(1);
1251
+ body[configGroupTerm][0].service.should.equal('testservice');
1252
+ body[configGroupTerm][0].subservice.should.equal('/testingPath');
1253
+ done();
1254
+ });
1255
+ });
1256
+ });
1257
+ });
999
1258
  });