Files
myep-team/tests/Repository/StatisticsEventRepositoryTest.php
T

108 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Repository;
use App\Entity\StatisticsEvent;
use App\Enum\StatisticsDateBasis;
use App\Enum\StatisticsEventName;
use App\Repository\StatisticsEventRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
/**
* Everywhere else in this app a date range means the season an assignment runs in, and
* these events are recorded months before it - an application for the coming winter
* arrives in summer. Picking the wrong basis does not fail, it quietly answers a
* different question from the screen next to it, so the compiled DQL is pinned here.
*/
class StatisticsEventRepositoryTest extends KernelTestCase
{
public function testAPeriodMeansTheSeasonUnlessToldOtherwise(): void
{
$dql = $this->query(dateFrom: new \DateTimeImmutable('2026-07-01'))->getDQL();
$this->assertStringContainsString('destination.dateFrom >= :dateFrom', $dql);
$this->assertStringNotContainsString('event.occurredAt', $dql);
}
/**
* The season is the destination's date range, the convention shared with SeasonPeriodFilter.
*/
public function testTheSeasonIsTheDestinationDateRange(): void
{
$dql = $this->query(
dateFrom: new \DateTimeImmutable('2026-07-01'),
dateTo: new \DateTimeImmutable('2027-06-30'),
)->getDQL();
$this->assertStringContainsString('destination.dateFrom >= :dateFrom', $dql);
$this->assertStringContainsString('destination.dateTo <= :dateTo', $dql);
}
/**
* The dimension columns are plain integers, not relations, so the assignment is only
* reachable through an arbitrary join.
*/
public function testTheSeasonReachesTheAssignmentThroughAnArbitraryJoin(): void
{
$dql = $this->query(dateFrom: new \DateTimeImmutable('2026-07-01'))->getDQL();
$this->assertStringContainsString('assignment.id = event.assignmentId', $dql);
}
public function testOccurrenceAsksWhenTheEventWasRecordedAndJoinsNothing(): void
{
$dql = $this->query(
dateFrom: new \DateTimeImmutable('2026-07-01'),
dateBasis: StatisticsDateBasis::OCCURRENCE,
)->getDQL();
$this->assertStringContainsString('event.occurredAt >= :dateFrom', $dql);
$this->assertStringNotContainsString('JOIN', $dql);
}
/**
* An unfiltered count spans every season there is, so there is nothing to join for.
*/
public function testNoPeriodMeansNoJoinEitherWay(): void
{
$this->assertStringNotContainsString('JOIN', $this->query()->getDQL());
}
public function testTheGroupingColumnStaysWhitelisted(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->query(dimension: 'payload');
}
private function query(
string $dimension = 'hotelCode',
?\DateTimeImmutable $dateFrom = null,
?\DateTimeImmutable $dateTo = null,
StatisticsDateBasis $dateBasis = StatisticsDateBasis::SEASON,
): Query {
return $this->repository()->getCountGroupedByQuery(
StatisticsEventName::APPLICATION_CREATED,
$dimension,
$dateFrom,
$dateTo,
$dateBasis,
);
}
private function repository(): StatisticsEventRepository
{
/** @var EntityManagerInterface $entityManager */
$entityManager = static::getContainer()->get(EntityManagerInterface::class);
/** @var StatisticsEventRepository $repository */
$repository = $entityManager->getRepository(StatisticsEvent::class);
return $repository;
}
}