ltbxd-actorle/tests/Controller/ImportControllerTest.php

116 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Controller;
use App\Controller\ImportController;
use App\Entity\Import;
use App\Entity\User;
use App\Repository\ImportRepository;
use Doctrine\ORM\EntityManagerInterface;
use League\Flysystem\FilesystemOperator;
use PHPUnit\Framework\MockObject\Stub;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class ImportControllerTest extends TestCase
{
private ImportController $controller;
private FilesystemOperator&Stub $storage;
private EntityManagerInterface&Stub $em;
private ImportRepository&Stub $importRepository;
private MessageBusInterface&Stub $bus;
private User $user;
protected function setUp(): void
{
$this->storage = $this->createStub(FilesystemOperator::class);
$this->em = $this->createStub(EntityManagerInterface::class);
$this->importRepository = $this->createStub(ImportRepository::class);
$this->bus = $this->createStub(MessageBusInterface::class);
$this->user = new User();
$idProp = new \ReflectionProperty(User::class, 'id');
$idProp->setValue($this->user, 1);
$token = $this->createStub(TokenInterface::class);
$token->method('getUser')->willReturn($this->user);
$tokenStorage = $this->createStub(TokenStorageInterface::class);
$tokenStorage->method('getToken')->willReturn($token);
$container = $this->createStub(ContainerInterface::class);
$container->method('has')->willReturnCallback(static fn(string $id): bool => match ($id) {
'security.token_storage' => true,
'serializer' => false,
default => false,
});
$container->method('get')->willReturnCallback(static fn(string $id) => match ($id) {
'security.token_storage' => $tokenStorage,
default => null,
});
$this->controller = new ImportController();
$this->controller->setContainer($container);
}
private function createRequest(): Request
{
$tmpFile = tempnam(sys_get_temp_dir(), 'import_test_');
file_put_contents($tmpFile, "Date,Name,Year,Letterboxd URI,Rating\n2024-01-01,Inception,2010,https://letterboxd.com/film/inception/,5");
$uploadedFile = new UploadedFile($tmpFile, 'films.csv', 'text/csv', null, true);
return Request::create('/api/imports', 'POST', files: ['file' => $uploadedFile]);
}
private function configureEmWithImportCapture(?Import &$capturedImport): void
{
$this->em->method('persist')->willReturnCallback(function (object $entity) use (&$capturedImport): void {
if ($entity instanceof Import) {
$capturedImport = $entity;
$idProp = new \ReflectionProperty(Import::class, 'id');
$idProp->setValue($entity, 42);
}
});
}
public function testSetsImportStatusToFailedWhenStorageWriteThrows(): void
{
$this->importRepository->method('hasActiveImport')->willReturn(false);
$capturedImport = null;
$this->configureEmWithImportCapture($capturedImport);
$this->storage->method('write')->willThrowException(new \RuntimeException('Storage unavailable'));
$bus = $this->createMock(MessageBusInterface::class);
$bus->expects($this->never())->method('dispatch');
$response = $this->controller->create($this->createRequest(), $this->storage, $this->em, $this->importRepository, $bus);
$this->assertSame(Import::STATUS_FAILED, $capturedImport->getStatus());
$this->assertSame(500, $response->getStatusCode());
}
public function testSetsImportStatusToFailedWhenBusDispatchThrows(): void
{
$this->importRepository->method('hasActiveImport')->willReturn(false);
$capturedImport = null;
$this->configureEmWithImportCapture($capturedImport);
$this->storage->method('write')->willReturnCallback(static fn() => null);
$this->bus->method('dispatch')->willThrowException(new \RuntimeException('Bus unavailable'));
$response = $this->controller->create($this->createRequest(), $this->storage, $this->em, $this->importRepository, $this->bus);
$this->assertSame(Import::STATUS_FAILED, $capturedImport->getStatus());
$this->assertSame(500, $response->getStatusCode());
}
}