Отладка теста начинается не с исправления, а с воспроизведения. Соблазн велик - увидев красный тест корзины, сразу лезть в код и менять что-то наугад. Но пока падение не воспроизводится стабильно, любая правка - выстрел вслепую: уберёт симптом, не тронув причину. Дисциплина проста - сузить область до одного теста, понять, что он ждал и что получил, потом чинить. Наш случай: тест checkout то падает на несовпадении суммы, то подвешивает Jest.
Первый шаг - убрать шум. Когда в файле десятки тестов, отделите подозреваемого. test.only запускает только помеченный тест, прочие пропускаются; describe.only делает то же для целого блока. Обратный инструмент - test.skip выключает тест временно, не удаляя, а test.todo резервирует имя для ещё не написанного, чтобы он числился как невыполненный. only легко забыть и закоммитить - тогда CI прогонит один тест вместо тысячи; правило линтера no-focused-tests ловит это.
Сужать можно и снаружи, из командной строки, не трогая код. Флаг -t (--testNamePattern) запускает только тесты, чьё имя из describe/test совпало с шаблоном. Позиционный аргумент фильтрует по пути файла: jest checkout запустит только файлы, чей путь содержит checkout. Два фильтра складываются - jest checkout -t total сузит и до файла, и до имени. Результат тот же, что от only, но без правки исходника - удобнее для быстрой итерации.
--watch и --watchAll держат Jest запущенным и перезапускают тесты при сохранении файла. Разница в объёме: --watch прогоняет только тесты, затронутые изменениями с последнего коммита (опирается на git), а --watchAll перегоняет всё и не требует репозитория. Watch-режим интерактивен: p фильтрует по шаблону пути, t - по имени, f гоняет только упавшие в прошлый раз, Enter повторяет прогон. Это рабочий цикл отладки: сузил клавишей, поправил, результат за секунды.
Красный тест сам говорит, что случилось - надо прочитать. Matcher вроде toBe или toEqual печатает блок Expected / Received: сверху ожидаемое, снизу пришедшее, а для объектов - дифф отличий. Стек-трейс под ним указывает файл и строку, где сработал assert; читайте его сверху вниз до первого кадра в вашем коде, а не в глубинах Jest. Флаг --verbose разворачивает отчёт до строки на тест - видно, какой упал. console.log Jest не глотает: печатает его с файлом и строкой.
Когда печати мало, нужен отладчик с точками останова. Jest - обычный Node-процесс, поэтому его запускают под инспектором: node --inspect-brk ./node_modules/.bin/jest --runInBand. Флаг --inspect-brk останавливает исполнение на первой строке и ждёт клиента - chrome://inspect или отладчик VS Code. Ключевой момент - --runInBand: по умолчанию Jest раскидывает тесты по воркерам, и брейкпоинт из главного процесса в них не сработает - --runInBand сводит всё в процесс с инспектором, иначе точки останова не ловятся.
Вторая половина случая - Jest не завершается: 'a worker process has failed to exit gracefully'. Тесты прошли, но что-то держит event loop открытым - таймер, сокет, соединение с базой. Флаг --detectOpenHandles отслеживает эти ресурсы и печатает стек их создания, обычно указывая на setInterval или db-клиент, забытый в afterAll. Чинить надо закрытием ресурса, а не флагом --forceExit: тот убивает процесс после тестов, пряча утечку как retry прячет флаки. У нас держал event loop таймер проверки платежа; убрали в afterEach - Jest завершился, а несовпадение суммы оказалось округлением копеек.
# Запустить только тесты, чьё имя совпадает с шаблоном
npx jest -t 'checkout total'
# Запустить только файлы, в пути которых есть "checkout"
npx jest checkout
# Комбинация: сузить до файла И имени
npx jest checkout -t total# Запустить Jest под инспектором Node, в один процесс
node --inspect-brk ./node_modules/.bin/jest --runInBand
# Затем открыть chrome://inspect или подключить отладчик VS Code