import { EMPTY_FEEDBACK, type IFeedbackData } from './model'; import { TEXTS } from './texts'; import { validateFeedback } from './validateFeedback'; const VALID_COMPANY = '9de064a4-44c8-88ef-11ec-8285925d83d2'; const LONG_TEXT = 'Развёрнутое описание, которого достаточно для проверки правила'; const SHORT_TEXT = 'коротко'; /** Полностью заполненное обращение — стартовая точка для тестов. */ function buildValidComplaint(overrides: Partial = {}): IFeedbackData { return { ...EMPTY_FEEDBACK, company: VALID_COMPANY, fullName: 'Иванов Иван Иванович', kind: 'complaint', situation: LONG_TEXT, suggestion: LONG_TEXT, ...overrides }; } describe('validateFeedback: базовые обязательные поля', () => { it('полностью заполненное обращение проходит без ошибок', () => { expect(validateFeedback(buildValidComplaint())).toEqual({}); }); it('без компании — ошибка', () => { const errors = validateFeedback(buildValidComplaint({ company: '' })); expect(errors.company).toBeDefined(); }); it('именное обращение без ФИО — ошибка', () => { const errors = validateFeedback(buildValidComplaint({ fullName: '' })); expect(errors.fullName).toBeDefined(); }); it('анонимное обращение без ФИО — не ошибка (поле скрыто, требовать его нельзя)', () => { const errors = validateFeedback( buildValidComplaint({ isAnonymous: true, fullName: '' }) ); expect(errors.fullName).toBeUndefined(); }); }); describe('validateFeedback: вид обращения "Другое"', () => { it('без уточнения вида — ошибка', () => { const errors = validateFeedback( buildValidComplaint({ kind: 'other', kindOther: '', situation: LONG_TEXT }) ); expect(errors.kindOther).toBeDefined(); }); it('с уточнением — ошибки по kindOther нет', () => { const errors = validateFeedback( buildValidComplaint({ kind: 'other', kindOther: 'Свой вариант', situation: LONG_TEXT }) ); expect(errors.kindOther).toBeUndefined(); }); }); // Состав обязательных полей зависит от вида обращения (см. getAppealFieldsConfig // в model.ts) — эти тесты фиксируют контракт, чтобы форма и валидация не разошлись. describe('validateFeedback: обязательность полей по видам обращения', () => { it('обращение: описание ситуации обязательно', () => { const errors = validateFeedback(buildValidComplaint({ situation: '' })); expect(errors.situation).toBeDefined(); }); it('обращение: предложение по улучшению НЕ обязательно', () => { const errors = validateFeedback(buildValidComplaint({ suggestion: '' })); expect(errors.suggestion).toBeUndefined(); }); it('обращение: если предложение всё же указано, но слишком коротко — ошибка', () => { const errors = validateFeedback(buildValidComplaint({ suggestion: SHORT_TEXT })); expect(errors.suggestion).toBeDefined(); }); it('предложение: описание ситуации не требуется, даже если пустое', () => { const errors = validateFeedback( buildValidComplaint({ kind: 'suggestion', situation: '', suggestion: LONG_TEXT }) ); expect(errors.situation).toBeUndefined(); }); it('предложение: сама суть предложения обязательна', () => { const errors = validateFeedback( buildValidComplaint({ kind: 'suggestion', situation: '', suggestion: '' }) ); expect(errors.suggestion).toBeDefined(); }); it('другое: описание обязательно, предложение не спрашивается вовсе', () => { const errors = validateFeedback( buildValidComplaint({ kind: 'other', kindOther: 'Свой вариант', situation: '', suggestion: '' }) ); expect(errors.situation).toBeDefined(); expect(errors.suggestion).toBeUndefined(); }); }); describe('validateFeedback: минимальная длина текста', () => { it('пустое описание — ошибка «заполните поле»', () => { const errors = validateFeedback(buildValidComplaint({ situation: '' })); expect(errors.situation).toBe(TEXTS.errors.required); }); it('слишком короткое описание — ошибка «коротко», а не «пусто»', () => { const errors = validateFeedback(buildValidComplaint({ situation: SHORT_TEXT })); expect(errors.situation).toBe(TEXTS.errors.tooShort); }); it('достаточно длинное описание — без ошибки', () => { const errors = validateFeedback(buildValidComplaint({ situation: LONG_TEXT })); expect(errors.situation).toBeUndefined(); }); });