Files
portal/app/tests/Feature/Autopodbor/DeepStudyCollectorTest.php
T
Дмитрий 133eb9d0f0 feat(автоподбор): текстовые номера с сайта → «на сайте, проверьте» (unverified)
Второй пробел после фикса таймаута рендера: номера, написанные на сайте простым
текстом (не кликабельные tel:/schema, без коллтрекинга), терялись. Пример Центрофинанс:
8 800 200-00-10 («Телефон:» у юр. адреса), +7 931 106-54-50 (подвал) — движок брал
только tel:-ссылки.

- HtmlPhoneScanner: тело сканируем БЕЗ <script>/<style> (меньше шума из конфигов)
- CandidateBuilder: без трекера body-номера (не в code/visible) → kind 'text' «проверьте»
- SourceAggregator + DeepStudyCollector: text-only → phone_kind 'unverified' (не теряем,
  но и за 100% настоящий не выдаём); code/справочник перебивают → 'real'
- фронт: бейдж «⚠ на сайте — проверьте» (amber), сортировка ниже настоящих, легенда
- 7 тестов (scanner/builder/aggregator/DeepStudy); вся ветка 493/493, build ок

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 19:23:37 +03:00

72 lines
3.3 KiB
PHP

<?php
use App\Services\Autopodbor\Agent\Fetch\FetchedSite;
use App\Services\Autopodbor\Agent\Fetch\Fetcher;
use App\Services\Autopodbor\Agent\Fetch\XfetchClient;
use App\Services\Autopodbor\Agent\Study\DeepStudyCollector;
use App\Services\Autopodbor\Agent\Study\Fingerprint;
use App\Services\Autopodbor\Agent\Study\SiteOpener;
use Illuminate\Support\Facades\Http;
it('оба сайта-близнеца — две отдельные строки-источника (НЕ слиты)', function () {
config()->set('services.exa', ['key' => 't', 'base_url' => 'https://api.exa.ai']);
Http::fake([
'api.exa.ai/*' => Http::response(['results' => [
['url' => 'https://kraslombard24.ru/'],
['url' => 'https://xn--80aacn0ahhppgf.xn--p1ai/'], // красломбард.рф в punycode
]]),
'*' => Http::response(['response_body_base64' => '']),
]);
$siteFetcher = new class implements Fetcher
{
public function site(string $url): FetchedSite
{
return new FetchedSite($url, '<a href="tel:+73912920000">'.$url.'</a>');
}
public function directory(string $url): array
{
return [];
}
};
$collector = new DeepStudyCollector(new XfetchClient(null), new SiteOpener($siteFetcher));
$fp = new Fingerprint('КрасЛомбард', 'kraslombard24.ru', 'Красноярск', '391', 'krasnoyarsk', false);
$rows = $collector->collect($fp);
$sites = array_values(array_filter($rows, fn ($r) => $r['signal_type'] === 'site'));
$domains = array_map(fn ($r) => $r['identifier'], $sites);
expect(count($sites))->toBe(2)
->and($domains)->toContain('kraslombard24.ru')
->and($domains)->toContain('красломбард.рф');
$call = array_values(array_filter($rows, fn ($r) => $r['signal_type'] === 'call' && $r['identifier'] === '73912920000'))[0];
expect(collect($call['where_found'])->pluck('label'))->toContain('в коде сайта')
->and($call['phone_kind'])->toBe('real');
});
it('текстовый номер сайта → phone_kind unverified «проверьте»; tel: остаётся real', function () {
config()->set('services.exa', ['key' => 't', 'base_url' => 'https://api.exa.ai']);
Http::fake(['*' => Http::response(['response_body_base64' => ''])]);
$siteFetcher = new class implements Fetcher
{
public function site(string $url): FetchedSite
{
return new FetchedSite($url, '<a href="tel:+74950110359">код</a><div>Телефон: 8 (800) 200-00-10</div>');
}
public function directory(string $url): array
{
return [];
}
};
$collector = new DeepStudyCollector(new XfetchClient(null), new SiteOpener($siteFetcher));
$fp = new Fingerprint('Фирма', 'k.ru', 'Красноярск', '391', 'krasnoyarsk', false);
$byNum = collect($collector->collect($fp))->where('signal_type', 'call')->keyBy('identifier');
expect($byNum['74950110359']['phone_kind'])->toBe('real') // из tel: — настоящий
->and($byNum)->toHaveKey('78002000010') // текстовый НЕ потерян
->and($byNum['78002000010']['phone_kind'])->toBe('unverified'); // помечен «проверьте»
});