Skip to content

Commit

Permalink
refactor wait function and util testing
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-s-nava committed Feb 27, 2025
1 parent 8a222ba commit 82ef499
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 16 deletions.
5 changes: 3 additions & 2 deletions frontend/src/components/search/SearchAnalytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ function SearchAnalytics({
if (!newRelicEnabled) {
return;
}
const ready = waitForNewRelic();
setNewRelicInitialized(!!ready);
waitForNewRelic()
.then((ready) => setNewRelicInitialized(!!ready))
.catch((e) => console.error("Error waiting for new relic", e));
}, [newRelicEnabled]);

// set new relic query param based custom attributes
Expand Down
37 changes: 23 additions & 14 deletions frontend/src/utils/analyticsUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,37 @@ import { validSearchQueryParamKeys } from "src/types/search/searchResponseTypes"
type NewRelicBrowser = typeof newrelic;

const NEW_RELIC_POLL_INTERVAL = 2;
const NEW_RELIC_POLL_TIMEOUT = 2000;
const NEW_RELIC_POLL_TIMEOUT = 500;

// taking less than 2 ms to intantiate locally but not ready on first run
// this will wait until it's present on the window
export const waitForNewRelic = (elapsed = 0) => {
const present = !!window.newrelic;
if (elapsed > NEW_RELIC_POLL_TIMEOUT) {
console.error("New Relic browser code not found");
return false;
export const waitForNewRelic = async (): Promise<boolean> => {
let present = !!window.newrelic;
if (present) {
return true;
}
console.debug("Waiting for new relic: ", elapsed);
if (!present) {
return setTimeout(
() => waitForNewRelic(elapsed + NEW_RELIC_POLL_INTERVAL),
NEW_RELIC_POLL_INTERVAL,
);

let elapsed = 0;
let timedOut = false;

while (!present && !timedOut) {
elapsed += NEW_RELIC_POLL_INTERVAL;
await new Promise((resolve) => {
setTimeout(() => {
return resolve(null);
}, elapsed);
});
present = !!window.newrelic;
if (elapsed >= NEW_RELIC_POLL_TIMEOUT) {
console.error("Timed out waiting for new relic browser object");
timedOut = true;
}
}
return true;
return present;
};

const getNewRelicBrowserInstance = (): NewRelicBrowser | null => {
return window && window.newrelic ? window.newrelic : null;
return window?.newrelic ?? null;
};

export const setNewRelicCustomAttribute = (
Expand Down
94 changes: 94 additions & 0 deletions frontend/tests/utils/analyticsUtils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { validSearchQueryParamKeys } from "src/types/search/searchResponseTypes";
import {
setNewRelicCustomAttribute,
unsetAllNewRelicQueryAttributes,
waitForNewRelic,
} from "src/utils/analyticsUtil";

jest.useFakeTimers();
const mockSetCustomAttribute = jest.fn();

describe("waitForNewRelic", () => {
afterEach(() => {
// eslint-disable-next-line
// @ts-ignore
window.newrelic = undefined;
jest.resetAllMocks();
});
it("returns true if new relic is found", async () => {
// eslint-disable-next-line
// @ts-ignore
window.newrelic = {};
const result = await waitForNewRelic();
expect(result).toEqual(true);
});
it("when the timeout is reached returns false", async () => {
// eslint-disable-next-line
const resolution = new Promise<boolean>((resolve) =>
waitForNewRelic().then((result) => {
resolve(result);
}),
);
await jest.runAllTimersAsync();

const result = await resolution;
expect(result).toEqual(false);
});
});

describe("setNewRelicCustomAttribute", () => {
afterEach(() => {
// eslint-disable-next-line
// @ts-ignore
window.newrelic = undefined;
jest.resetAllMocks();
});
it("does not attempt to call new relic if new relic does not exist", () => {
setNewRelicCustomAttribute("key", "value");
expect(mockSetCustomAttribute).not.toHaveBeenCalled();
});
it("calls new relic with passed values, with key properly prefixed", () => {
// eslint-disable-next-line
// @ts-ignore
window.newrelic = {
setCustomAttribute: mockSetCustomAttribute,
};

setNewRelicCustomAttribute("key", "value");
expect(mockSetCustomAttribute).toHaveBeenCalledWith(
"search_param_key",
"value",
);
});
});

describe("unsetAllNewRelicQueryAttributes", () => {
afterEach(() => {
// eslint-disable-next-line
// @ts-ignore
window.newrelic = undefined;
jest.resetAllMocks();
});
it("does not attempt to call new relic if new relic does not exist", () => {
unsetAllNewRelicQueryAttributes("key");
expect(mockSetCustomAttribute).not.toHaveBeenCalled();
});
it("calls new relic with passed values, with key properly prefixed", () => {
// eslint-disable-next-line
// @ts-ignore
window.newrelic = {
setCustomAttribute: mockSetCustomAttribute,
};

unsetAllNewRelicQueryAttributes();
expect(mockSetCustomAttribute).toHaveBeenCalledTimes(
validSearchQueryParamKeys.length,
);
validSearchQueryParamKeys.forEach((key) => {
expect(mockSetCustomAttribute).toHaveBeenCalledWith(
`search_param_${key}`,
"",
);
});
});
});

0 comments on commit 82ef499

Please sign in to comment.