Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
591 changes: 591 additions & 0 deletions frontend/TESTING.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note (non-blocking): when we merge this, I'll refactor the agent instructions to incorporate this too.

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ const customJestConfig = {
// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 50,
functions: 30,
lines: 50,
statements: 50,
branches: 70,
functions: 70,
lines: 80,
statements: 80,
},
},

Expand Down
143 changes: 141 additions & 2 deletions frontend/src/components/GoogleAnalyticsWorkaround.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,27 +153,166 @@ describe("GoogleAnalyticsWorkaround", () => {

expect(scriptContent).toContain("gtag('config', 'G-CUSTOM456'");
});

it("sets debug_mode to false when debugMode prop is false", () => {
render(<GoogleAnalyticsWorkaround gaId="G-TEST123" debugMode={false} />);

const initScript = screen.getByTestId("_next-ga-init");
const scriptContent = initScript.innerHTML;

expect(scriptContent).toContain("'debug_mode': false");
});

it("includes gtag function definition in the init script", () => {
render(<GoogleAnalyticsWorkaround gaId="G-TEST123" />);

const initScript = screen.getByTestId("_next-ga-init");
const scriptContent = initScript.innerHTML;

expect(scriptContent).toContain("function gtag()");
expect(scriptContent).toContain(".push(arguments)");
});

it("includes gtag js call with new Date in the init script", () => {
render(<GoogleAnalyticsWorkaround gaId="G-TEST123" />);

const initScript = screen.getByTestId("_next-ga-init");
const scriptContent = initScript.innerHTML;

expect(scriptContent).toContain("gtag('js', new Date())");
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (non-blocking): combine these.


it("handles nonce being undefined", () => {
render(<GoogleAnalyticsWorkaround gaId="G-TEST123" nonce={undefined} />);

const initScript = screen.getByTestId("_next-ga-init");
const mainScript = screen.getByTestId("_next-ga");

expect(initScript).toBeInTheDocument();
expect(mainScript).toBeInTheDocument();
});

it("renders correctly with all optional props", () => {
render(
<GoogleAnalyticsWorkaround
gaId="G-ALL-PROPS"
dataLayerName="myLayer"
nonce="my-nonce"
debugMode={true}
/>,
);

const initScript = screen.getByTestId("_next-ga-init");
const mainScript = screen.getByTestId("_next-ga");
const scriptContent = initScript.innerHTML;

expect(initScript).toHaveAttribute("data-nonce", "my-nonce");
expect(mainScript).toHaveAttribute("data-nonce", "my-nonce");
expect(scriptContent).toContain("window['myLayer']");
expect(scriptContent).toContain("'debug_mode': true");
expect(scriptContent).toContain("gtag('config', 'G-ALL-PROPS'");
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): it seems like this test might be the "integration" level test that we want to keep and we could drop the other "unit"-style tests?

});

describe("sendGAEvent", () => {
let consoleWarnSpy: jest.SpyInstance;
let originalEnv: string | undefined;

beforeEach(() => {
consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation();
originalEnv = process.env.NODE_ENV;
});

afterEach(() => {
consoleWarnSpy.mockRestore();
process.env.NODE_ENV = originalEnv;
});

it("returns early in test environment without calling gtag", () => {
const originalEnv = process.env.NODE_ENV;
process.env.NODE_ENV = "test";

sendGAEvent("event", "test_event", { test: "data" });

expect(consoleWarnSpy).not.toHaveBeenCalled();
});

process.env.NODE_ENV = originalEnv;
it("warns when dataLayer does not exist on window", () => {
process.env.NODE_ENV = "production";

render(<GoogleAnalyticsWorkaround gaId="G-TEST123" />);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (window as any).dataLayer;

sendGAEvent("event", "click_event", { button: "submit" });

expect(consoleWarnSpy).toHaveBeenCalledWith(
"@next/third-parties: GA dataLayer dataLayer does not exist",
);
});

it("calls window.gtag when dataLayer exists", () => {
process.env.NODE_ENV = "production";
const mockGtag = jest.fn();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).gtag = mockGtag;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).dataLayer = [];

render(<GoogleAnalyticsWorkaround gaId="G-TEST123" />);

sendGAEvent("event", "conversion", { value: 100, currency: "USD" });

expect(mockGtag).toHaveBeenCalledWith("event", "conversion", {
value: 100,
currency: "USD",
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (window as any).gtag;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (window as any).dataLayer;
});

it("calls gtag with different event names and arguments", () => {
process.env.NODE_ENV = "production";
const mockGtag = jest.fn();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).gtag = mockGtag;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).dataLayer = [];

render(<GoogleAnalyticsWorkaround gaId="G-TEST123" />);

sendGAEvent("event", "page_view", { page: "/home" });

expect(mockGtag).toHaveBeenCalledWith("event", "page_view", {
page: "/home",
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (window as any).gtag;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (window as any).dataLayer;
});

it("handles empty event arguments", () => {
process.env.NODE_ENV = "production";
const mockGtag = jest.fn();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).gtag = mockGtag;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).dataLayer = [];

render(<GoogleAnalyticsWorkaround gaId="G-TEST123" />);

sendGAEvent("event", "simple_event", {});

expect(mockGtag).toHaveBeenCalledWith("event", "simple_event", {});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (window as any).gtag;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (window as any).dataLayer;
});
});
Loading