fchris82 / time-traveller-bundle
Helps to handle 'now' in tests.
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: >=7.4
- symfony/config: ^4.0|^5.0|^6.0
- symfony/dependency-injection: ^4.0|^5.0|^6.0
- symfony/http-kernel: ^4.0|^5.0|^6.0
- symfony/yaml: ^4.0|^5.0|^6.0
Requires (Dev)
- phpunit/phpunit: 9.5.x-dev
This package is auto-updated.
Last update: 2025-01-06 18:09:16 UTC
README
It helps you in writing tests for project which has time dependencies. You can control what now
means.
// Original way: $entity->setCreatedAt(new \DateTime()); // New way with the TimeManager: $entity->setCreatedAt($timeManager->getNow());
Limitations
- The
CURRENT_TIMESTAMP()
in Doctrine or the PDONOW()
functions will get back the "right" dates and times. You have to avoid these "outside" functions.- Some (third party) listeners (eg: TimestampableListener) use the original
new DateTime()
method. You have to pay attention to this, and you have to override, or fix in the background with your own listener.
Install
Install the bundle
Install bundle with composer:
$ composer require fchris82/time-traveller-bundle
Edit the config/bundles.php
file:
<?php return [ // ... Fchris82\TimeTravellerBundle\TimeTravellerBundle::class => ['all' => true], ];
Create config file:
$ echo "time_traveller:" > config/packages/time_traveller.yaml $ echo " time_passing: false" >> config/packages/time_traveller.yaml
Change configuration if you need in the config/packages/time_traveller.yaml
file.
About 'time passing behaviour'
When you start shifting the
now
AND you have longer processes - because of high load eg - you would need the time passing in tests. Iftime_passing
istrue
, it means, time will be passing. If you setnow
to:2010-01-01T00:00:00
and you ask fornow
withgetNow()
5 seconds later, you will get back:2010-01-01T00:00:05
.If it is
false
AND you shifted the time, you will get back always the same time:2010-01-01T00:00:00
, it does not matter how much time has passed.This config value has no any effects:
- if you do not have longer running processes
- if you have not set/shifted the time with
setNow()
yet
false
needs less resources.
Replace date creating everywhere you need
You installed it, you configured it, now it's time to use it.
- Add
Fchris82\TimeTravellerBundle\Manager\TimeManager
service to every service, command, controller where you usenow
- Replace
new DateTime()
to$this->timeManager->getNow()
- Replace
new DateTime('+1 day')
or similar to$this->timeManager->getNow()->modify('+1 day')'
- Refactor your PHPUnit tests. In your integration tests you can retrieve the
TimeManager
service, see: https://symfony.com/doc/current/testing.html#retrieving-services-in-the-test - Refactor your Behat tests
Usage
Getting 'now'
There are 2 getters:
getNow()
gets back a\DateTime
objectgetSqlNow()
gets back an SQL compatible date string
"Travelling" in/shifting the time
setNow()
helps you setting an accurate appointmentmodify()
is the same to\DateTime::modify()
method. It depends on what was set in thesetNow()
.shiftForward()
andshiftBackward()
need a\DateInterval
object, and it will add or sub the datetime that was set with thesetNow()
Eg:
// Without calling `setNow()` $real = $timeManager->getNow(); // Init $timeManager->setNow(new DateTime('2010-01-01 00:00:00')); $now = $timeManager->getNow(); // '2010-01-01 00:00:00' // Change ! $timeManager->setNow(new DateTime('2010-01-02 00:00:00')); $now = $timeManager->getNow(); // '2010-01-02 00:00:00' // ^ // Modify: adding 3 days to '2010-01-02 00:00:00' $timeManager->modify('+3 day'); $now = $timeManager->getNow(); // '2010-01-05 00:00:00' // ^ // Shift: Adding 2 hours to '2010-01-05 00:00:00' $timeManager->shiftForward(new \DateInterval('PT2H')); $now = $timeManager->getNow(); // '2010-01-05 02:00:00' // ^ // You can play with the timezone as well: $timeManager->setNow(new \DateTime('now', new \DateTimeZone('Europa/Budapest'))); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^