Область видимости

Область видимости (scope) в контексте Cypress играет ключевую роль при организации тестов, работе с DOM и управлении асинхронными операциями. Понимание того, как Cypress определяет видимость элементов и контекст выполнения команд, позволяет создавать надежные и стабильные автоматизированные тесты.


Контекст выполнения команд

Cypress использует цепочку команд, каждая из которых выполняется асинхронно, но код выглядит синхронно благодаря внутреннему управлению очередью команд. Каждая команда имеет текущий контекст, который определяет, к каким элементам DOM она применяется.

Пример:

cy.get('.form')
  .find('input[name="email"]')
  .type('user@example.com');

В этом случае:

  • cy.get('.form') устанавливает контекст на контейнер формы.
  • find('input[name="email"]') выполняется внутри этого контекста, а не по всему DOM.
  • type() применяется только к найденному элементу.

Использование контекста позволяет ограничивать область поиска и уменьшает вероятность ошибок из-за совпадений селекторов в других частях страницы.


Видимость элементов

Cypress автоматически проверяет видимость элементов перед взаимодействием. Под видимостью понимается, что элемент:

  • существует в DOM,
  • не скрыт с помощью CSS (display: none, visibility: hidden, opacity: 0),
  • имеет размеры (width и height больше нуля),
  • не находится за другим элементом.

Пример проверки видимости:

cy.get('#submit-button').should('be.visible').click();

Команда should('be.visible') подтверждает, что элемент доступен для пользователя, а click() выполняется только после этого условия. Cypress автоматически делает повторные попытки до истечения таймаута, если элемент временно отсутствует или не видим.


Цепочки команд и область видимости

Каждая команда Cypress возвращает объект цепочки (Chainable), который сохраняет текущий контекст. Это позволяет строить цепочки без потери видимости:

cy.get('.list')
  .children('li')
  .first()
  .should('contain.text', 'Первый элемент');

Здесь:

  • get('.list') задает родительский контейнер,
  • children('li') сужает область видимости до дочерних элементов,
  • first() выбирает первый элемент в текущей области,
  • should('contain.text', ...) проверяет текст именно этого элемента.

Использование цепочек обеспечивает локализацию действий и предотвращает случайное взаимодействие с элементами вне нужного контекста.


Применение within()

Метод within() позволяет явно ограничить область видимости блока элементов. Все команды внутри within() выполняются относительно заданного контейнера:

cy.get('.modal').within(() => {
  cy.get('input[name="username"]').type('admin');
  cy.get('button.submit').click();
});

Преимущества within():

  • Явное указание контейнера уменьшает риск конфликтов селекторов.
  • Улучшает читаемость тестов, так как действия логически сгруппированы.
  • Поддерживает асинхронность Cypress без необходимости использовать отдельные переменные для хранения элементов.

Асинхронность и переменные

Cypress не рекомендует сохранять элементы в переменные для последующего использования, так как команды выполняются асинхронно, а DOM может изменяться. Вместо этого следует использовать цепочки команд или within().

Пример неправильного подхода:

const button = cy.get('#save'); // НЕ РЕКОМЕНДУЕТСЯ
button.click();

Правильный подход:

cy.get('#save').click();

или с контекстом:

cy.get('.form').within(() => {
  cy.get('#save').click();
});

Это гарантирует, что команда всегда выполняется на актуальном элементе.


Влияние таймаутов на область видимости

Cypress автоматически повторяет команды до истечения таймаута, проверяя условия видимости и существования элемента. Таймауты можно настраивать:

cy.get('.notification', { timeout: 10000 }).should('be.visible');

Здесь область видимости и условие видимости комбинируются, чтобы дождаться появления элемента. Если таймаут истекает, тест падает, предотвращая ложноположительные результаты.


Примеры практического использования

  1. Формы с динамическими полями:
cy.get('.dynamic-form').within(() => {
  cy.get('input[name="first"]').type('John');
  cy.get('input[name="last"]').type('Doe');
  cy.get('button.submit').click();
});
  1. Таблицы и списки:
cy.get('table#users').within(() => {
  cy.get('tr').eq(2).should('contain.text', 'admin');
});
  1. Модальные окна:
cy.get('.modal.active').within(() => {
  cy.get('.close-btn').click();
});

Ключевые моменты

  • Контекст выполнения команд определяет область видимости.
  • within() обеспечивает локализованное взаимодействие с элементами.
  • Cypress проверяет видимость элементов автоматически перед действиями.
  • Асинхронность требует использования цепочек команд вместо хранения элементов в переменных.
  • Таймауты и повторные попытки делают тесты более стабильными и устойчивыми к задержкам DOM.

Область видимости в Cypress — фундаментальный инструмент для точного и надежного тестирования интерфейсов, минимизирующий ошибки взаимодействия с элементами и повышающий читаемость тестов.