134 lines
4.6 KiB
PHP
134 lines
4.6 KiB
PHP
<?php
|
|||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
require_once __DIR__ . '/../app/Domain/SLA/SlaAgreement.php';
|
||
|
|
|
||
|
|
use App\Domain\SLA\SlaAgreement;
|
||
|
|
|
||
|
|
function sla_agreement_assert_same(mixed $expected, mixed $actual, string $message): void
|
||
|
|
{
|
||
|
|
if ($expected !== $actual) {
|
||
|
|
throw new RuntimeException($message . "\nExpected: " . var_export($expected, true) . "\nActual: " . var_export($actual, true));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$agreement = new SlaAgreement();
|
||
|
|
|
||
|
|
sla_agreement_assert_same([
|
||
|
|
'client_id' => 42,
|
||
|
|
'enabled' => true,
|
||
|
|
'agreement_type' => 'Premium Support',
|
||
|
|
'allocated_hours' => 12.5,
|
||
|
|
'period_type' => 'annual',
|
||
|
|
'start_date' => '2026-01-01',
|
||
|
|
'end_date' => '2026-12-31',
|
||
|
|
'rollover_enabled' => false,
|
||
|
|
'notes' => 'Priority client',
|
||
|
|
], $agreement->normalize([
|
||
|
|
'client_id' => ' 42 ',
|
||
|
|
'enabled' => 'yes',
|
||
|
|
'agreement_type' => ' Premium Support ',
|
||
|
|
'allocated_hours' => '12.50',
|
||
|
|
'period_type' => ' ANNUAL ',
|
||
|
|
'start_date' => ' 2026-01-01 ',
|
||
|
|
'end_date' => ' 2026-12-31 ',
|
||
|
|
'rollover_enabled' => 'off',
|
||
|
|
'notes' => ' Priority client ',
|
||
|
|
]), 'SLA agreement fields should normalize deterministically.');
|
||
|
|
|
||
|
|
$valid = $agreement->validate([
|
||
|
|
'client_id' => '7',
|
||
|
|
'enabled' => '1',
|
||
|
|
'allocated_hours' => '0',
|
||
|
|
'period_type' => 'monthly',
|
||
|
|
'rollover_enabled' => '0',
|
||
|
|
]);
|
||
|
|
sla_agreement_assert_same(true, $valid['valid'], 'A minimal SLA agreement should be valid.');
|
||
|
|
sla_agreement_assert_same([], $valid['errors'], 'A valid SLA agreement should have no errors.');
|
||
|
|
sla_agreement_assert_same(null, $valid['agreement_type'], 'Optional agreement type should normalize to null.');
|
||
|
|
sla_agreement_assert_same(null, $valid['start_date'], 'Optional start date should normalize to null.');
|
||
|
|
sla_agreement_assert_same(null, $valid['end_date'], 'Optional end date should normalize to null.');
|
||
|
|
sla_agreement_assert_same(null, $valid['notes'], 'Optional notes should normalize to null.');
|
||
|
|
|
||
|
|
$invalid = $agreement->validate([
|
||
|
|
'client_id' => '4.2',
|
||
|
|
'enabled' => 'sometimes',
|
||
|
|
'agreement_type' => str_repeat('A', 121),
|
||
|
|
'allocated_hours' => '-0.01',
|
||
|
|
'period_type' => [],
|
||
|
|
'start_date' => [],
|
||
|
|
'end_date' => [],
|
||
|
|
'rollover_enabled' => [],
|
||
|
|
'notes' => [],
|
||
|
|
]);
|
||
|
|
foreach (['client_id', 'enabled', 'agreement_type', 'allocated_hours', 'period_type', 'start_date', 'end_date', 'rollover_enabled', 'notes'] as $field) {
|
||
|
|
if (!isset($invalid['errors'][$field])) {
|
||
|
|
throw new RuntimeException("Expected validation error for {$field}.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
sla_agreement_assert_same(false, $invalid['valid'], 'Invalid SLA agreement fields should report valid=false.');
|
||
|
|
|
||
|
|
$reversed = $agreement->validate([
|
||
|
|
'client_id' => 7,
|
||
|
|
'allocated_hours' => 10,
|
||
|
|
'start_date' => '2026-12-31',
|
||
|
|
'end_date' => '2026-01-01',
|
||
|
|
]);
|
||
|
|
if (!isset($reversed['errors']['end_date'])) {
|
||
|
|
throw new RuntimeException('An end date before the start date must be rejected.');
|
||
|
|
}
|
||
|
|
|
||
|
|
$badStartOnly = $agreement->validate([
|
||
|
|
'client_id' => 7,
|
||
|
|
'allocated_hours' => 'not-a-number',
|
||
|
|
'start_date' => 'not-a-date',
|
||
|
|
'end_date' => '2026-12-31',
|
||
|
|
]);
|
||
|
|
if (!isset($badStartOnly['errors']['allocated_hours'], $badStartOnly['errors']['start_date'])) {
|
||
|
|
throw new RuntimeException('Non-numeric allocation and malformed dates must be rejected.');
|
||
|
|
}
|
||
|
|
if (isset($badStartOnly['errors']['end_date'])) {
|
||
|
|
throw new RuntimeException('A valid end date must not receive a range error when the start date is malformed.');
|
||
|
|
}
|
||
|
|
|
||
|
|
$equalDates = $agreement->validate([
|
||
|
|
'client_id' => 7,
|
||
|
|
'start_date' => '2026-06-01',
|
||
|
|
'end_date' => '2026-06-01',
|
||
|
|
]);
|
||
|
|
sla_agreement_assert_same(true, $equalDates['valid'], 'Equal start and end dates should be accepted.');
|
||
|
|
|
||
|
|
$display = $agreement->display([
|
||
|
|
'id' => 9,
|
||
|
|
'client_id' => 7,
|
||
|
|
'enabled' => true,
|
||
|
|
'agreement_type' => 'Premium',
|
||
|
|
'allocated_hours' => 12.5,
|
||
|
|
'period_type' => 'monthly',
|
||
|
|
'start_date' => '2026-01-01',
|
||
|
|
'end_date' => '2026-12-31',
|
||
|
|
'rollover_enabled' => false,
|
||
|
|
'notes' => 'Visible note',
|
||
|
|
'password_hash' => 'omit',
|
||
|
|
'credentials' => 'omit',
|
||
|
|
'internal_token' => 'omit',
|
||
|
|
]);
|
||
|
|
sla_agreement_assert_same([
|
||
|
|
'id' => 9,
|
||
|
|
'client_id' => 7,
|
||
|
|
'enabled' => true,
|
||
|
|
'agreement_type' => 'Premium',
|
||
|
|
'allocated_hours' => 12.5,
|
||
|
|
'period_type' => 'monthly',
|
||
|
|
'start_date' => '2026-01-01',
|
||
|
|
'end_date' => '2026-12-31',
|
||
|
|
'rollover_enabled' => false,
|
||
|
|
'notes' => 'Visible note',
|
||
|
|
], $display, 'Display projection must be explicitly allow-listed.');
|
||
|
|
sla_agreement_assert_same($display, $agreement->toDisplay([
|
||
|
|
...$display,
|
||
|
|
'credentials' => 'omit',
|
||
|
|
]), 'toDisplay should provide the same safe projection.');
|
||
|
|
|
||
|
|
printf("SLA agreement tests: 7 passed\n");
|