instances added god may help
This commit is contained in:
53
tests/Service/Scheduler/ScheduleCalculatorTest.php
Normal file
53
tests/Service/Scheduler/ScheduleCalculatorTest.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Tests\Service\Scheduler;
|
||||
|
||||
use MintyPHP\Service\Scheduler\ScheduleCalculator;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ScheduleCalculatorTest extends TestCase
|
||||
{
|
||||
public function testCalculateNextRunUtcDailySameDayWhenTimeIsInFuture(): void
|
||||
{
|
||||
$calculator = new ScheduleCalculator();
|
||||
$job = [
|
||||
'schedule_type' => 'daily',
|
||||
'schedule_interval' => 1,
|
||||
'timezone' => 'UTC',
|
||||
'schedule_time' => '12:00',
|
||||
];
|
||||
$reference = new \DateTimeImmutable('2026-02-22 10:30:00', new \DateTimeZone('UTC'));
|
||||
|
||||
$next = $calculator->calculateNextRunUtc($job, $reference);
|
||||
|
||||
$this->assertInstanceOf(\DateTimeImmutable::class, $next);
|
||||
$this->assertSame('2026-02-22 12:00:00', $next?->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
public function testCalculateNextRunUtcDailyMovesToNextDayWhenTimeAlreadyPassed(): void
|
||||
{
|
||||
$calculator = new ScheduleCalculator();
|
||||
$job = [
|
||||
'schedule_type' => 'daily',
|
||||
'schedule_interval' => 1,
|
||||
'timezone' => 'UTC',
|
||||
'schedule_time' => '08:00',
|
||||
];
|
||||
$reference = new \DateTimeImmutable('2026-02-22 10:30:00', new \DateTimeZone('UTC'));
|
||||
|
||||
$next = $calculator->calculateNextRunUtc($job, $reference);
|
||||
|
||||
$this->assertInstanceOf(\DateTimeImmutable::class, $next);
|
||||
$this->assertSame('2026-02-23 08:00:00', $next?->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
public function testNormalizeWeekdaysCsvRemovesDuplicatesAndInvalidValues(): void
|
||||
{
|
||||
$calculator = new ScheduleCalculator();
|
||||
|
||||
$normalized = $calculator->normalizeWeekdaysCsv(['7', '3', '3', '9', '0', '1']);
|
||||
|
||||
$this->assertSame('1,3,7', $normalized);
|
||||
}
|
||||
}
|
||||
|
||||
126
tests/Service/Scheduler/ScheduledJobServiceTest.php
Normal file
126
tests/Service/Scheduler/ScheduledJobServiceTest.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Tests\Service\Scheduler;
|
||||
|
||||
use MintyPHP\Repository\Scheduler\ScheduledJobRepository;
|
||||
use MintyPHP\Repository\Scheduler\ScheduledJobRunRepository;
|
||||
use MintyPHP\Service\Scheduler\ScheduleCalculator;
|
||||
use MintyPHP\Service\Scheduler\ScheduledJobRegistry;
|
||||
use MintyPHP\Service\Scheduler\ScheduledJobService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ScheduledJobServiceTest extends TestCase
|
||||
{
|
||||
public function testUpdateFromAdminReturnsValidationErrorForWeeklyWithoutWeekdays(): void
|
||||
{
|
||||
$jobRepository = $this->createMock(ScheduledJobRepository::class);
|
||||
$runRepository = $this->createMock(ScheduledJobRunRepository::class);
|
||||
$registry = $this->createMock(ScheduledJobRegistry::class);
|
||||
$calculator = new ScheduleCalculator();
|
||||
|
||||
$registry->expects($this->once())->method('definitions')->willReturn([]);
|
||||
$jobRepository->expects($this->once())->method('find')->with(10)->willReturn([
|
||||
'id' => 10,
|
||||
'job_key' => 'user_lifecycle_run',
|
||||
'label' => 'User lifecycle run',
|
||||
'description' => '',
|
||||
'enabled' => 1,
|
||||
'timezone' => 'UTC',
|
||||
'schedule_type' => 'daily',
|
||||
'schedule_interval' => 1,
|
||||
'schedule_time' => '02:15',
|
||||
'schedule_weekdays_csv' => null,
|
||||
'catchup_once' => 1,
|
||||
]);
|
||||
$registry->expects($this->once())->method('get')->with('user_lifecycle_run')->willReturn([
|
||||
'label' => 'User lifecycle run',
|
||||
'description' => '',
|
||||
'allowed_schedule_types' => ['hourly', 'daily', 'weekly'],
|
||||
]);
|
||||
$jobRepository->expects($this->never())->method('updateJobMeta');
|
||||
|
||||
$service = new ScheduledJobService($jobRepository, $runRepository, $registry, $calculator);
|
||||
$result = $service->updateFromAdmin(10, [
|
||||
'enabled' => '1',
|
||||
'timezone' => 'UTC',
|
||||
'schedule_type' => 'weekly',
|
||||
'schedule_interval' => '1',
|
||||
'schedule_time' => '03:00',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result['ok']);
|
||||
$this->assertNotEmpty($result['errors']);
|
||||
}
|
||||
|
||||
public function testUpdateFromAdminPersistsNormalizedValuesAndReturnsFreshJob(): void
|
||||
{
|
||||
$jobRepository = $this->createMock(ScheduledJobRepository::class);
|
||||
$runRepository = $this->createMock(ScheduledJobRunRepository::class);
|
||||
$registry = $this->createMock(ScheduledJobRegistry::class);
|
||||
$calculator = new ScheduleCalculator();
|
||||
|
||||
$registry->expects($this->exactly(2))->method('definitions')->willReturn([]);
|
||||
$jobRepository->expects($this->exactly(2))->method('find')->with(11)->willReturnOnConsecutiveCalls(
|
||||
[
|
||||
'id' => 11,
|
||||
'job_key' => 'user_lifecycle_run',
|
||||
'label' => 'User lifecycle run',
|
||||
'description' => 'Runs lifecycle',
|
||||
'enabled' => 1,
|
||||
'timezone' => 'UTC',
|
||||
'schedule_type' => 'daily',
|
||||
'schedule_interval' => 1,
|
||||
'schedule_time' => '02:15',
|
||||
'schedule_weekdays_csv' => null,
|
||||
'catchup_once' => 1,
|
||||
],
|
||||
[
|
||||
'id' => 11,
|
||||
'job_key' => 'user_lifecycle_run',
|
||||
'label' => 'User lifecycle run',
|
||||
'description' => 'Runs lifecycle',
|
||||
'enabled' => 0,
|
||||
'timezone' => 'UTC',
|
||||
'schedule_type' => 'daily',
|
||||
'schedule_interval' => 1,
|
||||
'schedule_time' => '04:00',
|
||||
'schedule_weekdays_csv' => null,
|
||||
'catchup_once' => 0,
|
||||
'next_run_at' => null,
|
||||
]
|
||||
);
|
||||
$registry->expects($this->once())->method('get')->with('user_lifecycle_run')->willReturn([
|
||||
'label' => 'User lifecycle run',
|
||||
'description' => 'Runs lifecycle',
|
||||
'allowed_schedule_types' => ['hourly', 'daily', 'weekly'],
|
||||
]);
|
||||
$capturedUpdate = null;
|
||||
$jobRepository->expects($this->once())
|
||||
->method('updateJobMeta')
|
||||
->with(11, $this->anything())
|
||||
->willReturnCallback(function (int $id, array $data) use (&$capturedUpdate): bool {
|
||||
$capturedUpdate = $data;
|
||||
return true;
|
||||
});
|
||||
|
||||
$service = new ScheduledJobService($jobRepository, $runRepository, $registry, $calculator);
|
||||
$result = $service->updateFromAdmin(11, [
|
||||
'timezone' => 'UTC',
|
||||
'schedule_type' => 'daily',
|
||||
'schedule_interval' => '1',
|
||||
'schedule_time' => '04:00',
|
||||
]);
|
||||
|
||||
$this->assertTrue($result['ok']);
|
||||
$this->assertSame(11, (int) (($result['job'] ?? [])['id'] ?? 0));
|
||||
$this->assertSame(0, (int) (($result['job'] ?? [])['enabled'] ?? 1));
|
||||
$this->assertIsArray($capturedUpdate);
|
||||
$this->assertSame(0, (int) ($capturedUpdate['enabled'] ?? -1));
|
||||
$this->assertSame('UTC', (string) ($capturedUpdate['timezone'] ?? ''));
|
||||
$this->assertSame('daily', (string) ($capturedUpdate['schedule_type'] ?? ''));
|
||||
$this->assertSame(1, (int) ($capturedUpdate['schedule_interval'] ?? -1));
|
||||
$this->assertSame('04:00', (string) ($capturedUpdate['schedule_time'] ?? ''));
|
||||
$this->assertSame(0, (int) ($capturedUpdate['catchup_once'] ?? -1));
|
||||
$this->assertNull($capturedUpdate['next_run_at'] ?? null);
|
||||
}
|
||||
}
|
||||
35
tests/Service/Scheduler/SchedulerRunServiceTest.php
Normal file
35
tests/Service/Scheduler/SchedulerRunServiceTest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Tests\Service\Scheduler;
|
||||
|
||||
use MintyPHP\Repository\Scheduler\ScheduledJobRepository;
|
||||
use MintyPHP\Repository\Scheduler\ScheduledJobRunRepository;
|
||||
use MintyPHP\Repository\Scheduler\SchedulerRuntimeRepository;
|
||||
use MintyPHP\Service\Scheduler\ScheduleCalculator;
|
||||
use MintyPHP\Service\Scheduler\ScheduledJobRegistry;
|
||||
use MintyPHP\Service\Scheduler\ScheduledJobService;
|
||||
use MintyPHP\Service\Scheduler\SchedulerRunService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SchedulerRunServiceTest extends TestCase
|
||||
{
|
||||
public function testRunJobNowRejectsInvalidRequest(): void
|
||||
{
|
||||
$scheduledJobService = $this->createMock(ScheduledJobService::class);
|
||||
$scheduledJobService->expects($this->once())->method('ensureSystemJobs');
|
||||
|
||||
$service = new SchedulerRunService(
|
||||
$scheduledJobService,
|
||||
$this->createMock(ScheduledJobRepository::class),
|
||||
$this->createMock(ScheduledJobRunRepository::class),
|
||||
$this->createMock(SchedulerRuntimeRepository::class),
|
||||
$this->createMock(ScheduledJobRegistry::class),
|
||||
new ScheduleCalculator()
|
||||
);
|
||||
|
||||
$result = $service->runJobNow(0, 0);
|
||||
|
||||
$this->assertFalse($result['ok']);
|
||||
$this->assertSame('invalid_request', $result['error']);
|
||||
}
|
||||
}
|
||||
33
tests/Service/Scheduler/SchedulerServicesFactoryTest.php
Normal file
33
tests/Service/Scheduler/SchedulerServicesFactoryTest.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Tests\Service\Scheduler;
|
||||
|
||||
use MintyPHP\Service\Scheduler\ScheduledJobService;
|
||||
use MintyPHP\Service\Scheduler\SchedulerRunService;
|
||||
use MintyPHP\Service\Scheduler\SchedulerServicesFactory;
|
||||
use MintyPHP\Service\User\UserLifecycleService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SchedulerServicesFactoryTest extends TestCase
|
||||
{
|
||||
public function testFactoryReturnsStableInstancesPerFactoryObject(): void
|
||||
{
|
||||
$factory = new SchedulerServicesFactory();
|
||||
|
||||
$scheduledJobServiceA = $factory->createScheduledJobService();
|
||||
$scheduledJobServiceB = $factory->createScheduledJobService();
|
||||
$this->assertInstanceOf(ScheduledJobService::class, $scheduledJobServiceA);
|
||||
$this->assertSame($scheduledJobServiceA, $scheduledJobServiceB);
|
||||
|
||||
$schedulerRunServiceA = $factory->createSchedulerRunService();
|
||||
$schedulerRunServiceB = $factory->createSchedulerRunService();
|
||||
$this->assertInstanceOf(SchedulerRunService::class, $schedulerRunServiceA);
|
||||
$this->assertSame($schedulerRunServiceA, $schedulerRunServiceB);
|
||||
|
||||
$userLifecycleServiceA = $factory->createUserLifecycleService();
|
||||
$userLifecycleServiceB = $factory->createUserLifecycleService();
|
||||
$this->assertInstanceOf(UserLifecycleService::class, $userLifecycleServiceA);
|
||||
$this->assertSame($userLifecycleServiceA, $userLifecycleServiceB);
|
||||
}
|
||||
}
|
||||
|
||||
56
tests/Service/Scheduler/UserLifecycleJobHandlerTest.php
Normal file
56
tests/Service/Scheduler/UserLifecycleJobHandlerTest.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Tests\Service\Scheduler;
|
||||
|
||||
use MintyPHP\Service\Scheduler\Handler\UserLifecycleJobHandler;
|
||||
use MintyPHP\Service\User\UserLifecycleService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class UserLifecycleJobHandlerTest extends TestCase
|
||||
{
|
||||
public function testExecuteReturnsSuccessWithMappedResult(): void
|
||||
{
|
||||
$lifecycleService = $this->createMock(UserLifecycleService::class);
|
||||
$lifecycleService->expects($this->once())
|
||||
->method('run')
|
||||
->with(42)
|
||||
->willReturn([
|
||||
'ok' => true,
|
||||
'run_uuid' => 'run-1',
|
||||
'deactivated_count' => 3,
|
||||
'deleted_count' => 2,
|
||||
'skipped_count' => 1,
|
||||
'duration_ms' => 99,
|
||||
]);
|
||||
|
||||
$handler = new UserLifecycleJobHandler($lifecycleService);
|
||||
$result = $handler->execute(42);
|
||||
|
||||
$this->assertSame('success', $result['status']);
|
||||
$this->assertNull($result['error_code']);
|
||||
$this->assertSame('run-1', $result['result']['run_uuid']);
|
||||
$this->assertSame(3, $result['result']['deactivated_count']);
|
||||
$this->assertSame(2, $result['result']['deleted_count']);
|
||||
$this->assertSame(1, $result['result']['skipped_count']);
|
||||
$this->assertSame(99, $result['result']['duration_ms']);
|
||||
}
|
||||
|
||||
public function testExecuteReturnsSkippedWhenLifecycleLockIsNotAcquired(): void
|
||||
{
|
||||
$lifecycleService = $this->createMock(UserLifecycleService::class);
|
||||
$lifecycleService->expects($this->once())
|
||||
->method('run')
|
||||
->with(null)
|
||||
->willReturn([
|
||||
'ok' => false,
|
||||
'error' => 'lock_not_acquired',
|
||||
]);
|
||||
|
||||
$handler = new UserLifecycleJobHandler($lifecycleService);
|
||||
$result = $handler->execute(null);
|
||||
|
||||
$this->assertSame('skipped', $result['status']);
|
||||
$this->assertSame('lock_not_acquired', $result['error_code']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user