feat(project-pause): set/clear paused_at on toggle and bulk pause-resume

This commit is contained in:
Дмитрий
2026-05-26 11:27:53 +03:00
parent 84272c5ccd
commit 69aeac3756
3 changed files with 69 additions and 2 deletions
@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Services\Project;
use App\Http\Controllers\Api\ProjectController;
use App\Services\Project\ProjectService;
use ReflectionMethod;
use Tests\TestCase;
/**
* Гарантирует, что переключение `is_active` всегда сопровождается записью `paused_at`:
* - is_active = false paused_at := NOW()
* - is_active = true paused_at := null
*
* Без этого SupplierSnapshotGuard для bulk-paused проектов начнёт считать их
* "защищёнными навсегда" (paused_at NULL trait), и удаление никогда не разблокируется.
*
* Тест читает исходник методов и проверяет наличие явной записи `paused_at` рядом
* с записью `is_active`. Это структурный smoke поведенческие тесты (через БД)
* пишутся отдельно (Task 14 final regression).
*
* Spec: docs/superpowers/plans/2026-05-26-supplier-snapshot-guard.md (Task 11).
*/
class PausedAtWriteSideTest extends TestCase
{
public function test_project_service_bulk_pause_resume_writes_paused_at(): void
{
$body = $this->methodBody(ProjectService::class, 'bulkPauseResume');
$this->assertStringContainsString('paused_at', $body,
'bulkPauseResume должен явно обновлять paused_at вместе с is_active');
$this->assertStringContainsString('is_active', $body);
}
public function test_project_controller_toggle_active_writes_paused_at(): void
{
$body = $this->methodBody(ProjectController::class, 'toggleActive');
$this->assertStringContainsString('paused_at', $body,
'toggleActive должен явно обновлять paused_at вместе с is_active');
$this->assertStringContainsString('is_active', $body);
}
private function methodBody(string $class, string $method): string
{
$rm = new ReflectionMethod($class, $method);
$lines = file($rm->getFileName());
$body = array_slice($lines, $rm->getStartLine() - 1, $rm->getEndLine() - $rm->getStartLine() + 1);
return implode('', $body);
}
}