168 lines
5.1 KiB
PHP
168 lines
5.1 KiB
PHP
<?php
|
|
|
|
app_require('routes/moduleWeatherAPIRoute.php');
|
|
|
|
use routes\moduleWeatherAPIRoute;
|
|
|
|
function weather_status_targets_invoke_private(moduleWeatherAPIRoute $route, string $method, array $args = []): mixed
|
|
{
|
|
$reflection = new ReflectionClass($route);
|
|
$target = $reflection->getMethod($method);
|
|
$target->setAccessible(true);
|
|
|
|
return $target->invokeArgs($route, $args);
|
|
}
|
|
|
|
beforeEach(function (): void {
|
|
$_SERVER['REQUEST_URI'] = '/departments/weather';
|
|
});
|
|
|
|
it('evaluates healthy degraded and unhealthy statuses from configured department targets', function (): void {
|
|
$route = new moduleWeatherAPIRoute();
|
|
$targets = [
|
|
'degraded_threshold' => 1.0,
|
|
'healthy_threshold' => 1.3,
|
|
];
|
|
|
|
$healthy = weather_status_targets_invoke_private($route, 'calculateStatus', [13, 10.0, true, $targets]);
|
|
$degraded = weather_status_targets_invoke_private($route, 'calculateStatus', [10, 10.0, true, $targets]);
|
|
$unhealthy = weather_status_targets_invoke_private($route, 'calculateStatus', [9, 10.0, true, $targets]);
|
|
|
|
expect($healthy)->toBe('healthy');
|
|
expect($degraded)->toBe('degraded');
|
|
expect($unhealthy)->toBe('unhealthy');
|
|
});
|
|
|
|
it('returns unknown when configured targets are missing for department status evaluation', function (): void {
|
|
$route = new moduleWeatherAPIRoute();
|
|
|
|
$status = weather_status_targets_invoke_private($route, 'calculateStatus', [10, 10.0, true, null]);
|
|
|
|
expect($status)->toBe('unknown');
|
|
});
|
|
|
|
it('aggregates multi-department slot statuses using worst severity when any department is unhealthy', function (): void {
|
|
$route = new moduleWeatherAPIRoute();
|
|
$slotKey = '2026-03-24 10:00';
|
|
$targets = [
|
|
1 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
2 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
];
|
|
|
|
$worst = weather_status_targets_invoke_private($route, 'calculateAggregatedDepartmentStatus', [
|
|
[1, 2],
|
|
[
|
|
1 => [$slotKey => 14],
|
|
2 => [$slotKey => 8],
|
|
],
|
|
[
|
|
1 => [$slotKey => 10.0],
|
|
2 => [$slotKey => 10.0],
|
|
],
|
|
$slotKey,
|
|
true,
|
|
$targets,
|
|
]);
|
|
expect($worst)->toBe('unhealthy');
|
|
});
|
|
|
|
it('aggregates all-unhealthy multi-department slot statuses as unhealthy', function (): void {
|
|
$route = new moduleWeatherAPIRoute();
|
|
$slotKey = '2026-03-24 10:00';
|
|
$targets = [
|
|
1 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
2 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
];
|
|
|
|
$worst = weather_status_targets_invoke_private($route, 'calculateAggregatedDepartmentStatus', [
|
|
[1, 2],
|
|
[
|
|
1 => [$slotKey => 3],
|
|
2 => [$slotKey => 4],
|
|
],
|
|
[
|
|
1 => [$slotKey => 10.0],
|
|
2 => [$slotKey => 10.0],
|
|
],
|
|
$slotKey,
|
|
true,
|
|
$targets,
|
|
]);
|
|
|
|
expect($worst)->toBe('unhealthy');
|
|
});
|
|
|
|
it('returns unknown when aggregated multi-department slot targets are missing', function (): void {
|
|
$route = new moduleWeatherAPIRoute();
|
|
$slotKey = '2026-03-24 10:00';
|
|
|
|
$missingTargets = weather_status_targets_invoke_private($route, 'calculateAggregatedDepartmentStatus', [
|
|
[1, 2],
|
|
[
|
|
1 => [$slotKey => 14],
|
|
2 => [$slotKey => 8],
|
|
],
|
|
[
|
|
1 => [$slotKey => 10.0],
|
|
2 => [$slotKey => 10.0],
|
|
],
|
|
$slotKey,
|
|
true,
|
|
[
|
|
1 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
],
|
|
]);
|
|
expect($missingTargets)->toBe('unknown');
|
|
});
|
|
|
|
it('returns unknown when aggregated multi-department slot has no evaluable hours', function (): void {
|
|
$route = new moduleWeatherAPIRoute();
|
|
$slotKey = '2026-03-24 10:00';
|
|
$targets = [
|
|
1 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
2 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
];
|
|
|
|
$noEvaluableHours = weather_status_targets_invoke_private($route, 'calculateAggregatedDepartmentStatus', [
|
|
[1, 2],
|
|
[
|
|
1 => [$slotKey => 0],
|
|
2 => [$slotKey => 0],
|
|
],
|
|
[
|
|
1 => [$slotKey => 0.0],
|
|
2 => [$slotKey => 0.0],
|
|
],
|
|
$slotKey,
|
|
true,
|
|
$targets,
|
|
]);
|
|
expect($noEvaluableHours)->toBe('unknown');
|
|
});
|
|
|
|
it('returns unknown when aggregated multi-department slot has not started yet', function (): void {
|
|
$route = new moduleWeatherAPIRoute();
|
|
$slotKey = '2026-03-24 10:00';
|
|
$targets = [
|
|
1 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
2 => ['degraded_threshold' => 1.0, 'healthy_threshold' => 1.3],
|
|
];
|
|
|
|
$futureSlot = weather_status_targets_invoke_private($route, 'calculateAggregatedDepartmentStatus', [
|
|
[1, 2],
|
|
[
|
|
1 => [$slotKey => 14],
|
|
2 => [$slotKey => 8],
|
|
],
|
|
[
|
|
1 => [$slotKey => 10.0],
|
|
2 => [$slotKey => 10.0],
|
|
],
|
|
$slotKey,
|
|
false,
|
|
$targets,
|
|
]);
|
|
|
|
expect($futureSlot)->toBe('unknown');
|
|
});
|