diff --git a/frontend/tests/components/search/SearchAnalytics.test.tsx b/frontend/tests/components/search/SearchAnalytics.test.tsx
index 134bf4806..9a472a424 100644
--- a/frontend/tests/components/search/SearchAnalytics.test.tsx
+++ b/frontend/tests/components/search/SearchAnalytics.test.tsx
@@ -3,24 +3,37 @@ import { render } from "@testing-library/react";
import SearchAnalytics from "src/components/search/SearchAnalytics";
const sendGAEventMock = jest.fn();
+const waitForNewRelicMock = jest.fn();
+const setNewRelicCustomAttributeMock = jest.fn();
+const unsetAllNewRelicQueryAttributesMock = jest.fn();
jest.mock("@next/third-parties/google", () => ({
/* eslint-disable-next-line @typescript-eslint/no-unsafe-return */
sendGAEvent: (...args: unknown[]) => sendGAEventMock(...args),
}));
+jest.mock("src/utils/analyticsUtil", () => ({
+ waitForNewRelic: () => waitForNewRelicMock(),
+ setNewRelicCustomAttribute: (...args) =>
+ setNewRelicCustomAttributeMock(...args),
+ unsetAllNewRelicQueryAttributes: () => unsetAllNewRelicQueryAttributesMock(),
+}));
+
+const basicParams = {
+ fundingInstrument: "cooperative_agreement",
+ status: "posted, archived",
+ agency: "AC,PAMS-SC",
+ page: "1",
+ query: "a random search term",
+};
+
describe("SearchAnalytics", () => {
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
it("calls sendGAEvent with expected params on render", () => {
const { rerender } = render(
- ,
+ ,
);
expect(sendGAEventMock).toHaveBeenCalledWith("event", "search_attempt", {
search_filters:
@@ -36,6 +49,7 @@ describe("SearchAnalytics", () => {
page: "1",
query: "a random search term",
}}
+ newRelicEnabled={false}
/>,
);
expect(sendGAEventMock).toHaveBeenCalledWith("event", "search_attempt", {
@@ -43,4 +57,85 @@ describe("SearchAnalytics", () => {
'{"status":"posted, archived, closed","agency":"AC","category":"recovery_act"}',
});
});
+
+ it("does not waitForNewRelic if New Relic is not enabled", () => {
+ render();
+ expect(waitForNewRelicMock).not.toHaveBeenCalled();
+ });
+
+ it("does not attempt to set custom attributes if New Relic is not enabled", () => {
+ const { rerender } = render(
+ ,
+ );
+
+ rerender(
+ ,
+ );
+ expect(setNewRelicCustomAttributeMock).not.toHaveBeenCalled();
+ });
+
+ it("does not attempt to set custom attributes if New Relic is not initialized", () => {
+ waitForNewRelicMock.mockResolvedValue(false);
+ const { rerender } = render(
+ ,
+ );
+
+ rerender(
+ ,
+ );
+ expect(setNewRelicCustomAttributeMock).not.toHaveBeenCalled();
+ });
+
+ it("calls setNewRelicCustomAttribute for all search params when params change", async () => {
+ waitForNewRelicMock.mockImplementation(() => {
+ return Promise.resolve(true);
+ });
+ const { rerender } = render(
+ ,
+ );
+
+ // have to wait a tick for the wait promise to resolve
+ const animationFramePromise = new Promise((resolve) => {
+ requestAnimationFrame(resolve);
+ });
+
+ await animationFramePromise;
+
+ rerender(
+ ,
+ );
+ Object.entries({
+ ...basicParams,
+ page: "2",
+ }).forEach(([key, value]) => {
+ expect(setNewRelicCustomAttributeMock).toHaveBeenCalledWith(key, value);
+ });
+ });
+
+ it("calls unsetAllNewRelicQueryAttributes on cleanup", () => {
+ waitForNewRelicMock.mockImplementation(() => {
+ return Promise.resolve(true);
+ });
+ render();
+
+ expect(unsetAllNewRelicQueryAttributesMock).toHaveBeenCalled();
+ });
});