133eb9d0f0
Второй пробел после фикса таймаута рендера: номера, написанные на сайте простым текстом (не кликабельные 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>
72 lines
3.3 KiB
PHP
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'); // помечен «проверьте»
|
|
});
|