new FetchedSite( url: 'https://k.ru', rawHtml: 'x8(391)111-22-33', visiblePhones: ['8(391)111-22-33'], ), ], cards: [ 'https://2gis.ru/firm/1' => [ new DirectoryCard(number: '8(391)292-00-00', office: 'Единая справочная', url: 'https://2gis.ru/firm/1', source: '2ГИС'), ], ], ); $agent = new RealCompetitorAgent($fetcher, new FakeCompetitorAgent); $res = $agent->studyCompetitor(new StudyCompetitorRequest( competitor: ['name' => 'КрасЛомбард', 'site_url' => 'k.ru', 'directory_urls' => ['https://2gis.ru/firm/1']], regionCode: 391, )); $calls = array_values(array_filter($res->sources, fn ($s) => $s['signal_type'] === 'call')); $sites = array_values(array_filter($res->sources, fn ($s) => $s['signal_type'] === 'site')); // настоящий 292-00-00 (код+2ГИС = 2 подтверждения) выше подменного 111-22-33 expect($calls[0]['identifier'])->toBe('73912920000'); expect($calls[0]['phone_kind'])->toBe('real'); expect(end($calls)['phone_kind'])->toBe('substitute'); // сайт конкурента — отдельной строкой expect(collect($sites)->pluck('identifier'))->toContain('k.ru'); }); it('телефонная строка несёт список «где нашли», офис и число подтверждений', function () { $fetcher = new FakeFetcher( sites: ['https://k.ru' => new FetchedSite(url: 'https://k.ru', rawHtml: 'x')], cards: [ 'https://2gis.ru/firm/1' => [new DirectoryCard(number: '8(391)292-00-00', office: 'Единая справочная', url: 'https://2gis.ru/firm/1', source: '2ГИС')], ], ); $agent = new RealCompetitorAgent($fetcher, new FakeCompetitorAgent); $res = $agent->studyCompetitor(new StudyCompetitorRequest( competitor: ['name' => 'КрасЛомбард', 'site_url' => 'k.ru', 'directory_urls' => ['https://2gis.ru/firm/1']], regionCode: 391, )); $top = array_values(array_filter($res->sources, fn ($s) => $s['signal_type'] === 'call'))[0]; // 292-00-00 найден в коде сайта и в 2ГИС → 2 подтверждения, 2 места «где нашли» expect($top['confirmations'])->toBe(2); expect($top['where_found'])->toHaveCount(2); expect(collect($top['where_found'])->pluck('label'))->toContain('в коде сайта'); expect(collect($top['where_found'])->pluck('label'))->toContain('2ГИС'); expect($top['office'])->toBe('Единая справочная'); // адрес/ссылка 2ГИС в списке кликабельны expect(collect($top['where_found'])->pluck('url'))->toContain('https://2gis.ru/firm/1'); }); it('по региону достраивает короткий номер, если на странице нет полных', function () { // На странице только короткий локальный номер в tel:, полных номеров нет — // код города берём по региону конкурента (Красноярский край → 391). $fetcher = new FakeFetcher( sites: ['https://k.ru' => new FetchedSite(url: 'https://k.ru', rawHtml: 'Позвонить')], cards: [], ); $agent = new RealCompetitorAgent($fetcher, new FakeCompetitorAgent); $res = $agent->studyCompetitor(new StudyCompetitorRequest( competitor: ['name' => 'КрасЛомбард', 'site_url' => 'k.ru', 'directory_urls' => []], regionCode: RussianRegions::nameToCode()['Красноярский край'], )); $calls = array_values(array_filter($res->sources, fn ($s) => $s['signal_type'] === 'call')); expect(collect($calls)->pluck('identifier'))->toContain('73912920000'); }); it('строка-сайт тоже несёт where_found и одно подтверждение', function () { $fetcher = new FakeFetcher( sites: ['https://k.ru' => new FetchedSite(url: 'https://k.ru', rawHtml: 'x')], cards: [], ); $agent = new RealCompetitorAgent($fetcher, new FakeCompetitorAgent); $res = $agent->studyCompetitor(new StudyCompetitorRequest( competitor: ['name' => 'КрасЛомбард', 'site_url' => 'k.ru', 'directory_urls' => []], regionCode: 391, )); $site = array_values(array_filter($res->sources, fn ($s) => $s['signal_type'] === 'site'))[0]; expect($site['confirmations'])->toBe(1); expect($site['where_found'])->toHaveCount(1); expect($site['where_found'][0]['url'])->toBe('https://k.ru'); }); it('сводит филиалы из разных справочников: больше подтверждений — выше', function () { $fetcher = new FakeFetcher( sites: ['https://k.ru' => new FetchedSite(url: 'https://k.ru', rawHtml: 'x')], cards: [ 'https://2gis.ru/firm/1' => [new DirectoryCard(number: '8(391)292-00-00', office: 'Справочная', url: 'https://2gis.ru/firm/1', source: '2ГИС')], 'https://yandex.ru/maps/2' => [new DirectoryCard(number: '8(391)281-70-70', office: 'Кр. рабочий, 61', url: 'https://yandex.ru/maps/2', source: 'Яндекс.Карты')], ], ); $agent = new RealCompetitorAgent($fetcher, new FakeCompetitorAgent); $res = $agent->studyCompetitor(new StudyCompetitorRequest( competitor: ['name' => 'КрасЛомбард', 'site_url' => 'k.ru', 'directory_urls' => ['https://2gis.ru/firm/1', 'https://yandex.ru/maps/2']], regionCode: 391, )); $calls = array_values(array_filter($res->sources, fn ($s) => $s['signal_type'] === 'call')); // 292-00-00: код + 2ГИС = 2 подтверждения → выше, чем 281-70-70 (только Яндекс = 1) expect($calls[0]['identifier'])->toBe('73912920000'); expect(collect($calls)->pluck('identifier'))->toContain('73912817070'); });