Проверьте отслеживание Google Analytics с помощью Cypress

Я пытаюсь написать кипарисовые тесты для отслеживания нашей аналитики 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');
    });
});
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать 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);
})

Это сработает, если я установлю cy.wait(xxx) на достаточно долгое ожидание. Это кажется немного проблематичным, потому что я не могу знать, как долго мне придется ждать, а это может потребовать очень долгого ожидания, чтобы убедиться, что window.dataLayer содержит необходимые данные.

maxhb 05.08.2024 07:32
Ответ принят как подходящий

Метод 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 работает, но требует установки тайм-аута, чтобы гарантировать, что данные действительно доступны.
maxhb 05.08.2024 07:27

Хорошо, я не понял, какие значения устанавливаются в слое данных. Настроить обратный вызов some просто. И oneOfчек.

Woody 05.08.2024 09:34

Попробуйте 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')
})

К сожалению, это не работает, если мы хотим подтвердить свойство объекта. Он работает безупречно при попытке найти (скалярное) значение внутри объекта.

maxhb 05.08.2024 07:30

Другие вопросы по теме