testinggoogle-analyticscypress

Test google analytics tracking with cypress


I am trying to write cypress tests for our google analytics tracking.

At first glance it works with a test like this:

describe('Basic GTM Tests', () => {
    it('Event ce.pageload gets fired on page load', () => {
        cy.visit('https://www.my.domain');
        cy.waitForResource('gtm.js');
        cy.wait(1000); // wait for events to be fired

        cy.window().then((win) => {
            assert.equal(win.dataLayer[14].event, 'ce.pageload')
        })
    });
});

This will indeed check that the event ce.pageload has been fired. Unfortunately this seems to be quite fragile as the code relies on the fact that the event is stored at a spefic potition (14 in this example) inside the dataLayer.

As events are asynchrounus and events may be deleted/added in the future I wonder if/how I could check that there exists an Object (at any position) inside win.dataLayer array that has the property event holding the value ce.pageload.

Question 1: How to assert that inside an array there exists an object with property event set equal to a given value?

Question 2: Is there a better approach to check that a certain GA event has been fired?


Update

I could solve my problem by adopting the solution provided by Woody:

const gaEventGetsFired = (eventName: string) => {
    cy.window().should((win) => {
        const events = win.dataLayer.map(obj => obj.event)
        expect(eventName).to.be.oneOf(events)
    })
}

describe('Basic GTM Tests', () => {
    it('Event ce.pageload gets fired on page load', () => {
        cy.visit('https://www.my.domain');    
        gaEventGetsFired('ce.pageload');
    });
});

Solution

  • The Array.some method returns true or false.

    Array.prototype.some()

    The some() method of Array instances tests whether at least one element in the array passes the test implemented by the provided function.

    It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false.

    cy.window().then((win) => {
      assert(win.dataLayer.some(obj => obj.event === 'ce.pageload'), 
        'Page load was found')
    })
    

    The "Cypress" way

    Cypress provides .should() assert wrapper which retries until true (or timeout limit). This allows the removal of cy.wait(1000) which might be flaky.

    The chaiJs assertion oneOf is equivalent to Array.some().

    cy.window().should((win) => {
      const events = win.dataLayer.map(obj => obj.event)  // extract events
      expect('ce.pageload').to.be.oneOf(events)
    })