229 lines
7.2 KiB
PHP
229 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Support;
|
|
|
|
use App\Support\DateRange;
|
|
use Illuminate\Support\Carbon;
|
|
use InvalidArgumentException;
|
|
use Tests\TestCase;
|
|
|
|
class DateRangeTest extends TestCase
|
|
{
|
|
public function test_it_exposes_from_and_to(): void
|
|
{
|
|
$from = Carbon::parse('2026-07-01 00:00:00');
|
|
$to = Carbon::parse('2026-07-31 23:59:59');
|
|
|
|
$range = new DateRange($from, $to);
|
|
|
|
$this->assertTrue($from->equalTo($range->from));
|
|
$this->assertTrue($to->equalTo($range->to));
|
|
}
|
|
|
|
public function test_it_rejects_a_to_earlier_than_from(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
new DateRange(
|
|
Carbon::parse('2026-07-31 00:00:00'),
|
|
Carbon::parse('2026-07-01 00:00:00'),
|
|
);
|
|
}
|
|
|
|
public function test_it_allows_a_range_covering_a_single_instant(): void
|
|
{
|
|
$instant = Carbon::parse('2026-07-01 12:00:00');
|
|
|
|
$range = new DateRange($instant, $instant);
|
|
|
|
$this->assertTrue($range->from->equalTo($range->to));
|
|
}
|
|
|
|
public function test_it_builds_today_as_the_current_day(): void
|
|
{
|
|
Carbon::setTestNow('2026-07-15 13:45:00');
|
|
|
|
$range = DateRange::preset('today');
|
|
|
|
$this->assertSame('2026-07-15 00:00:00', $range->from->toDateTimeString());
|
|
$this->assertSame('2026-07-15 23:59:59', $range->to->toDateTimeString());
|
|
}
|
|
|
|
public function test_it_builds_week_month_and_year_presets(): void
|
|
{
|
|
Carbon::setTestNow('2026-07-15 13:45:00');
|
|
|
|
$week = DateRange::preset('week');
|
|
$this->assertTrue($week->from->equalTo(Carbon::parse('2026-07-15')->startOfWeek()));
|
|
$this->assertTrue($week->to->equalTo(Carbon::parse('2026-07-15')->endOfWeek()));
|
|
|
|
$month = DateRange::preset('month');
|
|
$this->assertSame('2026-07-01 00:00:00', $month->from->toDateTimeString());
|
|
$this->assertSame('2026-07-31 23:59:59', $month->to->toDateTimeString());
|
|
|
|
$year = DateRange::preset('year');
|
|
$this->assertSame('2026-01-01 00:00:00', $year->from->toDateTimeString());
|
|
$this->assertSame('2026-12-31 23:59:59', $year->to->toDateTimeString());
|
|
}
|
|
|
|
public function test_it_builds_all_as_a_bounded_range_ending_now(): void
|
|
{
|
|
Carbon::setTestNow('2026-07-15 13:45:00');
|
|
|
|
$range = DateRange::preset('all');
|
|
|
|
$this->assertSame('2026-07-15 23:59:59', $range->to->toDateTimeString());
|
|
$this->assertTrue($range->from->lessThan(Carbon::parse('2000-01-01')));
|
|
}
|
|
|
|
public function test_it_rejects_an_unknown_preset(): void
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
DateRange::preset('fortnight');
|
|
}
|
|
|
|
public function test_it_lists_the_available_presets(): void
|
|
{
|
|
$presets = DateRange::presets();
|
|
|
|
$this->assertSame(
|
|
['today', 'week', 'month', 'year', 'all'],
|
|
array_keys($presets),
|
|
);
|
|
$this->assertSame('Today', $presets['today']);
|
|
$this->assertSame('All Time', $presets['all']);
|
|
}
|
|
|
|
public function test_it_lists_each_day_in_the_range(): void
|
|
{
|
|
$range = new DateRange(
|
|
Carbon::parse('2026-07-01 09:30:00'),
|
|
Carbon::parse('2026-07-04 18:00:00'),
|
|
);
|
|
|
|
$this->assertSame(
|
|
['2026-07-01', '2026-07-02', '2026-07-03', '2026-07-04'],
|
|
$range->days(),
|
|
);
|
|
}
|
|
|
|
public function test_it_lists_a_single_day_for_a_same_day_range(): void
|
|
{
|
|
$range = new DateRange(
|
|
Carbon::parse('2026-07-01 00:00:00'),
|
|
Carbon::parse('2026-07-01 23:59:59'),
|
|
);
|
|
|
|
$this->assertSame(['2026-07-01'], $range->days());
|
|
}
|
|
|
|
public function test_it_lists_days_across_a_month_boundary(): void
|
|
{
|
|
$range = new DateRange(
|
|
Carbon::parse('2026-01-30 00:00:00'),
|
|
Carbon::parse('2026-02-02 23:59:59'),
|
|
);
|
|
|
|
$this->assertSame(
|
|
['2026-01-30', '2026-01-31', '2026-02-01', '2026-02-02'],
|
|
$range->days(),
|
|
);
|
|
}
|
|
|
|
public function test_it_lists_days_across_a_year_boundary(): void
|
|
{
|
|
$range = new DateRange(
|
|
Carbon::parse('2025-12-30 00:00:00'),
|
|
Carbon::parse('2026-01-02 23:59:59'),
|
|
);
|
|
|
|
$this->assertSame(
|
|
['2025-12-30', '2025-12-31', '2026-01-01', '2026-01-02'],
|
|
$range->days(),
|
|
);
|
|
}
|
|
|
|
public function test_it_lists_every_day_of_a_leap_february(): void
|
|
{
|
|
$range = new DateRange(
|
|
Carbon::parse('2028-02-27 00:00:00'),
|
|
Carbon::parse('2028-03-01 23:59:59'),
|
|
);
|
|
|
|
$this->assertSame(
|
|
['2028-02-27', '2028-02-28', '2028-02-29', '2028-03-01'],
|
|
$range->days(),
|
|
);
|
|
}
|
|
|
|
public function test_it_lists_days_up_to_the_maximum_span(): void
|
|
{
|
|
$from = Carbon::parse('2026-01-01 00:00:00');
|
|
$range = new DateRange($from, $from->copy()->addDays(DateRange::MAX_DAYS - 1)->endOfDay());
|
|
|
|
$this->assertCount(DateRange::MAX_DAYS, $range->days());
|
|
}
|
|
|
|
public function test_it_refuses_to_list_days_for_a_range_wider_than_the_maximum(): void
|
|
{
|
|
$from = Carbon::parse('2026-01-01 00:00:00');
|
|
$range = new DateRange($from, $from->copy()->addDays(DateRange::MAX_DAYS)->endOfDay());
|
|
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
$range->days();
|
|
}
|
|
|
|
public function test_it_refuses_to_list_days_for_the_all_preset(): void
|
|
{
|
|
Carbon::setTestNow('2026-07-15 13:45:00');
|
|
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
DateRange::preset('all')->days();
|
|
}
|
|
|
|
public function test_it_is_bucketable_by_day_for_a_normal_range(): void
|
|
{
|
|
$this->assertTrue(DateRange::preset('week')->isBucketableByDay());
|
|
$this->assertTrue(DateRange::preset('month')->isBucketableByDay());
|
|
}
|
|
|
|
public function test_it_is_bucketable_by_day_at_the_maximum_span(): void
|
|
{
|
|
$from = Carbon::parse('2026-01-01 00:00:00');
|
|
$range = new DateRange($from, $from->copy()->addDays(DateRange::MAX_DAYS - 1)->endOfDay());
|
|
|
|
$this->assertTrue($range->isBucketableByDay());
|
|
}
|
|
|
|
public function test_it_is_not_bucketable_by_day_one_day_beyond_the_maximum_span(): void
|
|
{
|
|
$from = Carbon::parse('2026-01-01 00:00:00');
|
|
$range = new DateRange($from, $from->copy()->addDays(DateRange::MAX_DAYS)->endOfDay());
|
|
|
|
$this->assertFalse($range->isBucketableByDay());
|
|
}
|
|
|
|
public function test_it_is_not_bucketable_by_day_for_the_all_preset(): void
|
|
{
|
|
Carbon::setTestNow('2026-07-15 13:45:00');
|
|
|
|
$this->assertFalse(DateRange::preset('all')->isBucketableByDay());
|
|
}
|
|
|
|
public function test_is_bucketable_by_day_agrees_with_days_at_every_boundary(): void
|
|
{
|
|
$from = Carbon::parse('2026-01-01 00:00:00');
|
|
|
|
$withinBounds = new DateRange($from, $from->copy()->addDays(DateRange::MAX_DAYS - 1)->endOfDay());
|
|
$withinBounds->days();
|
|
$this->assertTrue($withinBounds->isBucketableByDay());
|
|
|
|
$beyondBounds = new DateRange($from, $from->copy()->addDays(DateRange::MAX_DAYS)->endOfDay());
|
|
$this->assertFalse($beyondBounds->isBucketableByDay());
|
|
$this->expectException(InvalidArgumentException::class);
|
|
$beyondBounds->days();
|
|
}
|
|
}
|