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(); } }