123 lines
4.3 KiB
PHP
123 lines
4.3 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
use App\Services\ClientTg\RobotResult;
|
||
|
|
use App\Services\ClientTg\TelegramRobotRunner;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Обёртка вызова робота (план §Сессия 2, задача 2.2). Робот ЗАМОКАН node-скриптами
|
||
|
|
* из tests/Fixtures/tg-robot, печатающими известный JSON. Проверяем: формирование
|
||
|
|
* task.json, разбор {ok,matched,launched,campaignId}, и что таймаут/мусорный вывод
|
||
|
|
* дают аккуратный ok:false, а не падение воркера.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/** Указывает обёртку на конкретный fixture-скрипт вместо реального робота. */
|
||
|
|
function useRobotFixture(string $script, float $timeout = 30.0): void
|
||
|
|
{
|
||
|
|
config()->set('client_tg.robot', [
|
||
|
|
'node' => 'node',
|
||
|
|
'script' => base_path('tests/fixtures/tg-robot/'.$script),
|
||
|
|
'cwd' => base_path('tests/fixtures/tg-robot'),
|
||
|
|
'timeout' => $timeout,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @return array<string, mixed> */
|
||
|
|
function sampleTaskParams(): array
|
||
|
|
{
|
||
|
|
return [
|
||
|
|
'mode' => 'draft',
|
||
|
|
'phonesFile' => '/tmp/phones-tg-test.txt',
|
||
|
|
'adText' => 'Приходите к нам',
|
||
|
|
'budgetRub' => '1000.00',
|
||
|
|
'buttonUrl' => 'https://example.test',
|
||
|
|
'ordCategory' => 'Размещение рекламы',
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
it('строит task.json со всеми полями задания робота', function () {
|
||
|
|
$runner = app(TelegramRobotRunner::class);
|
||
|
|
|
||
|
|
$payload = $runner->taskPayload(sampleTaskParams());
|
||
|
|
|
||
|
|
expect($payload)->toMatchArray([
|
||
|
|
'mode' => 'draft',
|
||
|
|
'phonesFile' => '/tmp/phones-tg-test.txt',
|
||
|
|
'adText' => 'Приходите к нам',
|
||
|
|
'budgetRub' => '1000.00',
|
||
|
|
'buttonUrl' => 'https://example.test',
|
||
|
|
'ordCategory' => 'Размещение рекламы',
|
||
|
|
]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('подставляет дефолты mode=draft и категорию ОРД', function () {
|
||
|
|
$runner = app(TelegramRobotRunner::class);
|
||
|
|
|
||
|
|
$payload = $runner->taskPayload([
|
||
|
|
'phonesFile' => '/tmp/x.txt',
|
||
|
|
'adText' => 'текст',
|
||
|
|
'budgetRub' => '500.00',
|
||
|
|
'buttonUrl' => 'https://a.test',
|
||
|
|
]);
|
||
|
|
|
||
|
|
expect($payload['mode'])->toBe('draft')
|
||
|
|
->and($payload['ordCategory'])->toBe('Размещение рекламы')
|
||
|
|
->and($payload['mediaFile'])->toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('запускает робота и разбирает успешный JSON', function () {
|
||
|
|
useRobotFixture('print-ok.js');
|
||
|
|
$runner = app(TelegramRobotRunner::class);
|
||
|
|
|
||
|
|
$res = $runner->run(sampleTaskParams());
|
||
|
|
|
||
|
|
expect($res)->toBeInstanceOf(RobotResult::class)
|
||
|
|
->and($res->ok)->toBeTrue()
|
||
|
|
->and($res->matched)->toBe(512)
|
||
|
|
->and($res->launched)->toBeFalse()
|
||
|
|
->and($res->campaignId)->toBe('draft');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('штатный отказ робота (exit 1) → ok:false с причиной, без исключения', function () {
|
||
|
|
useRobotFixture('print-fail.js');
|
||
|
|
$runner = app(TelegramRobotRunner::class);
|
||
|
|
|
||
|
|
$res = $runner->run(sampleTaskParams());
|
||
|
|
|
||
|
|
expect($res->ok)->toBeFalse()
|
||
|
|
->and($res->step)->toBe('upload')
|
||
|
|
->and($res->reason)->toContain('Недостаточно номеров');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('непарсабельный вывод → аккуратный ok:false, воркер не падает', function () {
|
||
|
|
useRobotFixture('print-garbage.js');
|
||
|
|
$runner = app(TelegramRobotRunner::class);
|
||
|
|
|
||
|
|
$res = $runner->run(sampleTaskParams());
|
||
|
|
|
||
|
|
expect($res->ok)->toBeFalse()
|
||
|
|
->and($res->reason)->not->toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('таймаут робота → аккуратный ok:false, воркер не падает', function () {
|
||
|
|
useRobotFixture('sleep.js', timeout: 1.0);
|
||
|
|
$runner = app(TelegramRobotRunner::class);
|
||
|
|
|
||
|
|
$res = $runner->run(sampleTaskParams());
|
||
|
|
|
||
|
|
expect($res->ok)->toBeFalse()
|
||
|
|
->and($res->reason)->not->toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('НЕ оставляет временный task-файл после запуска (чистка)', function () {
|
||
|
|
useRobotFixture('print-ok.js');
|
||
|
|
$runner = app(TelegramRobotRunner::class);
|
||
|
|
|
||
|
|
$before = glob(sys_get_temp_dir().'/tg-task-*.json') ?: [];
|
||
|
|
$runner->run(sampleTaskParams());
|
||
|
|
$after = glob(sys_get_temp_dir().'/tg-task-*.json') ?: [];
|
||
|
|
|
||
|
|
expect(count($after))->toBeLessThanOrEqual(count($before));
|
||
|
|
});
|