117 lines
4.8 KiB
PHP
117 lines
4.8 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
use App\Services\Autopodbor\Agent\Aggregator\AggregatorClassifier;
|
||
|
|
use App\Services\Autopodbor\Agent\Aggregator\AggregatorFilter;
|
||
|
|
use App\Services\Autopodbor\Agent\Dto\FindCompetitorsRequest;
|
||
|
|
use App\Services\Autopodbor\Agent\FindCompetitorsAssembler;
|
||
|
|
use App\Services\Autopodbor\Agent\LiveFindCompetitors;
|
||
|
|
use App\Services\Autopodbor\Agent\Resolve\TwoGisResolver;
|
||
|
|
use App\Services\Autopodbor\Agent\Resolve\YandexResolver;
|
||
|
|
use App\Services\Autopodbor\Agent\Search\SearchResultsParser;
|
||
|
|
use App\Services\Autopodbor\Agent\Similarity\Embedder;
|
||
|
|
use App\Services\Autopodbor\Agent\Similarity\EmbeddingRelevance;
|
||
|
|
use App\Services\Autopodbor\AutopodborDedup;
|
||
|
|
use App\Services\Autopodbor\AutopodborNormalizer;
|
||
|
|
|
||
|
|
// stubPages()/autopodborFixture() — глобальные хелперы из tests/Pest.php.
|
||
|
|
|
||
|
|
function liveEngine(): LiveFindCompetitors
|
||
|
|
{
|
||
|
|
$nullClassifier = new class implements AggregatorClassifier
|
||
|
|
{
|
||
|
|
public function isAggregator(string $name, ?string $siteUrl, ?string $description): ?bool
|
||
|
|
{
|
||
|
|
return null; // без ИИ — никого не выкидываем
|
||
|
|
}
|
||
|
|
};
|
||
|
|
$zeroEmbedder = new class implements Embedder
|
||
|
|
{
|
||
|
|
public function embed(array $texts): array
|
||
|
|
{
|
||
|
|
return array_map(fn () => [0.0], $texts);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
$assembler = new FindCompetitorsAssembler(
|
||
|
|
new AggregatorFilter($nullClassifier),
|
||
|
|
new AutopodborDedup(new AutopodborNormalizer),
|
||
|
|
new EmbeddingRelevance($zeroEmbedder),
|
||
|
|
);
|
||
|
|
|
||
|
|
return new LiveFindCompetitors(
|
||
|
|
stubPages([
|
||
|
|
// выдача
|
||
|
|
'2gis.ru/krasnoyarsk/search/' => autopodborFixture('2gis-search-kraslombard.html'),
|
||
|
|
'maps/?text=' => autopodborFixture('yandex-search-kraslombard.html'),
|
||
|
|
// карточки
|
||
|
|
'/firm/' => autopodborFixture('2gis-firm-kraslombard.html'),
|
||
|
|
'/maps/org/' => autopodborFixture('yandex-org-kraslombard.html'),
|
||
|
|
]),
|
||
|
|
new SearchResultsParser,
|
||
|
|
new TwoGisResolver,
|
||
|
|
new YandexResolver,
|
||
|
|
$assembler,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
it('живой поиск по нише → настоящий конкурент, склеенный из 2ГИС и Яндекса', function () {
|
||
|
|
$res = liveEngine()->find(new FindCompetitorsRequest(
|
||
|
|
regionCode: 29, // Красноярский край → город Красноярск, слаг krasnoyarsk
|
||
|
|
examples: [],
|
||
|
|
aboutSelf: ['ломбард', 'moy-lombard.ru'], // ниша + ВАШ сайт (другой — себя НЕ вычитаем)
|
||
|
|
includeFederal: true,
|
||
|
|
maxCompetitors: 20,
|
||
|
|
));
|
||
|
|
|
||
|
|
$names = array_column($res->competitors, 'name');
|
||
|
|
expect($names)->toContain('КрасЛомбард'); // найден живым поиском по нише
|
||
|
|
|
||
|
|
$kl = collect($res->competitors)->firstWhere('name', 'КрасЛомбард');
|
||
|
|
expect($kl['site_url'])->toBe('http://kraslombard24.ru');
|
||
|
|
// склейка одной фирмы из 2ГИС + Яндекс: в «где нашли» обе ссылки справочников
|
||
|
|
expect(collect($kl['directory_urls'])->contains(fn (string $u): bool => str_contains($u, '/firm/')))->toBeTrue();
|
||
|
|
expect(collect($kl['directory_urls'])->contains(fn (string $u): bool => str_contains($u, '/maps/org/')))->toBeTrue();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('свой сайт вычитается из конкурентов', function () {
|
||
|
|
$res = liveEngine()->find(new FindCompetitorsRequest(
|
||
|
|
regionCode: 29,
|
||
|
|
examples: [],
|
||
|
|
aboutSelf: ['ломбард', 'kraslombard24.ru'], // теперь КрасЛомбард = это «мы»
|
||
|
|
includeFederal: true,
|
||
|
|
maxCompetitors: 20,
|
||
|
|
));
|
||
|
|
|
||
|
|
expect(array_column($res->competitors, 'name'))->not->toContain('КрасЛомбард');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('пустая выдача → пустой список, без падения', function () {
|
||
|
|
$engine = new LiveFindCompetitors(
|
||
|
|
stubPages([]), // на всё ''
|
||
|
|
new SearchResultsParser,
|
||
|
|
new TwoGisResolver,
|
||
|
|
new YandexResolver,
|
||
|
|
new FindCompetitorsAssembler(
|
||
|
|
new AggregatorFilter(new class implements AggregatorClassifier
|
||
|
|
{
|
||
|
|
public function isAggregator(string $name, ?string $siteUrl, ?string $description): ?bool
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}),
|
||
|
|
new AutopodborDedup(new AutopodborNormalizer),
|
||
|
|
new EmbeddingRelevance(new class implements Embedder
|
||
|
|
{
|
||
|
|
public function embed(array $texts): array
|
||
|
|
{
|
||
|
|
return array_map(fn () => [0.0], $texts);
|
||
|
|
}
|
||
|
|
}),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
$res = $engine->find(new FindCompetitorsRequest(29, [], ['ничего', 'self.ru'], false, 10));
|
||
|
|
expect($res->competitors)->toBe([]);
|
||
|
|
});
|