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');
});
});
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')
})
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)
})