Управление организацией

Cypress — это современный инструмент для энд-ту-энд тестирования веб-приложений, который позволяет автоматизировать взаимодействие с пользовательским интерфейсом в браузере. Основная структура теста в Cypress строится вокруг команд describe, context и it.

  • describe и context используются для логической группировки тестов.
  • it содержит конкретный тестовый сценарий.
  • before, beforeEach, after, afterEach позволяют управлять состоянием перед запуском тестов и после них.

Пример базового шаблона:

describe('Управление организацией', () => {
  beforeEach(() => {
    cy.visit('/login');
    cy.get('#username').type('admin');
    cy.get('#password').type('password');
    cy.get('#login-button').click();
  });

  it('Создание новой организации', () => {
    cy.get('#create-organization').click();
    cy.get('#organization-name').type('Новая организация');
    cy.get('#save-button').click();
    cy.contains('Организация успешно создана').should('be.visible');
  });
});

Навигация и взаимодействие с элементами

Cypress использует команды типа cy.get(), cy.contains() и cy.find() для поиска элементов на странице. Выбор селекторов является ключевым моментом, чтобы тесты были стабильными:

  • Предпочтение отдаётся data-атрибутам, например data-cy="organization-name".
  • Избегать использования классов и ID, которые могут изменяться с версткой.

Для работы с формами применяются команды:

  • cy.type() для ввода текста.
  • cy.select() для выбора опций из выпадающего списка.
  • cy.check() и cy.uncheck() для работы с чекбоксами.
  • cy.click() для кнопок и ссылок.

Пример взаимодействия с формой создания организации:

cy.get('[data-cy="organization-name"]').type('Компания A');
cy.get('[data-cy="organization-type"]').select('IT');
cy.get('[data-cy="organization-active"]').check();
cy.get('[data-cy="save-organization"]').click();
cy.contains('Организация успешно создана').should('exist');

Проверки и ассерты

Cypress использует библиотеку Chai для ассертов. Основные методы проверки:

  • should('be.visible') — элемент видим на странице.
  • should('have.text', 'текст') — проверка текста.
  • should('contain', 'текст') — частичное совпадение текста.
  • should('have.value', 'значение') — проверка значения инпута.

Ассерты можно комбинировать:

cy.get('[data-cy="organization-name"]')
  .should('be.visible')
  .and('have.value', 'Компания A');

Управление организацией: CRUD операции

Создание организации:

  1. Переход на страницу организаций.
  2. Клик по кнопке “Создать организацию”.
  3. Заполнение полей формы.
  4. Сохранение и проверка успешного уведомления.

Чтение и проверка списка:

  • Используется cy.get() для поиска таблицы и cy.contains() для поиска конкретной организации.
  • Для проверки количества элементов можно использовать should('have.length', n).
cy.get('[data-cy="organization-row"]').should('have.length', 5);
cy.contains('Компания A').should('exist');

Обновление организации:

  1. Поиск организации в списке.
  2. Клик по кнопке “Редактировать”.
  3. Изменение нужных полей и сохранение.
  4. Проверка обновлённого значения в таблице.
cy.contains('Компания A')
  .parent()
  .find('[data-cy="edit-button"]')
  .click();
cy.get('[data-cy="organization-name"]').clear().type('Компания B');
cy.get('[data-cy="save-organization"]').click();
cy.contains('Компания B').should('exist');

Удаление организации:

  • Клик по кнопке “Удалить”.
  • Подтверждение действия через диалоговое окно.
  • Проверка отсутствия записи в таблице.
cy.contains('Компания B')
  .parent()
  .find('[data-cy="delete-button"]')
  .click();
cy.get('[data-cy="confirm-delete"]').click();
cy.contains('Компания B').should('not.exist');

Работа с асинхронностью

Cypress автоматически ожидает загрузку элементов и завершение асинхронных операций.

  • Команды цепляются и выполняются поочередно.
  • Для ожидания конкретного состояния используются cy.wait() и cy.intercept().
  • cy.intercept() позволяет перехватывать запросы к API и проверять данные до отображения на UI.

Пример проверки API при создании организации:

cy.intercept('POST', '/api/organizations').as('createOrg');
cy.get('[data-cy="save-organization"]').click();
cy.wait('@createOrg').its('response.statusCode').should('eq', 201);

Использование фикстур и параметризация

Фикстуры позволяют хранить тестовые данные в виде JSON и использовать их для тестов. Это обеспечивает масштабируемость и поддерживаемость.

Пример:

cy.fixture('organization.json').then((org) => {
  cy.get('[data-cy="organization-name"]').type(org.name);
  cy.get('[data-cy="organization-type"]').select(org.type);
});

Параметризация через массивы позволяет выполнять один и тот же тест для разных организаций:

const organizations = ['Компания A', 'Компания B', 'Компания C'];

organizations.forEach((name) => {
  it(`Создание организации ${name}`, () => {
    cy.get('[data-cy="organization-name"]').type(name);
    cy.get('[data-cy="save-organization"]').click();
    cy.contains(name).should('exist');
  });
});

Логирование и отладка

Cypress предоставляет встроенные инструменты для логирования и дебага:

  • cy.log('Сообщение') — вывод сообщения в консоль тестов.
  • debugger — стандартный JS-отладчик, работает при запуске Cypress в интерактивном режиме.
  • cy.pause() — приостанавливает выполнение теста для ручной проверки состояния.

Пример:

cy.get('[data-cy="organization-name"]').type('Компания A');
cy.log('Имя организации введено');
cy.pause();
cy.get('[data-cy="save-organization"]').click();

Советы по поддерживаемости тестов

  • Использовать семантические селекторы (data-cy) для устойчивости тестов.
  • Разделять тестовые сценарии на малые логические блоки.
  • Обрабатывать асинхронные операции через cy.intercept() вместо cy.wait() с фиксированным временем.
  • Хранить тестовые данные в фикстурах и избегать хардкода.
  • Писать ассерты сразу после действия, чтобы тесты были детерминированными.

Эти практики обеспечивают надежность, масштабируемость и читаемость тестов для управления организацией в веб-приложении.