Files
portal/app/tests/Unit/Autopodbor/ProposalClassifierTest.php
T
Дмитрий 6d48503a0e feat(автоподбор): сверка находок со состоянием клиента — 3 группы предложений + скрытые дубли, мягкое удаление в архив, убран вычет себя
Stage 1: опознавалка фирмы по сайту/карточкам, ProposalClassifier new/actualize/archived/hidden, box=archived, bulk удалить всех ранее удалённых. Backend 249/249, front autopodbor 61/61.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 15:45:11 +03:00

79 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
use App\Services\Autopodbor\AutopodborNormalizer;
use App\Services\Autopodbor\CompetitorIdentity;
use App\Services\Autopodbor\ProposalClassifier;
function classifier(): ProposalClassifier
{
return new ProposalClassifier(new CompetitorIdentity(new AutopodborNormalizer));
}
function grp(array $out, int $findId): array
{
foreach ($out as $row) {
if ($row['find']['id'] === $findId) {
return $row;
}
}
throw new RuntimeException("find $findId not classified");
}
it('новая — ни с чем не пересеклась', function () {
$out = classifier()->classify(
finds: [['id' => 1, 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => []]],
existing: [['id' => 9, 'box' => 'field', 'name' => 'B', 'site_url' => 'b.ru', 'directory_urls' => []]],
);
expect(grp($out, 1)['group'])->toBe('new');
});
it('скрытая — полный дубль активной (те же опознавалки)', function () {
$out = classifier()->classify(
finds: [['id' => 1, 'name' => 'A новое имя', 'site_url' => 'a.ru', 'directory_urls' => []]],
existing: [['id' => 9, 'box' => 'field', 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => []]],
);
expect(grp($out, 1)['group'])->toBe('hidden');
});
it('на актуализацию — совпала карточка, но новый сайт (дельта не пуста)', function () {
$out = classifier()->classify(
finds: [['id' => 1, 'name' => 'A', 'site_url' => 'a-new.ru', 'directory_urls' => ['https://2gis.ru/x/firm/111']]],
existing: [['id' => 9, 'box' => 'field', 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => ['https://2gis.ru/x/firm/111']]],
);
$r = grp($out, 1);
expect($r['group'])->toBe('actualize')
->and($r['matched_id'])->toBe(9)
->and($r['delta_keys'])->toBe(['s:a-new.ru']);
});
it('ранее удалённая — совпала только с архивом', function () {
$out = classifier()->classify(
finds: [['id' => 1, 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => []]],
existing: [['id' => 9, 'box' => 'archived', 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => []]],
);
$r = grp($out, 1);
expect($r['group'])->toBe('archived')->and($r['matched_id'])->toBe(9);
});
it('приоритет активного над архивом', function () {
$out = classifier()->classify(
finds: [['id' => 1, 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => []]],
existing: [
['id' => 8, 'box' => 'archived', 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => []],
['id' => 9, 'box' => 'field', 'name' => 'A', 'site_url' => 'a.ru', 'directory_urls' => []],
],
);
$r = grp($out, 1);
expect($r['group'])->toBe('hidden')->and($r['matched_id'])->toBe(9);
});
it('без опознавалок находка всегда новая', function () {
$out = classifier()->classify(
finds: [['id' => 1, 'name' => 'Безымянный', 'site_url' => null, 'directory_urls' => []]],
existing: [['id' => 9, 'box' => 'field', 'name' => 'Безымянный', 'site_url' => null, 'directory_urls' => []]],
);
expect(grp($out, 1)['group'])->toBe('new');
});