Lorsqu'un super-admin crée un établissement via l'interface, le système doit automatiquement créer la base tenant, exécuter les migrations, créer le premier utilisateur admin et envoyer l'invitation — le tout de manière asynchrone pour ne pas bloquer la réponse HTTP. Ce mécanisme rend chaque établissement opérationnel dès sa création sans intervention manuelle sur l'infrastructure.
139 lines
4.6 KiB
PHP
139 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Unit\Scolarite\Application\Command\UploadSubmissionAttachment;
|
|
|
|
use App\Administration\Domain\Model\User\UserId;
|
|
use App\Scolarite\Application\Command\UploadSubmissionAttachment\UploadSubmissionAttachmentCommand;
|
|
use App\Scolarite\Application\Command\UploadSubmissionAttachment\UploadSubmissionAttachmentHandler;
|
|
use App\Scolarite\Application\Port\FileStorage;
|
|
use App\Scolarite\Domain\Exception\RenduDejaSoumisException;
|
|
use App\Scolarite\Domain\Model\Homework\HomeworkId;
|
|
use App\Scolarite\Domain\Model\HomeworkSubmission\HomeworkSubmission;
|
|
use App\Scolarite\Infrastructure\Persistence\InMemory\InMemoryHomeworkSubmissionRepository;
|
|
use App\Shared\Domain\Clock;
|
|
use App\Shared\Domain\Tenant\TenantId;
|
|
use DateTimeImmutable;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class UploadSubmissionAttachmentHandlerTest extends TestCase
|
|
{
|
|
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
|
|
private const string HOMEWORK_ID = '550e8400-e29b-41d4-a716-446655440050';
|
|
private const string STUDENT_ID = '550e8400-e29b-41d4-a716-446655440060';
|
|
|
|
private InMemoryHomeworkSubmissionRepository $submissionRepository;
|
|
private string $tempFile;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->submissionRepository = new InMemoryHomeworkSubmissionRepository();
|
|
$this->tempFile = tempnam(sys_get_temp_dir(), 'e2e_upload_');
|
|
file_put_contents($this->tempFile, 'fake PDF content');
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
if (file_exists($this->tempFile)) {
|
|
unlink($this->tempFile);
|
|
}
|
|
}
|
|
|
|
#[Test]
|
|
public function itUploadsAttachmentForDraftSubmission(): void
|
|
{
|
|
$submission = $this->createDraftSubmission();
|
|
$this->submissionRepository->save($submission);
|
|
|
|
$handler = $this->createHandler();
|
|
$command = new UploadSubmissionAttachmentCommand(
|
|
tenantId: self::TENANT_ID,
|
|
submissionId: (string) $submission->id,
|
|
filename: 'devoir.pdf',
|
|
mimeType: 'application/pdf',
|
|
fileSize: 1024,
|
|
tempFilePath: $this->tempFile,
|
|
);
|
|
|
|
$attachment = $handler($command);
|
|
|
|
self::assertSame('devoir.pdf', $attachment->filename);
|
|
self::assertSame('application/pdf', $attachment->mimeType);
|
|
self::assertSame(1024, $attachment->fileSize);
|
|
self::assertStringContainsString('submissions/', $attachment->filePath);
|
|
}
|
|
|
|
#[Test]
|
|
public function itRejectsUploadOnSubmittedSubmission(): void
|
|
{
|
|
$submission = $this->createDraftSubmission();
|
|
$submission->soumettre(
|
|
dueDate: new DateTimeImmutable('2026-04-15'),
|
|
now: new DateTimeImmutable('2026-03-24 11:00:00'),
|
|
);
|
|
$this->submissionRepository->save($submission);
|
|
|
|
$handler = $this->createHandler();
|
|
$command = new UploadSubmissionAttachmentCommand(
|
|
tenantId: self::TENANT_ID,
|
|
submissionId: (string) $submission->id,
|
|
filename: 'devoir.pdf',
|
|
mimeType: 'application/pdf',
|
|
fileSize: 1024,
|
|
tempFilePath: $this->tempFile,
|
|
);
|
|
|
|
$this->expectException(RenduDejaSoumisException::class);
|
|
|
|
$handler($command);
|
|
}
|
|
|
|
private function createDraftSubmission(): HomeworkSubmission
|
|
{
|
|
return HomeworkSubmission::creerBrouillon(
|
|
tenantId: TenantId::fromString(self::TENANT_ID),
|
|
homeworkId: HomeworkId::fromString(self::HOMEWORK_ID),
|
|
studentId: UserId::fromString(self::STUDENT_ID),
|
|
responseHtml: '<p>Ma réponse</p>',
|
|
now: new DateTimeImmutable('2026-03-24 10:00:00'),
|
|
);
|
|
}
|
|
|
|
private function createHandler(): UploadSubmissionAttachmentHandler
|
|
{
|
|
$fileStorage = new class implements FileStorage {
|
|
public function upload(string $path, mixed $content, string $mimeType): string
|
|
{
|
|
return $path;
|
|
}
|
|
|
|
public function delete(string $path): void
|
|
{
|
|
}
|
|
|
|
public function readStream(string $path): mixed
|
|
{
|
|
/** @var resource $stream */
|
|
$stream = fopen('php://memory', 'r+');
|
|
|
|
return $stream;
|
|
}
|
|
};
|
|
|
|
$clock = new class implements Clock {
|
|
public function now(): DateTimeImmutable
|
|
{
|
|
return new DateTimeImmutable('2026-03-24 10:00:00');
|
|
}
|
|
};
|
|
|
|
return new UploadSubmissionAttachmentHandler(
|
|
$this->submissionRepository,
|
|
$fileStorage,
|
|
$clock,
|
|
);
|
|
}
|
|
}
|