@webex/internal-plugin-device 2.59.3-next.1 → 2.59.4

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 (41) hide show
  1. package/.eslintrc.js +6 -6
  2. package/README.md +80 -80
  3. package/babel.config.js +3 -3
  4. package/dist/config.js +27 -27
  5. package/dist/config.js.map +1 -1
  6. package/dist/constants.js.map +1 -1
  7. package/dist/device.js +226 -226
  8. package/dist/device.js.map +1 -1
  9. package/dist/features/feature-collection.js +14 -14
  10. package/dist/features/feature-collection.js.map +1 -1
  11. package/dist/features/feature-model.js +73 -73
  12. package/dist/features/feature-model.js.map +1 -1
  13. package/dist/features/features-model.js +28 -28
  14. package/dist/features/features-model.js.map +1 -1
  15. package/dist/features/index.js.map +1 -1
  16. package/dist/index.js +4 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/interceptors/device-url.js +8 -8
  19. package/dist/interceptors/device-url.js.map +1 -1
  20. package/dist/metrics.js.map +1 -1
  21. package/jest.config.js +3 -3
  22. package/package.json +16 -17
  23. package/process +1 -1
  24. package/src/config.js +60 -60
  25. package/src/constants.js +23 -23
  26. package/src/device.js +835 -835
  27. package/src/features/feature-collection.js +30 -30
  28. package/src/features/feature-model.js +189 -189
  29. package/src/features/features-model.js +96 -96
  30. package/src/features/index.js +5 -5
  31. package/src/index.js +29 -29
  32. package/src/interceptors/device-url.js +61 -61
  33. package/src/metrics.js +5 -5
  34. package/test/integration/spec/device.js +904 -904
  35. package/test/integration/spec/webex.js +42 -42
  36. package/test/unit/spec/device.js +409 -409
  37. package/test/unit/spec/features/feature-collection.js +24 -24
  38. package/test/unit/spec/features/feature-model.js +255 -255
  39. package/test/unit/spec/features/features-model.js +97 -97
  40. package/test/unit/spec/interceptors/device-url.js +215 -215
  41. package/test/unit/spec/wdm-dto.json +104 -104
@@ -1,409 +1,409 @@
1
- import {assert} from '@webex/test-helper-chai';
2
- import {cloneDeep} from 'lodash';
3
- import MockWebex from '@webex/test-helper-mock-webex';
4
- import sinon from 'sinon';
5
- import Device from '@webex/internal-plugin-device';
6
-
7
- import dto from './wdm-dto';
8
-
9
- describe('plugin-device', () => {
10
- describe('Device', () => {
11
- let webex;
12
- let device;
13
-
14
- beforeEach(() => {
15
- webex = new MockWebex({
16
- children: {
17
- device: Device,
18
- },
19
- });
20
-
21
- const clonedDTO = cloneDeep(dto);
22
-
23
- webex.internal.device.set(clonedDTO);
24
-
25
- device = webex.internal.device;
26
- });
27
-
28
- describe('events', () => {
29
- describe('when a feature is changed', () => {
30
- let spy;
31
- let modifiedDTOFeatures;
32
-
33
- beforeEach(() => {
34
- spy = sinon.spy();
35
- modifiedDTOFeatures = {
36
- ...dto.features,
37
- user: [...dto.features.user, ...dto.features.developer],
38
- };
39
- });
40
-
41
- it("should trigger a 'change' event", () => {
42
- device.on('change', spy);
43
- device.features.set(modifiedDTOFeatures);
44
- assert.called(spy);
45
- });
46
-
47
- it("should trigger a 'change:features' event", () => {
48
- device.on('change:features', spy);
49
- device.features.set(modifiedDTOFeatures);
50
- assert.called(spy);
51
- });
52
- });
53
-
54
- describe('when an network inactivity property changes', () => {
55
- beforeEach(() => {
56
- device.checkNetworkReachability = sinon.spy();
57
- });
58
-
59
- describe('when the \'intranetInactivityCheckUrl\' changes', () => {
60
- beforeEach(() => {
61
- device.intranetInactivityCheckUrl = 'https://not-a-url.com';
62
- });
63
-
64
- it("should call 'checkNetworkReachability()'", () => {
65
- assert.called(device.checkNetworkReachability);
66
- });
67
-
68
- it('should set isReachabilityChecked to true', () => {
69
- assert.isTrue(device.isReachabilityChecked);
70
- });
71
- });
72
-
73
- describe('when the \'intranetInactivityDuration\' changes', () => {
74
- beforeEach(() => {
75
- device.intranetInactivityDuration = 1234;
76
- });
77
-
78
- it("should call 'checkNetworkReachability()'", () => {
79
- assert.called(device.checkNetworkReachability);
80
- });
81
-
82
- it('should set isReachabilityChecked to true', () => {
83
- assert.isTrue(device.isReachabilityChecked);
84
- });
85
- });
86
-
87
- describe('when the \'inNetworkInactivityDuration\' changes', () => {
88
- beforeEach(() => {
89
- device.inNetworkInactivityDuration = 1234;
90
- });
91
-
92
- it("should call 'checkNetworkReachability()'", () => {
93
- assert.called(device.checkNetworkReachability);
94
- assert.isTrue(device.isReachabilityChecked);
95
- });
96
- });
97
- });
98
- });
99
-
100
- describe('derived properties', () => {
101
- describe('#registered', () => {
102
- describe('when the device does not have a url', () => {
103
- beforeEach(() => {
104
- device.url = undefined;
105
- });
106
-
107
- it('should return false', () => {
108
- assert.isFalse(device.registered);
109
- });
110
- });
111
-
112
- describe('when the device does have a url', () => {
113
- beforeEach(() => {
114
- device.url = dto.url;
115
- });
116
-
117
- it('should return true', () => {
118
- assert.isTrue(device.registered);
119
- });
120
- });
121
- });
122
- });
123
-
124
- describe('#setLogoutTimer()', () => {
125
- describe('when the duration parameter is not set', () => {
126
- it('should not change the existing timer', () => {
127
- const {logoutTimer} = device;
128
-
129
- device.setLogoutTimer();
130
- assert.equal(device.logoutTimer, logoutTimer);
131
- });
132
- });
133
-
134
- describe('when the duration parameter is zero or negative', () => {
135
- it('should not change the existing timer', () => {
136
- const {logoutTimer} = device;
137
-
138
- device.setLogoutTimer(-1);
139
- assert.equal(device.logoutTimer, logoutTimer);
140
- });
141
- });
142
-
143
- describe('when the duration is valid', () => {
144
- beforeEach(() => {
145
- device.resetLogoutTimer = sinon.spy();
146
- });
147
-
148
- it("should create a 'change:lastUserActivityDate' listener", () => {
149
- device.setLogoutTimer(60000);
150
- device.trigger('change:lastUserActivityDate');
151
- assert.called(device.resetLogoutTimer);
152
- });
153
-
154
- it('should set the logout timer', () => {
155
- const {logoutTimer} = device;
156
-
157
- device.setLogoutTimer(60000);
158
- assert.notEqual(device.logoutTimer, logoutTimer);
159
- });
160
- });
161
- });
162
-
163
- describe('#serialize()', () => {
164
- it('should serialize entitlement feature keys', () => {
165
- assert.hasAllKeys(
166
- device.serialize().features.entitlement,
167
- Object.keys(dto.features.entitlement)
168
- );
169
- });
170
-
171
- it('should serialize user feature keys', () => {
172
- assert.hasAllKeys(device.serialize().features.user, Object.keys(dto.features.user));
173
- });
174
- });
175
-
176
- describe('#refresh()', () => {
177
- let requestSpy;
178
-
179
- const setup = () => {
180
- sinon.stub(device, 'canRegister').callsFake(() => Promise.resolve());
181
- sinon.stub(device, 'processRegistrationSuccess').callsFake(() => {});
182
- requestSpy = sinon.spy(device, 'request');
183
- device.config.defaults = {};
184
- device.set('registered', true);
185
- };
186
-
187
- it('If-None-Match header is added if etag is set', async () => {
188
- setup();
189
-
190
- device.set('etag', 'etag-value');
191
-
192
- const result = device.refresh();
193
-
194
- await result;
195
-
196
- assert.deepEqual(requestSpy.args[0][0].headers, {
197
- 'If-None-Match': 'etag-value',
198
- });
199
- });
200
-
201
- it('If-None-Match header is not added if etag is not set', async () => {
202
- setup();
203
-
204
- const result = device.refresh();
205
-
206
- await result;
207
-
208
- assert.deepEqual(requestSpy.args[0][0].headers, {});
209
- });
210
- });
211
-
212
- describe('#processRegistrationSuccess()', () => {
213
- const getClonedDTO = (overrides) => {
214
- const clonedDTO = cloneDeep(dto);
215
-
216
- clonedDTO.features = {
217
- developer: [
218
- {
219
- key: '1',
220
- type: 'boolean',
221
- val: 'true',
222
- value: true,
223
- mutable: true,
224
- lastModified: '2015-06-29T20:02:48.033Z',
225
- },
226
- ],
227
- entitlement: [
228
- {
229
- key: '2',
230
- val: 'true',
231
- value: true,
232
- mutable: false,
233
- },
234
- ],
235
- user: [
236
- {
237
- key: '3',
238
- val: 'true',
239
- value: true,
240
- mutable: true,
241
- },
242
- ],
243
- ...overrides,
244
- };
245
-
246
- return clonedDTO;
247
- };
248
-
249
- const checkFeatureNotPresent = (type, key) => {
250
- assert.isUndefined(device.features[type].get(key));
251
- };
252
-
253
- const checkFeature = (type, key, expectedValue) => {
254
- assert.equal(device.features[type].length, 1);
255
- assert.deepEqual(device.features[type].get(key).get('value'), expectedValue);
256
- };
257
-
258
- it('features are set correctly if etag not in headers', () => {
259
- const clonedDTO = getClonedDTO();
260
-
261
- const response = {
262
- body: {
263
- ...clonedDTO,
264
- },
265
- headers: {},
266
- };
267
-
268
- checkFeatureNotPresent('developer', '1');
269
- checkFeatureNotPresent('entitlement', '2');
270
- checkFeatureNotPresent('user', '3');
271
-
272
- device.processRegistrationSuccess(response);
273
-
274
- checkFeature('developer', '1', true);
275
- checkFeature('entitlement', '2', true);
276
- checkFeature('user', '3', true);
277
- });
278
-
279
- it('if the etag matches only the user and entitlement features are updated', () => {
280
- const clonedDTO = getClonedDTO();
281
-
282
- device.set('etag', 'etag-value');
283
-
284
- const response = {
285
- body: {
286
- ...clonedDTO,
287
- },
288
- headers: {
289
- etag: 'etag-value',
290
- },
291
- };
292
-
293
- checkFeatureNotPresent('developer', '1');
294
- checkFeatureNotPresent('entitlement', '2');
295
- checkFeatureNotPresent('user', '3');
296
-
297
- device.processRegistrationSuccess(response);
298
-
299
- checkFeatureNotPresent('developer', '1');
300
- checkFeature('entitlement', '2', true);
301
- checkFeature('user', '3', true);
302
-
303
- // confirm that the etag is unchanged
304
- assert.equal(device.get('etag'), 'etag-value');
305
- });
306
-
307
- it('if the etag matches only the user and entitlement features are updated - check when developer features are set', () => {
308
- const clonedDTO = getClonedDTO();
309
-
310
- device.set('etag', 'etag-value');
311
-
312
- const response = {
313
- body: {
314
- ...clonedDTO,
315
- },
316
- headers: {
317
- etag: 'etag-value',
318
- },
319
- };
320
-
321
- checkFeatureNotPresent('developer', '1');
322
- checkFeatureNotPresent('entitlement', '2');
323
- checkFeatureNotPresent('user', '3');
324
-
325
- device.processRegistrationSuccess(response);
326
-
327
- checkFeatureNotPresent('developer', '1');
328
- checkFeature('entitlement', '2', true);
329
- checkFeature('user', '3', true);
330
-
331
- // confirm that the etag is unchanged
332
- assert.equal(device.get('etag'), 'etag-value');
333
- });
334
-
335
- it('if the etag does not match all the features are updated', () => {
336
- const clonedDTO = getClonedDTO();
337
-
338
- device.set('etag', 'etag-value');
339
-
340
- const response = {
341
- body: {
342
- ...clonedDTO,
343
- },
344
- headers: {
345
- etag: 'different-etag-value',
346
- },
347
- };
348
-
349
- checkFeatureNotPresent('developer', '1');
350
- checkFeatureNotPresent('entitlement', '2');
351
- checkFeatureNotPresent('user', '3');
352
-
353
- device.processRegistrationSuccess(response);
354
-
355
- checkFeature('developer', '1', true);
356
- checkFeature('entitlement', '2', true);
357
- checkFeature('user', '3', true);
358
-
359
- // confirm that the new etag is set
360
- assert.equal(device.get('etag'), 'different-etag-value');
361
-
362
- const newClonedDTO = getClonedDTO({
363
- developer: [
364
- {
365
- key: '1',
366
- type: 'boolean',
367
- val: 'false',
368
- value: false,
369
- mutable: true,
370
- lastModified: '2015-06-29T20:02:48.033Z',
371
- },
372
- ],
373
- entitlement: [
374
- {
375
- key: '2',
376
- val: 'false',
377
- value: false,
378
- mutable: false,
379
- },
380
- ],
381
- user: [
382
- {
383
- key: '3',
384
- val: 'false',
385
- value: false,
386
- mutable: true,
387
- },
388
- ],
389
- });
390
-
391
- const newResponse = {
392
- body: {
393
- ...newClonedDTO,
394
- },
395
- headers: {
396
- etag: 'different-etag-value',
397
- },
398
- };
399
-
400
- device.processRegistrationSuccess(newResponse);
401
-
402
- // only the entitlement and user features should have been changed to false
403
- checkFeature('developer', '1', true);
404
- checkFeature('entitlement', '2', false);
405
- checkFeature('user', '3', false);
406
- });
407
- });
408
- });
409
- });
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import {cloneDeep} from 'lodash';
3
+ import MockWebex from '@webex/test-helper-mock-webex';
4
+ import sinon from 'sinon';
5
+ import Device from '@webex/internal-plugin-device';
6
+
7
+ import dto from './wdm-dto';
8
+
9
+ describe('plugin-device', () => {
10
+ describe('Device', () => {
11
+ let webex;
12
+ let device;
13
+
14
+ beforeEach(() => {
15
+ webex = new MockWebex({
16
+ children: {
17
+ device: Device,
18
+ },
19
+ });
20
+
21
+ const clonedDTO = cloneDeep(dto);
22
+
23
+ webex.internal.device.set(clonedDTO);
24
+
25
+ device = webex.internal.device;
26
+ });
27
+
28
+ describe('events', () => {
29
+ describe('when a feature is changed', () => {
30
+ let spy;
31
+ let modifiedDTOFeatures;
32
+
33
+ beforeEach(() => {
34
+ spy = sinon.spy();
35
+ modifiedDTOFeatures = {
36
+ ...dto.features,
37
+ user: [...dto.features.user, ...dto.features.developer],
38
+ };
39
+ });
40
+
41
+ it("should trigger a 'change' event", () => {
42
+ device.on('change', spy);
43
+ device.features.set(modifiedDTOFeatures);
44
+ assert.called(spy);
45
+ });
46
+
47
+ it("should trigger a 'change:features' event", () => {
48
+ device.on('change:features', spy);
49
+ device.features.set(modifiedDTOFeatures);
50
+ assert.called(spy);
51
+ });
52
+ });
53
+
54
+ describe('when an network inactivity property changes', () => {
55
+ beforeEach(() => {
56
+ device.checkNetworkReachability = sinon.spy();
57
+ });
58
+
59
+ describe('when the \'intranetInactivityCheckUrl\' changes', () => {
60
+ beforeEach(() => {
61
+ device.intranetInactivityCheckUrl = 'https://not-a-url.com';
62
+ });
63
+
64
+ it("should call 'checkNetworkReachability()'", () => {
65
+ assert.called(device.checkNetworkReachability);
66
+ });
67
+
68
+ it('should set isReachabilityChecked to true', () => {
69
+ assert.isTrue(device.isReachabilityChecked);
70
+ });
71
+ });
72
+
73
+ describe('when the \'intranetInactivityDuration\' changes', () => {
74
+ beforeEach(() => {
75
+ device.intranetInactivityDuration = 1234;
76
+ });
77
+
78
+ it("should call 'checkNetworkReachability()'", () => {
79
+ assert.called(device.checkNetworkReachability);
80
+ });
81
+
82
+ it('should set isReachabilityChecked to true', () => {
83
+ assert.isTrue(device.isReachabilityChecked);
84
+ });
85
+ });
86
+
87
+ describe('when the \'inNetworkInactivityDuration\' changes', () => {
88
+ beforeEach(() => {
89
+ device.inNetworkInactivityDuration = 1234;
90
+ });
91
+
92
+ it("should call 'checkNetworkReachability()'", () => {
93
+ assert.called(device.checkNetworkReachability);
94
+ assert.isTrue(device.isReachabilityChecked);
95
+ });
96
+ });
97
+ });
98
+ });
99
+
100
+ describe('derived properties', () => {
101
+ describe('#registered', () => {
102
+ describe('when the device does not have a url', () => {
103
+ beforeEach(() => {
104
+ device.url = undefined;
105
+ });
106
+
107
+ it('should return false', () => {
108
+ assert.isFalse(device.registered);
109
+ });
110
+ });
111
+
112
+ describe('when the device does have a url', () => {
113
+ beforeEach(() => {
114
+ device.url = dto.url;
115
+ });
116
+
117
+ it('should return true', () => {
118
+ assert.isTrue(device.registered);
119
+ });
120
+ });
121
+ });
122
+ });
123
+
124
+ describe('#setLogoutTimer()', () => {
125
+ describe('when the duration parameter is not set', () => {
126
+ it('should not change the existing timer', () => {
127
+ const {logoutTimer} = device;
128
+
129
+ device.setLogoutTimer();
130
+ assert.equal(device.logoutTimer, logoutTimer);
131
+ });
132
+ });
133
+
134
+ describe('when the duration parameter is zero or negative', () => {
135
+ it('should not change the existing timer', () => {
136
+ const {logoutTimer} = device;
137
+
138
+ device.setLogoutTimer(-1);
139
+ assert.equal(device.logoutTimer, logoutTimer);
140
+ });
141
+ });
142
+
143
+ describe('when the duration is valid', () => {
144
+ beforeEach(() => {
145
+ device.resetLogoutTimer = sinon.spy();
146
+ });
147
+
148
+ it("should create a 'change:lastUserActivityDate' listener", () => {
149
+ device.setLogoutTimer(60000);
150
+ device.trigger('change:lastUserActivityDate');
151
+ assert.called(device.resetLogoutTimer);
152
+ });
153
+
154
+ it('should set the logout timer', () => {
155
+ const {logoutTimer} = device;
156
+
157
+ device.setLogoutTimer(60000);
158
+ assert.notEqual(device.logoutTimer, logoutTimer);
159
+ });
160
+ });
161
+ });
162
+
163
+ describe('#serialize()', () => {
164
+ it('should serialize entitlement feature keys', () => {
165
+ assert.hasAllKeys(
166
+ device.serialize().features.entitlement,
167
+ Object.keys(dto.features.entitlement)
168
+ );
169
+ });
170
+
171
+ it('should serialize user feature keys', () => {
172
+ assert.hasAllKeys(device.serialize().features.user, Object.keys(dto.features.user));
173
+ });
174
+ });
175
+
176
+ describe('#refresh()', () => {
177
+ let requestSpy;
178
+
179
+ const setup = () => {
180
+ sinon.stub(device, 'canRegister').callsFake(() => Promise.resolve());
181
+ sinon.stub(device, 'processRegistrationSuccess').callsFake(() => {});
182
+ requestSpy = sinon.spy(device, 'request');
183
+ device.config.defaults = {};
184
+ device.set('registered', true);
185
+ };
186
+
187
+ it('If-None-Match header is added if etag is set', async () => {
188
+ setup();
189
+
190
+ device.set('etag', 'etag-value');
191
+
192
+ const result = device.refresh();
193
+
194
+ await result;
195
+
196
+ assert.deepEqual(requestSpy.args[0][0].headers, {
197
+ 'If-None-Match': 'etag-value',
198
+ });
199
+ });
200
+
201
+ it('If-None-Match header is not added if etag is not set', async () => {
202
+ setup();
203
+
204
+ const result = device.refresh();
205
+
206
+ await result;
207
+
208
+ assert.deepEqual(requestSpy.args[0][0].headers, {});
209
+ });
210
+ });
211
+
212
+ describe('#processRegistrationSuccess()', () => {
213
+ const getClonedDTO = (overrides) => {
214
+ const clonedDTO = cloneDeep(dto);
215
+
216
+ clonedDTO.features = {
217
+ developer: [
218
+ {
219
+ key: '1',
220
+ type: 'boolean',
221
+ val: 'true',
222
+ value: true,
223
+ mutable: true,
224
+ lastModified: '2015-06-29T20:02:48.033Z',
225
+ },
226
+ ],
227
+ entitlement: [
228
+ {
229
+ key: '2',
230
+ val: 'true',
231
+ value: true,
232
+ mutable: false,
233
+ },
234
+ ],
235
+ user: [
236
+ {
237
+ key: '3',
238
+ val: 'true',
239
+ value: true,
240
+ mutable: true,
241
+ },
242
+ ],
243
+ ...overrides,
244
+ };
245
+
246
+ return clonedDTO;
247
+ };
248
+
249
+ const checkFeatureNotPresent = (type, key) => {
250
+ assert.isUndefined(device.features[type].get(key));
251
+ };
252
+
253
+ const checkFeature = (type, key, expectedValue) => {
254
+ assert.equal(device.features[type].length, 1);
255
+ assert.deepEqual(device.features[type].get(key).get('value'), expectedValue);
256
+ };
257
+
258
+ it('features are set correctly if etag not in headers', () => {
259
+ const clonedDTO = getClonedDTO();
260
+
261
+ const response = {
262
+ body: {
263
+ ...clonedDTO,
264
+ },
265
+ headers: {},
266
+ };
267
+
268
+ checkFeatureNotPresent('developer', '1');
269
+ checkFeatureNotPresent('entitlement', '2');
270
+ checkFeatureNotPresent('user', '3');
271
+
272
+ device.processRegistrationSuccess(response);
273
+
274
+ checkFeature('developer', '1', true);
275
+ checkFeature('entitlement', '2', true);
276
+ checkFeature('user', '3', true);
277
+ });
278
+
279
+ it('if the etag matches only the user and entitlement features are updated', () => {
280
+ const clonedDTO = getClonedDTO();
281
+
282
+ device.set('etag', 'etag-value');
283
+
284
+ const response = {
285
+ body: {
286
+ ...clonedDTO,
287
+ },
288
+ headers: {
289
+ etag: 'etag-value',
290
+ },
291
+ };
292
+
293
+ checkFeatureNotPresent('developer', '1');
294
+ checkFeatureNotPresent('entitlement', '2');
295
+ checkFeatureNotPresent('user', '3');
296
+
297
+ device.processRegistrationSuccess(response);
298
+
299
+ checkFeatureNotPresent('developer', '1');
300
+ checkFeature('entitlement', '2', true);
301
+ checkFeature('user', '3', true);
302
+
303
+ // confirm that the etag is unchanged
304
+ assert.equal(device.get('etag'), 'etag-value');
305
+ });
306
+
307
+ it('if the etag matches only the user and entitlement features are updated - check when developer features are set', () => {
308
+ const clonedDTO = getClonedDTO();
309
+
310
+ device.set('etag', 'etag-value');
311
+
312
+ const response = {
313
+ body: {
314
+ ...clonedDTO,
315
+ },
316
+ headers: {
317
+ etag: 'etag-value',
318
+ },
319
+ };
320
+
321
+ checkFeatureNotPresent('developer', '1');
322
+ checkFeatureNotPresent('entitlement', '2');
323
+ checkFeatureNotPresent('user', '3');
324
+
325
+ device.processRegistrationSuccess(response);
326
+
327
+ checkFeatureNotPresent('developer', '1');
328
+ checkFeature('entitlement', '2', true);
329
+ checkFeature('user', '3', true);
330
+
331
+ // confirm that the etag is unchanged
332
+ assert.equal(device.get('etag'), 'etag-value');
333
+ });
334
+
335
+ it('if the etag does not match all the features are updated', () => {
336
+ const clonedDTO = getClonedDTO();
337
+
338
+ device.set('etag', 'etag-value');
339
+
340
+ const response = {
341
+ body: {
342
+ ...clonedDTO,
343
+ },
344
+ headers: {
345
+ etag: 'different-etag-value',
346
+ },
347
+ };
348
+
349
+ checkFeatureNotPresent('developer', '1');
350
+ checkFeatureNotPresent('entitlement', '2');
351
+ checkFeatureNotPresent('user', '3');
352
+
353
+ device.processRegistrationSuccess(response);
354
+
355
+ checkFeature('developer', '1', true);
356
+ checkFeature('entitlement', '2', true);
357
+ checkFeature('user', '3', true);
358
+
359
+ // confirm that the new etag is set
360
+ assert.equal(device.get('etag'), 'different-etag-value');
361
+
362
+ const newClonedDTO = getClonedDTO({
363
+ developer: [
364
+ {
365
+ key: '1',
366
+ type: 'boolean',
367
+ val: 'false',
368
+ value: false,
369
+ mutable: true,
370
+ lastModified: '2015-06-29T20:02:48.033Z',
371
+ },
372
+ ],
373
+ entitlement: [
374
+ {
375
+ key: '2',
376
+ val: 'false',
377
+ value: false,
378
+ mutable: false,
379
+ },
380
+ ],
381
+ user: [
382
+ {
383
+ key: '3',
384
+ val: 'false',
385
+ value: false,
386
+ mutable: true,
387
+ },
388
+ ],
389
+ });
390
+
391
+ const newResponse = {
392
+ body: {
393
+ ...newClonedDTO,
394
+ },
395
+ headers: {
396
+ etag: 'different-etag-value',
397
+ },
398
+ };
399
+
400
+ device.processRegistrationSuccess(newResponse);
401
+
402
+ // only the entitlement and user features should have been changed to false
403
+ checkFeature('developer', '1', true);
404
+ checkFeature('entitlement', '2', false);
405
+ checkFeature('user', '3', false);
406
+ });
407
+ });
408
+ });
409
+ });