Your IP : 216.73.217.117


Current Path : /var/www/v3.cesa.co.za/tests/ContentBundle/Services/
Upload File :
Current File : /var/www/v3.cesa.co.za/tests/ContentBundle/Services/FormManagerCopyDatesTest.php

<?php

namespace App\Tests\ContentBundle\Services;

use App\ContentBundle\Entity\Form;
use App\ContentBundle\Services\FormManager;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class FormManagerCopyDatesTest extends TestCase
{
    private function createManager(ObjectManager $objectManager, bool $expectPersistAndFlush, ?int $persistFlushCount = null): FormManager
    {
        $managerRegistry = $this->createMock(ManagerRegistry::class);
        $managerRegistry->method('getManager')
            ->with('default')
            ->willReturn($objectManager);

        $container = $this->createMock(ContainerInterface::class);
        $container->method('get')
            ->with('doctrine')
            ->willReturn($managerRegistry);

        if ($expectPersistAndFlush) {
            $n = $persistFlushCount ?? 1;
            $objectManager->expects($this->exactly($n))->method('persist');
            $objectManager->expects($this->exactly($n))->method('flush');
        } else {
            $objectManager->expects($this->never())->method('persist');
            $objectManager->expects($this->never())->method('flush');
        }

        $securityContext = $this->createMock(TokenStorageInterface::class);
        $token = $this->createMock(TokenInterface::class);
        $user = $this->createMock(UserInterface::class);
        $user->method('getUserIdentifier')->willReturn('test-creator');
        $token->method('getUser')->willReturn($user);
        $securityContext->method('getToken')->willReturn($token);
        $formFactory = $this->createMock(FormFactoryInterface::class);

        return new FormManager($container, $securityContext, $formFactory);
    }

    public function testCopySetsDatesWhenEndDateIsMissing(): void
    {
        $em = $this->createMock(ObjectManager::class);
        $manager = $this->createManager($em, true);

        $template = new Form();
        $template->setTitle('Template');
        $template->setStartDate(new \DateTime('2025-01-01 10:00:00'));
        $template->setEndDate(null);

        $before = new \DateTime();
        $copied = $manager->copy($template, 'Copied title');
        $after = new \DateTime();

        $this->assertInstanceOf(Form::class, $copied);
        $this->assertInstanceOf(\DateTimeInterface::class, $copied->getStartDate());
        $this->assertInstanceOf(\DateTimeInterface::class, $copied->getEndDate());

        $startTs = $copied->getStartDate()->getTimestamp();
        $this->assertGreaterThanOrEqual($before->getTimestamp(), $startTs);
        $this->assertLessThanOrEqual($after->getTimestamp(), $startTs);

        $expectedEnd = clone $copied->getStartDate();
        $expectedEnd->modify('+2 months');

        $this->assertEquals(
            $expectedEnd->format('Y-m-d H:i:s'),
            $copied->getEndDate()->format('Y-m-d H:i:s')
        );
    }

    public function testCopyDoesNotOverrideDatesWhenBothPresent(): void
    {
        $em = $this->createMock(ObjectManager::class);
        $manager = $this->createManager($em, true);

        $start = new \DateTime('2025-01-01 10:00:00');
        $end = new \DateTime('2025-03-01 10:00:00');

        $template = new Form();
        $template->setTitle('Template');
        $template->setStartDate($start);
        $template->setEndDate($end);

        $copied = $manager->copy($template, 'Copied title');

        $this->assertEquals($start->format('Y-m-d H:i:s'), $copied->getStartDate()->format('Y-m-d H:i:s'));
        $this->assertEquals($end->format('Y-m-d H:i:s'), $copied->getEndDate()->format('Y-m-d H:i:s'));
    }

    public function testCopyOrGetForAssignmentReturnsExistingWithoutPersisting(): void
    {
        $assignmentId = 123;
        $year = (int) (new \DateTime())->format('Y');
        $title = 'REF001 - Assignment Name - '.$year;

        $existingStart = new \DateTime('2025-01-01 10:00:00');
        $existingEnd = new \DateTime('2025-03-01 10:00:00');

        $existing = new Form();
        $existing->setTitle($title);
        $existing->setStartDate($existingStart);
        $existing->setEndDate($existingEnd);

        $repo = $this->createMock(EntityRepository::class);
        $repo->method('findBy')
            ->with(
                array('title' => $title),
                array('title' => 'ASC')
            )
            ->willReturn(array($existing));

        $em = $this->createMock(ObjectManager::class);
        $em->method('getRepository')
            ->with(Form::class)
            ->willReturn($repo);

        $manager = $this->createManager($em, false);

        $template = new Form();
        $template->setTitle('Template');
        $template->setStartDate(new \DateTime('2025-01-01 10:00:00'));

        $result = $manager->copyOrGetForAssignment($template, $title, $assignmentId);

        $this->assertTrue($result['already_copied']);
        $this->assertSame($existing, $result['form']);
    }

    public function testCopyOrGetForAssignmentCreatesNewCopyWhenLegacyFormIsPreviousYear(): void
    {
        $assignmentId = 123;
        $requestedTitle = 'REF001 - Assignment Name';
        $expectedYear = (int) (new \DateTime())->format('Y');
        $expectedTitle = 'REF001 - Assignment Name - '.$expectedYear;

        $legacyExisting = new Form();
        $legacyExisting->setTitle($requestedTitle);
        $legacyExisting->setStartDate(new \DateTime('2025-01-01 10:00:00'));
        $legacyExisting->setEndDate(new \DateTime('2025-03-01 10:00:00'));

        $repo = $this->createMock(EntityRepository::class);
        $repo->method('findBy')
            ->willReturnOnConsecutiveCalls(
                array(), // lookup by year-suffixed title
                array($legacyExisting) // lookup by legacy title
            );

        $em = $this->createMock(ObjectManager::class);
        $em->method('getRepository')
            ->with(Form::class)
            ->willReturn($repo);

        $manager = $this->createManager($em, true, 2);

        $template = new Form();
        $template->setTitle('Template');
        $template->setStartDate(new \DateTime('2026-01-01 10:00:00'));
        $template->setEndDate(new \DateTime('2026-03-01 10:00:00'));

        $result = $manager->copyOrGetForAssignment($template, $requestedTitle, $assignmentId);

        $this->assertFalse($result['already_copied']);
        $this->assertInstanceOf(Form::class, $result['form']);
        $this->assertEquals($expectedTitle, $result['form']->getTitle());
    }
}