@microsoft/applicationinsights-channel-js 2.7.2-nightly.2111-08 → 2.7.2-nightly.2111-09

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 (38) hide show
  1. package/Tests/Unit/src/Sample.tests.ts +154 -0
  2. package/Tests/Unit/src/Sender.tests.ts +1578 -0
  3. package/Tests/Unit/src/aichannel.tests.ts +7 -0
  4. package/Tests/UnitTests.html +53 -0
  5. package/Tests/tsconfig.json +17 -0
  6. package/api-extractor.json +361 -0
  7. package/applicationinsights-channel-js.build.error.log +20 -0
  8. package/applicationinsights-channel-js.build.log +265 -0
  9. package/browser/applicationinsights-channel-js.integrity.json +9 -9
  10. package/browser/applicationinsights-channel-js.js +2 -2
  11. package/browser/applicationinsights-channel-js.js.map +1 -1
  12. package/browser/applicationinsights-channel-js.min.js +2 -2
  13. package/browser/applicationinsights-channel-js.min.js.map +1 -1
  14. package/dist/applicationinsights-channel-js.api.json +1 -1
  15. package/dist/applicationinsights-channel-js.d.ts +1 -1
  16. package/dist/applicationinsights-channel-js.js +2 -2
  17. package/dist/applicationinsights-channel-js.js.map +1 -1
  18. package/dist/applicationinsights-channel-js.min.js +2 -2
  19. package/dist/applicationinsights-channel-js.min.js.map +1 -1
  20. package/dist/applicationinsights-channel-js.rollup.d.ts +1 -1
  21. package/dist-esm/EnvelopeCreator.js +2 -2
  22. package/dist-esm/EnvelopeCreator.js.map +1 -1
  23. package/dist-esm/Interfaces.js +1 -1
  24. package/dist-esm/Offline.js +1 -1
  25. package/dist-esm/SendBuffer.js +1 -1
  26. package/dist-esm/Sender.js +1 -1
  27. package/dist-esm/Serializer.js +1 -1
  28. package/dist-esm/TelemetryProcessors/Sample.js +1 -1
  29. package/dist-esm/TelemetryProcessors/SamplingScoreGenerators/HashCodeScoreGenerator.js +1 -1
  30. package/dist-esm/TelemetryProcessors/SamplingScoreGenerators/SamplingScoreGenerator.js +1 -1
  31. package/dist-esm/applicationinsights-channel-js.js +1 -1
  32. package/microsoft-applicationinsights-channel-js-2.7.2-nightly.2111-09.tgz +0 -0
  33. package/package.json +3 -3
  34. package/rollup.config.js +139 -0
  35. package/src/EnvelopeCreator.ts +1 -1
  36. package/temp/applicationinsights-channel-js.api.md +62 -0
  37. package/tslint.json +8 -0
  38. package/types/tsdoc-metadata.json +1 -1
@@ -0,0 +1,1578 @@
1
+ import { AITestClass } from "@microsoft/ai-test-framework";
2
+ import { Sender } from "../../../src/Sender";
3
+ import { Offline } from '../../../src/Offline';
4
+ import { EnvelopeCreator } from '../../../src/EnvelopeCreator';
5
+ import { Exception, CtxTagKeys, Util } from "@microsoft/applicationinsights-common";
6
+ import { ITelemetryItem, AppInsightsCore, ITelemetryPlugin, DiagnosticLogger, NotificationManager, SendRequestReason, _InternalMessageId, LoggingSeverity, getGlobalInst, getGlobal } from "@microsoft/applicationinsights-core-js";
7
+
8
+ export class SenderTests extends AITestClass {
9
+ private _sender: Sender;
10
+ private _instrumentationKey = 'iKey';
11
+
12
+ public testInitialize() {
13
+ this._sender = new Sender();
14
+ this._sender.initialize({ instrumentationKey: this._instrumentationKey }, new AppInsightsCore(), []);
15
+ }
16
+
17
+ public testCleanup() {
18
+ this._sender = null;
19
+ }
20
+
21
+ public registerTests() {
22
+
23
+ this.testCase({
24
+ name: "Channel Config: Channel can properly take args from root config",
25
+ test: () => {
26
+ this._sender.initialize(
27
+ {
28
+ instrumentationKey: 'abc',
29
+ maxBatchInterval: 123,
30
+ endpointUrl: 'https://example.com',
31
+ maxBatchSizeInBytes: 654,
32
+ extensionConfig: {
33
+ [this._sender.identifier]: {
34
+ maxBatchSizeInBytes: 456
35
+ }
36
+ }
37
+
38
+ }, new AppInsightsCore(), []
39
+ );
40
+
41
+ QUnit.assert.equal(123, this._sender._senderConfig.maxBatchInterval(), 'Channel config can be set from root config (maxBatchInterval)');
42
+ QUnit.assert.equal('https://example.com', this._sender._senderConfig.endpointUrl(), 'Channel config can be set from root config (endpointUrl)');
43
+ QUnit.assert.notEqual(654, this._sender._senderConfig.maxBatchSizeInBytes(), 'Channel config does not equal root config option if extensionConfig field is also set');
44
+ QUnit.assert.equal(456, this._sender._senderConfig.maxBatchSizeInBytes(), 'Channel config prioritizes extensionConfig over root config');
45
+ }
46
+ });
47
+
48
+ this.testCase({
49
+ name: "processTelemetry can be called with optional fields undefined",
50
+ useFakeTimers: true,
51
+ test: () => {
52
+ this._sender.initialize({
53
+ instrumentationKey: 'abc'
54
+ }, new AppInsightsCore(), []);
55
+
56
+ const loggerSpy = this.sandbox.stub(this._sender, "triggerSend");
57
+ const telemetryItem: ITelemetryItem = {
58
+ name: 'fake item',
59
+ iKey: 'iKey',
60
+ baseType: 'some type',
61
+ baseData: {}
62
+ };
63
+ try {
64
+ this._sender.processTelemetry(telemetryItem, null);
65
+ } catch(e) {
66
+ QUnit.assert.ok(false, "Exception - " + e);
67
+ }
68
+
69
+ QUnit.assert.equal(false, loggerSpy.calledOnce, "The send has not yet been triggered");
70
+ this.clock.tick(15000);
71
+ QUnit.assert.equal(true, loggerSpy.calledOnce, "The send has been triggered");
72
+ }
73
+ })
74
+
75
+ this.testCase({
76
+ name: "processTelemetry process ItelemetryItem with iKey",
77
+ useFakeTimers: true,
78
+ test: () => {
79
+ this._sender.initialize({
80
+ instrumentationKey: 'abc'
81
+ }, new AppInsightsCore(), []);
82
+
83
+ const loggerSpy = this.sandbox.stub(this._sender, "triggerSend");
84
+ const expectedIkey = 'testIkey';
85
+ const telemetryItem: ITelemetryItem = {
86
+ name: 'fake item',
87
+ iKey: expectedIkey,
88
+ baseType: 'some type',
89
+ baseData: {}
90
+ };
91
+ try {
92
+ this._sender.processTelemetry(telemetryItem, null);
93
+ let buffer = this._sender._buffer.getItems();
94
+ let payload = JSON.parse(buffer[buffer.length-1]);
95
+ var actualIkey = payload.iKey;
96
+ } catch(e) {
97
+ QUnit.assert.ok(false, "Exception - " + e);
98
+ }
99
+
100
+ QUnit.assert.equal(false, loggerSpy.calledOnce, "The send has not yet been triggered");
101
+ QUnit.assert.equal(expectedIkey, actualIkey, "processTelemetry replaced ItelemetryItem Ikey");
102
+ this.clock.tick(15000);
103
+ QUnit.assert.equal(true, loggerSpy.calledOnce, "The send has been triggered");
104
+ }
105
+ })
106
+
107
+ this.testCase({
108
+ name: "telemetry is not send when legacy telemetry initializer returns false",
109
+ test: () => {
110
+ const cr = new AppInsightsCore();
111
+ cr.logger = new DiagnosticLogger({instrumentationKey: "ikey"});
112
+ this._sender.initialize({
113
+ instrumentationKey: 'abc'
114
+ }, cr, []);
115
+
116
+ const nextPlugin = <ITelemetryPlugin> {
117
+ identifier: "foo",
118
+ processTelemetry: (it) => {},
119
+ priority: 200,
120
+ setNextPlugin: (it) => {}
121
+ };
122
+ this._sender.setNextPlugin(nextPlugin);
123
+
124
+ const processTelemetrySpy = this.sandbox.stub(nextPlugin, "processTelemetry");
125
+ const telemetryItem: ITelemetryItem = {
126
+ name: 'fake item',
127
+ iKey: 'iKey',
128
+ baseType: 'some type',
129
+ baseData: {},
130
+ tags: [
131
+ ]
132
+ };
133
+
134
+ telemetryItem.tags["ProcessLegacy"] = [e => true, e => false, f=> true];
135
+ try {
136
+ this._sender.processTelemetry(telemetryItem, null);
137
+ } catch(e) {
138
+ QUnit.assert.ok(false);
139
+ }
140
+
141
+ QUnit.assert.ok(!processTelemetrySpy.calledOnce);
142
+ }
143
+ });
144
+
145
+ this.testCase({
146
+ name: 'BeaconAPI is not used when isBeaconApiDisabled flag is true',
147
+ test: () => {
148
+ let sendBeaconCalled = false;
149
+ this.hookSendBeacon((url: string) => {
150
+ sendBeaconCalled = true;
151
+ return true;
152
+ });
153
+
154
+ const sender = new Sender();
155
+ const cr = new AppInsightsCore();
156
+
157
+ sender.initialize({
158
+ instrumentationKey: 'abc',
159
+ isBeaconApiDisabled: true
160
+ }, cr, []);
161
+
162
+ const telemetryItem: ITelemetryItem = {
163
+ name: 'fake item',
164
+ iKey: 'iKey',
165
+ baseType: 'some type',
166
+ baseData: {}
167
+ };
168
+
169
+ QUnit.assert.ok(Util.IsBeaconApiSupported(), "Beacon API is supported");
170
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API was not called before");
171
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender was not called before");
172
+
173
+ try {
174
+ sender.processTelemetry(telemetryItem, null);
175
+ sender.flush();
176
+ } catch(e) {
177
+ QUnit.assert.ok(false);
178
+ }
179
+
180
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API is disabled, Beacon API is not called");
181
+ QUnit.assert.equal(1, this._getXhrRequests().length, "xhr sender is called when Beacon API is disabled");
182
+ }
183
+ });
184
+
185
+ this.testCase({
186
+ name: 'beaconSender is called when isBeaconApiDisabled flag is false',
187
+ useFakeTimers: true,
188
+ test: () => {
189
+ let sendBeaconCalled = false;
190
+ this.hookSendBeacon((url: string) => {
191
+ sendBeaconCalled = true;
192
+ return true;
193
+ });
194
+
195
+ const cr = new AppInsightsCore();
196
+ const sender = new Sender();
197
+
198
+ sender.initialize({
199
+ instrumentationKey: 'abc',
200
+ isBeaconApiDisabled: false
201
+ }, cr, []);
202
+
203
+ const telemetryItem: ITelemetryItem = {
204
+ name: 'fake item',
205
+ iKey: 'iKey',
206
+ baseType: 'some type',
207
+ baseData: {}
208
+ };
209
+
210
+ QUnit.assert.ok(Util.IsBeaconApiSupported(), "Beacon API is supported");
211
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API was not called before");
212
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender was not called before");
213
+
214
+ try {
215
+ sender.processTelemetry(telemetryItem, null);
216
+ sender.flush();
217
+ } catch(e) {
218
+ QUnit.assert.ok(false);
219
+ }
220
+
221
+ this.clock.tick(15000);
222
+
223
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender is not called when Beacon API is enabled");
224
+ QUnit.assert.equal(true, sendBeaconCalled, "Beacon API is enabled, Beacon API is called");
225
+ }
226
+ });
227
+
228
+ this.testCase({
229
+ name: 'BeaconAPI is not used when isBeaconApiDisabled flag is false but payload size is over 64k, fall off to xhr sender',
230
+ useFakeTimers: true,
231
+ test: () => {
232
+ let sendBeaconCalled = false;
233
+ this.hookSendBeacon((url: string) => {
234
+ sendBeaconCalled = true;
235
+ return false;
236
+ });
237
+
238
+ const sender = new Sender();
239
+ const cr = new AppInsightsCore();
240
+ cr["logger"] = new DiagnosticLogger();
241
+ const MAX_PROPERTIES_SIZE = 8000;
242
+ const payload = new Array(MAX_PROPERTIES_SIZE).join('a');
243
+
244
+ sender.initialize({
245
+ instrumentationKey: 'abc',
246
+ isBeaconApiDisabled: false
247
+ }, cr, []);
248
+
249
+ const telemetryItems: ITelemetryItem[] = [];
250
+ for (let i = 0; i < 8; i ++) {
251
+ const telemetryItem: ITelemetryItem = {
252
+ name: 'fake item',
253
+ iKey: 'iKey',
254
+ baseType: 'some type',
255
+ baseData: {},
256
+ data: {
257
+ properties: {
258
+ payload
259
+ }
260
+ }
261
+ };
262
+ telemetryItems[i] = telemetryItem;
263
+ }
264
+
265
+ QUnit.assert.ok(Util.IsBeaconApiSupported(), "Beacon API is supported");
266
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API was not called before");
267
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender was not called before");
268
+
269
+ try {
270
+ for (let i = 0; i < 8; i++) {
271
+ sender.processTelemetry(telemetryItems[i], null);
272
+ }
273
+ sender.flush();
274
+ } catch(e) {
275
+ QUnit.assert.ok(false);
276
+ }
277
+
278
+ this.clock.tick(15000);
279
+
280
+ QUnit.assert.equal(true, sendBeaconCalled, "Beacon API is enabled but payload is over size, Beacon API is called");
281
+ QUnit.assert.ok(this._getXhrRequests().length > 0, "xhr sender is called when payload is over size");
282
+ }
283
+ });
284
+
285
+ this.testCase({
286
+ name: 'FetchAPI is used when isBeaconApiDisabled flag is true and disableXhr flag is true , use fetch sender.',
287
+ test: () => {
288
+ let window = getGlobalInst("window");
289
+ let fakeXMLHttpRequest = (window as any).XMLHttpRequest;
290
+ let fetchstub = this.sandbox.stub((window as any), "fetch");
291
+
292
+ let sendBeaconCalled = false;
293
+ this.hookSendBeacon((url: string) => {
294
+ sendBeaconCalled = true;
295
+ return false;
296
+ });
297
+
298
+ const sender = new Sender();
299
+ const cr = new AppInsightsCore();
300
+
301
+ sender.initialize({
302
+ instrumentationKey: 'abc',
303
+ isBeaconApiDisabled: true,
304
+ disableXhr: true
305
+ }, cr, []);
306
+
307
+ const telemetryItem: ITelemetryItem = {
308
+ name: 'fake item',
309
+ iKey: 'iKey',
310
+ baseType: 'some type',
311
+ baseData: {}
312
+ };
313
+
314
+ QUnit.assert.ok(Util.IsBeaconApiSupported(), "Beacon API is supported");
315
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API was not called before");
316
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender was not called before");
317
+
318
+ try {
319
+ sender.processTelemetry(telemetryItem, null);
320
+ sender.flush();
321
+ } catch(e) {
322
+ QUnit.assert.ok(false);
323
+ }
324
+
325
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API is disabled, Beacon API is not called");
326
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender is not called");
327
+ QUnit.assert.ok(fetchstub.called, "fetch sender is called");
328
+ // store it back
329
+ (window as any).XMLHttpRequest = fakeXMLHttpRequest;
330
+ }
331
+ });
332
+
333
+ this.testCase({
334
+ name: 'FetchAPI is used when isBeaconApiDisabled flag is true and XMLHttpRequest is not supported, use fetch sender.',
335
+ test: () => {
336
+ let window = getGlobalInst("window");
337
+ let fakeXMLHttpRequest = (window as any).XMLHttpRequest;
338
+ (window as any).XMLHttpRequest = undefined;
339
+ let fetchstub = this.sandbox.stub((window as any), "fetch");
340
+
341
+ let sendBeaconCalled = false;
342
+ this.hookSendBeacon((url: string) => {
343
+ sendBeaconCalled = true;
344
+ return false;
345
+ });
346
+
347
+ const sender = new Sender();
348
+ const cr = new AppInsightsCore();
349
+
350
+ sender.initialize({
351
+ instrumentationKey: 'abc',
352
+ isBeaconApiDisabled: true
353
+ }, cr, []);
354
+
355
+ const telemetryItem: ITelemetryItem = {
356
+ name: 'fake item',
357
+ iKey: 'iKey',
358
+ baseType: 'some type',
359
+ baseData: {}
360
+ };
361
+
362
+ QUnit.assert.ok(Util.IsBeaconApiSupported(), "Beacon API is supported");
363
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API was not called before");
364
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender was not called before");
365
+
366
+ try {
367
+ sender.processTelemetry(telemetryItem, null);
368
+ sender.flush();
369
+ } catch(e) {
370
+ QUnit.assert.ok(false);
371
+ }
372
+
373
+ QUnit.assert.equal(false, sendBeaconCalled, "Beacon API is disabled, Beacon API is not called");
374
+ QUnit.assert.equal(0, this._getXhrRequests().length, "xhr sender is not called");
375
+ QUnit.assert.ok(fetchstub.called, "fetch sender is called");
376
+ // store it back
377
+ (window as any).XMLHttpRequest = fakeXMLHttpRequest;
378
+ }
379
+ });
380
+
381
+ this.testCase({
382
+ name: 'Users are not allowed to add customHeaders when endpointUrl is Breeze.',
383
+ test: () => {
384
+ let sendBeaconCalled = false;
385
+ this.hookSendBeacon((url: string) => {
386
+ sendBeaconCalled = true;
387
+ return true;
388
+ });
389
+
390
+ const sender = new Sender();
391
+ const cr = new AppInsightsCore();
392
+
393
+ sender.initialize({
394
+ instrumentationKey: 'abc',
395
+ isBeaconApiDisabled: true,
396
+ customHeaders: [
397
+ {
398
+ header: 'testHeader',
399
+ value: 'testValue'
400
+ }
401
+ ]
402
+ }, cr, []);
403
+
404
+ const telemetryItem: ITelemetryItem = {
405
+ name: 'fake item',
406
+ iKey: 'iKey',
407
+ baseType: 'some type',
408
+ baseData: {}
409
+ };
410
+
411
+ try {
412
+ sender.processTelemetry(telemetryItem, null);
413
+ sender.flush();
414
+ } catch(e) {
415
+ QUnit.assert.ok(false);
416
+ }
417
+
418
+ QUnit.assert.equal(1, this._getXhrRequests().length, "xhr sender is called");
419
+ QUnit.assert.notOk(this._getXhrRequests()[0].requestHeaders.hasOwnProperty('testHeader'));
420
+ }
421
+ });
422
+
423
+ this.testCase({
424
+ name: 'Users are allowed to add customHeaders when endpointUrl is not Breeze.',
425
+ test: () => {
426
+ let sendBeaconCalled = false;
427
+ this.hookSendBeacon((url: string) => {
428
+ sendBeaconCalled = true;
429
+ return true;
430
+ });
431
+
432
+ const sender = new Sender();
433
+ const cr = new AppInsightsCore();
434
+
435
+ sender.initialize({
436
+ instrumentationKey: 'abc',
437
+ isBeaconApiDisabled: true,
438
+ endpointUrl: 'https://example.com',
439
+ customHeaders: [
440
+ {
441
+ header: 'testHeader',
442
+ value: 'testValue'
443
+ }
444
+ ]
445
+ }, cr, []);
446
+
447
+ const telemetryItem: ITelemetryItem = {
448
+ name: 'fake item',
449
+ iKey: 'iKey',
450
+ baseType: 'some type',
451
+ baseData: {}
452
+ };
453
+
454
+ try {
455
+ sender.processTelemetry(telemetryItem, null);
456
+ sender.flush();
457
+ } catch(e) {
458
+ QUnit.assert.ok(false);
459
+ }
460
+
461
+ QUnit.assert.equal(1, this._getXhrRequests().length, "xhr sender is called");
462
+ QUnit.assert.ok(this._getXhrRequests()[0].requestHeaders.hasOwnProperty('testHeader'));
463
+ QUnit.assert.equal(this._getXhrRequests()[0].requestHeaders.testHeader, 'testValue');
464
+ }
465
+ });
466
+
467
+ this.testCase({
468
+ name: 'Users are allowed to add customHeaders via addHeader method.',
469
+ test: () => {
470
+ let sendBeaconCalled = false;
471
+ this.hookSendBeacon((url: string) => {
472
+ sendBeaconCalled = true;
473
+ return true;
474
+ });
475
+
476
+ const sender = new Sender();
477
+ const cr = new AppInsightsCore();
478
+
479
+ sender.addHeader('testHeader', 'testValue');
480
+
481
+ sender.initialize({
482
+ instrumentationKey: 'abc',
483
+ isBeaconApiDisabled: true
484
+ }, cr, []);
485
+
486
+ const telemetryItem: ITelemetryItem = {
487
+ name: 'fake item',
488
+ iKey: 'iKey',
489
+ baseType: 'some type',
490
+ baseData: {}
491
+ };
492
+
493
+ try {
494
+ sender.processTelemetry(telemetryItem, null);
495
+ sender.flush();
496
+ } catch(e) {
497
+ QUnit.assert.ok(false);
498
+ }
499
+
500
+ QUnit.assert.equal(1, this._getXhrRequests().length, "xhr sender is called");
501
+ QUnit.assert.ok(this._getXhrRequests()[0].requestHeaders.hasOwnProperty('testHeader'));
502
+ QUnit.assert.equal(this._getXhrRequests()[0].requestHeaders.testHeader, 'testValue');
503
+ }
504
+ });
505
+
506
+ this.testCase({
507
+ name: "AppInsightsTests: AppInsights Envelope created for Custom Event",
508
+ test: () => {
509
+ const inputEnvelope: ITelemetryItem = {
510
+ name: "test",
511
+ time: new Date("2018-06-12").toISOString(),
512
+ iKey: "iKey",
513
+ ext: {
514
+ app: {
515
+ sesId: "d041d2e5fa834b4f9eee41ac163bf402"
516
+ },
517
+ device: {
518
+ deviceClass: "Browser",
519
+ localId: "browser"
520
+ }
521
+
522
+ },
523
+ tags: [{"ai.internal.sdkVersion": "javascript:2.5.1"}],
524
+ data: {
525
+ "property1": "val1",
526
+ "measurement1": 50.0,
527
+ "measurement2": 1.3,
528
+ "property2": "val2"
529
+ },
530
+ baseData: {
531
+ "name": "Event Name"
532
+ }
533
+ };
534
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
535
+
536
+ const baseData = appInsightsEnvelope.data.baseData;
537
+
538
+ // Assert measurements
539
+ const resultMeasurements = baseData.measurements;
540
+ QUnit.assert.ok(resultMeasurements);
541
+ QUnit.assert.ok(resultMeasurements["measurement1"]);
542
+ QUnit.assert.equal(50.0, resultMeasurements["measurement1"]);
543
+ QUnit.assert.ok(resultMeasurements["measurement2"]);
544
+ QUnit.assert.equal(1.3, resultMeasurements["measurement2"]);
545
+
546
+ // Assert custom properties
547
+ QUnit.assert.ok(baseData.properties);
548
+ QUnit.assert.equal("val1", baseData.properties["property1"]);
549
+ QUnit.assert.equal("val2", baseData.properties["property2"]);
550
+
551
+ // Assert Event name
552
+ QUnit.assert.ok(baseData.name);
553
+ QUnit.assert.equal("Event Name", baseData.name);
554
+
555
+ // Assert ver
556
+ QUnit.assert.ok(baseData.ver);
557
+ QUnit.assert.equal(2, baseData.ver);
558
+
559
+ // Assert baseType added by default
560
+ QUnit.assert.ok(appInsightsEnvelope.data.baseType);
561
+ QUnit.assert.equal("EventData", appInsightsEnvelope.data.baseType);
562
+
563
+ // Assert tags
564
+ QUnit.assert.ok(appInsightsEnvelope.tags);
565
+ QUnit.assert.equal("d041d2e5fa834b4f9eee41ac163bf402", appInsightsEnvelope.tags["ai.session.id"]);
566
+ QUnit.assert.equal("browser", appInsightsEnvelope.tags["ai.device.id"]);
567
+ QUnit.assert.equal("Browser", appInsightsEnvelope.tags["ai.device.type"]);
568
+ QUnit.assert.equal("javascript:2.5.1", appInsightsEnvelope.tags["ai.internal.sdkVersion"]);
569
+
570
+ // Assert name
571
+ QUnit.assert.ok(appInsightsEnvelope.name);
572
+ QUnit.assert.equal("Microsoft.ApplicationInsights.iKey.Event", appInsightsEnvelope.name);
573
+
574
+ // Assert iKey
575
+ QUnit.assert.ok(appInsightsEnvelope.iKey);
576
+ QUnit.assert.equal("iKey", appInsightsEnvelope.iKey);
577
+
578
+ // Assert timestamp
579
+ QUnit.assert.ok(appInsightsEnvelope.time);
580
+ }
581
+ });
582
+
583
+ this.testCase({
584
+ name: "AppInsightsTests: AppInsights Envelope use default config iKey when iKey of ItelemetryItem is empty",
585
+ test: () => {
586
+ const inputEnvelope: ITelemetryItem = {
587
+ name: "test",
588
+ iKey: "",
589
+ ext: {},
590
+ data: { "property1": "val1"},
591
+ baseData: {
592
+ "name": "Event Name"
593
+ }
594
+ };
595
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
596
+
597
+ const baseData = appInsightsEnvelope.data.baseData;
598
+
599
+ // Assert Event name
600
+ QUnit.assert.ok(baseData.name);
601
+ QUnit.assert.equal("Event Name", baseData.name);
602
+
603
+ // Assert name
604
+ QUnit.assert.ok(appInsightsEnvelope.name);
605
+ QUnit.assert.equal("Microsoft.ApplicationInsights.iKey.Event", appInsightsEnvelope.name);
606
+
607
+ // Assert iKey
608
+ QUnit.assert.ok(appInsightsEnvelope.iKey);
609
+ QUnit.assert.equal( this._instrumentationKey, appInsightsEnvelope.iKey, "default config iKey is not set");
610
+ }
611
+ });
612
+
613
+ this.testCase({
614
+ name: "AppInsightsTests: AppInsights Envelope unknown type returns custom Event data type",
615
+ test: () => {
616
+ const inputEnvelope: ITelemetryItem = {
617
+ name: "test",
618
+ time: new Date("2018-06-12").toISOString(),
619
+ iKey: "iKey",
620
+ ext: {
621
+ "ai.session.id": "d041d2e5fa834b4f9eee41ac163bf402",
622
+ "ai.device.id": "browser",
623
+ "ai.device.type": "Browser",
624
+ },
625
+ tags: [{}],
626
+ data: {
627
+ "property1": "val1",
628
+ "measurement1": 50.0,
629
+ "measurement2": 1.3,
630
+ "property2": "val2"
631
+ },
632
+ baseType: "PageUnloadData",
633
+ baseData: {
634
+ id: "EADE2F09-DEBA-4B60-A222-E1D80BB8AA7F",
635
+ vpHeight: 1002,
636
+ vScrollOffset: 292
637
+ }
638
+ };
639
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
640
+ const baseData = appInsightsEnvelope.data.baseData;
641
+
642
+ // Assert measurements
643
+ const resultMeasurements = baseData.measurements;
644
+ QUnit.assert.ok(resultMeasurements);
645
+ QUnit.assert.ok(resultMeasurements["measurement1"]);
646
+ QUnit.assert.equal(50.0, resultMeasurements["measurement1"]);
647
+ QUnit.assert.ok(resultMeasurements["measurement2"]);
648
+ QUnit.assert.equal(1.3, resultMeasurements["measurement2"]);
649
+ QUnit.assert.ok(resultMeasurements["vpHeight"]);
650
+ QUnit.assert.equal(1002, resultMeasurements["vpHeight"]);
651
+ QUnit.assert.ok(resultMeasurements["vScrollOffset"]);
652
+ QUnit.assert.equal(292, resultMeasurements["vScrollOffset"]);
653
+
654
+ // Assert custom properties
655
+ QUnit.assert.ok(baseData.properties);
656
+ QUnit.assert.equal("val1", baseData.properties["property1"]);
657
+ QUnit.assert.equal("val2", baseData.properties["property2"]);
658
+ QUnit.assert.equal("EADE2F09-DEBA-4B60-A222-E1D80BB8AA7F", baseData.properties["id"]);
659
+
660
+ // Assert Event name
661
+ QUnit.assert.ok(baseData.name);
662
+ QUnit.assert.equal("PageUnloadData", baseData.properties['baseTypeSource']);
663
+
664
+ // Assert ver
665
+ QUnit.assert.ok(baseData.ver);
666
+ QUnit.assert.equal(2, baseData.ver);
667
+
668
+ QUnit.assert.equal("javascript:2.7.2-nightly.2111-09", appInsightsEnvelope.tags["ai.internal.sdkVersion"]);
669
+ }
670
+ })
671
+
672
+ this.testCase({
673
+ name: "AppInsightsTests: AppInsights Envelope create for Dependency Data",
674
+ test: () => {
675
+ // setup
676
+ const inputEnvelope: ITelemetryItem = {
677
+ name: "test",
678
+ time: new Date("2018-06-12").toISOString(),
679
+ iKey: "iKey",
680
+ ext: {
681
+ "user" : {
682
+ "localId": "TestId",
683
+ "authId": "AuthenticatedId",
684
+ "id": "TestId"
685
+ }
686
+ },
687
+ tags: [{"ai.user.accountId": "TestAccountId"},
688
+ {"ai.location.ip": "10.22.8.2"}],
689
+ baseType: "RemoteDependencyData",
690
+ baseData: {
691
+ id: 'some id',
692
+ name: "Some name given",
693
+ success: true,
694
+ responseCode: 200,
695
+ duration: 123,
696
+ type: 'Fetch',
697
+ data: 'some data',
698
+ target: 'https://example.com/test/name?q=bar',
699
+ correlationContext: "cid-v1:foo"
700
+ },
701
+ data: {
702
+ property1: "val1",
703
+ property2: "val2",
704
+ measurement1: 50.0,
705
+ measurement2: 1.3
706
+ }
707
+
708
+ }
709
+
710
+ // act
711
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
712
+ const { baseData } = appInsightsEnvelope.data;
713
+
714
+ // assert
715
+ const resultDuration = baseData.duration;
716
+ QUnit.assert.equal("00:00:00.123", resultDuration);
717
+
718
+ // Assert measurements
719
+ const resultMeasurements = baseData.measurements;
720
+ QUnit.assert.ok(resultMeasurements);
721
+ QUnit.assert.ok(resultMeasurements["measurement1"]);
722
+ QUnit.assert.equal(50.0, resultMeasurements["measurement1"]);
723
+ QUnit.assert.ok(resultMeasurements["measurement2"]);
724
+ QUnit.assert.equal(1.3, resultMeasurements["measurement2"]);
725
+ QUnit.assert.ok(!resultMeasurements.duration, "duration is not supposed to be treated as measurement");
726
+
727
+ // Assert custom properties
728
+ QUnit.assert.ok(baseData.properties);
729
+ QUnit.assert.equal("val1", baseData.properties["property1"]);
730
+ QUnit.assert.equal("val2", baseData.properties["property2"]);
731
+
732
+ // Assert baseData
733
+ QUnit.assert.ok(baseData.name);
734
+ QUnit.assert.equal("Some name given", baseData.data);
735
+ QUnit.assert.equal("some id", baseData.id);
736
+ QUnit.assert.equal(true, baseData.success);
737
+ QUnit.assert.equal(200, baseData.resultCode);
738
+ QUnit.assert.equal("Some name given", baseData.name);
739
+ QUnit.assert.equal("example.com | cid-v1:foo", baseData.target);
740
+
741
+ // Assert ver
742
+ QUnit.assert.ok(baseData.ver);
743
+ QUnit.assert.equal(2, baseData.ver);
744
+
745
+ // Assert baseType
746
+ QUnit.assert.ok(appInsightsEnvelope.data.baseType);
747
+ QUnit.assert.equal("RemoteDependencyData", appInsightsEnvelope.data.baseType);
748
+
749
+ // Assert tags
750
+ QUnit.assert.ok(appInsightsEnvelope.tags);
751
+ QUnit.assert.equal("TestAccountId", appInsightsEnvelope.tags["ai.user.accountId"]);
752
+ QUnit.assert.equal("10.22.8.2", appInsightsEnvelope.tags["ai.location.ip"]);
753
+
754
+ QUnit.assert.equal("AuthenticatedId", appInsightsEnvelope.tags["ai.user.authUserId"]);
755
+ QUnit.assert.equal("TestId", appInsightsEnvelope.tags["ai.user.id"]);
756
+
757
+ // Assert name
758
+ QUnit.assert.ok(appInsightsEnvelope.name);
759
+ QUnit.assert.equal("Microsoft.ApplicationInsights.iKey.RemoteDependency", appInsightsEnvelope.name);
760
+
761
+ // Assert iKey
762
+ QUnit.assert.ok(appInsightsEnvelope.iKey);
763
+ QUnit.assert.equal("iKey", appInsightsEnvelope.iKey);
764
+
765
+ // Assert timestamp
766
+ QUnit.assert.ok(appInsightsEnvelope.time);
767
+ }
768
+ });
769
+
770
+ this.testCase({
771
+ name: "AppInsightsTests: When name is not provided, it is obtained from hostname",
772
+ test: () => {
773
+ // setup
774
+ const inputEnvelope: ITelemetryItem = {
775
+ name: "test",
776
+ time: new Date("2018-06-12").toISOString(),
777
+ iKey: "iKey",
778
+ ext: {
779
+ "user" : {
780
+ "localId": "TestId",
781
+ "authId": "AuthenticatedId",
782
+ "id": "TestId"
783
+ }
784
+ },
785
+ tags: [{"ai.user.accountId": "TestAccountId"},
786
+ {"ai.location.ip": "10.22.8.2"}, {"ai.internal.sdkVersion": "1234"}],
787
+ baseType: "RemoteDependencyData",
788
+ baseData: {
789
+ id: 'some id',
790
+ success: true,
791
+ responseCode: 200,
792
+ duration: 123,
793
+ type: 'Fetch',
794
+ data: 'some data',
795
+ target: 'https://example.com/test/name'
796
+ },
797
+ data: {
798
+ property1: "val1",
799
+ property2: "val2",
800
+ measurement1: 50.0,
801
+ measurement2: 1.3
802
+ }
803
+
804
+ }
805
+
806
+ // act
807
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
808
+ const { baseData } = appInsightsEnvelope.data;
809
+
810
+ // Assert baseData
811
+ QUnit.assert.ok(baseData.name);
812
+ QUnit.assert.equal("GET /test/name", baseData.name); // retrieved from target
813
+ QUnit.assert.equal("/test/name", baseData.data);
814
+
815
+ // Assert sdkVersion
816
+ QUnit.assert.equal("1234", appInsightsEnvelope.tags["ai.internal.sdkVersion"])
817
+ }
818
+ });
819
+
820
+ this.testCase({
821
+ name: "AppInsightsTests: AppInsights Envelope created for Page View",
822
+ test: () => {
823
+ // setup
824
+ const inputEnvelope: ITelemetryItem = {
825
+ name: "test",
826
+ time: new Date("2018-06-12").toISOString(),
827
+ iKey: "iKey",
828
+ ext: {
829
+ "user": {
830
+ "localId": "TestId",
831
+ "authId": "AuthenticatedId",
832
+ "id": "TestId"
833
+ },
834
+ "trace": {
835
+ "traceID": "1528B5FF-6455-4657-BE77-E6664CAC72DC",
836
+ "parentID": "1528B5FF-6455-4657-BE77-E6664CACEEEE"
837
+ }
838
+ },
839
+ tags: [{"ai.user.accountId": "TestAccountId"}],
840
+ baseType: "PageviewData",
841
+ baseData: {
842
+ "name": "Page View Name",
843
+ "uri": "https://fakeUri.com",
844
+ properties: {
845
+ "property1": "val1",
846
+ "property2": "val2",
847
+ "duration": 300000
848
+ },
849
+ measurements: {
850
+ "measurement1": 50.0,
851
+ "measurement2": 1.3,
852
+ }
853
+ },
854
+ data: {
855
+ "property3": "val3",
856
+ "measurement3": 1000
857
+ }
858
+ };
859
+
860
+ // Act
861
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
862
+ const baseData = appInsightsEnvelope.data.baseData;
863
+
864
+ // Assert duration
865
+ const resultDuration = baseData.duration;
866
+ QUnit.assert.equal("00:05:00.000", resultDuration);
867
+
868
+ // Assert measurements
869
+ const resultMeasurements = baseData.measurements;
870
+ const props = baseData.properties;
871
+ QUnit.assert.ok(resultMeasurements);
872
+ QUnit.assert.ok(resultMeasurements["measurement1"]);
873
+ QUnit.assert.equal(50.0, resultMeasurements["measurement1"]);
874
+ QUnit.assert.ok(resultMeasurements["measurement2"]);
875
+ QUnit.assert.equal(1.3, resultMeasurements["measurement2"]);
876
+ QUnit.assert.ok(!resultMeasurements.duration, "duration is not supposed to be treated as property in envelope");
877
+
878
+ // Assert custom properties
879
+ QUnit.assert.ok(baseData.properties);
880
+ QUnit.assert.equal("val1", baseData.properties["property1"]);
881
+ QUnit.assert.equal("val2", baseData.properties["property2"]);
882
+
883
+ // Assert deprecated data custom properties/measurements
884
+ QUnit.assert.equal("val3", baseData.properties["property3"])
885
+ QUnit.assert.equal(1000, baseData.measurements["measurement3"]);
886
+
887
+ // Assert Page View name
888
+ QUnit.assert.ok(baseData.name);
889
+ QUnit.assert.equal("Page View Name", baseData.name);
890
+
891
+
892
+ // Assert ver
893
+ QUnit.assert.ok(baseData.ver);
894
+ QUnit.assert.equal(2, baseData.ver);
895
+
896
+ // Assert baseType
897
+ QUnit.assert.ok(appInsightsEnvelope.data.baseType);
898
+ QUnit.assert.equal("PageviewData", appInsightsEnvelope.data.baseType);
899
+
900
+ // Assert tags
901
+ QUnit.assert.ok(appInsightsEnvelope.tags);
902
+ QUnit.assert.equal("TestAccountId", appInsightsEnvelope.tags["ai.user.accountId"]);
903
+ QUnit.assert.equal("AuthenticatedId", appInsightsEnvelope.tags["ai.user.authUserId"]);
904
+ QUnit.assert.equal("TestId", appInsightsEnvelope.tags["ai.user.id"]);
905
+
906
+ // Assert sdkVersion
907
+ QUnit.assert.ok(EnvelopeCreator.Version)
908
+ QUnit.assert.ok(EnvelopeCreator.Version.length > 0)
909
+ QUnit.assert.equal(`javascript:${EnvelopeCreator.Version}`, appInsightsEnvelope.tags["ai.internal.sdkVersion"])
910
+
911
+ // QUnit.assert.equal("d041d2e5fa834b4f9eee41ac163bf402", appInsightsEnvelope.tags["ai.session.id"]);
912
+ // QUnit.assert.equal("browser", appInsightsEnvelope.tags["ai.device.id"]);
913
+ // QUnit.assert.equal("Browser", appInsightsEnvelope.tags["ai.device.type"]);
914
+ // QUnit.assert.equal("javascript:1.0.18", appInsightsEnvelope.tags["ai.internal.sdkVersion"]);
915
+
916
+ // Assert name
917
+ QUnit.assert.ok(appInsightsEnvelope.name);
918
+ QUnit.assert.equal("Microsoft.ApplicationInsights.iKey.Pageview", appInsightsEnvelope.name);
919
+
920
+ // Assert iKey
921
+ QUnit.assert.ok(appInsightsEnvelope.iKey);
922
+ QUnit.assert.equal("iKey", appInsightsEnvelope.iKey);
923
+
924
+ // Assert timestamp
925
+ QUnit.assert.ok(appInsightsEnvelope.time);
926
+
927
+
928
+ QUnit.assert.equal("1528B5FF-6455-4657-BE77-E6664CAC72DC", appInsightsEnvelope.tags["ai.operation.id"]);
929
+ QUnit.assert.equal("1528B5FF-6455-4657-BE77-E6664CACEEEE", appInsightsEnvelope.tags["ai.operation.parentId"])
930
+ }
931
+ });
932
+
933
+ this.testCase({
934
+ name: "AppInsightsTests: AppInsights Envelope created for Page View with duration in customProperties Part C",
935
+ test: () => {
936
+ // setup
937
+ const inputEnvelope: ITelemetryItem = {
938
+ name: "test",
939
+ time: new Date("2018-06-12").toISOString(),
940
+ iKey: "iKey",
941
+ ext: {
942
+ "user": {
943
+ "localId": "TestId",
944
+ "authId": "AuthenticatedId",
945
+ "id": "TestId"
946
+ },
947
+ "trace": {
948
+ "traceID": "1528B5FF-6455-4657-BE77-E6664CAC72DC",
949
+ "parentID": "1528B5FF-6455-4657-BE77-E6664CACEEEE"
950
+ }
951
+ },
952
+ tags: [{"ai.user.accountId": "TestAccountId"}],
953
+ baseType: "PageviewData",
954
+ baseData: {
955
+ "name": "Page View Name",
956
+ "uri": "https://fakeUri.com",
957
+ properties: {
958
+ "property1": "val1",
959
+ "property2": "val2",
960
+ },
961
+ measurements: {
962
+ "measurement1": 50.0,
963
+ "measurement2": 1.3,
964
+ }
965
+ },
966
+ data: {
967
+ "duration": 300000
968
+ }
969
+ };
970
+
971
+ // Act
972
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
973
+ const baseData = appInsightsEnvelope.data.baseData;
974
+
975
+ // Assert duration
976
+ const resultDuration = baseData.duration;
977
+ QUnit.assert.equal("00:05:00.000", resultDuration);
978
+ }
979
+ });
980
+
981
+ this.testCase({
982
+ name: 'Envelope: custom properties are put into envelope for Exception data type',
983
+ test: () => {
984
+ const bd = new Exception(
985
+ null,
986
+ new Error(),
987
+ {"property1": "val1", "property2": "val2" },
988
+ {"measurement1": 50.0, "measurement2": 1.3 }
989
+ );
990
+ const inputEnvelope: ITelemetryItem = {
991
+ name: "test",
992
+ time: new Date("2018-06-12").toISOString(),
993
+ iKey: "iKey",
994
+ baseType: Exception.dataType,
995
+ baseData: bd,
996
+ data: {
997
+ "property3": "val3",
998
+ "measurement3": 3.0
999
+ },
1000
+ ext: {
1001
+ "user": {
1002
+ "localId": "TestId",
1003
+ "authId": "AuthenticatedId",
1004
+ "id": "TestId"
1005
+ }
1006
+ },
1007
+ tags: [{"user.accountId": "TestAccountId"}],
1008
+ };
1009
+
1010
+ // Act
1011
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
1012
+ const baseData = appInsightsEnvelope.data.baseData;
1013
+
1014
+ QUnit.assert.equal("val3", baseData.properties["property3"], "ExceptionData: customProperties (item.data) are added to the properties of the envelope and not included in the item.data")
1015
+ QUnit.assert.equal("val1", baseData.properties["property1"], "ExceptionData: properties (item.baseData.properties) are added to telemetry envelope");
1016
+ QUnit.assert.equal(50.0, baseData.measurements["measurement1"], "ExceptionData: measurements (item.baseData.measurements) are added to telemetry envelope");
1017
+
1018
+ }
1019
+ });
1020
+
1021
+ this.testCase({
1022
+ name: 'Offline watcher is listening to events',
1023
+ test: () => {
1024
+ QUnit.assert.ok(Offline.isListening, 'Offline is listening');
1025
+ QUnit.assert.equal(true, Offline.isOnline(), 'Offline reports online status');
1026
+ QUnit.assert.equal(false, Offline.isOffline(), 'Offline reports offline status');
1027
+ }
1028
+ });
1029
+
1030
+ this.testCase({
1031
+ name: 'Offline watcher responds to offline events (window.addEventListener)',
1032
+ useFakeTimers: true,
1033
+ test: () => {
1034
+ // Setup
1035
+ const offlineEvent = new Event('offline');
1036
+ const onlineEvent = new Event('online');
1037
+
1038
+ // Verify precondition
1039
+ QUnit.assert.ok(Offline.isListening);
1040
+ QUnit.assert.ok(Offline.isOnline());
1041
+
1042
+ // Act - Go offline
1043
+ window.dispatchEvent(offlineEvent);
1044
+ this.clock.tick(1);
1045
+
1046
+ // Verify offline
1047
+ QUnit.assert.ok(Offline.isOffline());
1048
+
1049
+ // Act - Go online
1050
+ window.dispatchEvent(onlineEvent);
1051
+ this.clock.tick(1);
1052
+
1053
+ // Verify online
1054
+ QUnit.assert.ok(Offline.isOnline());
1055
+ }
1056
+ });
1057
+
1058
+ this.testCase({
1059
+ name: "AppInsightsTests: AppInsights Envelope created for Page View with new web extension",
1060
+ test: () => {
1061
+ // setup
1062
+ const inputEnvelope: ITelemetryItem = {
1063
+ name: "test",
1064
+ iKey: "iKey",
1065
+ ext: {
1066
+ "web": {
1067
+ "domain": "www.bing.com",
1068
+ "userConsent": true,
1069
+ "screenRes": "1024x768",
1070
+ "browser": "internet explorer",
1071
+ "browserVer": "48.0",
1072
+ "isManual": true,
1073
+ "browserLang": "EN"
1074
+ }
1075
+ },
1076
+ baseType: "PageviewData",
1077
+ baseData: {
1078
+ "name": "Page View Name",
1079
+ "uri": "https://fakeUri.com",
1080
+ "startTime": new Date(123),
1081
+ properties: {
1082
+ "property1": "val1",
1083
+ "property2": "val2"
1084
+ },
1085
+ measurements: {
1086
+ "measurement1": 50.0,
1087
+ }
1088
+ }
1089
+ };
1090
+
1091
+ // Act
1092
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
1093
+ const baseData = appInsightsEnvelope.data.baseData;
1094
+
1095
+ // Assert envelope
1096
+ QUnit.assert.deepEqual(appInsightsEnvelope.time, new Date(123).toISOString());
1097
+
1098
+ // Assert measurements
1099
+ const resultMeasurements = baseData.measurements;
1100
+ QUnit.assert.ok(resultMeasurements);
1101
+ QUnit.assert.ok(resultMeasurements["measurement1"]);
1102
+ QUnit.assert.equal(50.0, resultMeasurements["measurement1"]);
1103
+
1104
+ // Assert custom properties
1105
+ QUnit.assert.ok(baseData.properties);
1106
+ QUnit.assert.equal("val1", baseData.properties["property1"]);
1107
+ QUnit.assert.equal("val2", baseData.properties["property2"]);
1108
+ QUnit.assert.equal("true", baseData.properties["isManual"]);
1109
+ QUnit.assert.equal("1024x768", baseData.properties["screenRes"]);
1110
+ QUnit.assert.equal("true", baseData.properties["userConsent"]);
1111
+ QUnit.assert.equal("www.bing.com", baseData.properties["domain"]);
1112
+
1113
+ QUnit.assert.equal("internet explorer", appInsightsEnvelope.tags[CtxTagKeys.deviceBrowser]);
1114
+ QUnit.assert.equal("48.0", appInsightsEnvelope.tags[CtxTagKeys.deviceBrowserVersion]);
1115
+ QUnit.assert.equal("EN", appInsightsEnvelope.tags[CtxTagKeys.deviceLanguage]);
1116
+
1117
+ // Assert Page View name
1118
+ QUnit.assert.ok(baseData.name);
1119
+ QUnit.assert.equal("Page View Name", baseData.name);
1120
+
1121
+ // Assert ver
1122
+ QUnit.assert.ok(baseData.ver);
1123
+ QUnit.assert.equal(2, baseData.ver);
1124
+
1125
+ // Assert baseType
1126
+ QUnit.assert.ok(appInsightsEnvelope.data.baseType);
1127
+ QUnit.assert.equal("PageviewData", appInsightsEnvelope.data.baseType);
1128
+
1129
+ // Assert name
1130
+ QUnit.assert.ok(appInsightsEnvelope.name);
1131
+ QUnit.assert.equal("Microsoft.ApplicationInsights.iKey.Pageview", appInsightsEnvelope.name);
1132
+ }
1133
+ });
1134
+
1135
+ this.testCase({
1136
+ name: "Channel Config: Notification is sent when requests are being sent when requests exceed max batch size",
1137
+ useFakeTimers: true,
1138
+ test: () => {
1139
+ let sendNotifications = [];
1140
+ let notificationManager = new NotificationManager();
1141
+ notificationManager.addNotificationListener({
1142
+ eventsSendRequest: (sendReason: number, isAsync?: boolean) => {
1143
+ sendNotifications.push({
1144
+ sendReason,
1145
+ isAsync
1146
+ });
1147
+ }
1148
+ });
1149
+
1150
+ let core = new AppInsightsCore();
1151
+ this.sandbox.stub(core, "getNotifyMgr").returns(notificationManager);
1152
+
1153
+ this._sender.initialize(
1154
+ {
1155
+ instrumentationKey: 'abc',
1156
+ maxBatchInterval: 123,
1157
+ endpointUrl: 'https://example.com',
1158
+ maxBatchSizeInBytes: 100,
1159
+ extensionConfig: {
1160
+ [this._sender.identifier]: {
1161
+ maxBatchSizeInBytes: 100
1162
+ }
1163
+ }
1164
+
1165
+ }, core, []
1166
+ );
1167
+
1168
+ const loggerSpy = this.sandbox.spy(this._sender, "triggerSend");
1169
+ const telemetryItem: ITelemetryItem = {
1170
+ name: 'fake item',
1171
+ iKey: 'iKey',
1172
+ baseType: 'some type',
1173
+ baseData: {}
1174
+ };
1175
+ try {
1176
+ this._sender.processTelemetry(telemetryItem, null);
1177
+ } catch(e) {
1178
+ QUnit.assert.ok(false);
1179
+ }
1180
+
1181
+ QUnit.assert.equal(true, loggerSpy.calledOnce);
1182
+ this.clock.tick(1);
1183
+ QUnit.assert.ok(sendNotifications.length === 1);
1184
+ QUnit.assert.ok(sendNotifications[0].sendReason === SendRequestReason.MaxBatchSize);
1185
+ }
1186
+ });
1187
+
1188
+ this.testCase({
1189
+ name: "Channel Config: Notification is sent when requests are being sent with manual flush",
1190
+ useFakeTimers: true,
1191
+ test: () => {
1192
+ let sendNotifications = [];
1193
+ let notificationManager = new NotificationManager();
1194
+ notificationManager.addNotificationListener({
1195
+ eventsSendRequest: (sendReason: number, isAsync?: boolean) => {
1196
+ sendNotifications.push({
1197
+ sendReason,
1198
+ isAsync
1199
+ });
1200
+ }
1201
+ });
1202
+
1203
+ let core = new AppInsightsCore();
1204
+ this.sandbox.stub(core, "getNotifyMgr").returns(notificationManager);
1205
+
1206
+ this._sender.initialize(
1207
+ {
1208
+ instrumentationKey: 'abc',
1209
+ maxBatchInterval: 123,
1210
+ endpointUrl: 'https://example.com',
1211
+ extensionConfig: {
1212
+ }
1213
+
1214
+ }, core, []
1215
+ );
1216
+
1217
+ const loggerSpy = this.sandbox.spy(this._sender, "triggerSend");
1218
+ const telemetryItem: ITelemetryItem = {
1219
+ name: 'fake item',
1220
+ iKey: 'iKey',
1221
+ baseType: 'some type',
1222
+ baseData: {}
1223
+ };
1224
+ try {
1225
+ this._sender.processTelemetry(telemetryItem, null);
1226
+ } catch(e) {
1227
+ QUnit.assert.ok(false);
1228
+ }
1229
+
1230
+ QUnit.assert.equal(false, loggerSpy.calledOnce);
1231
+ QUnit.assert.equal(0, sendNotifications.length);
1232
+
1233
+ this._sender.flush();
1234
+ QUnit.assert.equal(true, loggerSpy.calledOnce);
1235
+ QUnit.assert.equal(0, sendNotifications.length);
1236
+
1237
+ this.clock.tick(1);
1238
+
1239
+ QUnit.assert.equal(1, sendNotifications.length);
1240
+ QUnit.assert.equal(SendRequestReason.ManualFlush, sendNotifications[0].sendReason);
1241
+ }
1242
+ });
1243
+
1244
+ this.testCase({
1245
+ name: "IKey Validation Test",
1246
+ test: () => {
1247
+ let appInsightsCore = new AppInsightsCore();
1248
+ appInsightsCore.logger = new DiagnosticLogger();
1249
+ let messageId: _InternalMessageId = _InternalMessageId.InvalidInstrumentationKey;
1250
+ let logInternalSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
1251
+ this._sender.initialize(
1252
+ {
1253
+ instrumentationKey: '1aa11111-bbbb-1ccc-8ddd-eeeeffff3333',
1254
+ maxBatchInterval: 123,
1255
+ endpointUrl: 'https://example.com',
1256
+ maxBatchSizeInBytes: 654,
1257
+ extensionConfig: {
1258
+ [this._sender.identifier]: {
1259
+ maxBatchSizeInBytes: 456
1260
+ }
1261
+ }
1262
+
1263
+ }, appInsightsCore, []
1264
+ );
1265
+
1266
+ QUnit.assert.equal(false,logInternalSpy.calledOnce, 'valid Ikey test-1');
1267
+ QUnit.assert.equal(0, appInsightsCore.logger.queue.length, "POST: No messageId logged");
1268
+
1269
+ appInsightsCore = new AppInsightsCore();
1270
+ appInsightsCore.logger = new DiagnosticLogger();
1271
+ messageId = _InternalMessageId.InvalidInstrumentationKey;
1272
+ logInternalSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
1273
+ this._sender.initialize(
1274
+ {
1275
+ instrumentationKey: '1aa11111bbbb1ccc8dddeeeeffff3333',
1276
+ maxBatchInterval: 123,
1277
+ endpointUrl: 'https://example.com',
1278
+ maxBatchSizeInBytes: 654,
1279
+ extensionConfig: {
1280
+ [this._sender.identifier]: {
1281
+ maxBatchSizeInBytes: 456
1282
+ }
1283
+ }
1284
+
1285
+ }, appInsightsCore, []
1286
+ );
1287
+
1288
+ QUnit.assert.ok(logInternalSpy.calledOnce, 'iKey Validation check -throwInternal called');
1289
+ QUnit.assert.equal(messageId, logInternalSpy.args[0][1].messageId, "Correct message logged");
1290
+ QUnit.assert.ok(logInternalSpy.args[0][1].message.indexOf('Invalid Instrumentation key') !== -1, "Correct message logged");
1291
+ QUnit.assert.equal(1, appInsightsCore.logger.queue.length, "POST: Correct messageId logged");
1292
+ QUnit.assert.ok(appInsightsCore.logger.queue[0].message.indexOf('Invalid Instrumentation key') !== -1, "Correct message logged");
1293
+ QUnit.assert.equal(messageId, appInsightsCore.logger.queue[0].messageId, "Correct message logged");
1294
+
1295
+ appInsightsCore = new AppInsightsCore();
1296
+ appInsightsCore.logger = new DiagnosticLogger();
1297
+ messageId = _InternalMessageId.InvalidInstrumentationKey;
1298
+ logInternalSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
1299
+ this._sender.initialize(
1300
+ {
1301
+ instrumentationKey: 'abc',
1302
+ maxBatchInterval: 123,
1303
+ endpointUrl: 'https://example.com',
1304
+ maxBatchSizeInBytes: 654,
1305
+ extensionConfig: {
1306
+ [this._sender.identifier]: {
1307
+ maxBatchSizeInBytes: 456
1308
+ }
1309
+ }
1310
+
1311
+ }, appInsightsCore, []
1312
+ );
1313
+
1314
+ QUnit.assert.ok(logInternalSpy.calledOnce, 'iKey Validation check -throwInternal called');
1315
+ QUnit.assert.equal(messageId, logInternalSpy.args[0][1].messageId, "Correct message logged");
1316
+ QUnit.assert.ok(logInternalSpy.args[0][1].message.indexOf('Invalid Instrumentation key') !== -1, "Correct message logged");
1317
+ QUnit.assert.equal(1, appInsightsCore.logger.queue.length, "POST: Correct messageId logged");
1318
+ QUnit.assert.ok(appInsightsCore.logger.queue[0].message.indexOf('Invalid Instrumentation key') !== -1, "Correct message logged");
1319
+ QUnit.assert.equal(messageId, appInsightsCore.logger.queue[0].messageId, "Correct message logged");
1320
+
1321
+ appInsightsCore = new AppInsightsCore();
1322
+ appInsightsCore.logger = new DiagnosticLogger();
1323
+ messageId = _InternalMessageId.InvalidInstrumentationKey;
1324
+ logInternalSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
1325
+ this._sender.initialize(
1326
+ {
1327
+ instrumentationKey: '',
1328
+ maxBatchInterval: 123,
1329
+ endpointUrl: 'https://example.com',
1330
+ maxBatchSizeInBytes: 654,
1331
+ extensionConfig: {
1332
+ [this._sender.identifier]: {
1333
+ maxBatchSizeInBytes: 456
1334
+ }
1335
+ }
1336
+
1337
+ }, appInsightsCore, []
1338
+ );
1339
+
1340
+ QUnit.assert.ok(logInternalSpy.calledOnce, 'iKey Validation check -throwInternal called');
1341
+ QUnit.assert.equal(messageId, logInternalSpy.args[0][1].messageId, "Correct message logged");
1342
+ QUnit.assert.ok(logInternalSpy.args[0][1].message.indexOf('Invalid Instrumentation key') !== -1, "Correct message logged");
1343
+ QUnit.assert.equal(1, appInsightsCore.logger.queue.length, "POST: Correct messageId logged");
1344
+ QUnit.assert.ok(appInsightsCore.logger.queue[0].message.indexOf('Invalid Instrumentation key') !== -1, "Correct message logged");
1345
+ QUnit.assert.equal(messageId, appInsightsCore.logger.queue[0].messageId, "Correct message logged");
1346
+
1347
+ appInsightsCore = new AppInsightsCore();
1348
+ appInsightsCore.logger = new DiagnosticLogger();
1349
+ messageId = _InternalMessageId.InvalidInstrumentationKey;
1350
+ logInternalSpy = this.sandbox.spy(appInsightsCore.logger, 'logInternalMessage');
1351
+ this._sender.initialize(
1352
+ {
1353
+ instrumentationKey: 'abc',
1354
+ maxBatchInterval: 123,
1355
+ endpointUrl: 'https://example.com',
1356
+ maxBatchSizeInBytes: 654,
1357
+ extensionConfig: {
1358
+ [this._sender.identifier]: {
1359
+ maxBatchSizeInBytes: 456
1360
+ }
1361
+ },
1362
+ disableInstrumentationKeyValidation: true
1363
+
1364
+ }, appInsightsCore, []
1365
+ );
1366
+
1367
+ QUnit.assert.equal(false,logInternalSpy.calledOnce, 'disableIKeyValidation flag set to yes');
1368
+ QUnit.assert.equal(0, appInsightsCore.logger.queue.length, "POST: No messageId logged");
1369
+ }
1370
+
1371
+
1372
+ });
1373
+
1374
+ this.testCase({
1375
+ name: "Channel Config: convert custom dimension undefined values to customer defined value with config convertUndefined",
1376
+ test: () => {
1377
+ const inputEnvelope: ITelemetryItem = {
1378
+ name: "test",
1379
+ iKey: "iKey",
1380
+ data: {
1381
+ "property1": undefined,
1382
+ "property2": "value2"
1383
+ },
1384
+ baseData: {
1385
+ "name": "Event Name"
1386
+ }
1387
+ };
1388
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null, "test");
1389
+
1390
+ const baseData = appInsightsEnvelope.data.baseData;
1391
+
1392
+ // Assert custom properties
1393
+ QUnit.assert.ok(baseData.properties);
1394
+ QUnit.assert.equal("test", baseData.properties["property1"]);
1395
+ QUnit.assert.equal("value2", baseData.properties["property2"]);
1396
+ }
1397
+ });
1398
+
1399
+ this.testCase({
1400
+ name: "Channel Config: Validate pausing and resuming sending with manual flush",
1401
+ useFakeTimers: true,
1402
+ test: () => {
1403
+ let sendNotifications = [];
1404
+ let notificationManager = new NotificationManager();
1405
+ notificationManager.addNotificationListener({
1406
+ eventsSendRequest: (sendReason: number, isAsync?: boolean) => {
1407
+ sendNotifications.push({
1408
+ sendReason,
1409
+ isAsync
1410
+ });
1411
+ }
1412
+ });
1413
+
1414
+ let core = new AppInsightsCore();
1415
+ this.sandbox.stub(core, "getNotifyMgr").returns(notificationManager);
1416
+
1417
+ this._sender.initialize(
1418
+ {
1419
+ instrumentationKey: 'abc',
1420
+ maxBatchInterval: 123,
1421
+ endpointUrl: 'https://example.com',
1422
+ extensionConfig: {
1423
+ }
1424
+
1425
+ }, core, []
1426
+ );
1427
+
1428
+ const loggerSpy = this.sandbox.spy(this._sender, "triggerSend");
1429
+ const telemetryItem: ITelemetryItem = {
1430
+ name: 'fake item',
1431
+ iKey: 'iKey',
1432
+ baseType: 'some type',
1433
+ baseData: {}
1434
+ };
1435
+ try {
1436
+ this._sender.processTelemetry(telemetryItem, null);
1437
+ } catch(e) {
1438
+ QUnit.assert.ok(false);
1439
+ }
1440
+
1441
+ QUnit.assert.equal(false, loggerSpy.calledOnce);
1442
+ QUnit.assert.equal(0, sendNotifications.length);
1443
+
1444
+ this._sender.pause();
1445
+ this._sender.flush();
1446
+ QUnit.assert.equal(false, loggerSpy.calledOnce);
1447
+ QUnit.assert.equal(0, sendNotifications.length);
1448
+
1449
+ this.clock.tick(1);
1450
+
1451
+ QUnit.assert.equal(0, sendNotifications.length);
1452
+
1453
+ this._sender.resume();
1454
+ this._sender.flush();
1455
+ QUnit.assert.equal(true, loggerSpy.calledOnce);
1456
+ QUnit.assert.equal(0, sendNotifications.length);
1457
+
1458
+ this.clock.tick(1);
1459
+
1460
+ QUnit.assert.equal(1, sendNotifications.length);
1461
+ QUnit.assert.equal(SendRequestReason.ManualFlush, sendNotifications[0].sendReason);
1462
+ }
1463
+ });
1464
+
1465
+ this.testCase({
1466
+ name: "Channel Config: Validate pausing and resuming sending when exceeding the batch size limits",
1467
+ useFakeTimers: true,
1468
+ test: () => {
1469
+ let sendNotifications = [];
1470
+ let notificationManager = new NotificationManager();
1471
+ notificationManager.addNotificationListener({
1472
+ eventsSendRequest: (sendReason: number, isAsync?: boolean) => {
1473
+ sendNotifications.push({
1474
+ sendReason,
1475
+ isAsync
1476
+ });
1477
+ }
1478
+ });
1479
+
1480
+ let core = new AppInsightsCore();
1481
+ this.sandbox.stub(core, "getNotifyMgr").returns(notificationManager);
1482
+
1483
+ this._sender.initialize(
1484
+ {
1485
+ instrumentationKey: 'abc',
1486
+ maxBatchInterval: 123,
1487
+ maxBatchSizeInBytes: 4096,
1488
+ endpointUrl: 'https://example.com',
1489
+ extensionConfig: {
1490
+ }
1491
+
1492
+ }, core, []
1493
+ );
1494
+
1495
+ const triggerSendSpy = this.sandbox.spy(this._sender, "triggerSend");
1496
+ const telemetryItem: ITelemetryItem = {
1497
+ name: 'fake item',
1498
+ iKey: 'iKey',
1499
+ baseType: 'some type',
1500
+ baseData: {}
1501
+ };
1502
+
1503
+ this._sender.pause();
1504
+
1505
+ // Keep sending events until the max payload size is reached
1506
+ while (!triggerSendSpy.calledOnce) {
1507
+ try {
1508
+ this._sender.processTelemetry(telemetryItem, null);
1509
+ } catch(e) {
1510
+ QUnit.assert.ok(false);
1511
+ }
1512
+ }
1513
+
1514
+ QUnit.assert.equal(true, triggerSendSpy.calledOnce);
1515
+ QUnit.assert.equal(0, sendNotifications.length);
1516
+
1517
+ this.clock.tick(1);
1518
+
1519
+ QUnit.assert.equal(0, sendNotifications.length);
1520
+
1521
+ QUnit.assert.equal(false, triggerSendSpy.calledTwice);
1522
+ this._sender.resume();
1523
+
1524
+ QUnit.assert.equal(true, triggerSendSpy.calledTwice);
1525
+ QUnit.assert.equal(0, sendNotifications.length);
1526
+
1527
+ this.clock.tick(1);
1528
+
1529
+ QUnit.assert.equal(1, sendNotifications.length);
1530
+ QUnit.assert.equal(SendRequestReason.MaxBatchSize, sendNotifications[0].sendReason);
1531
+ }
1532
+ });
1533
+
1534
+ this.testCase({
1535
+ name: 'Envelope: operation.name is correctly truncated if required',
1536
+ test: () => {
1537
+ const excessiveName = new Array(1234).join("a"); // exceeds max of 1024
1538
+
1539
+ const bd = new Exception(
1540
+ null,
1541
+ new Error(),
1542
+ {"property1": "val1", "property2": "val2" },
1543
+ {"measurement1": 50.0, "measurement2": 1.3 }
1544
+ );
1545
+ const inputEnvelope: ITelemetryItem = {
1546
+ name: "test",
1547
+ time: new Date("2018-06-12").toISOString(),
1548
+ iKey: "iKey",
1549
+ baseType: Exception.dataType,
1550
+ baseData: bd,
1551
+ data: {
1552
+ "property3": "val3",
1553
+ "measurement3": 3.0
1554
+ },
1555
+ ext: {
1556
+ "trace": {
1557
+ "traceID": "1528B5FF-6455-4657-BE77-E6664CAC72DC",
1558
+ "parentID": "1528B5FF-6455-4657-BE77-E6664CACEEEE",
1559
+ "name": excessiveName
1560
+ }
1561
+ },
1562
+ tags: [
1563
+ {"user.accountId": "TestAccountId"},
1564
+ ],
1565
+ };
1566
+
1567
+ // Act
1568
+ const appInsightsEnvelope = Sender.constructEnvelope(inputEnvelope, this._instrumentationKey, null);
1569
+ const baseData = appInsightsEnvelope.data.baseData;
1570
+
1571
+ QUnit.assert.equal("val3", baseData.properties["property3"], "ExceptionData: customProperties (item.data) are added to the properties of the envelope and not included in the item.data")
1572
+ QUnit.assert.equal("val1", baseData.properties["property1"], "ExceptionData: properties (item.baseData.properties) are added to telemetry envelope");
1573
+ QUnit.assert.equal(50.0, baseData.measurements["measurement1"], "ExceptionData: measurements (item.baseData.measurements) are added to telemetry envelope");
1574
+ QUnit.assert.equal(1024, appInsightsEnvelope.tags["ai.operation.name"].length, "The ai.operation.name should have been truncated to the maximum");
1575
+ }
1576
+ });
1577
+ }
1578
+ }