Files
portal/app/tests/Feature/Supplier/Channel/FormProjectChannelTest.php
T
Дмитрий 54365015d8 feat(supplier): FormProjectChannel (Tier 2) + DI binding
PHP wrapper над manage-project.js через PlaywrightBridge.
+PlaywrightBridge::run(array): generic Node-скрипт runner (refreshSession
не тронут) — план Step 7.4 предусмотрел расширение bridge.
SupplierProjectChannel::class в DI резолвится в FailoverProjectChannel
(ярус 1 AjaxProjectChannel → ярус 2 FormProjectChannel → ярус 3 queue).

Spec §4.3, §4.4. Task 7 of 12. Channel-тесты 16/16 (Ajax 4 + Failover 7 + Form 5).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:55:08 +03:00

101 lines
3.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
use App\Services\Supplier\Channel\FormProjectChannel;
use App\Services\Supplier\Channel\SupplierProjectChannel;
use App\Services\Supplier\Dto\SupplierProjectDto;
use App\Services\Supplier\PlaywrightBridge;
/*
* FormProjectChannel (Tier 2) — PHP wrapper над manage-project.js.
*
* PlaywrightBridge подменяется stub-ом (extends PlaywrightBridge с пустым
* конструктором — реальный требует ProcessFactory; run() переопределён целиком,
* processFactory не трогается).
*/
function bridgeStub(callable $onRun): PlaywrightBridge
{
return new class($onRun) extends PlaywrightBridge
{
/** @var array<string, mixed>|null */
public ?array $lastArgs = null;
/** @var callable */
private $onRun;
public function __construct(callable $onRun)
{
$this->onRun = $onRun;
}
public function run(array $args): array
{
$this->lastArgs = $args;
return ($this->onRun)($args);
}
};
}
it('FormProjectChannel implements SupplierProjectChannel', function (): void {
app()->instance(PlaywrightBridge::class, bridgeStub(fn () => []));
expect(app(FormProjectChannel::class))->toBeInstanceOf(SupplierProjectChannel::class);
});
it('createProject calls PlaywrightBridge with operation=create and returns external_id', function (): void {
$stub = bridgeStub(fn () => ['external_id' => '12345']);
app()->instance(PlaywrightBridge::class, $stub);
$dto = new SupplierProjectDto(
platform: 'B1', signalType: 'site', uniqueKey: 'foo.com',
limit: 10, workdays: [1, 2], regions: [], regionsReverse: false, status: 'active',
);
$id = app(FormProjectChannel::class)->createProject($dto);
expect($id)->toBe(12345);
expect($stub->lastArgs['operation'])->toBe('create');
expect($stub->lastArgs['script'])->toBe('manage-project.js');
expect($stub->lastArgs['dto']['name'])->toBe('foo.com');
expect($stub->lastArgs['dto']['platforms'])->toBe(['B1']);
});
it('updateProject calls bridge with operation=update and externalId', function (): void {
$stub = bridgeStub(fn () => ['ok' => true]);
app()->instance(PlaywrightBridge::class, $stub);
$dto = new SupplierProjectDto(
platform: 'B1', signalType: 'site', uniqueKey: 'foo.com',
limit: 20, workdays: [1], regions: [], regionsReverse: false, status: 'active',
);
app(FormProjectChannel::class)->updateProject(700123, $dto);
expect($stub->lastArgs['operation'])->toBe('update');
expect($stub->lastArgs['externalId'])->toBe(700123);
});
it('listProjects calls bridge with operation=list and returns array', function (): void {
$stub = bridgeStub(fn () => ['projects' => [['id' => 1, 'name' => 'A']]]);
app()->instance(PlaywrightBridge::class, $stub);
$list = app(FormProjectChannel::class)->listProjects();
expect($list)->toBe([['id' => 1, 'name' => 'A']]);
expect($stub->lastArgs['operation'])->toBe('list');
});
it('createProject throws when bridge returns empty external_id', function (): void {
app()->instance(PlaywrightBridge::class, bridgeStub(fn () => ['external_id' => '0']));
$dto = new SupplierProjectDto(
platform: 'B1', signalType: 'site', uniqueKey: 'foo.com',
limit: 10, workdays: [1], regions: [], regionsReverse: false, status: 'active',
);
expect(fn () => app(FormProjectChannel::class)->createProject($dto))
->toThrow(RuntimeException::class, 'empty external_id');
});