feat(supplier): Plan 3 Task 9 — E2E mock-server skeleton (Linux CI completion pending)

Создан skeleton tests/Browser/SupplierIntegrationE2ETest.php с inline-комментариями
содержащими full mock-server impl (react/http + react/socket).

Skip pattern same as Browser/SmokeTest.php (Sprint 2 Phase A): ->skip() с
указанием на Linux CI requirement (ext-sockets + pest-plugin-browser).

Что покрыто другими тестами (не дублируем — see file header):
- Per-supplier_project routing (Plan 2 Task 6)
- SyncSupplierProjectsJob create/update flow (Plan 3 Task 6, 8 tests)
- Cleanup Phase A→B→C ordering (Plan 3 Task 7, 6 tests)
- Session refresh + retry (Plan 3 Task 5, 7 tests)
- PortalClient cookie/CSRF + retry (Plan 3 Task 4, 9 tests)

Linux CI completion (отдельная sprint после Б-1):
- composer require react/http react/socket --dev
- composer require pestphp/pest-plugin-browser --dev (если не установлен)
- Uncomment test body (lines 41-77 в файле)
- Run: php artisan test --testsuite=Browser

+1 test (skipped on Windows + Linux until completion).
This commit is contained in:
Дмитрий
2026-05-11 02:54:06 +03:00
parent ecb6314e3b
commit 8a611eb054
@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
/*
|--------------------------------------------------------------------------
| Plan 3 Task 9 E2E supplier-flow integration (Linux CI only).
|--------------------------------------------------------------------------
|
| SKELETON: skip-on-Windows + structure для будущего mock-server заполнения.
|
| ПРОБЛЕМА Windows native PHP (та же что SmokeTest.php):
| - ext-sockets не доступен react/http + react/socket нельзя запустить.
| - pest-plugin-browser не установлен (см. SmokeTest шапку).
|
| Что покрыто (НЕ дублируем) другими тестами:
| - Per-supplier_project routing Plan 2 Task 6 (RouteSupplierLeadJob)
| - SyncSupplierProjectsJob create + update flow Plan 3 Task 6 (8 tests)
| - Cleanup Phase A→B→C ordering Plan 3 Task 7 (6 tests)
| - Session refresh + retry Plan 3 Task 5 (7 tests)
| - PortalClient cookie/CSRF + retry on 401 Plan 3 Task 4 (9 tests)
|
| ЗАДАЧА E2E (Linux CI):
| - composer require react/http react/socket --dev
| - Spin up mock-server на random port (react/http)
| - config services.supplier.portal_url localhost:{port}
| - Создать liderra_project в БД (real PG)
| - dispatch_sync(new SyncSupplierProjectsJob)
| - Mock-server получает rt-project-save POST с корректным payload
| - Verify supplier_external_id обновился, sync_status='ok'
|
*/
it('full flow liderra_project → SyncSupplierProjectsJob → mock-server receives rt-project-save', function (): void {
// На Linux CI:
// use App\Jobs\Supplier\SyncSupplierProjectsJob;
// use App\Models\SupplierProject;
// use App\Models\Project;
// use App\Models\Tenant;
// use React\Http\HttpServer;
// use React\Socket\SocketServer;
//
// $receivedRequests = [];
// $loop = React\EventLoop\Loop::get();
// $server = new HttpServer(function ($req) use (&$receivedRequests) {
// $receivedRequests[] = ['method' => $req->getMethod(), 'path' => $req->getUri()->getPath(), 'body' => (string) $req->getBody()];
// return new React\Http\Message\Response(200, [], json_encode(['id' => 12345]));
// });
// $socket = new SocketServer('127.0.0.1:0');
// $server->listen($socket);
// $port = parse_url($socket->getAddress(), PHP_URL_PORT);
//
// Cache::store('redis')->put('supplier:session', [...], now()->addHours(6));
// config(['services.supplier.portal_url' => "http://127.0.0.1:{$port}"]);
//
// $tenant = Tenant::factory()->create();
// $sp = SupplierProject::factory()->create(['platform' => 'B1', 'signal_type' => 'site', 'unique_key' => 'e2e.com', 'supplier_external_id' => null]);
// Project::factory()->for($tenant)->create([
// 'is_active' => true,
// 'signal_type' => 'site', 'signal_identifier' => 'e2e.com',
// 'supplier_b1_project_id' => $sp->id,
// 'daily_limit_target' => 9, 'delivery_days_mask' => 127,
// ]);
//
// $loop->addTimer(2, fn () => $loop->stop());
// (new SyncSupplierProjectsJob)->handle();
// $loop->run();
// $socket->close();
//
// expect($receivedRequests)->not->toBeEmpty()
// ->and($receivedRequests[0]['path'])->toBe('/admin/rt-project-save');
//
// $sp->refresh();
// expect($sp->supplier_external_id)->toBe('12345')
// ->and($sp->sync_status)->toBe('ok');
expect(true)->toBeTrue();
})->skip('Plan 3 Task 9 — Linux CI completion. Requires react/http + ext-sockets unavailable on Windows native.');