'Unit test Google tag manager Initialization and events

I am trying to Unit test Google tag manager code in React project. Following is what I want to test precisely:

  1. If Google tag manager is initialized with given properties
  2. Check if events are getting fired fine and are being pushed to DataLayer in window object

Sample component with gtm initialization in useEffect:

 useEffect(() => {
    if (!isLoading) {
      try {
        let dataLayer = {
          userProject: 'project-ui'
        }
        if (typeof data.id !== 'undefined') {
          dataLayer = {
            userId: data.id,
            userProject: 'project-ui'
          }
        }

        const tagManagerArgs = {
          gtmId: process.env.REACT_APP_GTAG_TRACKING,
          dataLayer
        }

        TagManager.initialize(tagManagerArgs)
      } catch (e) {/**/ }
    }
}, [isLoading])

I am trying to cover mutation of if (typeof data.id !== 'undefined') as well is !isLoading here. This is the exact goal.

please note data is coming from react-query:

const { isLoading, data } = useQuery([USER_TRACKING_ID], () =>
getLoggedInUserProfile())

Code I have written so far for Unit Testing:

  test("Ga loads", async () => {
    window.dataLayer = {
      push: jest.fn().mockImplementation(config => {
        config.eventCallback()
      }),
    }

    render(
      <QueryClientProvider client={queryClient}>
        <BrowserRouter>
          <Provider store={store}>
            <MainContainer />
          </Provider>
        </BrowserRouter>
      </QueryClientProvider>
    )
    const { result, waitFor } = renderHook(() => useCustomHook(), {
      wrapper: createWrapper()
    })
  
    await waitFor(() => result.current.isSuccess)

    console.log('test data: ', result.current)
    console.log('data layer data: ', window.dataLayer) // this is throwing undefined
    const eventSpy  = jest.spyOn(TagManager, 'initialize')


    expect(result.current.data).toEqual({
      "employeeId": "797979878",
      "name": "UserFirstName lastName",
      "userEmail": "[email protected]",
      "loginTime": 1652073402000
    })
    expect(window.dataLayer.push).toHaveBeenCalled()
    // expect(eventSpy).toHaveBeenCalled()
  })

Sample code for one of the dataLayer push I want to test:

    const messageBoardhandler = () => {
    try {
      dataLayer.push({
        event: 'NotificationBoard',
        userId: queryClient.getQueryData('USER_TRACKING_ID').id,
        category: 'MessageBoard',
        action: 'NotificationClicked',
        label: 'NotificationIcon',
        value: ''
      })
    } catch (e) { /* */ }
    dispatch(appCategoryAction.setAppCategoryFlyer(false))
    if (!pinMessageBoard) {
      dispatch(messageBoardActions.setMessageBoardChatFlyer(true))
    }
  }

I want to understand first of as I tried to mock the react-query for data, how shall I render the component and in what order, and how can I get this initialization to be tested.

I tried taking multiple approach:

  1. Tried directly asserting on Data Layer array from window which turns out is undefined.
  2. Tried using jest mock to import TagManager library that I am using to load gtag and mock TagManager.initialize and no luck.


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source