Files
portal/app/tests/Unit/Autopodbor/LiveFindCompetitorsTest.php
T
Дмитрий 84e769e454 feat(автоподбор): шаг1 — живой findCompetitors (канал А: ниша → 2ГИС+Яндекс → резолв → сборка)
LiveFindCompetitors: ниша из формы → поиск 2ГИС (по слагу города) + Яндекс (по «ниша город») →
парсер выдачи → резолв каждой карточки напрямую → FindCompetitorsAssembler (фильтр/слияние/
похожесть → DTO §7.2). Добыча за PageFetcher — обход тестируется офлайн на фикстурах.
RegionCity — слаг/имя города центра субъекта (как RegionAreaCode, только уверенные).

Тесты: live 3/3 (склейка 2ГИС+Яндекс одной фирмы, вычет своего сайта, пустая выдача);
модуль Автоподбора unit 99/99; Pint чисто. Провайдер ещё не флипнут — следующий шаг.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:23:29 +03:00

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([]);
});