src/app/components/ChartbeatAnalytics/canonical/index.test.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import React from 'react';
import { Helmet } from 'react-helmet';
import { render, act, waitFor } from '@testing-library/react';
import CanonicalChartbeatAnalytics from '.';
import { CanonicalChartbeatConfig } from '../types';

describe('CanonicalChartbeatAnalytics', () => {
  // @ts-expect-error chartbeat requires pSUPERFLY object on global window
  global.pSUPERFLY = {
    virtualPage: jest.fn(),
  };

  afterEach(jest.clearAllMocks);

  // @ts-expect-error partial data for testing purposes
  const pageAConfig: CanonicalChartbeatConfig = {
    domain: 'test-domain',
    sections: 'section1 section2',
    virtualReferrer: null,
    useCanonical: true,
    title: 'Page A',
    uid: 123,
  };

  const pageBConfig = {
    chartbeatConfig: {
      domain: 'test-domain',
      type: 'article',
      sections: 'section1 section2',
      chartbeatUID: 1111,
      useCanonical: true,
      virtualReferrer: '/page-A',
      title: 'Page B',
      uid: 123,
    },
  };

  const pageCConfig = {
    chartbeatConfig: {
      domain: 'test-domain',
      type: 'article',
      sections: 'section1 section2',
      chartbeatUID: 1111,
      useCanonical: true,
      virtualReferrer: '/page-B',
      title: 'Page C',
      uid: 123,
    },
  };

  it('should return the helmet wrapper with the script snippet', () => {
    render(
      <CanonicalChartbeatAnalytics
        chartbeatConfig={pageAConfig}
        chartbeatSource="//chartbeat.js"
      />,
    );
    expect(Helmet.peek().scriptTags).toMatchSnapshot();
  });

  it('should not re-render helment wrapper when config changes to Page B', async () => {
    const { rerender } = render(
      <CanonicalChartbeatAnalytics
        chartbeatConfig={pageAConfig}
        chartbeatSource="//chartbeat.js"
      />,
    );

    await act(async () => {
      rerender(
        <CanonicalChartbeatAnalytics
          chartbeatConfig={pageBConfig.chartbeatConfig}
          chartbeatSource="//chartbeat.js"
        />,
      );
    });

    await waitFor(() => {
      expect(document.querySelectorAll('script')[0].textContent).toMatch(
        /"title":"Page A"/,
      );
    });
  });

  it('should call the global virtualPage function when props change', async () => {
    const { rerender } = render(
      <CanonicalChartbeatAnalytics
        chartbeatConfig={pageAConfig}
        chartbeatSource="//chartbeat.js"
      />,
    );

    await act(async () => {
      rerender(
        <CanonicalChartbeatAnalytics
          chartbeatConfig={{
            domain: 'test-domain',
            type: 'article',
            sections: 'section1 section2',
            useCanonical: true,
            virtualReferrer: '/page-A',
            title: 'Page B',
            uid: 123,
          }}
          chartbeatSource="//chartbeat.js"
        />,
      );
    });

    await act(async () => {
      // unmount
      rerender(<div />);
    });

    // @ts-expect-error chartbeat requires pSUPERFLY object on global window
    expect(global.pSUPERFLY.virtualPage).toHaveBeenCalled();
    // @ts-expect-error chartbeat requires pSUPERFLY object on global window
    expect(global.pSUPERFLY.virtualPage).toHaveBeenCalledWith({
      domain: 'test-domain',
      type: 'article',
      sections: 'section1 section2',
      useCanonical: true,
      virtualReferrer: '/page-A',
      title: 'Page B',
      uid: 123,
    });
  });

  it('should report correct virtual referrer when user navigates back from onward journey', async () => {
    // initial PWA load (Page A)
    const { rerender } = render(
      <CanonicalChartbeatAnalytics
        chartbeatConfig={pageAConfig}
        chartbeatSource="//chartbeat.js"
      />,
    );

    // inline link to Page B
    await act(async () => {
      rerender(
        <CanonicalChartbeatAnalytics
          chartbeatConfig={pageBConfig.chartbeatConfig}
          chartbeatSource="//chartbeat.js"
        />,
      );
    });

    // inline link to Page C
    await act(async () => {
      rerender(
        <CanonicalChartbeatAnalytics
          chartbeatConfig={pageCConfig.chartbeatConfig}
          chartbeatSource="//chartbeat.js"
        />,
      );
    });

    // press back, return to Page B
    await act(async () => {
      rerender(
        <CanonicalChartbeatAnalytics
          chartbeatConfig={pageBConfig.chartbeatConfig}
          chartbeatSource="//chartbeat.js"
        />,
      );
    });

    const [[firstCall], [secondCall], [thirdCall]] =
      // @ts-expect-error chartbeat requires pSUPERFLY object on global window
      global.pSUPERFLY.virtualPage.mock.calls;

    expect(firstCall.virtualReferrer).toEqual('/page-A');
    expect(secondCall.virtualReferrer).toEqual('/page-B');
    expect(thirdCall.virtualReferrer).toEqual('/page-A');
  });
});