2026-05-19 11:55:37 +03:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
use App\Services\Supplier\Channel\AjaxProjectChannel;
|
|
|
|
|
use App\Services\Supplier\Channel\SupplierProjectChannel;
|
|
|
|
|
use App\Services\Supplier\Dto\SupplierProjectDto;
|
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* AjaxProjectChannel (Tier 1) — тонкий адаптер над SupplierPortalClient.
|
|
|
|
|
*
|
|
|
|
|
* Контракт rt-project-* верифицирован Task 1 (см. SupplierPortalClientRtProjectTest);
|
|
|
|
|
* здесь проверяем только что адаптер прозрачно делегирует на правильный endpoint.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
beforeEach(function (): void {
|
|
|
|
|
Cache::store('redis')->put('supplier:session', [
|
|
|
|
|
'phpsessid' => 'test', 'csrf' => 'test',
|
|
|
|
|
], now()->addHour());
|
|
|
|
|
config(['services.supplier.portal_url' => 'https://crm.bp-gr.ru']);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('AjaxProjectChannel implements SupplierProjectChannel', function (): void {
|
|
|
|
|
expect(app(AjaxProjectChannel::class))->toBeInstanceOf(SupplierProjectChannel::class);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('createProject delegates to SupplierPortalClient::saveProject and returns external id', function (): void {
|
|
|
|
|
Http::fake([
|
|
|
|
|
'crm.bp-gr.ru/admin/visit/rt-project-save' => Http::response(
|
|
|
|
|
['status' => 'OK', 'message' => '', 'result' => null, 'id' => '700777'],
|
|
|
|
|
200,
|
|
|
|
|
),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$dto = new SupplierProjectDto(
|
|
|
|
|
platform: 'B1',
|
|
|
|
|
signalType: 'site',
|
|
|
|
|
uniqueKey: 'foo.com',
|
|
|
|
|
limit: 5,
|
|
|
|
|
workdays: [1, 2, 3],
|
|
|
|
|
regions: [],
|
|
|
|
|
regionsReverse: false,
|
|
|
|
|
status: 'active',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$id = app(AjaxProjectChannel::class)->createProject($dto);
|
|
|
|
|
|
|
|
|
|
expect($id)->toBe(700777);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('updateProject delegates to SupplierPortalClient::updateProject with id:N', function (): void {
|
|
|
|
|
Http::fake([
|
|
|
|
|
'crm.bp-gr.ru/admin/visit/rt-project-save' => Http::response(
|
|
|
|
|
['status' => 'OK', 'message' => '', 'result' => null, 'id' => '700777'],
|
|
|
|
|
200,
|
|
|
|
|
),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$dto = new SupplierProjectDto(
|
|
|
|
|
platform: 'B1',
|
|
|
|
|
signalType: 'site',
|
|
|
|
|
uniqueKey: 'foo.com',
|
|
|
|
|
limit: 10,
|
|
|
|
|
workdays: [1],
|
|
|
|
|
regions: [],
|
|
|
|
|
regionsReverse: false,
|
|
|
|
|
status: 'active',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
app(AjaxProjectChannel::class)->updateProject(700777, $dto);
|
|
|
|
|
|
|
|
|
|
Http::assertSent(fn ($r) => $r['id'] === 700777);
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-19 13:09:48 +03:00
|
|
|
it('listProjects normalizes raw rt-rows to channel contract (platform/signal_type/unique_key)', function (): void {
|
|
|
|
|
// Сырая форма портала (verified 2026-05-19): конверт {projects:[...]},
|
|
|
|
|
// строка {id, name:"B<n>_<key>", type, content}. Адаптер маппит в контракт.
|
2026-05-19 11:55:37 +03:00
|
|
|
Http::fake([
|
2026-05-19 13:09:48 +03:00
|
|
|
'crm.bp-gr.ru/admin/visit/rt-projects-load*' => Http::response([
|
|
|
|
|
'projects' => [
|
|
|
|
|
['id' => '700001', 'name' => 'B1_okna.ru', 'type' => 'hosts', 'content' => 'okna.ru'],
|
|
|
|
|
['id' => '700002', 'name' => 'B3_79991112233', 'type' => 'calls', 'content' => '79991112233'],
|
|
|
|
|
['id' => '700003', 'name' => 'noPrefix', 'type' => 'sms', 'content' => 'KEYWORD'],
|
|
|
|
|
],
|
|
|
|
|
], 200),
|
2026-05-19 11:55:37 +03:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$list = app(AjaxProjectChannel::class)->listProjects();
|
|
|
|
|
|
2026-05-19 13:09:48 +03:00
|
|
|
expect($list)->toHaveCount(3);
|
|
|
|
|
|
|
|
|
|
expect($list[0]['platform'])->toBe('B1');
|
|
|
|
|
expect($list[0]['signal_type'])->toBe('site');
|
|
|
|
|
expect($list[0]['unique_key'])->toBe('okna.ru');
|
|
|
|
|
expect($list[0]['id'])->toBe('700001'); // сырое поле сохранено
|
|
|
|
|
|
|
|
|
|
expect($list[1]['platform'])->toBe('B3');
|
|
|
|
|
expect($list[1]['signal_type'])->toBe('call');
|
|
|
|
|
expect($list[1]['unique_key'])->toBe('79991112233');
|
|
|
|
|
|
|
|
|
|
// name без B<n>_ префикса → platform null (контракт не ломается)
|
|
|
|
|
expect($list[2]['platform'])->toBeNull();
|
|
|
|
|
expect($list[2]['signal_type'])->toBe('sms');
|
|
|
|
|
expect($list[2]['unique_key'])->toBe('KEYWORD');
|
2026-05-19 11:55:37 +03:00
|
|
|
});
|