From eb0957404a03811496c5c06ce29624afd0b653e2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 17:34:53 +0000 Subject: [PATCH 1/7] Initial plan for issue From e76b4cf1f6fab5a413a480a1deb360a83b5fe2ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 17:53:13 +0000 Subject: [PATCH 2/7] Updated async tests to use asyncQueue Co-authored-by: MSNev <54870357+MSNev@users.noreply.github.com> --- .../Tests/Unit/src/AnalyticsPlugin.tests.ts | 549 +++++++++--------- 1 file changed, 277 insertions(+), 272 deletions(-) diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts index 35b99ab45..5f6bca05f 100644 --- a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts @@ -1063,324 +1063,329 @@ export class AnalyticsPluginTests extends AITestClass { }); - this.testCaseAsync({ + this.testCase({ name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics", - stepDelay: 1, useFakeTimers: true, - steps: [() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + test: () => { + return this._asyncQueue().add(() => { + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } - } - }, - [sender] - ); - const appInsights = new AnalyticsPlugin(); - core.addPlugin(appInsights); - appInsights.addTelemetryInitializer((item: ITelemetryItem) => { - Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); - }); + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } + } + }, + [sender] + ); + const appInsights = new AnalyticsPlugin(); + core.addPlugin(appInsights); + appInsights.addTelemetryInitializer((item: ITelemetryItem) => { + Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); + }); - this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); - sender._sender = (payload:any[], isAsync:boolean) => { - sender._onSuccess(payload, payload.length); - }; - this.sandbox.spy() - this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); + this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); + sender._sender = (payload:any[], isAsync:boolean) => { + sender._onSuccess(payload, payload.length); + }; + this.sandbox.spy() + this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); - this.exceptionHelper.capture(appInsights); + this.exceptionHelper.capture(appInsights); - this.causeException(() => { - this.exceptionHelper.throwRuntimeException(AITestClass.orgSetTimeout); - }); + this.causeException(() => { + this.exceptionHelper.throwRuntimeException(AITestClass.orgSetTimeout); + }); - Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); - Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }].concat(this.waitForException(1)) - .concat(() => { - let isLocal = window.location.protocol === "file:"; - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); - - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - if (isLocal) { - Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.equal("String", ex.typeName, "Got the correct typename [" + ex.typeName + "]"); - } else { - Assert.ok(ex.message.indexOf("ug is not a function") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.equal("TypeError", ex.typeName, "Got the correct typename [" + ex.typeName + "]"); - Assert.ok(baseData.properties["columnNumber"], "has column number"); - Assert.ok(baseData.properties["lineNumber"], "has Line number"); + Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); + Assert.ok(!this.throwInternalSpy.called, "No internal errors"); + }) + .concat(this.waitForException(1)) + .add(() => { + let isLocal = window.location.protocol === "file:"; + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + if (isLocal) { + Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.equal("String", ex.typeName, "Got the correct typename [" + ex.typeName + "]"); + } else { + Assert.ok(ex.message.indexOf("ug is not a function") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.equal("TypeError", ex.typeName, "Got the correct typename [" + ex.typeName + "]"); + Assert.ok(baseData.properties["columnNumber"], "has column number"); + Assert.ok(baseData.properties["lineNumber"], "has Line number"); + } + + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.ok(baseData.properties["url"], "has Url"); + Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } - - Assert.ok(ex.stack.length > 0, "Has stack"); - Assert.ok(ex.parsedStack, "Stack was parsed"); - Assert.ok(ex.hasFullStack, "Stack has been decoded"); - Assert.ok(baseData.properties["url"], "has Url"); - Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } } - } - }) - + }); + } }); - this.testCaseAsync({ + this.testCase({ name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a text exception", - stepDelay: 1, useFakeTimers: true, - steps: [() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + test: () => { + return this._asyncQueue().add(() => { + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } - } - }, - [sender] - ); - const appInsights = new AnalyticsPlugin(); - core.addPlugin(appInsights); - appInsights.addTelemetryInitializer((item: ITelemetryItem) => { - Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); - }); + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } + } + }, + [sender] + ); + const appInsights = new AnalyticsPlugin(); + core.addPlugin(appInsights); + appInsights.addTelemetryInitializer((item: ITelemetryItem) => { + Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); + }); - this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); - sender._sender = (payload:any[], isAsync:boolean) => { - sender._onSuccess(payload, payload.length); - }; - this.sandbox.spy() - this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); + this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); + sender._sender = (payload:any[], isAsync:boolean) => { + sender._onSuccess(payload, payload.length); + }; + this.sandbox.spy() + this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); - this.exceptionHelper.capture(appInsights); - this.causeException(() => { - this.exceptionHelper.throw("Test Text Error!"); - }); + this.exceptionHelper.capture(appInsights); + this.causeException(() => { + this.exceptionHelper.throw("Test Text Error!"); + }); - Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); - Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }].concat(this.waitForException(1)) - .concat(() => { - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.ok(baseData.properties["columnNumber"], "has column number"); - Assert.ok(baseData.properties["lineNumber"], "has Line number"); - Assert.equal("String", ex.typeName, "Got the correct typename"); - Assert.ok(ex.stack.length > 0, "Has stack"); - Assert.ok(ex.parsedStack, "Stack was parsed"); - Assert.ok(ex.hasFullStack, "Stack has been decoded"); - Assert.ok(baseData.properties["url"], "has Url"); - Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); + Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); + Assert.ok(!this.throwInternalSpy.called, "No internal errors"); + }) + .concat(this.waitForException(1)) + .add(() => { + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.ok(baseData.properties["columnNumber"], "has column number"); + Assert.ok(baseData.properties["lineNumber"], "has Line number"); + Assert.equal("String", ex.typeName, "Got the correct typename"); + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.ok(baseData.properties["url"], "has Url"); + Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); + } } } - } - }) + }); + } }); - this.testCaseAsync({ + this.testCase({ name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a custom direct exception", - stepDelay: 1, useFakeTimers: true, - steps: [() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + test: () => { + return this._asyncQueue().add(() => { + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } - } - }, - [sender] - ); - const appInsights = new AnalyticsPlugin(); - core.addPlugin(appInsights); - appInsights.addTelemetryInitializer((item: ITelemetryItem) => { - Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); - }); + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } + } + }, + [sender] + ); + const appInsights = new AnalyticsPlugin(); + core.addPlugin(appInsights); + appInsights.addTelemetryInitializer((item: ITelemetryItem) => { + Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); + }); - this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); - sender._sender = (payload:any[], isAsync:boolean) => { - sender._onSuccess(payload, payload.length); - }; - this.sandbox.spy() - this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); + this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); + sender._sender = (payload:any[], isAsync:boolean) => { + sender._onSuccess(payload, payload.length); + }; + this.sandbox.spy() + this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); - this.exceptionHelper.capture(appInsights); - this.causeException(() => { - this.exceptionHelper.throw(new CustomTestError("Test Text Error!")); - }); + this.exceptionHelper.capture(appInsights); + this.causeException(() => { + this.exceptionHelper.throw(new CustomTestError("Test Text Error!")); + }); - Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); - Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }].concat(this.waitForException(1)) - .concat(() => { - - let isLocal = window.location.protocol === "file:"; - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - if (isLocal) { - Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.equal("String", ex.typeName, "Got the correct typename"); - } else { - Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]"); - Assert.equal("CustomTestError", ex.typeName, "Got the correct typename"); - Assert.ok(baseData.properties["columnNumber"], "has column number"); - Assert.ok(baseData.properties["lineNumber"], "has Line number"); + Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); + Assert.ok(!this.throwInternalSpy.called, "No internal errors"); + }) + .concat(this.waitForException(1)) + .add(() => { + let isLocal = window.location.protocol === "file:"; + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + if (isLocal) { + Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.equal("String", ex.typeName, "Got the correct typename"); + } else { + Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]"); + Assert.equal("CustomTestError", ex.typeName, "Got the correct typename"); + Assert.ok(baseData.properties["columnNumber"], "has column number"); + Assert.ok(baseData.properties["lineNumber"], "has Line number"); + } + + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.ok(baseData.properties["url"], "has Url"); + Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } - - Assert.ok(ex.stack.length > 0, "Has stack"); - Assert.ok(ex.parsedStack, "Stack was parsed"); - Assert.ok(ex.hasFullStack, "Stack has been decoded"); - Assert.ok(baseData.properties["url"], "has Url"); - Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } } - } - }) + }); + } }); - this.testCaseAsync({ + this.testCase({ name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a strict custom direct exception", - stepDelay: 1, useFakeTimers: true, - steps: [() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + test: () => { + return this._asyncQueue().add(() => { + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } - } - }, - [sender] - ); - const appInsights = new AnalyticsPlugin(); - core.addPlugin(appInsights); - appInsights.addTelemetryInitializer((item: ITelemetryItem) => { - Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); - }); + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } + } + }, + [sender] + ); + const appInsights = new AnalyticsPlugin(); + core.addPlugin(appInsights); + appInsights.addTelemetryInitializer((item: ITelemetryItem) => { + Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); + }); - this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); - sender._sender = (payload:any[], isAsync:boolean) => { - sender._onSuccess(payload, payload.length); - }; - this.sandbox.spy() - this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); + this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); + sender._sender = (payload:any[], isAsync:boolean) => { + sender._onSuccess(payload, payload.length); + }; + this.sandbox.spy() + this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); - this.exceptionHelper.capture(appInsights); - this.causeException(() => { - this.exceptionHelper.throwStrict(new CustomTestError("Test Text Error!")); - }); + this.exceptionHelper.capture(appInsights); + this.causeException(() => { + this.exceptionHelper.throwStrict(new CustomTestError("Test Text Error!")); + }); - Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); - Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }].concat(this.waitForException(1)) - .concat(() => { - - let isLocal = window.location.protocol === "file:"; - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - if (isLocal) { - Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.equal("String", ex.typeName, "Got the correct typename"); - } else { - Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]"); - Assert.equal("CustomTestError", ex.typeName, "Got the correct typename"); - Assert.ok(baseData.properties["columnNumber"], "has column number"); - Assert.ok(baseData.properties["lineNumber"], "has Line number"); + Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); + Assert.ok(!this.throwInternalSpy.called, "No internal errors"); + }) + .concat(this.waitForException(1)) + .add(() => { + let isLocal = window.location.protocol === "file:"; + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + if (isLocal) { + Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.equal("String", ex.typeName, "Got the correct typename"); + } else { + Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]"); + Assert.equal("CustomTestError", ex.typeName, "Got the correct typename"); + Assert.ok(baseData.properties["columnNumber"], "has column number"); + Assert.ok(baseData.properties["lineNumber"], "has Line number"); + } + + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.ok(baseData.properties["url"], "has Url"); + Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } - - Assert.ok(ex.stack.length > 0, "Has stack"); - Assert.ok(ex.parsedStack, "Stack was parsed"); - Assert.ok(ex.hasFullStack, "Stack has been decoded"); - Assert.ok(baseData.properties["url"], "has Url"); - Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } } - } - }) + }); + } }); } From ae08b9b2f70d19ec389f71c94d3e0b6524f83263 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 18:34:05 +0000 Subject: [PATCH 3/7] Updated async tests to use waitForExceptionPromise with asyncQueue pattern Co-authored-by: MSNev <54870357+MSNev@users.noreply.github.com> --- .../Tests/Unit/src/AnalyticsPlugin.tests.ts | 497 ++++++++++-------- 1 file changed, 279 insertions(+), 218 deletions(-) diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts index 5f6bca05f..89b04aec2 100644 --- a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts @@ -1067,67 +1067,67 @@ export class AnalyticsPluginTests extends AITestClass { name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics", useFakeTimers: true, test: () => { - return this._asyncQueue().add(() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } - } - }, - [sender] - ); - const appInsights = new AnalyticsPlugin(); - core.addPlugin(appInsights); - appInsights.addTelemetryInitializer((item: ITelemetryItem) => { - Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); - }); + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } + } + }, + [sender] + ); + const appInsights = new AnalyticsPlugin(); + core.addPlugin(appInsights); + appInsights.addTelemetryInitializer((item: ITelemetryItem) => { + Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); + }); - this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); - sender._sender = (payload:any[], isAsync:boolean) => { - sender._onSuccess(payload, payload.length); - }; - this.sandbox.spy() - this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); + this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); + sender._sender = (payload:any[], isAsync:boolean) => { + sender._onSuccess(payload, payload.length); + }; + this.sandbox.spy() + this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); - this.exceptionHelper.capture(appInsights); + this.exceptionHelper.capture(appInsights); - this.causeException(() => { - this.exceptionHelper.throwRuntimeException(AITestClass.orgSetTimeout); - }); + this.causeException(() => { + this.exceptionHelper.throwRuntimeException(AITestClass.orgSetTimeout); + }); - Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); - Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }) - .concat(this.waitForException(1)) - .add(() => { - let isLocal = window.location.protocol === "file:"; - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); + Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - if (isLocal) { - Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.equal("String", ex.typeName, "Got the correct typename [" + ex.typeName + "]"); + return this._asyncQueue() + .concat(this.waitForExceptionPromise(1)) + .add(() => { + let isLocal = window.location.protocol === "file:"; + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + if (isLocal) { + Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.equal("String", ex.typeName, "Got the correct typename [" + ex.typeName + "]"); } else { Assert.ok(ex.message.indexOf("ug is not a function") !== -1, "Make sure the error message is present [" + ex.message + "]"); Assert.equal("TypeError", ex.typeName, "Got the correct typename [" + ex.typeName + "]"); @@ -1151,23 +1151,22 @@ export class AnalyticsPluginTests extends AITestClass { name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a text exception", useFakeTimers: true, test: () => { - return this._asyncQueue().add(() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } } }, [sender] @@ -1192,33 +1191,34 @@ export class AnalyticsPluginTests extends AITestClass { Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }) - .concat(this.waitForException(1)) - .add(() => { - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.ok(baseData.properties["columnNumber"], "has column number"); - Assert.ok(baseData.properties["lineNumber"], "has Line number"); - Assert.equal("String", ex.typeName, "Got the correct typename"); - Assert.ok(ex.stack.length > 0, "Has stack"); - Assert.ok(ex.parsedStack, "Stack was parsed"); - Assert.ok(ex.hasFullStack, "Stack has been decoded"); - Assert.ok(baseData.properties["url"], "has Url"); - Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); + + return this._asyncQueue() + .concat(this.waitForExceptionPromise(1)) + .add(() => { + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.ok(baseData.properties["columnNumber"], "has column number"); + Assert.ok(baseData.properties["lineNumber"], "has Line number"); + Assert.equal("String", ex.typeName, "Got the correct typename"); + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.ok(baseData.properties["url"], "has Url"); + Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); + } + } } - } - } - }); + }); } }); @@ -1226,82 +1226,82 @@ export class AnalyticsPluginTests extends AITestClass { name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a custom direct exception", useFakeTimers: true, test: () => { - return this._asyncQueue().add(() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } - } - }, - [sender] - ); - const appInsights = new AnalyticsPlugin(); - core.addPlugin(appInsights); - appInsights.addTelemetryInitializer((item: ITelemetryItem) => { - Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); - }); + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } + } + }, + [sender] + ); + const appInsights = new AnalyticsPlugin(); + core.addPlugin(appInsights); + appInsights.addTelemetryInitializer((item: ITelemetryItem) => { + Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); + }); - this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); - sender._sender = (payload:any[], isAsync:boolean) => { - sender._onSuccess(payload, payload.length); - }; - this.sandbox.spy() - this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); + this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); + sender._sender = (payload:any[], isAsync:boolean) => { + sender._onSuccess(payload, payload.length); + }; + this.sandbox.spy() + this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); - this.exceptionHelper.capture(appInsights); - this.causeException(() => { - this.exceptionHelper.throw(new CustomTestError("Test Text Error!")); - }); + this.exceptionHelper.capture(appInsights); + this.causeException(() => { + this.exceptionHelper.throw(new CustomTestError("Test Text Error!")); + }); - Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); - Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }) - .concat(this.waitForException(1)) - .add(() => { - let isLocal = window.location.protocol === "file:"; - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - if (isLocal) { - Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.equal("String", ex.typeName, "Got the correct typename"); - } else { - Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]"); - Assert.equal("CustomTestError", ex.typeName, "Got the correct typename"); - Assert.ok(baseData.properties["columnNumber"], "has column number"); - Assert.ok(baseData.properties["lineNumber"], "has Line number"); + Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); + Assert.ok(!this.throwInternalSpy.called, "No internal errors"); + + return this._asyncQueue() + .concat(this.waitForExceptionPromise(1)) + .add(() => { + let isLocal = window.location.protocol === "file:"; + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + if (isLocal) { + Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.equal("String", ex.typeName, "Got the correct typename"); + } else { + Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]"); + Assert.equal("CustomTestError", ex.typeName, "Got the correct typename"); + Assert.ok(baseData.properties["columnNumber"], "has column number"); + Assert.ok(baseData.properties["lineNumber"], "has Line number"); + } + + Assert.ok(ex.stack.length > 0, "Has stack"); + Assert.ok(ex.parsedStack, "Stack was parsed"); + Assert.ok(ex.hasFullStack, "Stack has been decoded"); + Assert.ok(baseData.properties["url"], "has Url"); + Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } - - Assert.ok(ex.stack.length > 0, "Has stack"); - Assert.ok(ex.parsedStack, "Stack was parsed"); - Assert.ok(ex.hasFullStack, "Stack has been decoded"); - Assert.ok(baseData.properties["url"], "has Url"); - Assert.ok(baseData.properties["errorSrc"].indexOf("window.onerror@") !== -1, "has source"); } } - } - }); + }); } }); @@ -1309,66 +1309,66 @@ export class AnalyticsPluginTests extends AITestClass { name: "OnErrorTests: _onerror logs name of unexpected error thrown by trackException for diagnostics with a strict custom direct exception", useFakeTimers: true, test: () => { - return this._asyncQueue().add(() => { - // setup - const sender: Sender = new Sender(); - const core = new AppInsightsCore(); + // setup + const sender: Sender = new Sender(); + const core = new AppInsightsCore(); - this.onDone(() => { - core.unload(false); - }); + this.onDone(() => { + core.unload(false); + }); - core.initialize( - { - instrumentationKey: "key", - extensionConfig: { - [sender.identifier]: { - enableSessionStorageBuffer: false, - maxBatchInterval: 1 - } - } - }, - [sender] - ); - const appInsights = new AnalyticsPlugin(); - core.addPlugin(appInsights); - appInsights.addTelemetryInitializer((item: ITelemetryItem) => { - Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); - }); + core.initialize( + { + instrumentationKey: "key", + extensionConfig: { + [sender.identifier]: { + enableSessionStorageBuffer: false, + maxBatchInterval: 1 + } + } + }, + [sender] + ); + const appInsights = new AnalyticsPlugin(); + core.addPlugin(appInsights); + appInsights.addTelemetryInitializer((item: ITelemetryItem) => { + Assert.equal("4.0", item.ver, "Telemetry items inside telemetry initializers should be in CS4.0 format"); + }); - this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); - sender._sender = (payload:any[], isAsync:boolean) => { - sender._onSuccess(payload, payload.length); - }; - this.sandbox.spy() - this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); + this.throwInternalSpy = this.sandbox.spy(appInsights.core.logger, "throwInternal"); + sender._sender = (payload:any[], isAsync:boolean) => { + sender._onSuccess(payload, payload.length); + }; + this.sandbox.spy() + this.trackSpy = this.sandbox.spy(sender, "_onSuccess"); - this.exceptionHelper.capture(appInsights); - this.causeException(() => { - this.exceptionHelper.throwStrict(new CustomTestError("Test Text Error!")); - }); + this.exceptionHelper.capture(appInsights); + this.causeException(() => { + this.exceptionHelper.throwStrict(new CustomTestError("Test Text Error!")); + }); - Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); - Assert.ok(!this.throwInternalSpy.called, "No internal errors"); - }) - .concat(this.waitForException(1)) - .add(() => { - let isLocal = window.location.protocol === "file:"; - let exp = this.trackSpy.args[0]; - const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); - if (payloadStr.length > 0) { - const payload = JSON.parse(payloadStr[0]); - const data = payload.data; - Assert.ok(data, "Has Data"); - if (data) { - Assert.ok(data.baseData, "Has BaseData"); - let baseData = data.baseData; - if (baseData) { - const ex = baseData.exceptions[0]; - if (isLocal) { - Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); - Assert.equal("String", ex.typeName, "Got the correct typename"); - } else { + Assert.ok(!this.trackSpy.calledOnce, "track not called yet"); + Assert.ok(!this.throwInternalSpy.called, "No internal errors"); + + return this._asyncQueue() + .concat(this.waitForExceptionPromise(1)) + .add(() => { + let isLocal = window.location.protocol === "file:"; + let exp = this.trackSpy.args[0]; + const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const data = payload.data; + Assert.ok(data, "Has Data"); + if (data) { + Assert.ok(data.baseData, "Has BaseData"); + let baseData = data.baseData; + if (baseData) { + const ex = baseData.exceptions[0]; + if (isLocal) { + Assert.ok(ex.message.indexOf("Script error:") !== -1, "Make sure the error message is present [" + ex.message + "]"); + Assert.equal("String", ex.typeName, "Got the correct typename"); + } else { Assert.ok(ex.message.indexOf("Test Text Error!") !== -1, "Make sure the error message is present [" + ex.message + "]"); Assert.ok(ex.message.indexOf("CustomTestError") !== -1, "Make sure the error type is present [" + ex.message + "]"); Assert.equal("CustomTestError", ex.typeName, "Got the correct typename"); @@ -2169,6 +2169,7 @@ export class AnalyticsPluginTests extends AITestClass { } } + // Original waitForException returning an array for backwards compatibility with testCaseAsync private waitForException: any = (expectedCount:number, action: string = "", includeInit:boolean = false) => [ () => { const message = "polling: " + new Date().toISOString() + " " + action; @@ -2223,6 +2224,66 @@ export class AnalyticsPluginTests extends AITestClass { return false; }, "sender succeeded", 10, 1000)) ]; + + // New waitForException for use with _asyncQueue that returns a promise + private waitForExceptionPromise(expectedCount: number, action: string = "", includeInit: boolean = false) { + const testContext = this._testContext; + + return PollingAssert.asyncTaskPollingAssert(this, function () { + const message = "polling: " + new Date().toISOString() + " " + action; + Assert.ok(true, message); + console.log(message); + this.checkNoInternalErrors(); + if (testContext && testContext.clock) { + testContext.clock.tick(500); + } + + let argCount = 0; + if (this.trackSpy.called) { + this.trackSpy.args.forEach(call => { + argCount += call.length; + }); + } + + Assert.ok(true, "* [" + argCount + " of " + expectedCount + "] checking spy " + new Date().toISOString()); + try { + if (argCount >= expectedCount) { + let payloads: any = []; + this.trackSpy.args[0][0].forEach(item => { + payloads.push(item.item); + }); + const payload = JSON.parse(payloads); + const baseType = payload.data.baseType; + // call the appropriate Validate depending on the baseType + switch (baseType) { + case Event.dataType: + return EventValidator.EventValidator.Validate(payload, baseType); + case Trace.dataType: + return TraceValidator.TraceValidator.Validate(payload, baseType); + case Exception.dataType: + return ExceptionValidator.ExceptionValidator.Validate(payload, baseType); + case Metric.dataType: + return MetricValidator.MetricValidator.Validate(payload, baseType); + case PageView.dataType: + return PageViewValidator.PageViewValidator.Validate(payload, baseType); + case PageViewPerformance.dataType: + return PageViewPerformanceValidator.PageViewPerformanceValidator.Validate(payload, baseType); + case RemoteDependencyData.dataType: + return RemoteDepdencyValidator.RemoteDepdencyValidator.Validate(payload, baseType); + + default: + return EventValidator.EventValidator.Validate(payload, baseType); + } + } + } finally { + if (testContext && testContext.clock) { + testContext.clock.tick(500); + } + } + + return false; + }, "sender succeeded", 10, 1000); + } } class ChannelPlugin implements IPlugin { From cbc62f48d0ebc42d679de46f189102e57330eb12 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 19:20:21 +0000 Subject: [PATCH 4/7] Removed unused waitForException method Co-authored-by: MSNev <54870357+MSNev@users.noreply.github.com> --- .../Tests/Unit/src/AnalyticsPlugin.tests.ts | 58 +------------------ 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts index 89b04aec2..2f5f3a9e2 100644 --- a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts @@ -2169,63 +2169,7 @@ export class AnalyticsPluginTests extends AITestClass { } } - // Original waitForException returning an array for backwards compatibility with testCaseAsync - private waitForException: any = (expectedCount:number, action: string = "", includeInit:boolean = false) => [ - () => { - const message = "polling: " + new Date().toISOString() + " " + action; - Assert.ok(true, message); - console.log(message); - this.checkNoInternalErrors(); - this.clock.tick(500); - }, - (PollingAssert.createPollingAssert(() => { - this.checkNoInternalErrors(); - let argCount = 0; - if (this.trackSpy.called) { - this.trackSpy.args.forEach(call => { - argCount += call.length; - }); - } - - Assert.ok(true, "* [" + argCount + " of " + expectedCount + "] checking spy " + new Date().toISOString()); - try { - if (argCount >= expectedCount) { - let payloads: any = [] - this.trackSpy.args[0][0].forEach(item => { - payloads.push(item.item) - }); - const payload = JSON.parse(payloads); - const baseType = payload.data.baseType; - // call the appropriate Validate depending on the baseType - switch (baseType) { - case Event.dataType: - return EventValidator.EventValidator.Validate(payload, baseType); - case Trace.dataType: - return TraceValidator.TraceValidator.Validate(payload, baseType); - case Exception.dataType: - return ExceptionValidator.ExceptionValidator.Validate(payload, baseType); - case Metric.dataType: - return MetricValidator.MetricValidator.Validate(payload, baseType); - case PageView.dataType: - return PageViewValidator.PageViewValidator.Validate(payload, baseType); - case PageViewPerformance.dataType: - return PageViewPerformanceValidator.PageViewPerformanceValidator.Validate(payload, baseType); - case RemoteDependencyData.dataType: - return RemoteDepdencyValidator.RemoteDepdencyValidator.Validate(payload, baseType); - - default: - return EventValidator.EventValidator.Validate(payload, baseType); - } - } - } finally { - this.clock.tick(500); - } - - return false; - }, "sender succeeded", 10, 1000)) - ]; - - // New waitForException for use with _asyncQueue that returns a promise + // waitForExceptionPromise for use with _asyncQueue that returns a promise private waitForExceptionPromise(expectedCount: number, action: string = "", includeInit: boolean = false) { const testContext = this._testContext; From 1bf9533c20a5f1a9b237439579e26f7598b04e1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 19:30:49 +0000 Subject: [PATCH 5/7] Standardize async test pattern to use .add() consistently Co-authored-by: MSNev <54870357+MSNev@users.noreply.github.com> --- .../Tests/Unit/src/AnalyticsPlugin.tests.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts index 2f5f3a9e2..194b8e434 100644 --- a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts @@ -1110,7 +1110,7 @@ export class AnalyticsPluginTests extends AITestClass { Assert.ok(!this.throwInternalSpy.called, "No internal errors"); return this._asyncQueue() - .concat(this.waitForExceptionPromise(1)) + .add(this.waitForExceptionPromise(1)) .add(() => { let isLocal = window.location.protocol === "file:"; let exp = this.trackSpy.args[0]; @@ -1193,7 +1193,7 @@ export class AnalyticsPluginTests extends AITestClass { Assert.ok(!this.throwInternalSpy.called, "No internal errors"); return this._asyncQueue() - .concat(this.waitForExceptionPromise(1)) + .add(this.waitForExceptionPromise(1)) .add(() => { let exp = this.trackSpy.args[0]; const payloadStr: string[] = this.getPayloadMessages(this.trackSpy); @@ -1268,7 +1268,7 @@ export class AnalyticsPluginTests extends AITestClass { Assert.ok(!this.throwInternalSpy.called, "No internal errors"); return this._asyncQueue() - .concat(this.waitForExceptionPromise(1)) + .add(this.waitForExceptionPromise(1)) .add(() => { let isLocal = window.location.protocol === "file:"; let exp = this.trackSpy.args[0]; @@ -1351,7 +1351,7 @@ export class AnalyticsPluginTests extends AITestClass { Assert.ok(!this.throwInternalSpy.called, "No internal errors"); return this._asyncQueue() - .concat(this.waitForExceptionPromise(1)) + .add(this.waitForExceptionPromise(1)) .add(() => { let isLocal = window.location.protocol === "file:"; let exp = this.trackSpy.args[0]; From dc68b7f7b924bba4461adcff7ebd333e5eb58b04 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 21:37:37 +0000 Subject: [PATCH 6/7] Fixed waitForExceptionPromise to correctly handle spy arguments Co-authored-by: MSNev <54870357+MSNev@users.noreply.github.com> --- .../Tests/Unit/src/AnalyticsPlugin.tests.ts | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts index 194b8e434..5e8200ee6 100644 --- a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts @@ -2172,19 +2172,20 @@ export class AnalyticsPluginTests extends AITestClass { // waitForExceptionPromise for use with _asyncQueue that returns a promise private waitForExceptionPromise(expectedCount: number, action: string = "", includeInit: boolean = false) { const testContext = this._testContext; + const self = this; // Capture 'this' context to use in the polling function - return PollingAssert.asyncTaskPollingAssert(this, function () { + return PollingAssert.asyncTaskPollingAssert(function () { const message = "polling: " + new Date().toISOString() + " " + action; Assert.ok(true, message); console.log(message); - this.checkNoInternalErrors(); + self.checkNoInternalErrors(); if (testContext && testContext.clock) { testContext.clock.tick(500); } let argCount = 0; - if (this.trackSpy.called) { - this.trackSpy.args.forEach(call => { + if (self.trackSpy && self.trackSpy.called) { + self.trackSpy.args.forEach(call => { argCount += call.length; }); } @@ -2192,31 +2193,31 @@ export class AnalyticsPluginTests extends AITestClass { Assert.ok(true, "* [" + argCount + " of " + expectedCount + "] checking spy " + new Date().toISOString()); try { if (argCount >= expectedCount) { - let payloads: any = []; - this.trackSpy.args[0][0].forEach(item => { - payloads.push(item.item); - }); - const payload = JSON.parse(payloads); - const baseType = payload.data.baseType; - // call the appropriate Validate depending on the baseType - switch (baseType) { - case Event.dataType: - return EventValidator.EventValidator.Validate(payload, baseType); - case Trace.dataType: - return TraceValidator.TraceValidator.Validate(payload, baseType); - case Exception.dataType: - return ExceptionValidator.ExceptionValidator.Validate(payload, baseType); - case Metric.dataType: - return MetricValidator.MetricValidator.Validate(payload, baseType); - case PageView.dataType: - return PageViewValidator.PageViewValidator.Validate(payload, baseType); - case PageViewPerformance.dataType: - return PageViewPerformanceValidator.PageViewPerformanceValidator.Validate(payload, baseType); - case RemoteDependencyData.dataType: - return RemoteDepdencyValidator.RemoteDepdencyValidator.Validate(payload, baseType); - - default: - return EventValidator.EventValidator.Validate(payload, baseType); + // Use the existing getPayloadMessages method to extract payload data properly + const payloadStr: string[] = self.getPayloadMessages(self.trackSpy); + if (payloadStr.length > 0) { + const payload = JSON.parse(payloadStr[0]); + const baseType = payload.data.baseType; + // call the appropriate Validate depending on the baseType + switch (baseType) { + case Event.dataType: + return EventValidator.EventValidator.Validate(payload, baseType); + case Trace.dataType: + return TraceValidator.TraceValidator.Validate(payload, baseType); + case Exception.dataType: + return ExceptionValidator.ExceptionValidator.Validate(payload, baseType); + case Metric.dataType: + return MetricValidator.MetricValidator.Validate(payload, baseType); + case PageView.dataType: + return PageViewValidator.PageViewValidator.Validate(payload, baseType); + case PageViewPerformance.dataType: + return PageViewPerformanceValidator.PageViewPerformanceValidator.Validate(payload, baseType); + case RemoteDependencyData.dataType: + return RemoteDepdencyValidator.RemoteDepdencyValidator.Validate(payload, baseType); + + default: + return EventValidator.EventValidator.Validate(payload, baseType); + } } } } finally { From 4887abab43b828ece6de638d6c9a4a31022ba8d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 May 2025 00:20:54 +0000 Subject: [PATCH 7/7] Move initial setup outside asyncTaskPollingAssert in waitForExceptionPromise Co-authored-by: MSNev <54870357+MSNev@users.noreply.github.com> --- .../Tests/Unit/src/AnalyticsPlugin.tests.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts index 5e8200ee6..f444f20c1 100644 --- a/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts +++ b/extensions/applicationinsights-analytics-js/Tests/Unit/src/AnalyticsPlugin.tests.ts @@ -2174,15 +2174,16 @@ export class AnalyticsPluginTests extends AITestClass { const testContext = this._testContext; const self = this; // Capture 'this' context to use in the polling function + // Execute initial setup actions outside of the polling function + const message = "polling: " + new Date().toISOString() + " " + action; + Assert.ok(true, message); + console.log(message); + self.checkNoInternalErrors(); + if (testContext && testContext.clock) { + testContext.clock.tick(500); + } + return PollingAssert.asyncTaskPollingAssert(function () { - const message = "polling: " + new Date().toISOString() + " " + action; - Assert.ok(true, message); - console.log(message); - self.checkNoInternalErrors(); - if (testContext && testContext.clock) { - testContext.clock.tick(500); - } - let argCount = 0; if (self.trackSpy && self.trackSpy.called) { self.trackSpy.args.forEach(call => {