Я пытаюсь написать кипарисовые тесты для отслеживания нашей аналитики Google.
На первый взгляд это работает с таким тестом:
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')
})
});
});
Это действительно проверит, что событие ce.pageload было запущено. К сожалению, это кажется довольно хрупким, поскольку код полагается на тот факт, что событие сохраняется в определенном положении (14 в этом примере) внутри dataLayer.
Поскольку события являются асинхронными и события могут быть удалены/добавлены в будущем, мне интересно, могу ли я/как я проверить, существует ли объект (в любой позиции) внутри массива win.dataLayer, который имеет свойство event, содержащее значение ce.pageload.
Вопрос 1: Как утверждать, что внутри массива существует объект, свойство которого установлено равным заданному значению?
Вопрос 2. Есть ли лучший способ проверить, было ли запущено определенное событие GA?
Обновлять
Я мог бы решить свою проблему, приняв решение, предложенное Вуди:
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');
});
});





Вы можете использовать Array.filter() или Array.find(), чтобы найти объект внутри массива, который соответствует некоторым критериям.
cy.window().then((win) => {
const pageLoad = win.dataLayer.filter((x) => x.event === 'ce.pageload');
// If you want to check that there is at least one dataLayer object found
// If you are using `.find()`, then this assertion is functionally equivalent to the `.equal` below
assert.isAbove(pageLoad.length, 0, 'No ce.pageload event found in win.dataLayer');
// If you want to check that the there is exactly one dataLayer object found
assert.equal(pageLoad.length, 1);
})
Метод Array.some возвращает true или false.
Массив.прототип.некоторые()
Метод some() экземпляров Array проверяет, проходит ли хотя бы один элемент массива тест, реализованный предоставленной функцией.Он возвращает true, если в массиве находит элемент, для которого предоставленная функция возвращает true; в противном случае он возвращает false.
cy.window().then((win) => {
assert(win.dataLayer.some(obj => obj.event === 'ce.pageload'),
'Page load was found')
})
Cypress предоставляет оболочку .should() Assert, которая повторяет попытки до тех пор, пока не будет достигнуто истинное значение (или предел времени ожидания). Это позволяет удалить cy.wait(1000), который может быть шелушащимся.
Утверждение chaiJsoneOf эквивалентно Array.some().
cy.window().should((win) => {
const events = win.dataLayer.map(obj => obj.event) // extract events
expect('ce.pageload').to.be.oneOf(events)
})
expect('ce.pageload').to.be.oneOf(win.dataLayer) выглядит очень многообещающе, но терпит неудачу, поскольку я ищу объект со свойством event === 'someValue'. Можно ли это изменить, чтобы утверждать, что существует объект с заданным значением? Использование array.prototype работает, но требует установки тайм-аута, чтобы гарантировать, что данные действительно доступны.
Хорошо, я не понял, какие значения устанавливаются в слое данных. Настроить обратный вызов some просто. И oneOfчек.
Попробуйте assert.include вместо assert.eq
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.include(win.dataLayer, 'ce.pageload')
})
})
})
Простой пример:
it('assert include for in value in array', () => {
assert.include(['a', 'b', 'c'], 'b')
})
К сожалению, это не работает, если мы хотим подтвердить свойство объекта. Он работает безупречно при попытке найти (скалярное) значение внутри объекта.
Это сработает, если я установлю cy.wait(xxx) на достаточно долгое ожидание. Это кажется немного проблематичным, потому что я не могу знать, как долго мне придется ждать, а это может потребовать очень долгого ожидания, чтобы убедиться, что window.dataLayer содержит необходимые данные.