Enhance date parsing in DatesHelper to correctly handle RFC3339 format. Add tests for fallback scenarios with DateTimeImmutable.
108 lines
4.1 KiB
PHP
108 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Integration\Shared\Helpers;
|
|
|
|
use Carbon\CarbonImmutable;
|
|
use Shared\Helpers\DatesHelper;
|
|
|
|
covers(DatesHelper::class);
|
|
|
|
afterEach(function (): void {
|
|
CarbonImmutable::setTestNow();
|
|
});
|
|
|
|
describe('Date Helper Integration Tests', function (): void {
|
|
it('prevents direct instantiation but covers constructor', function (): void {
|
|
// GIVEN
|
|
$reflection = new \ReflectionClass(DatesHelper::class);
|
|
|
|
// WHEN
|
|
$constructor = $reflection->getConstructor();
|
|
$constructor->invoke($reflection->newInstanceWithoutConstructor());
|
|
|
|
// THEN
|
|
expect(fn () => $reflection->newInstance())
|
|
->toThrow(\ReflectionException::class);
|
|
});
|
|
|
|
it('can parse various date formats', function (string $input, string $expectedFormat): void {
|
|
// GIVEN & WHEN
|
|
$result = DatesHelper::parseDateTime($input);
|
|
|
|
// THEN
|
|
expect($result)->toBeInstanceOf(\DateTimeInterface::class)
|
|
->and($result->format('Y-m-d'))->toBe($expectedFormat);
|
|
})->with([
|
|
['2025-12-25 12:10:23', '2025-12-25'],
|
|
['2025-12-25', '2025-12-25'],
|
|
['25-12-2025', '2025-12-25'],
|
|
['2025-12-25T12:10:23Z', '2025-12-25'],
|
|
['2025-12-25T12:10:23+02:00', '2025-12-25'],
|
|
['2025-12-25T12:10:23.123456+02:00', '2025-12-25'],
|
|
['2025/12/25', '2025-12-25'],
|
|
]);
|
|
|
|
it('throws InvalidArgumentException for unparseable date strings', function (): void {
|
|
// GIVEN
|
|
$invalidDate = 'not-a-real-date-string';
|
|
|
|
// WHEN & THEN
|
|
expect(fn () => DatesHelper::parseDateTime($invalidDate))
|
|
->toThrow(\InvalidArgumentException::class, 'Unrecognized date/time format: not-a-real-date-string');
|
|
});
|
|
|
|
it('falls back to DateTimeImmutable for valid formats not fully handled by createFromFormat', function (): void {
|
|
// GIVEN
|
|
$fallbackDate = '2025-12-25T12:10:23.1234567Z'; // 7 digit microsecond matches regex but fails createFromFormat 'u' (6 digits)
|
|
|
|
// WHEN
|
|
$result = DatesHelper::parseDateTime($fallbackDate);
|
|
|
|
// THEN
|
|
expect($result)->toBeInstanceOf(\DateTimeInterface::class)
|
|
->and($result->format('Y-m-d'))->toBe('2025-12-25');
|
|
});
|
|
|
|
it('throws InvalidArgumentException in parseFallback when fallback date is completely invalid logically', function (): void {
|
|
// GIVEN
|
|
$invalidFallbackDate = '2025-12-25T25:10:23.1234567Z'; // Invalid hour 25, matches regex but fails both createFromFormat and new DateTimeImmutable
|
|
|
|
// WHEN & THEN
|
|
expect(fn () => DatesHelper::parseDateTime($invalidFallbackDate))
|
|
->toThrow(\InvalidArgumentException::class, "Unrecognized date/time format: {$invalidFallbackDate}");
|
|
});
|
|
|
|
it('handles isIn date boundary checks correctly', function (): void {
|
|
// GIVEN
|
|
$now = CarbonImmutable::create(2025, 6, 15, 12, 0, 0);
|
|
CarbonImmutable::setTestNow($now);
|
|
|
|
$past = CarbonImmutable::create(2025, 1, 1);
|
|
$future = CarbonImmutable::create(2025, 12, 31);
|
|
$farFuture = CarbonImmutable::create(2025, 12, 30);
|
|
|
|
// WHEN & THEN
|
|
expect(DatesHelper::isIn($past, $future))->toBeTrue()
|
|
->and(DatesHelper::isIn($farFuture, $future))->toBeFalse()
|
|
->and(DatesHelper::isIn($past, null))->toBeTrue()
|
|
->and(DatesHelper::isIn($future, null))->toBeFalse()
|
|
->and(DatesHelper::isIn(null, $future))->toBeTrue()
|
|
->and(DatesHelper::isIn(null, $past))->toBeFalse()
|
|
->and(DatesHelper::isIn(null, null))->toBeFalse();
|
|
});
|
|
|
|
it('formats string or DateTimeInterface to RFC3339', function (): void {
|
|
// GIVEN
|
|
$dateTimeObj = new \DateTimeImmutable('2025-12-25 12:10:23');
|
|
|
|
// WHEN
|
|
$resultFromObj = DatesHelper::toRfc3339($dateTimeObj);
|
|
$resultFromStr = DatesHelper::toRfc3339('2025-12-25 12:10:23');
|
|
|
|
// THEN
|
|
expect($resultFromObj)->toContain('2025-12-25T12:10:23')
|
|
->and($resultFromStr)->toContain('2025-12-25T12:10:23');
|
|
});
|
|
});
|