Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AI Beta: Minor bug fixes and additional debug info #1787

Merged
merged 1 commit into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 78 additions & 36 deletions common/Tests/Framework/src/AITestClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ export class AITestClass {

/** The instance of the currently running suite. */
public static currentTestClass: AITestClass;
public static currentTestInfo: TestCase|TestCaseAsync;
public static currentTestInfo: TestCase | TestCaseAsync;

/** Turns on/off sinon's fake implementation of XMLHttpRequest. On by default. */
public sandboxConfig: any = {};

public static orgSetTimeout: (handler: Function, timeout?: number) => number;
public static orgClearTimeout: (handle?: number) => void;
public static orgSetTimeout: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timeout;
public static orgClearTimeout: (timeoutId: NodeJS.Timeout) => void;
public static orgObjectDefineProperty = Object.defineProperty;

/**** Sinon methods and properties ***/
Expand Down Expand Up @@ -139,14 +139,6 @@ export class AITestClass {
* Use this method to call unload / teardown so the SDK can remove it's own events before being validated
*/
public testFinishedCleanup() {
this._onDoneFuncs.forEach((fn) => {
try {
fn();
} catch (e) {
// Do nothing during cleanup
}
});
this._onDoneFuncs = [];
}

/** Method called after each test method has completed and after the test sandbox has been cleanup up.
Expand Down Expand Up @@ -177,9 +169,20 @@ export class AITestClass {
testInfo.autoComplete = true;
}

if (!testInfo.orgClearTimeout) {
// Set as the real clearTimeout (as _testStarting and enable sinon fake timers)
testInfo.orgClearTimeout = clearTimeout;
}

if (!testInfo.orgSetTimeout) {
// Set as the real setTimeout (as _testStarting and enable sinon fake timers)
testInfo.orgSetTimeout = setTimeout;
}

// Create a wrapper around the test method so we can do test initilization and cleanup.
const testMethod = (assert: any) => {
const done = assert.async();
const self = this;

// Save off the instance of the currently running suite.
AITestClass.currentTestClass = this;
Expand All @@ -189,37 +192,45 @@ export class AITestClass {
const orgClearTimeout = clearTimeout;
const orgSetTimeout = setTimeout;

AITestClass.orgSetTimeout = (handler: Function, timeout?: number) => {
return orgSetTimeout(handler, timeout);
AITestClass.orgSetTimeout = (handler: (...args: any[]) => void, timeout: number, ...args: any[]) => {
if (AITestClass.currentTestInfo && AITestClass.currentTestInfo.orgSetTimeout) {
return AITestClass.currentTestInfo.orgSetTimeout.call(null, handler, timeout, args);
}

orgSetTimeout(handler, timeout, args);
};

AITestClass.orgClearTimeout = (handler: number) => {
orgClearTimeout(handler);
AITestClass.orgClearTimeout = (timeoutId: NodeJS.Timeout) => {
if (AITestClass.currentTestInfo && AITestClass.currentTestInfo.orgClearTimeout) {
AITestClass.currentTestInfo.orgClearTimeout.call(null, timeoutId);
} else {
orgClearTimeout(timeoutId);
}
};

let useFakeServer = testInfo.useFakeServer;
if (useFakeServer === undefined) {
useFakeServer = this.useFakeServer;
useFakeServer = self.useFakeServer;
}

if (useFakeServer) {
this._hookXhr();
self._hookXhr();
}

if (testInfo.useFakeTimers) {
this.clock = sinon.useFakeTimers();
self.clock = sinon.useFakeTimers();
}

if (this.isEmulatingEs3) {
this._emulateEs3();
if (self.isEmulatingEs3) {
self._emulateEs3();
}

if (testInfo.assertNoEvents === undefined) {
testInfo.assertNoEvents = this.assertNoEvents;
testInfo.assertNoEvents = self.assertNoEvents;
}

if (testInfo.assertNoHooks === undefined) {
testInfo.assertNoHooks = this.assertNoHooks;
testInfo.assertNoHooks = self.assertNoHooks;
}

// Run the test.
Expand All @@ -230,12 +241,7 @@ export class AITestClass {
let stepIndex = 0;

const testDone = () => {
this._onDoneFuncs.forEach((fn) => {
fn();
});
this._onDoneFuncs = [];

self.testFinishedCleanup();
self._testFinishedCleanup();

if (testInfo.assertNoEvents) {
self._assertEventsRemoved();
Expand Down Expand Up @@ -337,7 +343,7 @@ export class AITestClass {
} catch (ex) {
console.error("Failed: Unexpected Exception: " + ex);
Assert.ok(false, "Unexpected Exception: " + ex);
this._testCompleted(true);
self._testCompleted(true);

// done is QUnit callback indicating the end of the test
done();
Expand All @@ -358,6 +364,16 @@ export class AITestClass {
throw new Error("Must specify 'test' method in testInfo context in registerTestcase call");
}

if (!testInfo.orgClearTimeout) {
// Set as the real clearTimeout (as _testStarting and enable sinon fake timers)
testInfo.orgClearTimeout = clearTimeout;
}

if (!testInfo.orgSetTimeout) {
// Set as the real setTimeout (as _testStarting and enable sinon fake timers)
testInfo.orgSetTimeout = setTimeout;
}

// Create a wrapper around the test method so we can do test initilization and cleanup.
const testMethod = (assert: any) => {
// Treating all tests as async, so there is no issues with mixing them
Expand All @@ -369,7 +385,7 @@ export class AITestClass {
AITestClass.currentTestInfo = testInfo;

function _testFinished(failed?: boolean) {
self.testFinishedCleanup();
self._testFinishedCleanup();

if (testInfo.assertNoEvents) {
self._assertEventsRemoved();
Expand All @@ -387,12 +403,20 @@ export class AITestClass {
const orgClearTimeout = clearTimeout;
const orgSetTimeout = setTimeout;

AITestClass.orgSetTimeout = (handler: Function, timeout?: number) => {
return orgSetTimeout(handler, timeout);
AITestClass.orgSetTimeout = (handler: (...args: any[]) => void, timeout: number, ...args: any[]) => {
if (AITestClass.currentTestInfo && AITestClass.currentTestInfo.orgSetTimeout) {
return AITestClass.currentTestInfo.orgSetTimeout.call(null, handler, timeout, args);
}

orgSetTimeout(handler, timeout, args);
};

AITestClass.orgClearTimeout = (handler: number) => {
orgClearTimeout(handler);
AITestClass.orgClearTimeout = (timeoutId: NodeJS.Timeout) => {
if (AITestClass.currentTestInfo && AITestClass.currentTestInfo.orgClearTimeout) {
AITestClass.currentTestInfo.orgClearTimeout.call(null, timeoutId);
} else {
orgClearTimeout(timeoutId);
}
};

let useFakeServer = testInfo.useFakeServer;
Expand Down Expand Up @@ -813,8 +837,8 @@ export class AITestClass {
this._assertRemoveHooks(XMLHttpRequest, "XHR");
this._assertRemoveHooks(window, "window");
this._assertRemoveFuncHooks(window.fetch, "fetch");
this._assertRemoveFuncHooks(window.onerror, "onerror");
this._assertRemoveFuncHooks(window.onunhandledrejection, "onunhandledrejection");
this._assertRemoveFuncHooks(window.onerror, "window.onerror");
this._assertRemoveFuncHooks(window.onunhandledrejection, "window.onunhandledrejection");
}

/** Called when the test is starting. */
Expand Down Expand Up @@ -861,6 +885,19 @@ export class AITestClass {
this.testInitialize();
}

private _testFinishedCleanup() {
this._onDoneFuncs.forEach((fn) => {
try {
fn();
} catch (e) {
// Do nothing during cleanup
}
});
this._onDoneFuncs = [];

this.testFinishedCleanup();
}

/** Called when the test is completed. */
private _testCompleted(failed?: boolean) {
this._unhookXhr();
Expand Down Expand Up @@ -901,11 +938,16 @@ export class AITestClass {
(this.sandbox as any).verifyAndRestore();
}

this.sandbox = null;

this.testCleanup();

// Clear the instance of the currently running suite.
AITestClass.currentTestClass = null;
AITestClass.currentTestInfo = null;

AITestClass.orgSetTimeout = null;
AITestClass.orgClearTimeout = null;
}

private _assertRemoveFuncHooks(fn:any, targetName: string) {
Expand Down
7 changes: 7 additions & 0 deletions common/Tests/Framework/src/TestCase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export class TestCase {
* Automatically assert that all hooks have been removed
*/
assertNoHooks?: boolean;


orgSetTimeout?: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timeout;
orgClearTimeout?: (timeoutId: NodeJS.Timeout) => void;
}

export const enum StepResult {
Expand Down Expand Up @@ -78,4 +82,7 @@ export interface TestCaseAsync {
* Automatically assert that all hooks have been removed
*/
assertNoHooks?: boolean;

orgSetTimeout?: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timeout;
orgClearTimeout?: (timeoutId: NodeJS.Timeout) => void;
}
1 change: 1 addition & 0 deletions common/Tests/Selenium/ExceptionHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ function ExceptionHelper(config) {
return {
capture: capturePageOnError,
captureStrict: captureStrictPageOnError,
restore: restoreOnError,
throw: throwPageException,
throwCors: throwCorsException,
throwStrict: throwStrictException,
Expand Down
19 changes: 0 additions & 19 deletions common/config/rush/npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions extensions/applicationinsights-dependencies-js/src/ajax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ export class AjaxMonitor extends BaseTelemetryPlugin implements IDependenciesPlu
let isPolyfill = (fetch as any).polyfill;
if (_config.disableFetchTracking === false) {
_addHook(InstrumentFunc(global, strFetch, {
ns: _evtNamespace,
// Add request hook
req: (callDetails: IInstrumentCallDetails, input, init) => {
let fetchData: ajaxRecord;
Expand Down Expand Up @@ -472,6 +473,7 @@ export class AjaxMonitor extends BaseTelemetryPlugin implements IDependenciesPlu
// the workaround is to add a polyfill property to your fetch implementation before initializing
// App Insights
_addHook(InstrumentFunc(global, strFetch, {
ns: _evtNamespace,
req: (callDetails: IInstrumentCallDetails, input, init) => {
// Just call so that we record any disabled URL
_isDisabledRequest(null, input, init);
Expand All @@ -494,6 +496,7 @@ export class AjaxMonitor extends BaseTelemetryPlugin implements IDependenciesPlu
if (_supportsAjaxMonitoring(_self) && !_xhrInitialized) {
// Instrument open
_hookProto(XMLHttpRequest, "open", {
ns: _evtNamespace,
req: (args:IInstrumentCallDetails, method:string, url:string, async?:boolean) => {
let xhr = args.inst as XMLHttpRequestInstrumented;
let ajaxData = xhr[strAjaxData];
Expand All @@ -513,6 +516,7 @@ export class AjaxMonitor extends BaseTelemetryPlugin implements IDependenciesPlu

// Instrument send
_hookProto(XMLHttpRequest, "send", {
ns: _evtNamespace,
req: (args:IInstrumentCallDetails, context?: Document | BodyInit | null) => {
let xhr = args.inst as XMLHttpRequestInstrumented;
let ajaxData = xhr[strAjaxData];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Assert, AITestClass } from "@microsoft/ai-test-framework";
import * as pako from "pako";

export class AppInsightsCoreSizeCheck extends AITestClass {
private readonly MAX_DEFLATE_SIZE = 17;
private readonly MAX_DEFLATE_SIZE = 18;
private readonly rawFilePath = "../dist/applicationinsights-core-js.min.js";
private readonly prodFilePath = "../browser/applicationinsights-core-js.min.js";

Expand Down
Loading