Перехват WebSocket сообщений

Основы работы с WebSocket

WebSocket предоставляет двусторонний канал связи между клиентом и сервером, позволяя обмениваться данными в режиме реального времени. В отличие от HTTP-запросов, где клиент инициирует каждый запрос, WebSocket соединение открывается один раз, а сервер может отправлять данные в любой момент. В контексте тестирования это создаёт особые задачи: стандартные методы перехвата HTTP-запросов (cy.intercept) не работают напрямую с WebSocket, поэтому требуется использование других подходов.

Подключение к WebSocket

Для работы с WebSocket в Cypress можно использовать встроенные браузерные объекты WebSocket или сторонние библиотеки, например ws или socket.io-client. Основная идея заключается в создании «шпиона» для соединения, который перехватывает сообщения, отправляемые и получаемые клиентом.

Пример базового подключения к WebSocket в тесте Cypress:

describe('WebSocket тестирование', () => {
  it('перехватывает сообщения от сервера', () => {
    cy.window().then((win) => {
      const ws = new win.WebSocket('ws://localhost:8080');
      ws.onmess age = (event) => {
        console.log('Сообщение от сервера:', event.data);
      };
      ws.ono pen = () => {
        ws.send(JSON.stringify({ type: 'ping' }));
      };
    });
  });
});

В этом примере создаётся WebSocket соединение внутри контекста окна браузера, что позволяет напрямую взаимодействовать с объектом WebSocket, отправлять и получать сообщения.

Использование cy.intercept для WebSocket через HTTP-апгрейд

Хотя cy.intercept не работает с обычными WebSocket сообщениями, он может отслеживать HTTP-запросы на установку соединения (Upgrade), что позволяет проверять успешное подключение:

cy.intercept({
  url: '/socket',
  headers: { upgrade: 'websocket' },
}).as('wsConnect');

cy.visit('/');
cy.wait('@wsConnect').then((interception) => {
  expect(interception.response.statusCode).to.eq(101);
});

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

Перехват сообщений с использованием cy.stub

Для тестирования логики обработки сообщений можно заменить стандартный объект WebSocket на «заглушку» (stub), которая записывает все отправленные и полученные данные. Этот метод особенно удобен для unit-тестов или симуляции сообщений от сервера.

describe('Stub WebSocket', () => {
  it('логирует отправку и получение сообщений', () => {
    cy.window().then((win) => {
      const messages = [];
      const OriginalWebSocket = win.WebSocket;

      cy.stub(win, 'WebSocket').callsFake((url) => {
        const ws = new OriginalWebSocket(url);
        ws.send = cy.stub().callsFake((msg) => {
          messages.push({ type: 'sent', msg });
          OriginalWebSocket.prototype.send.call(ws, msg);
        });
        ws.addEventListener('message', (event) => {
          messages.push({ type: 'received', msg: event.data });
        });
        return ws;
      });

      cy.visit('/');
      cy.window().then(() => {
        console.log(messages);
      });
    });
  });
});

Этот способ позволяет не только проверять отправленные сообщения, но и создавать искусственные события для проверки реакции приложения.

Симуляция сообщений от сервера

Для тестирования поведения клиентского кода при получении определённых событий можно вручную отправлять сообщения через заглушенный объект WebSocket:

ws.onmessage({ data: JSON.stringify({ type: 'update', payload: { value: 42 } }) });

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

Тестирование интеграции с реальным сервером

Если требуется проверка взаимодействия с настоящим WebSocket сервером, Cypress позволяет выполнять асинхронные операции через cy.wrap и промисы. Пример:

cy.window().then((win) => {
  const ws = new win.WebSocket('ws://localhost:8080');
  cy.wrap(new Cypress.Promise((resolve) => {
    ws.onmess age = (event) => {
      if (JSON.parse(event.data).type === 'ready') {
        resolve(event.data);
      }
    };
  })).then((data) => {
    expect(JSON.parse(data).type).to.eq('ready');
  });
});

Использование промисов и cy.wrap обеспечивает корректную синхронизацию Cypress с асинхронным WebSocket кодом, что предотвращает случайные ошибки в тестах.

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

Для отладки WebSocket тестов полезно сохранять все отправленные и полученные сообщения в массив или объект, а затем выводить их через cy.log или console.log. Это помогает отслеживать последовательность событий и выявлять ошибки логики приложения.


Перехват WebSocket сообщений в Cypress требует комбинирования нескольких техник: наблюдение за соединением через cy.intercept, использование заглушек для перехвата сообщений и асинхронного тестирования с cy.wrap. Такой подход обеспечивает гибкость тестирования как unit-уровня, так и интеграционного взаимодействия в реальном времени.