Files
RecoReco/Test/OccurrenceCalculatorTest.php

104 lines
3.0 KiB
PHP

<?php
/*
* Standalone test for the RecoReco date math -- no Kanboard / PHPUnit harness needed.
* Run with: php Test/OccurrenceCalculatorTest.php
*
* OccurrenceCalculator is pure, so this exercises the highest-risk correctness surface (month
* lengths, leap years, the last-day rule, the drift-free clamp).
*/
require __DIR__.'/../Model/OccurrenceCalculator.php';
use Kanboard\Plugin\RecoReco\Model\OccurrenceCalculator;
date_default_timezone_set('UTC');
$calc = new OccurrenceCalculator();
$failures = 0;
function ts($str)
{
return strtotime($str.' UTC');
}
function check($label, $got, $expected, &$failures)
{
$ok = $got === $expected;
$g = $got === null ? 'null' : date('Y-m-d H:i', $got);
$e = $expected === null ? 'null' : date('Y-m-d H:i', $expected);
echo ($ok ? 'PASS' : 'FAIL').' '.$label.' got='.$g.' expected='.$e."\n";
if (! $ok) {
$failures++;
}
}
// 1. Plain day-of-month: the 15th, every month.
check(
'monthly 15th, next after Jan 20',
$calc->occurrenceFrom(ts('2023-01-15 10:30'), 'monthly_day', false, ts('2023-01-20 00:00'), false),
ts('2023-02-15 10:30'),
$failures
);
// 2. Drift-free clamp: the 30th -> Feb clamps to 28 -> back to 30 in March (NOT 28).
check(
'30th -> Feb (non-leap) clamps to 28',
$calc->occurrenceFrom(ts('2023-01-30 09:00'), 'monthly_day', false, ts('2023-01-30 09:00'), false),
ts('2023-02-28 09:00'),
$failures
);
check(
'30th -> March returns to 30 (no drift)',
$calc->occurrenceFrom(ts('2023-01-30 09:00'), 'monthly_day', false, ts('2023-02-28 09:00'), false),
ts('2023-03-30 09:00'),
$failures
);
// 3. Last-day rule: last day of each month.
check(
'last-day: Jan 31 -> Feb 28 (non-leap)',
$calc->occurrenceFrom(ts('2023-01-31 08:00'), 'monthly_day', true, ts('2023-01-31 08:00'), false),
ts('2023-02-28 08:00'),
$failures
);
check(
'last-day: Feb -> March 31',
$calc->occurrenceFrom(ts('2023-01-31 08:00'), 'monthly_day', true, ts('2023-02-28 08:00'), false),
ts('2023-03-31 08:00'),
$failures
);
// 4. Leap year: last day of Feb 2024 is the 29th.
check(
'last-day: Feb 2024 -> 29th (leap)',
$calc->occurrenceFrom(ts('2024-01-31 08:00'), 'monthly_day', true, ts('2024-02-01 00:00'), false),
ts('2024-02-29 08:00'),
$failures
);
// 5. Inclusive vs exclusive at an exact occurrence.
check(
'inclusive returns the same instant',
$calc->occurrenceFrom(ts('2023-03-10 12:00'), 'monthly_day', false, ts('2023-03-10 12:00'), true),
ts('2023-03-10 12:00'),
$failures
);
check(
'exclusive skips to next month',
$calc->occurrenceFrom(ts('2023-03-10 12:00'), 'monthly_day', false, ts('2023-03-10 12:00'), false),
ts('2023-04-10 12:00'),
$failures
);
// 6. Unsupported frequency (until v1.1) returns null.
check(
'weekly not supported yet -> null',
$calc->occurrenceFrom(ts('2023-03-10 12:00'), 'weekly', false, ts('2023-03-10 12:00'), false),
null,
$failures
);
echo "\n".($failures === 0 ? 'ALL PASSED' : $failures.' FAILURE(S)')."\n";
exit($failures === 0 ? 0 : 1);