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

97 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Repository;
use App\Entity\SeasonAssignmentTask;
use App\Repository\SeasonAssignmentTaskRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
/**
* The reminders are only as good as the set of rows they start from, so the conditions are
* compiled and pinned here - the suite has no fixtures.
*
* Note what is deliberately absent: the deadlines. They are a relative offset off the
* assignment's first day, and month arithmetic is not invertible day by day, so they are
* resolved in PHP rather than reproduced in DQL.
*/
class SeasonAssignmentTaskRepositoryTest extends KernelTestCase
{
public function testOpenTasksExcludeDoneOnesAndDeletedRecords(): void
{
$dql = $this->createOpenQueryBuilder()->getQuery()->getDQL();
$this->assertStringContainsString('task.done = :done', $dql);
$this->assertStringContainsString('season_assignment.deletedAt IS NULL', $dql);
$this->assertStringContainsString('teamer.deletedAt IS NULL', $dql);
// the period is the assignment's own, so there is no destination left to join
$this->assertStringNotContainsString('destination', $dql);
}
/**
* An inner join, not a left one: an assignment the office has laid out but not staffed yet
* has nobody to remind and nobody who could be late.
*/
public function testAnUnstaffedAssignmentIsLeftOut(): void
{
$dql = $this->createOpenQueryBuilder()->getQuery()->getDQL();
$this->assertStringContainsString('INNER JOIN season_assignment.teamer teamer', $dql);
$this->assertStringNotContainsString('LEFT JOIN', $dql);
}
public function testTheSeasonWindowIsOptional(): void
{
$unscoped = $this->createOpenQueryBuilder()->getQuery()->getDQL();
$scoped = $this
->createOpenQueryBuilder(new \DateTimeImmutable('2026-11-01'), new \DateTimeImmutable('2027-04-01'))
->getQuery()
->getDQL()
;
$this->assertStringNotContainsString('windowStart', $unscoped);
$this->assertStringContainsString('season_assignment.dateFrom >= :windowStart', $scoped);
$this->assertStringContainsString('season_assignment.dateFrom <= :windowEnd', $scoped);
}
/**
* What the propagate action may still rewrite: an entry that is not ticked off, on an
* assignment that has not ended. A finished entry keeps the document it handed out.
*/
public function testPropagationSkipsTickedEntriesAndEndedAssignments(): void
{
/** @var EntityManagerInterface $entityManager */
$entityManager = static::getContainer()->get(EntityManagerInterface::class);
/** @var SeasonAssignmentTaskRepository $repository */
$repository = $entityManager->getRepository(SeasonAssignmentTask::class);
$dql = $repository
->createOpenForTaskQueryBuilder('contract', new \DateTimeImmutable('2026-11-01'))
->getQuery()
->getDQL()
;
$this->assertStringContainsString('task.taskKey = :taskKey', $dql);
$this->assertStringContainsString('task.done = :done', $dql);
$this->assertStringContainsString('season_assignment.dateTo >= :today', $dql);
$this->assertStringContainsString('season_assignment.deletedAt IS NULL', $dql);
}
private function createOpenQueryBuilder(
?\DateTimeImmutable $windowStart = null,
?\DateTimeImmutable $windowEnd = null,
): QueryBuilder {
/** @var EntityManagerInterface $entityManager */
$entityManager = static::getContainer()->get(EntityManagerInterface::class);
/** @var SeasonAssignmentTaskRepository $repository */
$repository = $entityManager->getRepository(SeasonAssignmentTask::class);
return $repository->createOpenQueryBuilder($windowStart, $windowEnd);
}
}