WYSIWYG редакторы

WYSIWYG (What You See Is What You Get) редакторы предоставляют пользователю визуальный интерфейс для работы с контентом, скрывая HTML-код и предоставляя средства редактирования текста, форматирования и вставки медиа. Тестирование таких редакторов требует специфического подхода, так как взаимодействие с визуальным контентом отличается от обычных форм и полей ввода.


Инициализация Cypress для тестирования WYSIWYG

Для работы с редактором нужно корректно настроить окружение. Обычно редакторы интегрируются через iframe или shadow DOM, что требует дополнительных техник для взаимодействия.

// Пример команды для получения body внутри iframe
Cypress.Commands.add('getIframeBody', (iframeSelector) => {
    return cy
        .get(iframeSelector)
        .its('0.contentDocument.body')
        .should('not.be.empty')
        .then(cy.wrap);
});

Использование команды getIframeBody позволяет безопасно обращаться к элементам внутри редактора, как если бы они находились в обычном DOM.


Проверка и установка текста

Простейший сценарий — ввод и проверка текста. В WYSIWYG редакторах необходимо учитывать, что текст может быть обёрнут тегами <p>, <span> или <strong> в зависимости от форматирования.

cy.getIframeBody('#editor-iframe')
  .clear()
  .type('Тестирование Cypress')
  .should('contain.text', 'Тестирование Cypress');

Важно использовать contain.text, а не have.value, так как поле редактора обычно не является <input>.


Форматирование текста

Форматирование, такое как жирный, курсив, списки или ссылки, тестируется через имитацию клика на соответствующие кнопки панели инструментов и проверку изменения DOM внутри редактора.

cy.get('#bold-button').click();
cy.getIframeBody('#editor-iframe')
  .type('Жирный текст')
  .find('strong')
  .should('contain.text', 'Жирный текст');

Для списков:

cy.get('#unordered-list-button').click();
cy.getIframeBody('#editor-iframe')
  .type('Элемент списка{enter}')
  .find('li')
  .should('contain.text', 'Элемент списка');

Работа с изображениями и медиа

Вставка изображений и видео требует проверки как визуального отображения, так и атрибутов, например src для изображений.

cy.get('#insert-image-button').click();
cy.get('#image-url-input').type('https://example.com/image.png{enter}');
cy.getIframeBody('#editor-iframe')
  .find('img')
  .should('have.attr', 'src', 'https://example.com/image.png');

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


Тестирование событий и автосохранения

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

cy.intercept('POST', '/api/save').as('save');
cy.getIframeBody('#editor-iframe')
  .type('Сохранение тест')
cy.wait('@save').its('response.statusCode').should('eq', 200);

Такой подход позволяет убедиться, что изменения действительно сохраняются на сервере.


Тестирование undo/redo и горячих клавиш

Редакторы обычно поддерживают комбинации клавиш для отмены и повторения действий. В Cypress можно эмулировать нажатия клавиш:

cy.getIframeBody('#editor-iframe')
  .type('Текст для undo{ctrl+z}');
cy.getIframeBody('#editor-iframe')
  .should('not.contain.text', 'Текст для undo');

cy.getIframeBody('#editor-iframe')
  .type('{ctrl+y}');
cy.getIframeBody('#editor-iframe')
  .should('contain.text', 'Текст для undo');

Использование {ctrl+z} и {ctrl+y} позволяет имитировать поведение стандартного редактора и проверять корректность работы истории изменений.


Тестирование выделения и копирования текста

Работа с выделением текста в WYSIWYG редакторах также требует взаимодействия с iframe и методами Cypress для имитации мыши:

cy.getIframeBody('#editor-iframe')
  .type('Выделяемый текст');
cy.getIframeBody('#editor-iframe')
  .find('p')
  .trigger('mousedown')
  .trigger('mousemove', { clientX: 50, clientY: 0 })
  .trigger('mouseup')
  .then(($p) => {
    const selectedText = window.getSelection().toString();
    expect(selectedText).to.eq('Выделяемый текст');
  });

Проверка выделения позволяет убедиться, что текст реагирует на стандартные действия пользователя.


Обработка ошибок и нестандартных случаев

При тестировании важно предусматривать:

  • Попытку вставки некорректного HTML.
  • Вставку пустого текста или слишком большого объёма.
  • Проверку поведения редактора в разных браузерах и на разных разрешениях.
cy.getIframeBody('#editor-iframe')
  .invoke('html', '<script>alert("xss")</script>')
  .should('not.contain.html', '<script>alert("xss")</script>');

Это предотвращает уязвимости и гарантирует стабильность интерфейса.


Организация тестов и повторное использование команд

Для крупных проектов рекомендуется создавать кастомные команды Cypress для всех повторяющихся действий: ввод текста, форматирование, вставка медиа, проверка содержимого. Это упрощает написание тестов и делает их более читабельными.

Cypress.Commands.add('typeInEditor', (iframeSelector, text) => {
    cy.getIframeBody(iframeSelector).clear().type(text);
});

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