feat: mark import as 'error' in case it fails
This commit is contained in:
parent
15a50e02e4
commit
665a6c5385
2 changed files with 128 additions and 5 deletions
|
|
@ -79,13 +79,20 @@ class ImportController extends AbstractController
|
|||
$em->persist($import);
|
||||
$em->flush();
|
||||
|
||||
$filePath = sprintf('imports/%d/%d.csv', $user->getId(), $import->getId());
|
||||
$defaultStorage->write($filePath, file_get_contents($file->getPathname()));
|
||||
try {
|
||||
$filePath = sprintf('imports/%d/%d.csv', $user->getId(), $import->getId());
|
||||
$defaultStorage->write($filePath, file_get_contents($file->getPathname()));
|
||||
|
||||
$import->setFilePath($filePath);
|
||||
$em->flush();
|
||||
$import->setFilePath($filePath);
|
||||
$em->flush();
|
||||
|
||||
$bus->dispatch(new ProcessImportMessage($import->getId()));
|
||||
$bus->dispatch(new ProcessImportMessage($import->getId()));
|
||||
} catch (\Throwable) {
|
||||
$import->setStatus(Import::STATUS_FAILED);
|
||||
$em->flush();
|
||||
|
||||
return $this->json(['error' => 'An error occurred while starting the import.'], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return $this->json([
|
||||
'id' => $import->getId(),
|
||||
|
|
|
|||
116
tests/Controller/ImportControllerTest.php
Normal file
116
tests/Controller/ImportControllerTest.php
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<?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());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue