Files
portal/app/tests/Unit/Autopodbor/Extract/CandidateBuilderTest.php
T
Дмитрий b78c3edb8c fix(автоподбор шаг2): не терять номера офисов, написанные без кода города
Сканер кода сайта выкидывал короткие локальные номера (271-33-33,
2-828-828 и т.п.) как мусор — терялись реальные телефоны филиалов.
Теперь короткий номер из tel:/schema/microdata достраивается кодом
города: сперва по преобладающему коду полных номеров той же страницы,
иначе по коду региона запроса; если код не определить — номер не
теряется, а помечается «требует проверки» (phoneKind=uncertain).
Из тела текста короткие формы не достраиваются (защита от ложных).

TDD: 6 новых тестов, весь Autopodbor 40/40.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 12:11:27 +03:00

96 lines
4.8 KiB
PHP

<?php
use App\Services\Autopodbor\Agent\Extract\CandidateBuilder;
use App\Services\Autopodbor\Agent\Fetch\DirectoryCard;
use App\Services\Autopodbor\Agent\Fetch\FetchedSite;
it('из кода сайта делает кандидатов kind=code с флагом трекера', function () {
$site = new FetchedSite(
url: 'https://k.ru/',
rawHtml: '<a href="tel:+73912920000">x</a><script src="//cdn.roistat.com/x.js"></script>',
);
$cands = (new CandidateBuilder)->build([$site], []);
$byNum = collect($cands)->keyBy('number');
expect($byNum)->toHaveKey('73912920000');
expect($byNum['73912920000']['kind'])->toBe('code');
expect($byNum['73912920000']['url'])->toBe('https://k.ru/');
expect($byNum['73912920000']['tracker'])->toBeTrue(); // roistat найден
expect($byNum['73912920000']['label'])->toBe('в коде сайта');
});
it('достроенный короткий локальный номер становится кандидатом code', function () {
// КрасЛомбард-кейс: на странице полный 391-номер + короткие локальные без кода города.
// Короткие НЕ теряем — достраиваем кодом 391 со страницы.
$site = new FetchedSite(
url: 'https://k.ru/',
rawHtml: '<a href="tel:+7 (391) 200-00-00">главный</a>'
.'<a href="tel:271-33-33">филиал-1</a>'
.'<a href="tel:2-828-828">филиал-2</a>',
);
$cands = (new CandidateBuilder)->build([$site], []);
$byNum = collect($cands)->keyBy('number');
expect($byNum)->toHaveKey('73912713333'); // 271-33-33 достроен
expect($byNum)->toHaveKey('73912828828'); // 2-828-828 достроен
expect($byNum['73912713333']['kind'])->toBe('code');
});
it('короткий номер без определимого кода города попадает в кандидаты «требует проверки»', function () {
$site = new FetchedSite(
url: 'https://k.ru/',
rawHtml: '<a href="tel:271-33-33">единственный, без полного номера</a>',
);
$cands = (new CandidateBuilder)->build([$site], []);
$byNum = collect($cands)->keyBy('number');
expect($byNum)->toHaveKey('2713333'); // не потеряли
expect($byNum['2713333']['kind'])->toBe('uncertain');
});
it('размечает видимый подменный и скрытый пул при активном трекере', function () {
$site = new FetchedSite(
url: 'https://k.ru/',
rawHtml: '<script src="//cdn.callibri.ru/x.js"></script>'
.'<span>8 (391) 111-22-33</span>' // видимый подменный (нет в tel:/schema)
.'8(391)700-00-01 8(391)700-00-01', // пул: 2 вхождения, не код, не видимый
visiblePhones: ['8 (391) 111-22-33'],
);
$cands = (new CandidateBuilder)->build([$site], []);
$byNum = collect($cands)->keyBy('number');
expect($byNum['73911112233']['kind'])->toBe('displayed');
expect($byNum['73917000001']['kind'])->toBe('pool');
});
it('из страницы контактов делает кандидатов с офисом', function () {
$site = new FetchedSite(
url: 'https://k.ru/',
rawHtml: '<html>пусто</html>',
contactsNumbers: [
['number' => '8(391)281-70-70', 'office' => 'Кр. рабочий, 61'],
['number' => '8(391)250-00-00', 'office' => 'Калинина, 185'],
],
);
$cands = (new CandidateBuilder)->build([$site], []);
$byNum = collect($cands)->keyBy('number');
expect($byNum['73912817070']['kind'])->toBe('contacts');
expect($byNum['73912817070']['office'])->toBe('Кр. рабочий, 61');
expect($byNum['73912817070']['label'])->toBe('страница «Контакты»');
});
it('из карточек справочника делает кандидатов directory', function () {
$cards = [
new DirectoryCard(number: '8(391)292-00-00', office: 'Единая справочная', url: 'https://2gis.ru/firm/1', source: '2ГИС'),
new DirectoryCard(number: '8(391)250-00-00', office: 'Калинина, 185', url: 'https://yandex.ru/maps/9', source: 'Яндекс.Карты'),
];
$cands = (new CandidateBuilder)->build([], $cards);
$byNum = collect($cands)->keyBy('number');
expect($byNum['73912920000']['kind'])->toBe('directory');
expect($byNum['73912920000']['label'])->toBe('2ГИС');
expect($byNum['73912920000']['url'])->toBe('https://2gis.ru/firm/1');
expect($byNum['73912500000']['office'])->toBe('Калинина, 185');
});