Files
portal/app/tests/Frontend/creativeLimits.spec.ts
T
Дмитрий 8cd2ef91d3 feat(реклама яндекс): клиентские проверки лимитов креатива объявления
Три изолированных модуля по TDD (тест до кода) — заголовок/второй
заголовок/текст (creativeLimits.ts), проверка ссылки (urlRule.ts) и
проверка картинки (imageRule.ts + imageMeta.ts). Цифры и сообщения —
порт 1:1 из app/app/Services/Advertising/CreativeValidator.php
(единый источник лимитов Яндекс.Директа). 23 новых теста зелёные.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-25 20:32:58 +03:00

105 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect } from 'vitest';
import {
validateTitle,
validateTitle2,
validateText,
NARROW_CHARS,
countNormalAndNarrow,
} from '../../resources/js/lib/advertising/creativeLimits';
/** Строка заданной общей длины из слов не длиннее wordLen (для тестов общего лимита длины). */
function buildLine(totalLen: number, wordLen: number): string {
let result = '';
while (result.length < totalLen) {
if (result.length > 0) {
result += ' ';
}
const remaining = totalLen - result.length;
const w = Math.min(wordLen, remaining);
result += 'а'.repeat(w);
}
return result;
}
describe('creativeLimits — validateTitle', () => {
it('пропускает заголовок ровно 56 символов (слова не длиннее 22)', () => {
const title = buildLine(56, 20);
expect(validateTitle(title)).toBeNull();
});
it('отклоняет заголовок длиннее 56 символов', () => {
const title = buildLine(57, 20);
expect(validateTitle(title)).toBe('Заголовок длиннее 56 символов');
});
it('пропускает слово ровно 22 символа', () => {
const title = 'а'.repeat(22);
expect(validateTitle(title)).toBeNull();
});
it('отклоняет слово длиннее 22 символов', () => {
const title = 'а'.repeat(23);
expect(validateTitle(title)).toBe('В заголовке есть слово длиннее 22 символов');
});
});
describe('creativeLimits — validateTitle2', () => {
it('пропускает 30 обычных символов', () => {
const title2 = 'а'.repeat(30);
expect(validateTitle2(title2)).toBeNull();
});
it('отклоняет 31 обычный символ', () => {
const title2 = 'а'.repeat(31);
expect(validateTitle2(title2)).toBe(
'Второй заголовок длиннее нормы (30 обычных символов + до 15 узких)'
);
});
it('обычные и узкие считаются раздельно: 30 обычных + 5 узких — ок', () => {
const title2 = 'а'.repeat(30) + '!'.repeat(5);
expect(validateTitle2(title2)).toBeNull();
});
it('отклоняет, если узких больше 15 даже при малом числе обычных', () => {
const title2 = 'а'.repeat(5) + '!'.repeat(16);
expect(validateTitle2(title2)).toBe(
'Второй заголовок длиннее нормы (30 обычных символов + до 15 узких)'
);
});
});
describe('creativeLimits — validateText', () => {
it('пропускает 81 обычный символ (слова не длиннее 23)', () => {
const text = buildLine(81, 20);
expect(validateText(text)).toBeNull();
});
it('отклоняет 82 обычных символа', () => {
const text = buildLine(82, 20);
expect(validateText(text)).toBe(
'Текст длиннее нормы (81 обычных символов + до 15 узких)'
);
});
it('пропускает слово ровно 23 символа', () => {
const text = 'а'.repeat(23);
expect(validateText(text)).toBeNull();
});
it('отклоняет слово длиннее 23 символов', () => {
const text = 'а'.repeat(24);
expect(validateText(text)).toBe('В тексте есть слово длиннее 23 символов');
});
});
describe('creativeLimits — NARROW_CHARS и countNormalAndNarrow', () => {
it('содержит все узкие символы норматива', () => {
expect(NARROW_CHARS).toEqual(['!', ',', '.', ';', ':', '"']);
});
it('считает обычные и узкие раздельно', () => {
expect(countNormalAndNarrow('ab!c,')).toEqual({ normal: 3, narrow: 2 });
});
});