Каждый плагин @gorgo ежедневно проходит юнит-, интеграционные и контрактные тесты против реальных API провайдеров и проверяется на последней версии Medusa, чтобы ваши магазины работали стабильно. Рассказываем, как устроен этот процесс.

Устанавливая плагин приёма платежей или доставки, вы доверяете ему оформление заказа, и ошибка здесь стоит реальных денег. Поэтому тестирование каждого пакета в монорепозитории medusa-plugins автоматизировано полностью, от юнит-тестов до ежедневных проверок против боевых API провайдеров. В этой статье разберём, какие тесты мы запускаем, насколько они покрывают каждый плагин и как проверяется совместимость с последней версией Medusa.
Сейчас в репозитории 81 тестовый файл и 543 тест-кейса на шесть плагинов.
Юнит-тесты проверяют логику провайдера в изоляции, без сети и базы данных: сопоставление статусов, генерацию подписи, формирование чеков, разбор ошибок. Исходящие HTTP-запросы перехватывает MSW, поэтому легко проверить реакцию плагина на любой ответ провайдера, включая сценарии, которые сложно воспроизвести вручную: отклонённый платёж, некорректный вебхук, повторно отправленное событие.
Интеграционные тесты находятся в отдельных пакетах и поднимают полноценное приложение Medusa с установленным плагином и базой PostgreSQL через . Тестовая база создаётся и удаляется на каждом прогоне. HTTP-тесты проходят admin- и store-маршруты целиком, module-тесты обращаются к сервисам напрямую. Часть приёмов — структуру тестов и работу с тестовой базой — мы подсмотрели в самом репозитории Medusa, где эти инструменты используются для тестирования ядра.
Юнит- и интеграционные тесты имитируют внешний сервис, поэтому не заметят изменений на его стороне. Контрактные тесты решают обратную задачу: обращаются к API провайдера (ЮKassa, Т-Касса, Robokassa, ApiShip) и проверяют, что форматы запросов и ответов, которые использует плагин, всё ещё совпадают с фактическими.
В CI эти тесты выполняются ежедневно с действующими ключами API. Любое несовместимое изменение на стороне провайдера, будь то переименованное поле, новый статус или более строгая валидация, приводит к ошибкам в тестах. Вот, например, проверка, которая заметит новый статус жизненного цикла платежа:
1const KNOWN_STATUSES = [2 "pending",3 "waiting_for_capture",4 "succeeded",5 "canceled",6] as const7
8// ...9
10let client: YooCheckout11
12beforeAll(() => {13 client = new YooCheckout({ shopId: SHOP_ID!, secretKey: SECRET_KEY! })14})15
16it("createPayment → getPayment → cancelPayment honours the documented lifecycle contract", async () => {17 const idempotencyKey = `contract-no-receipt-${Date.now()}`18 const payment = await sdkCall(() =>19 client.createPayment(20 {21 amount: { value: "10.00", currency: "RUB" },22 confirmation: { type: "redirect", return_url: "https://example.com/return" },23 description: "medusa-plugin contract test (no receipt)",24 metadata: { session_id: idempotencyKey, receip_tmp: "{}" },25 },26 idempotencyKey27 )28 )29
30 expect(payment.id).toBeDefined()31 expect(payment.status).toBeDefined()32 expect(KNOWN_STATUSES).toContain(payment.status as any)33 expect(payment.amount.value).toBe("10.00")34 expect(payment.amount.currency).toBe("RUB")35 expect(payment.confirmation).toBeDefined()36 expect((payment.confirmation as any).confirmation_url).toMatch(/^https:\/\//)37 // ...38})Покрытие разное. Глубже всего протестированы платёжные плагины с помощью юнит-, интеграционных и контрактных тестов, ведь цена ошибки при оплате самая высокая. У самая большая кодовая база и самый большой набор тестов. Плагин находится в разработке, пока в нём только базовый smoke-тест.
Ниже актуальные цифры по каждому плагину. Проценты оценочные и отражают глубину тестирования, а не точное line-покрытие.
| Плагин | Юнит | Интеграционные | Контрактные | Покрытие | Бадж |
|---|---|---|---|---|---|
| 88 | 11 | 4 | ~90% | ||
| 76 | 11 | 5 | ~90% | ||
| 60 | 7 | 4 | ~85% | ||
| 149 | 80 | 19 | ~80% | ||
| 0 | 21 | 0 | ~60% | ||
| 0 | 1 | 0 | ~5% |
Бадж в README каждого плагина обновляется автоматически. Каждое утро воркфлоу выполняет следующие шаги:
Плагины при этом изолированы друг от друга: если один ломается на новом релизе Medusa, он исключается из обновления, а остальные тестируются дальше.
Так это выглядит на практике. 25 июня утренний прогон обнаружил свежую Medusa v2.17.1, обновил и проверил все шесть плагинов примерно за десять минут. Пять прошли, а не собрался: в новой версии из типа исчезло поле . Плагин остался на предыдущей проверенной версии, а поломка видна в пул-реквесте #358.
Сам бадж хранится в репозитории как JSON-файл, который отрисовывается с помощью shields.io. Значение в нём означает, что тесты плагина действительно прошли на этой версии:
1{2 "schemaVersion": 1,3 "label": "Tested with Medusa",4 "message": "v2.17.1",5 "color": "green"6}За автоматизацию отвечают три воркфлоу GitHub Actions:
В пул-реквестах запускает тесты только для изменившихся плагинов. Ночной прогон и ручной запуск тестируют всё.
1medusa-plugins/2├── examples/ # примеры проектов Medusa с интегрированными плагинами, версия Medusa всегда последняя3├── integration-tests/ # установки Medusa c интеграционными и контрактными тестами на каждый плагин4├── packages/ # npm-пакеты плагинов, юнит-тесты рядом с кодом5├── .badges/ # JSON «Протестировано с Medusa» на каждый плагин6├── scripts/ # обновление до новой Medusa и пересборка баджей7├── .github/workflows/ # test, update-medusa-version, publish8└── ...Все тесты открыты, их можно посмотреть в репозитории gorgojs/medusa-plugins, а описания плагинов в документации. Вопросы и сообщения об ошибках ждём в чате поддержки Gorgo и Telegram-сообществе Medusa. Issues и Pull Requests тоже всегда приветствуются.