/home/bdqbpbxa/demo-subdomains/ping-proxies.goodface.com.ua/node_modules/react-ga4/src/ga4.test.js
import gtag from "./gtag";
import GA4 from "./ga4";

const newDate = new Date("2020-01-01");
jest.mock("./gtag");
jest.useFakeTimers("modern").setSystemTime(newDate.getTime());

describe("GA4", () => {
  // Given
  const GA_MEASUREMENT_ID = "GA_MEASUREMENT_ID";

  beforeEach(() => {
    gtag.mockReset();
    GA4.reset();
  });

  describe("GA4.initialize()", () => {
    it("initialize() default", () => {
      // When
      GA4.initialize(GA_MEASUREMENT_ID);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "js", newDate);
      expect(gtag).toHaveBeenNthCalledWith(2, "config", GA_MEASUREMENT_ID);
      expect(gtag).toHaveBeenCalledTimes(2);
    });

    it("initialize() with options", () => {
      // Given
      const options = {
        gaOptions: {
          cookieUpdate: false,
        },
      };

      // When
      GA4.initialize(GA_MEASUREMENT_ID, options);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "js", newDate);
      expect(gtag).toHaveBeenNthCalledWith(2, "config", GA_MEASUREMENT_ID, {
        cookie_update: false,
      });
      expect(gtag).toHaveBeenCalledTimes(2);
    });

    it("initialize() in test mode", () => {
      // Given
      const options = {
        testMode: true,
      };
      const command = "send";
      const object = { hitType: "pageview" };

      // When
      GA4.initialize(GA_MEASUREMENT_ID, options);
      GA4.ga(command, object);

      // Then
      expect(gtag).toHaveBeenCalledTimes(0);
    });

    it("initialize() multiple products", () => {
      // Given
      const GA_MEASUREMENT_ID2 = "GA_MEASUREMENT_ID2";
      const config = [
        { trackingId: GA_MEASUREMENT_ID },
        { trackingId: GA_MEASUREMENT_ID2 },
      ];

      // When
      GA4.initialize(config);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "js", newDate);
      expect(gtag).toHaveBeenNthCalledWith(2, "config", GA_MEASUREMENT_ID);
      expect(gtag).toHaveBeenNthCalledWith(3, "config", GA_MEASUREMENT_ID2);
      expect(gtag).toHaveBeenCalledTimes(3);
    });
  });

  describe("GA4.ga()", () => {
    it("ga() send pageview", () => {
      // Given
      const command = "send";
      const object = { hitType: "pageview" };

      // When
      GA4.ga(command, object);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "event", "page_view");
    });

    it("ga() send timing", () => {
      // Given
      const command = "send";
      const hitType = "timing";
      const timingCategory = "DOM";
      const timingVar = "first-contentful-paint";
      const timingValue = 120;

      // When
      GA4.ga(command, hitType, timingCategory, timingVar, timingValue);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "event", "timing_complete", {
        event_category: timingCategory,
        name: timingVar,
        value: timingValue,
      });
    });

    it("ga() callback", (done) => {
      // Given
      const clientId = "clientId value";
      gtag.mockImplementationOnce((command, target, field_name, cb) =>
        cb(clientId)
      );

      const callback = jest.fn((tracker) => {
        const trackerClientId = tracker.get("clientId");
        const trackerTrackingId = tracker.get("trackingId");
        const trackerApiVersion = tracker.get("apiVersion");
        expect(trackerClientId).toEqual(clientId);
        expect(trackerTrackingId).toEqual(GA_MEASUREMENT_ID);
        expect(trackerApiVersion).toEqual("1");
        done();
      });

      // When
      GA4.ga(callback);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(
        1,
        "get",
        GA_MEASUREMENT_ID,
        "client_id",
        expect.any(Function)
      );
    });

    it("ga() async callback", (done) => {
      // Given
      const clientId = "clientId value";
      gtag.mockImplementationOnce((command, target, field_name, cb) =>
        cb(clientId)
      );

      const callback = jest.fn(async (tracker) => {
        const trackerClientId = tracker.get("clientId");
        expect(trackerClientId).toEqual(clientId);
        done();
      });

      // When
      GA4.ga(callback);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(
        1,
        "get",
        GA_MEASUREMENT_ID,
        "client_id",
        expect.any(Function)
      );
    });

    it("ga() callback queue", (done) => {
      // Given
      const clientId = "clientId value";
      gtag.mockImplementationOnce((command, target, field_name, cb) => {
        setImmediate(() => cb(clientId));
      });

      const callback = jest.fn(() => {
        GA4.ga("send", { hitType: "pageview" });
        expect(gtag).toHaveBeenNthCalledWith(2, "event", "page_view");
        done();
      });

      // When
      GA4.ga(callback);
      GA4.ga("send", "event", "category value");

      // Then
      expect(gtag).toHaveBeenNthCalledWith(
        1,
        "get",
        GA_MEASUREMENT_ID,
        "client_id",
        expect.any(Function)
      );
      expect(gtag).toHaveBeenCalledTimes(1);
      expect(GA4._isQueuing).toBeTruthy();
      expect(GA4._queueGtag).toHaveLength(1);

      jest.runAllTimers();

      expect(GA4._isQueuing).toBeFalsy();
      expect(GA4._queueGtag).toHaveLength(0);
      expect(gtag).toHaveBeenNthCalledWith(3, "event", undefined, {
        event_category: "category value",
      });
    });
  });

  describe("GA4.send()", () => {
    it("send() pageview", () => {
      // Given
      const object = { hitType: "pageview" };

      // When
      GA4.send(object);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "event", "page_view");
    });
  });

  describe("GA4.event()", () => {
    it("event() custom events", () => {
      // Given
      const eventName = "screen_view";
      const eventParams = {
        app_name: "myAppName",
        screen_name: "Home",
      };

      // When
      GA4.event(eventName, eventParams);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "event", eventName, eventParams);
    });

    it("event() simple", () => {
      // Given
      const object = {
        category: "category value",
        action: "action value",
        label: "label value",
        nonInteraction: true,
      };

      // When
      GA4.event(object);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "event", "Action Value", {
        event_category: "Category Value",
        event_label: "Label Value",
        non_interaction: true,
      });
    });
  });

  describe("GA4.set()", () => {
    it("set()", () => {
      // Given
      const object = {
        anonymizeIp: true,
        referrer: "/signup",
        allowAdFeatures: "allowAdFeatures value",
        allowAdPersonalizationSignals: "allowAdPersonalizationSignals value",
        page: "/home",
      };

      // When
      GA4.set(object);

      // Then
      expect(gtag).toHaveBeenNthCalledWith(1, "set", {
        anonymize_ip: true,
        referrer: "/signup",
        allow_google_signals: "allowAdFeatures value",
        allow_ad_personalization_signals: "allowAdPersonalizationSignals value",
        page_path: "/home",
      });
    });
  });

  describe("Reference", () => {
    it("pageview", () => {
      // Old https://developers.google.com/analytics/devguides/collection/analyticsjs/pages
      // New https://developers.google.com/gtagjs/reference/event#page_view

      // Given
      const hitType = "pageview";
      const path = "/location-pathname";
      const title = "title value";

      // When / Then

      // Without parameters
      GA4.send(hitType);
      expect(gtag).toHaveBeenNthCalledWith(1, "event", "page_view");
      GA4.send({ hitType });
      expect(gtag).toHaveBeenNthCalledWith(2, "event", "page_view");
      GA4.ga("send", hitType);
      expect(gtag).toHaveBeenNthCalledWith(3, "event", "page_view");

      // With path parameter
      GA4.send({ hitType, page: path });
      expect(gtag).toHaveBeenNthCalledWith(4, "event", "page_view", {
        page_path: path,
      });
      GA4.ga("send", hitType, path);
      expect(gtag).toHaveBeenNthCalledWith(5, "event", "page_view", {
        page_path: path,
      });

      // With path and title parameter
      GA4.send({ hitType, page: path, title });
      expect(gtag).toHaveBeenNthCalledWith(6, "event", "page_view", {
        page_path: path,
        page_title: title,
      });
      GA4.ga("send", hitType, path, { title });
      expect(gtag).toHaveBeenNthCalledWith(7, "event", "page_view", {
        page_path: path,
        page_title: title,
      });
    });
  });

  describe("Web vitals", () => {
    it("Web vitals", () => {
      // https://github.com/GoogleChrome/web-vitals/blob/main/README.md
      function sendToGoogleAnalytics({ name, delta, value, id }) {
        GA4.send({
          hitType: "event",
          eventCategory: "Web Vitals",
          eventAction: name,
          eventLabel: id,
          nonInteraction: true,
          // Built-in params:
          value: Math.round(name === "CLS" ? delta * 1000 : delta), // Use `delta` so the value can be summed.
          // Custom params:
          metric_id: id, // Needed to aggregate events.
          metric_value: value, // Optional.
          metric_delta: delta, // Optional.

          // OPTIONAL: any additional params or debug info here.
          // See: https://web.dev/debug-web-vitals-in-the-field/
          // metric_rating: 'good' | 'ni' | 'poor',
          // debug_info: '...',
          // ...
        });
      }

      sendToGoogleAnalytics({
        name: "CLS",
        delta: 12.34,
        value: 1,
        id: "v2-1632380328370-6426221164013",
      });

      expect(gtag).toHaveBeenNthCalledWith(1, "event", "CLS", {
        event_category: "Web Vitals",
        event_label: "v2-1632380328370-6426221164013",
        metric_delta: 12.34,
        metric_id: "v2-1632380328370-6426221164013",
        metric_value: 1,
        non_interaction: true,
        value: 12340,
      });
    });
  });
});