Skip to content

Commit

Permalink
Add helpers to allow rewinding/advancing fixed time (#371)
Browse files Browse the repository at this point in the history
* Add helpers to allow rewinding/advancing fixed time

* Update for TickingMockClock
  • Loading branch information
ben-challis authored Dec 22, 2022
1 parent f8ffaaf commit 702a465
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 0 deletions.
10 changes: 10 additions & 0 deletions lib/FixedClock.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ public function changeTimeTo(\DateTimeInterface $time): void
$this->now = \DateTimeImmutable::createFromInterface($time);
}

public function rewindTimeBy(\DateInterval $interval): void
{
$this->now = $this->now->sub($interval);
}

public function advanceTimeBy(\DateInterval $interval): void
{
$this->now = $this->now->add($interval);
}

public function today(): Date
{
return Date::fromDateTime($this->now());
Expand Down
4 changes: 4 additions & 0 deletions lib/MutableClock.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
interface MutableClock extends Clock
{
public function changeTimeTo(\DateTimeInterface $time): void;

public function rewindTimeBy(\DateInterval $interval): void;

public function advanceTimeBy(\DateInterval $interval): void;
}
12 changes: 12 additions & 0 deletions lib/PersistedFixedClock.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ public function changeTimeTo(\DateTimeInterface $time): void
$this->persist();
}

public function rewindTimeBy(\DateInterval $interval): void
{
$this->delegate->rewindTimeBy($interval);
$this->persist();
}

public function advanceTimeBy(\DateInterval $interval): void
{
$this->delegate->advanceTimeBy($interval);
$this->persist();
}

private function load(): void
{
$path = $this->getSerializationFilePath();
Expand Down
10 changes: 10 additions & 0 deletions lib/TickingMockClock.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public function today(): Date
return Date::fromDateTime($this->now());
}

public function rewindTimeBy(\DateInterval $interval): void
{
$this->now = $this->now->sub($interval);
}

public function advanceTimeBy(\DateInterval $interval): void
{
$this->now = $this->now->add($interval);
}

public function tickingFrom(): \DateTimeImmutable
{
return $this->tickingFrom;
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/FixedClockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,40 @@ public function it_can_change_the_time_to_a_new_fixed_value(): void
$this->assertSame('2021-05-05T14:41:49.128311', $clock->nowMutable()->format($timeFormat));
}

/**
* @test
*/
public function it_can_rewind_time(): void
{
$timeString = '2021-05-05T14:11:49.128311';
$timeFormat = 'Y-m-d\TH:i:s.u';
$now = \DateTimeImmutable::createFromFormat($timeFormat, $timeString, new \DateTimeZone('UTC'));
\assert($now instanceof \DateTimeImmutable);
$clock = new FixedClock($now);

$clock->rewindTimeBy(new \DateInterval('PT30M'));

$this->assertSame('2021-05-05T13:41:49.128311', $clock->now()->format($timeFormat));
$this->assertSame('2021-05-05T13:41:49.128311', $clock->nowMutable()->format($timeFormat));
}

/**
* @test
*/
public function it_can_advance_time(): void
{
$timeString = '2021-05-05T14:11:49.128311';
$timeFormat = 'Y-m-d\TH:i:s.u';
$now = \DateTimeImmutable::createFromFormat($timeFormat, $timeString, new \DateTimeZone('UTC'));
\assert($now instanceof \DateTimeImmutable);
$clock = new FixedClock($now);

$clock->advanceTimeBy(new \DateInterval('PT30M'));

$this->assertSame('2021-05-05T14:41:49.128311', $clock->now()->format($timeFormat));
$this->assertSame('2021-05-05T14:41:49.128311', $clock->nowMutable()->format($timeFormat));
}

/**
* @test
*/
Expand Down
54 changes: 54 additions & 0 deletions tests/unit/PersistedFixedClockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,60 @@ public function it_can_change_the_time_to_a_new_fixed_value(): void
$this->assertSame($expectedTimestamp, $clock->nowMutable()->format($timeFormat));
}

/**
* @test
*/
public function it_can_rewind_time(): void
{
$vfs = vfsStream::setup('serialized_time');
$timeString = '2021-05-05T14:11:49.128311';
$timeFormat = 'Y-m-d\TH:i:s.u';
$now = \DateTimeImmutable::createFromFormat($timeFormat, $timeString, new \DateTimeZone('UTC'));
\assert($now instanceof \DateTimeImmutable);
$fileNameGenerator = new FixedFileNameGenerator();
$clock = PersistedFixedClock::initializeWith($vfs->url(), $fileNameGenerator, $now);

$clock->rewindTimeBy(new \DateInterval('PT30M'));

$expectedTimestamp = '2021-05-05T13:41:49.128311';

$this->assertSame($expectedTimestamp, $clock->now()->format($timeFormat));
$this->assertSame($expectedTimestamp, $clock->nowMutable()->format($timeFormat));

// Verify that this value was persisted.
$clock = PersistedFixedClock::fromPersisted($vfs->url(), $fileNameGenerator);

$this->assertSame($expectedTimestamp, $clock->now()->format($timeFormat));
$this->assertSame($expectedTimestamp, $clock->nowMutable()->format($timeFormat));
}

/**
* @test
*/
public function it_can_advance_time(): void
{
$vfs = vfsStream::setup('serialized_time');
$timeString = '2021-05-05T14:11:49.128311';
$timeFormat = 'Y-m-d\TH:i:s.u';
$now = \DateTimeImmutable::createFromFormat($timeFormat, $timeString, new \DateTimeZone('UTC'));
\assert($now instanceof \DateTimeImmutable);
$fileNameGenerator = new FixedFileNameGenerator();
$clock = PersistedFixedClock::initializeWith($vfs->url(), $fileNameGenerator, $now);

$clock->advanceTimeBy(new \DateInterval('PT30M'));

$expectedTimestamp = '2021-05-05T14:41:49.128311';

$this->assertSame($expectedTimestamp, $clock->now()->format($timeFormat));
$this->assertSame($expectedTimestamp, $clock->nowMutable()->format($timeFormat));

// Verify that this value was persisted.
$clock = PersistedFixedClock::fromPersisted($vfs->url(), $fileNameGenerator);

$this->assertSame($expectedTimestamp, $clock->now()->format($timeFormat));
$this->assertSame($expectedTimestamp, $clock->nowMutable()->format($timeFormat));
}

/**
* @return iterable<string, array{string, string}>
*/
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/TickingMockClockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,38 @@ public function it_advances_the_date_once_it_has_been_ticking_for_24_hours(): vo
$this->assertSame(4, $date->month());
$this->assertSame(8, $date->day());
}

/**
* @test
*/
public function it_can_rewind_time(): void
{
$timeString = '2021-05-05T14:11:49.128311';
$timeFormat = 'Y-m-d\TH:i:s.u';
$now = \DateTimeImmutable::createFromFormat($timeFormat, $timeString, new \DateTimeZone('UTC'));
\assert($now instanceof \DateTimeImmutable);
$clock = TickingMockClock::tickingFromCurrentTime($now);

$clock->rewindTimeBy(new \DateInterval('PT30M'));

TickingTimeAssertions::assertDateTimeLessThanOneSecondAfter($now->sub(new \DateInterval('PT30M')), $clock->now());
TickingTimeAssertions::assertDateTimeLessThanOneSecondAfter($now->sub(new \DateInterval('PT30M')), $clock->nowMutable());
}

/**
* @test
*/
public function it_can_advance_time(): void
{
$timeString = '2021-05-05T14:11:49.128311';
$timeFormat = 'Y-m-d\TH:i:s.u';
$now = \DateTimeImmutable::createFromFormat($timeFormat, $timeString, new \DateTimeZone('UTC'));
\assert($now instanceof \DateTimeImmutable);
$clock = TickingMockClock::tickingFromCurrentTime($now);

$clock->advanceTimeBy(new \DateInterval('PT30M'));

TickingTimeAssertions::assertDateTimeLessThanOneSecondAfter($now->add(new \DateInterval('PT30M')), $clock->now());
TickingTimeAssertions::assertDateTimeLessThanOneSecondAfter($now->add(new \DateInterval('PT30M')), $clock->nowMutable());
}
}

0 comments on commit 702a465

Please sign in to comment.