54365015d8
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>
101 lines
3.5 KiB
PHP
101 lines
3.5 KiB
PHP
<?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');
|
||
});
|