test(support): закрепить привязку onError к мутациям тикетов

Дополнение к PR #548 при мерже. Код менять не пришлось — добавлены три теста.

Решение «это 409» автор вынес в утилиту и покрыл хорошо, а вот сама привязка
onError к мутациям осталась непокрытой — при том, что её отсутствие и есть
исходный баг: форма молчала, человек жал «Отправить» повторно. Проверил
мутациями: снятие onError у createMutation, снятие onError у replyMutation и
удаление обновления списка тикетов в ветке 409 набор не роняли.

Окружения для рендера компонентов в репозитории нет (vitest настроен на node,
без jsdom), поэтому закрепил структурно, по исходнику — приём тот же, что уже
используется в бот-репозитории. Крудовато, но ловит ровно ту регрессию, ради
которой PR и написан.

Остальное проверено, правок не потребовалось. Несущее допущение верно: 409 в
app/cabinet/routes/tickets.py встречается ровно один раз и именно про открытый
тикет, так что матч по статусу вместо текста detail — правильный выбор (текст
приходит только по-английски, а кабинет и бот версионируются раздельно).
Переименование rateLimitError → formError сквозное, хвостов не осталось; формы
create и reply взаимоисключающие, состояние сбрасывается на всех переходах.
Ключи support.errors.* есть во всех четырёх локалях. Шесть предупреждений biome
в Support.tsx — предсуществующие, столько же на чистом dev.
This commit is contained in:
Fringg
2026-08-11 13:44:00 +03:00
parent a82950126e
commit 533fc3073f

View File

@@ -1,3 +1,4 @@
import { readFileSync } from 'node:fs';
import { AxiosError, AxiosHeaders } from 'axios';
import { describe, expect, it } from 'vitest';
import { isOpenTicketConflict } from './ticketErrors';
@@ -48,3 +49,37 @@ describe('isOpenTicketConflict', () => {
expect(isOpenTicketConflict(null)).toBe(false);
});
});
describe('обработчики ошибок на форме поддержки', () => {
// Решение «это 409» вынесено в утилиту и покрыто выше, а вот сама привязка
// onError к мутациям — нет: в репозитории нет окружения для рендера
// компонентов (vitest настроен на node, без jsdom). Поэтому закрепляем
// структурно: пропажа onError — это ровно тот баг, который PR и чинит
// (форма молчала, человек жал «Отправить» повторно).
const source = readFileSync(new URL('../pages/Support.tsx', import.meta.url), 'utf8');
it('createMutation обрабатывает отказ бэка', () => {
const block = source.slice(
source.indexOf('const createMutation'),
source.indexOf('const replyMutation'),
);
expect(block).toContain('onError');
expect(block).toContain('isOpenTicketConflict');
});
it('replyMutation обрабатывает отказ бэка', () => {
const block = source.slice(
source.indexOf('const replyMutation'),
source.indexOf('const getStatusBadge'),
);
expect(block).toContain('onError');
});
it('409 подтягивает список тикетов — открытый мог появиться в другой сессии', () => {
const block = source.slice(
source.indexOf('isOpenTicketConflict(error)'),
source.indexOf('const replyMutation'),
);
expect(block).toContain('invalidateQueries');
});
});